Received: by 2002:a17:90a:1609:0:0:0:0 with SMTP id n9csp3652152pja; Tue, 31 Mar 2020 02:51:24 -0700 (PDT) X-Google-Smtp-Source: ADFU+vtDpAWtWRojciN3D3d8sk9+aEQH3xSbdnlTKH0X1S1njPDlFU8PXQlkrkIyeD5LegDztvn+ X-Received: by 2002:a05:6830:1ae9:: with SMTP id c9mr11719619otd.298.1585648284196; Tue, 31 Mar 2020 02:51:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585648284; cv=none; d=google.com; s=arc-20160816; b=zDUhJjSjf77Og9MWCKtBcjg3KV29kvQXxpbZy1tRY0FkGSgefK9Sfkktbl4m63rHUG ZeMCe8L57Giv+3bb6UF7Uq5RjJiQKVXbwfhHI03cV45RX+iLpe4ShVWcnamujJzezYg9 7PDttIOQo5qa35+54vsaNIkp+fcTI3O3D9IYKOyzTb65Y6tsbM2AjTLISk354ncShSmb Yn4NMn4skl3HC1nog9Qi7sOj0dGafTRjcw1NszfPqZBRB5e1O1dA0IwUz9LsND1IvqKh 8D3PyvZlVA/eFOJ6+xvlICA711XdQMhD5PhWh+MmsQ2l4PqJtRBGbQIq23vojMdBdZYu mHcQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from; bh=OUlrZC/jATrdMXw10aZ5qI0/2xnwzogUsRtOAkexaQE=; b=Cm4FRRVuktFZTPEYH9A2n5zRiFYBVj9ApoFi4XYQGW+vd6upfhQvCDwRBL9BLynaSG sXj2BWHYUPFiGdLDJKZrPihY+frbyeHKQCZbsmzLQ8IX57v0bsXSYetB31jaCrv8WPpg PIMcdP/LDJMvx6hPQ4DmSF4UD5zEY4JrzI0/t0/mreLNzvN2jufsgJW4sayW/874OhUn nIC12T7klr051xazO5zVgJyj3YkZhmzAob8R28fKp7UvU7YPjRGQR3m+hsaJX15lBoWB 9ns9qw9B67EZ70FMHxYwYjBLGZ1Yy4x5/I8I1en4YFWRFV5no0cdhzk1LU28zKK8/GEV OXow== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id k25si6566439oik.162.2020.03.31.02.51.11; Tue, 31 Mar 2020 02:51:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730478AbgCaJuC (ORCPT + 99 others); Tue, 31 Mar 2020 05:50:02 -0400 Received: from 59-120-53-16.HINET-IP.hinet.net ([59.120.53.16]:14592 "EHLO ATCSQR.andestech.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1730430AbgCaJt7 (ORCPT ); Tue, 31 Mar 2020 05:49:59 -0400 Received: from ATCSQR.andestech.com (localhost [127.0.0.2] (may be forged)) by ATCSQR.andestech.com with ESMTP id 02V9bYm1066402 for ; Tue, 31 Mar 2020 17:37:34 +0800 (GMT-8) (envelope-from tesheng@andestech.com) Received: from mail.andestech.com (atcpcs16.andestech.com [10.0.1.222]) by ATCSQR.andestech.com with ESMTP id 02V9WGga065487; Tue, 31 Mar 2020 17:32:16 +0800 (GMT-8) (envelope-from tesheng@andestech.com) Received: from atcsqa06.andestech.com (10.0.15.65) by ATCPCS16.andestech.com (10.0.1.222) with Microsoft SMTP Server id 14.3.123.3; Tue, 31 Mar 2020 17:33:08 +0800 From: Eric Lin To: CC: , , , , , , , , , , , , , , , , , , Eric Lin , Alan Kao Subject: [PATCH 2/3] riscv/mm: Implement kmap() and kmap_atomic() Date: Tue, 31 Mar 2020 17:32:40 +0800 Message-ID: <20200331093241.3728-3-tesheng@andestech.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20200331093241.3728-1-tesheng@andestech.com> References: <20200331093241.3728-1-tesheng@andestech.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.0.15.65] X-DNSRBL: X-MAIL: ATCSQR.andestech.com 02V9WGga065487 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Both kmap() and kmap_atomic() help kernel to create temporary mappings from a highmem page. Be aware that use kmap() might put calling function to sleep and it cannot use in interrupt context. kmap_atomic() is an atomic version of kmap() which can be used in interrupt context and it is faster than kmap() because it doesn't hold a lock. Here we preserve some memory slots from fixmap region for kmap_atomic() and kmap() will use pkmap region. Signed-off-by: Eric Lin Cc: Alan Kao --- arch/riscv/include/asm/fixmap.h | 9 +++- arch/riscv/include/asm/highmem.h | 30 +++++++++++++ arch/riscv/include/asm/pgtable.h | 5 +++ arch/riscv/mm/Makefile | 1 + arch/riscv/mm/highmem.c | 74 ++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/mm/highmem.c diff --git a/arch/riscv/include/asm/fixmap.h b/arch/riscv/include/asm/fixmap.h index 42d2c42f3cc9..8dedc2bf2917 100644 --- a/arch/riscv/include/asm/fixmap.h +++ b/arch/riscv/include/asm/fixmap.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2019 Western Digital Corporation or its affiliates. + * Copyright (C) 2020 Andes Technology Corporation */ #ifndef _ASM_RISCV_FIXMAP_H @@ -10,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_MMU /* @@ -28,7 +30,12 @@ enum fixed_addresses { FIX_PTE, FIX_PMD, FIX_EARLYCON_MEM_BASE, - __end_of_fixed_addresses +#ifdef CONFIG_HIGHMEM + FIX_KMAP_RESERVED, + FIX_KMAP_BEGIN, + FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS), +#endif + __end_of_fixed_addresses, }; #define FIXMAP_PAGE_IO PAGE_KERNEL diff --git a/arch/riscv/include/asm/highmem.h b/arch/riscv/include/asm/highmem.h index 7fc79e58f607..ec7c83d55830 100644 --- a/arch/riscv/include/asm/highmem.h +++ b/arch/riscv/include/asm/highmem.h @@ -17,3 +17,33 @@ #define PKMAP_NR(virt) (((virt) - (PKMAP_BASE)) >> PAGE_SHIFT) #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) #define kmap_prot PAGE_KERNEL + +static inline void flush_cache_kmaps(void) +{ + flush_cache_all(); +} + +/* Declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +extern pte_t *pkmap_page_table; + +extern void *kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +extern void kmap_init(void); + +/* + * The following functions are already defined by + * when CONFIG_HIGHMEM is not set. + */ +#ifdef CONFIG_HIGHMEM +extern void *kmap(struct page *page); +extern void kunmap(struct page *page); +extern void *kmap_atomic(struct page *page); +extern void __kunmap_atomic(void *kvaddr); +extern void *kmap_atomic_pfn(unsigned long pfn); +extern struct page *kmap_atomic_to_page(void *ptr); +#endif + +#endif diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index d9a3769f1f4e..1a774d5a8bbc 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -200,6 +200,11 @@ static inline pgd_t *pgd_offset(const struct mm_struct *mm, unsigned long addr) /* Locate an entry in the kernel page global directory */ #define pgd_offset_k(addr) pgd_offset(&init_mm, (addr)) +#ifdef CONFIG_HIGHMEM +/* Locate an entry in the second-level page table */ +#define pmd_off_k(addr) pmd_offset((pud_t *)pgd_offset_k(addr), addr) +#endif + static inline struct page *pmd_page(pmd_t pmd) { return pfn_to_page(pmd_val(pmd) >> _PAGE_PFN_SHIFT); diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile index 50b7af58c566..6f9305afc632 100644 --- a/arch/riscv/mm/Makefile +++ b/arch/riscv/mm/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_SMP) += tlbflush.o endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_KASAN) += kasan_init.o +obj-$(CONFIG_HIGHMEM) += highmem.o ifdef CONFIG_KASAN KASAN_SANITIZE_kasan_init.o := n diff --git a/arch/riscv/mm/highmem.c b/arch/riscv/mm/highmem.c new file mode 100644 index 000000000000..b01ebe34619e --- /dev/null +++ b/arch/riscv/mm/highmem.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2005-2020 Andes Technology Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void *kmap(struct page *page) +{ + unsigned long vaddr; + + might_sleep(); + if (!PageHighMem(page)) + return page_address(page); + vaddr = (unsigned long)kmap_high(page); + return (void *)vaddr; +} +EXPORT_SYMBOL(kmap); + +void kunmap(struct page *page) +{ + BUG_ON(in_interrupt()); + if (!PageHighMem(page)) + return; + kunmap_high(page); +} +EXPORT_SYMBOL(kunmap); + +void *kmap_atomic(struct page *page) +{ + unsigned int idx; + unsigned long vaddr; + int type; + pte_t *ptep; + + preempt_disable(); + pagefault_disable(); + + if (!PageHighMem(page)) + return page_address(page); + + type = kmap_atomic_idx_push(); + + idx = type + KM_TYPE_NR * smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); + + ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); + set_pte(ptep, mk_pte(page, kmap_prot)); + + return (void *)vaddr; +} +EXPORT_SYMBOL(kmap_atomic); + +void __kunmap_atomic(void *kvaddr) +{ + if (kvaddr >= (void *)FIXADDR_START && kvaddr < (void *)FIXADDR_TOP) { + unsigned long vaddr = (unsigned long)kvaddr; + pte_t *ptep; + + kmap_atomic_idx_pop(); + ptep = pte_offset_kernel(pmd_off_k(vaddr), vaddr); + set_pte(ptep, __pte(0)); + } + pagefault_enable(); + preempt_enable(); +} +EXPORT_SYMBOL(__kunmap_atomic); -- 2.17.0