From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9D5AC4363C for ; Sat, 19 Sep 2020 09:50:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9474F2075E for ; Sat, 19 Sep 2020 09:50:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726513AbgISJuu (ORCPT ); Sat, 19 Sep 2020 05:50:50 -0400 Received: from Galois.linutronix.de ([193.142.43.55]:40588 "EHLO galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726441AbgISJuY (ORCPT ); Sat, 19 Sep 2020 05:50:24 -0400 Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML Cc: linux-arch@vger.kernel.org, Linus Torvalds , Paul McKenney , x86@kernel.org, Sebastian Andrzej Siewior , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Daniel Bristot de Oliveira , Will Deacon , Andrew Morton , Linux-MM , Russell King , Linux ARM , Chris Zankel , Max Filippov , linux-xtensa@linux-xtensa.org, Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , David Airlie , Daniel Vetter , intel-gfx , dri-devel , Ard Biesheuvel , Herbert Xu , Vineet Gupta , linux-snps-arc@lists.infradead.org, Arnd Bergmann , Guo Ren , linux-csky@vger.kernel.org, Michal Simek , Thomas Bogendoerfer , linux-mips@vger.kernel.org, Nick Hu , Greentime Hu , Vincent Chen , Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , linuxppc-dev@lists.ozlabs.org, "David S. Miller" , sparclinux@vger.kernel.org Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-transfer-encoding: 8-bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Gleixner Date: Sat, 19 Sep 2020 09:18:06 +0000 Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* Message-Id: <20200919092617.375720378@linutronix.de> List-Id: References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: LKML Cc: Juri Lelli , Peter Zijlstra , Sebastian Andrzej Siewior , dri-devel , Ben Segall , Max Filippov , Guo Ren , sparclinux@vger.kernel.org, Vincent Chen , Will Deacon , Ard Biesheuvel , linux-arch@vger.kernel.org, Vincent Guittot , Herbert Xu , Michael Ellerman , x86@kernel.org, Russell King , linux-csky@vger.kernel.org, David Airlie , Mel Gorman , linux-snps-arc@lists.infradead.org, linux-xtensa@linux-xtensa.org, Paul McKenney , intel-gfx , linuxppc-dev@lists.ozlabs.org, Steven Rostedt , Linus Torvalds , Rodrigo Vivi , Dietmar Eggemann , Linux ARM , Chris Zankel , Michal Simek , Thomas Bogendoerfer , Nick Hu , Linux-MM , Vineet Gupta , linux-mips@vger.kernel.org, Arnd Bergmann , Paul Mackerras , Andrew Morton , Daniel Bristot de Oliveira , "David S. Miller" , Greentime Hu Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0FB96C35263 for ; Sat, 19 Sep 2020 09:50:41 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id A834E21D43 for ; Sat, 19 Sep 2020 09:50:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A834E21D43 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linutronix.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 99AAA6B006C; Sat, 19 Sep 2020 05:50:21 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 970AB900008; Sat, 19 Sep 2020 05:50:21 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7ECA56B0070; Sat, 19 Sep 2020 05:50:21 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0167.hostedemail.com [216.40.44.167]) by kanga.kvack.org (Postfix) with ESMTP id 5E5866B006C for ; Sat, 19 Sep 2020 05:50:21 -0400 (EDT) Received: from smtpin30.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 20084180AD802 for ; Sat, 19 Sep 2020 09:50:21 +0000 (UTC) X-FDA: 77279340642.30.error04_39069bb27132 Received: from filter.hostedemail.com (10.5.16.251.rfc1918.com [10.5.16.251]) by smtpin30.hostedemail.com (Postfix) with ESMTP id EBC00180B3AA7 for ; Sat, 19 Sep 2020 09:50:20 +0000 (UTC) X-HE-Tag: error04_39069bb27132 X-Filterd-Recvd-Size: 11813 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by imf36.hostedemail.com (Postfix) with ESMTP for ; Sat, 19 Sep 2020 09:50:20 +0000 (UTC) Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML Cc: linux-arch@vger.kernel.org, Linus Torvalds , Paul McKenney , x86@kernel.org, Sebastian Andrzej Siewior , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Daniel Bristot de Oliveira , Will Deacon , Andrew Morton , Linux-MM , Russell King , Linux ARM , Chris Zankel , Max Filippov , linux-xtensa@linux-xtensa.org, Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , David Airlie , Daniel Vetter , intel-gfx , dri-devel , Ard Biesheuvel , Herbert Xu , Vineet Gupta , linux-snps-arc@lists.infradead.org, Arnd Bergmann , Guo Ren , linux-csky@vger.kernel.org, Michal Simek , Thomas Bogendoerfer , linux-mips@vger.kernel.org, Nick Hu , Greentime Hu , Vincent Chen , Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , linuxppc-dev@lists.ozlabs.org, "David S. Miller" , sparclinux@vger.kernel.org Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-transfer-encoding: 8-bit X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E3449C43464 for ; Sat, 19 Sep 2020 10:17:31 +0000 (UTC) Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4F51121707 for ; Sat, 19 Sep 2020 10:17:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 4F51121707 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linutronix.de Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4Btmpx1MRvzDrHn for ; Sat, 19 Sep 2020 20:17:29 +1000 (AEST) Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linutronix.de (client-ip=2a0a:51c0:0:12e:550::1; helo=galois.linutronix.de; envelope-from=tglx@linutronix.de; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=linutronix.de header.i=@linutronix.de header.a=rsa-sha256 header.s=2020 header.b=uxskJelr; dkim=pass header.d=linutronix.de header.i=@linutronix.de header.a=ed25519-sha256 header.s=2020e header.b=PrQO9NIU; dkim-atps=neutral Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4BtmCj1n5czDqlJ for ; Sat, 19 Sep 2020 19:50:25 +1000 (AEST) Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-transfer-encoding: 8-bit X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Juri Lelli , Peter Zijlstra , Sebastian Andrzej Siewior , Joonas Lahtinen , dri-devel , Ben Segall , Max Filippov , Guo Ren , sparclinux@vger.kernel.org, Vincent Chen , Will Deacon , Ard Biesheuvel , linux-arch@vger.kernel.org, Vincent Guittot , Herbert Xu , x86@kernel.org, Russell King , linux-csky@vger.kernel.org, David Airlie , Mel Gorman , linux-snps-arc@lists.infradead.org, linux-xtensa@linux-xtensa.org, Paul McKenney , intel-gfx , linuxppc-dev@lists.ozlabs.org, Steven Rostedt , Linus Torvalds , Jani Nikula , Rodrigo Vivi , Dietmar Eggemann , Linux ARM , Chris Zankel , Michal Simek , Thomas Bogendoerfer , Nick Hu , Linux-MM , Vineet Gupta , linux-mips@vger.kernel.org, Arnd Bergmann , Daniel Vetter , Paul Mackerras , Andrew Morton , Daniel Bristot de Oliveira , "David S. Miller" , Greentime Hu Errors-To: linuxppc-dev-bounces+linuxppc-dev=archiver.kernel.org@lists.ozlabs.org Sender: "Linuxppc-dev" Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B283AC43464 for ; Sat, 19 Sep 2020 10:11:42 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1D9B421D42 for ; Sat, 19 Sep 2020 10:11:42 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="U/IOjRJc"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="tM1lL9Oa"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 1D9B421D42 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-snps-arc-bounces+linux-snps-arc=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:Subject:To:From:Date: Message-Id:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:List-Owner; bh=nvv9shN+ZcVRxemMknLMhzlPGLeU6mIkxUHsaHtRB98=; b=U/IOjRJciZqKVFVuD525tq1f+ ZZqLXrnmU2WJ/7syll6F4+bw9fto43Jr/fSPj7yiKivaOaDqu83opFnj8Gvz55TN4Kvb288ElzTZK 7i4s8BDZAvidPXXBwzMwOljnyVh1YVlZkg1g0nb9Z5dufwGbquvUIL0lwH12CbiRogZv/Yye02moh SEXv/rtsUlVfyMh91Wz6y2UgzpJbnCQz+DQly+H4PnjQDSQPBkbVjkkv0to/VyHX+yfTiktlAx8kN BJqISpTFGNEo0vwWNTR2SaCYn6ly3v21Vpu60JAfjtAr/ZUzoT0CowbyYS1X8YsQ1KROY3faRP0Qc xhGow/Gqg==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kJZqH-0006fQ-DB; Sat, 19 Sep 2020 10:11:41 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kJZqA-0006cm-Gs; Sat, 19 Sep 2020 10:11:34 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-transfer-encoding:Content-Type: MIME-Version:References:Subject:Cc:To:From:Date:Message-Id:Sender:Reply-To: Content-ID:Content-Description:In-Reply-To; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=tM1lL9Oa23A4qoJsy3l/3cvaD7 myzVrb2sZlYiXWocfn2YO5OI2fv8Oyz/1zAieuY9K6u6CqvY1BInZQLe51fczkNT9O+cKpme+fAFi u8M0la9/lm0X/zF5BMIB28Nysee6NBtlvoLnGfsYOO/fvOYINxN/YcE6HHM+WJZ6faWFMyHfwpbFG Ab6oUkiFsveJluI3a6RkVp8ehH2MY6YHTGEjsvl5C0feJ7yRD/HtPoRrjtK4OAgeihzJsAGaMz954 tvMjfqi32lx7ZEohysJPGw6f/wgVVvkjrGsklATcesnFavMMZhSM73g2H82MMSXUVeXafs6xqvmPx 5X8Ad5og==; Received: from galois.linutronix.de ([193.142.43.55]) by casper.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kJZVc-00061U-Ab; Sat, 19 Sep 2020 09:50:28 +0000 Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200919_105020_913947_539858AF X-CRM114-Status: GOOD ( 18.10 ) X-BeenThere: linux-snps-arc@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Linux on Synopsys ARC Processors List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Juri Lelli , Peter Zijlstra , Benjamin Herrenschmidt , Sebastian Andrzej Siewior , Joonas Lahtinen , dri-devel , Ben Segall , Max Filippov , Guo Ren , sparclinux@vger.kernel.org, Vincent Chen , Will Deacon , Ard Biesheuvel , linux-arch@vger.kernel.org, Vincent Guittot , Herbert Xu , Michael Ellerman , x86@kernel.org, Russell King , linux-csky@vger.kernel.org, David Airlie , Mel Gorman , linux-snps-arc@lists.infradead.org, linux-xtensa@linux-xtensa.org, Paul McKenney , intel-gfx , linuxppc-dev@lists.ozlabs.org, Steven Rostedt , Linus Torvalds , Jani Nikula , Rodrigo Vivi , Dietmar Eggemann , Linux ARM , Chris Zankel , Michal Simek , Thomas Bogendoerfer , Nick Hu , Linux-MM , Vineet Gupta , linux-mips@vger.kernel.org, Arnd Bergmann , Daniel Vetter , Paul Mackerras , Andrew Morton , Daniel Bristot de Oliveira , "David S. Miller" , Greentime Hu Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-snps-arc" Errors-To: linux-snps-arc-bounces+linux-snps-arc=archiver.kernel.org@lists.infradead.org Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { _______________________________________________ linux-snps-arc mailing list linux-snps-arc@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-snps-arc From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 016FEC43464 for ; Sat, 19 Sep 2020 10:13:20 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 83BA021D43 for ; Sat, 19 Sep 2020 10:13:19 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Jipl1G9Y"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="tM1lL9Oa"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 83BA021D43 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:Subject:To:From:Date: Message-Id:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:List-Owner; bh=wgaXUy8IGCXRD2tCMAACm5KwA/BU0hMQ+lIJDlJoVDI=; b=Jipl1G9YBbiu8k52O+1w3/ict flH70sP1QgqY/t1Mk5GQstFBu6Wyb2WURNJl/Y7d+B48iwkUI7i16im0Z2j/O4pPoWKZnx7Oa8thA IU076d29Pn57XUhp82IvOzjJ+YUDJ+4h7WNfpl5spZmZBI13uLRAZC/zSs9p4kZJWypuymPNXyBiw cqSQrHunkEDbBGv3jA1fl6GoEaCMytInc1W8wkKH3Mv37/FRw4RFXPCTi/suDewmSBpKcKdQwknbU yIBSrGpSLmoy8HnmdH68liLB+4sqZ8Hfii2/CjeDkzwxMgUJ0piCM9NiF7+U78NsfOLcL5mdji17a JLKXeUWmA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kJZqE-0006eU-GB; Sat, 19 Sep 2020 10:11:38 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kJZqA-0006cm-Gs; Sat, 19 Sep 2020 10:11:34 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-transfer-encoding:Content-Type: MIME-Version:References:Subject:Cc:To:From:Date:Message-Id:Sender:Reply-To: Content-ID:Content-Description:In-Reply-To; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=tM1lL9Oa23A4qoJsy3l/3cvaD7 myzVrb2sZlYiXWocfn2YO5OI2fv8Oyz/1zAieuY9K6u6CqvY1BInZQLe51fczkNT9O+cKpme+fAFi u8M0la9/lm0X/zF5BMIB28Nysee6NBtlvoLnGfsYOO/fvOYINxN/YcE6HHM+WJZ6faWFMyHfwpbFG Ab6oUkiFsveJluI3a6RkVp8ehH2MY6YHTGEjsvl5C0feJ7yRD/HtPoRrjtK4OAgeihzJsAGaMz954 tvMjfqi32lx7ZEohysJPGw6f/wgVVvkjrGsklATcesnFavMMZhSM73g2H82MMSXUVeXafs6xqvmPx 5X8Ad5og==; Received: from galois.linutronix.de ([193.142.43.55]) by casper.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kJZVc-00061U-Ab; Sat, 19 Sep 2020 09:50:28 +0000 Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200919_105020_913947_539858AF X-CRM114-Status: GOOD ( 18.10 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Juri Lelli , Peter Zijlstra , Benjamin Herrenschmidt , Sebastian Andrzej Siewior , Joonas Lahtinen , dri-devel , Ben Segall , Max Filippov , Guo Ren , sparclinux@vger.kernel.org, Vincent Chen , Will Deacon , Ard Biesheuvel , linux-arch@vger.kernel.org, Vincent Guittot , Herbert Xu , Michael Ellerman , x86@kernel.org, Russell King , linux-csky@vger.kernel.org, David Airlie , Mel Gorman , linux-snps-arc@lists.infradead.org, linux-xtensa@linux-xtensa.org, Paul McKenney , intel-gfx , linuxppc-dev@lists.ozlabs.org, Steven Rostedt , Linus Torvalds , Jani Nikula , Rodrigo Vivi , Dietmar Eggemann , Linux ARM , Chris Zankel , Michal Simek , Thomas Bogendoerfer , Nick Hu , Linux-MM , Vineet Gupta , linux-mips@vger.kernel.org, Arnd Bergmann , Daniel Vetter , Paul Mackerras , Andrew Morton , Daniel Bristot de Oliveira , "David S. Miller" , Greentime Hu Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.5 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 96BA0C43463 for ; Mon, 21 Sep 2020 07:36:29 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 42FC920719 for ; Mon, 21 Sep 2020 07:36:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 42FC920719 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 612946E22B; Mon, 21 Sep 2020 07:36:26 +0000 (UTC) Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by gabe.freedesktop.org (Postfix) with ESMTPS id A14D36E201; Sat, 19 Sep 2020 09:50:20 +0000 (UTC) Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML Subject: [patch RFC 15/15] mm/highmem: Provide kmap_temporary* References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 X-Mailman-Approved-At: Mon, 21 Sep 2020 07:34:44 +0000 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Juri Lelli , Peter Zijlstra , Sebastian Andrzej Siewior , dri-devel , Ben Segall , Max Filippov , Guo Ren , sparclinux@vger.kernel.org, Vincent Chen , Will Deacon , Ard Biesheuvel , linux-arch@vger.kernel.org, Vincent Guittot , Herbert Xu , Michael Ellerman , x86@kernel.org, Russell King , linux-csky@vger.kernel.org, David Airlie , Mel Gorman , linux-snps-arc@lists.infradead.org, linux-xtensa@linux-xtensa.org, Paul McKenney , intel-gfx , linuxppc-dev@lists.ozlabs.org, Steven Rostedt , Linus Torvalds , Rodrigo Vivi , Dietmar Eggemann , Linux ARM , Chris Zankel , Michal Simek , Thomas Bogendoerfer , Nick Hu , Linux-MM , Vineet Gupta , linux-mips@vger.kernel.org, Arnd Bergmann , Paul Mackerras , Andrew Morton , Daniel Bristot de Oliveira , "David S. Miller" , Greentime Hu Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC204C4346A for ; Sat, 19 Sep 2020 09:50:25 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5F41221582 for ; Sat, 19 Sep 2020 09:50:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="uxskJelr"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="PrQO9NIU" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5F41221582 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DD2C66E201; Sat, 19 Sep 2020 09:50:24 +0000 (UTC) Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by gabe.freedesktop.org (Postfix) with ESMTPS id A14D36E201; Sat, 19 Sep 2020 09:50:20 +0000 (UTC) Message-Id: <20200919092617.375720378@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=uxskJelrTfz/GKc9edsAEs0gb3DWYfCu7n8APYzVlc7bJQzv04iZOzHcmFq6t5qDrrVBZ/ 4C4PAFGkzsFp6nGQcpt5niy6S+9ydBCpiObiah/IVCCwDxhhHC5cgkAu/6V3V08Eh1r96m xmw3OVtejQT5gDr4T78MAAWwkDh33eqo6q17Wt0/k4vyjdndUorQf1g9379L4qm8930rmO GEKPqud78gf29AiUWocLXzxJzWSo2OEEBj/yrvwUOT1wKbOVlZ0FliAB+Yqg7cNrXdk79+ OO7sMlURN+BROu5//5m0JNoAo/MusM0EcFq1MWiz2xN8WqM4qDKFQ5QTwdF32g== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1600509019; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: references:references; bh=dJhau0LaFILj/IFm3JpK00/lnAjoDukMJ8R0j3dPchU=; b=PrQO9NIUtOX/0/EHlhtg0Juh5C5GtlSLp2/PPAA/aAaFXiFrlKNN8Eayg02fcVDZ14HDVH br4tlK6E4ZYXVrAg== Date: Sat, 19 Sep 2020 11:18:06 +0200 From: Thomas Gleixner To: LKML References: <20200919091751.011116649@linutronix.de> MIME-Version: 1.0 Subject: [Intel-gfx] [patch RFC 15/15] mm/highmem: Provide kmap_temporary* X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Juri Lelli , Peter Zijlstra , Benjamin Herrenschmidt , Sebastian Andrzej Siewior , dri-devel , Ben Segall , Max Filippov , Guo Ren , sparclinux@vger.kernel.org, Vincent Chen , Will Deacon , Ard Biesheuvel , linux-arch@vger.kernel.org, Herbert Xu , Michael Ellerman , x86@kernel.org, Russell King , linux-csky@vger.kernel.org, David Airlie , Mel Gorman , linux-snps-arc@lists.infradead.org, linux-xtensa@linux-xtensa.org, Paul McKenney , intel-gfx , linuxppc-dev@lists.ozlabs.org, Steven Rostedt , Linus Torvalds , Dietmar Eggemann , Linux ARM , Chris Zankel , Michal Simek , Thomas Bogendoerfer , Nick Hu , Linux-MM , Vineet Gupta , linux-mips@vger.kernel.org, Arnd Bergmann , Paul Mackerras , Andrew Morton , Daniel Bristot de Oliveira , "David S. Miller" , Greentime Hu Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Now that the kmap atomic index is stored in task struct provide a preemptible variant. On context switch the maps of an outgoing task are removed and the map of the incoming task are restored. That's obviously slow, but highmem is slow anyway. The kmap_temporary and iomap_temporary interfaces can be invoked from both preemptible and atomic context. A wholesale conversion of kmap_atomic to be fully preemptible is not possible because some of the usage sites might rely on the preemption disable for serialization or per CPUness. Needs to be done on a case by case basis. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/iomap.h | 16 ++++++++- arch/x86/mm/iomap_32.c | 7 +--- include/linux/highmem.h | 70 +++++++++++++++++++++++++++++++++---------- mm/highmem.c | 18 +++++------ 4 files changed, 80 insertions(+), 31 deletions(-) --- a/arch/x86/include/asm/iomap.h +++ b/arch/x86/include/asm/iomap.h @@ -13,11 +13,23 @@ #include #include -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); + +static inline void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, + pgprot_t prot) +{ + preempt_disable(); + return iomap_temporary_pfn_prot(pfn, prot); +} + +static inline void iounmap_temporary(void __iomem *vaddr) +{ + kunmap_temporary_indexed((void __force *)vaddr); +} static inline void iounmap_atomic(void __iomem *vaddr) { - kunmap_atomic_indexed((void __force *)vaddr); + iounmap_temporary(vaddr); preempt_enable(); } --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c @@ -44,7 +44,7 @@ void iomap_free(resource_size_t base, un } EXPORT_SYMBOL_GPL(iomap_free); -void __iomem *iomap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void __iomem *iomap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { /* * For non-PAT systems, translate non-WB request to UC- just in @@ -60,7 +60,6 @@ void __iomem *iomap_atomic_pfn_prot(unsi /* Filter out unsupported __PAGE_KERNEL* bits: */ pgprot_val(prot) &= __default_kernel_pte_mask; - preempt_disable(); - return (void __force __iomem *)kmap_atomic_pfn_prot(pfn, prot); + return (void __force __iomem *)__kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL_GPL(iomap_atomic_pfn_prot); +EXPORT_SYMBOL_GPL(iomap_temporary_pfn_prot); --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -35,9 +35,9 @@ static inline void invalidate_kernel_vma * Outside of CONFIG_HIGHMEM to support X86 32bit iomap_atomic() cruft. */ #ifdef CONFIG_KMAP_ATOMIC_GENERIC -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot); -void kunmap_atomic_indexed(void *vaddr); +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot); +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot); +void kunmap_temporary_indexed(void *vaddr); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next); # ifndef ARCH_NEEDS_KMAP_HIGH_GET static inline void *arch_kmap_temporary_high_get(struct page *page) @@ -95,16 +95,35 @@ static inline void kunmap(struct page *p * be used in IRQ contexts, so in some (very limited) cases we need * it. */ -static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) { - preempt_disable(); - return kmap_atomic_page_prot(page, prot); + return __kmap_temporary_page_prot(page, prot); } -static inline void *kmap_atomic_pfn(unsigned long pfn) +static inline void *kmap_temporary_page(struct page *page) +{ + return kmap_temporary_page_prot(page, kmap_prot); +} + +static inline void *kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) +{ + return __kmap_temporary_pfn_prot(pfn, prot); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_pfn_prot(pfn, kmap_prot); +} + +static inline void __kunmap_temporary(void *vaddr) +{ + kunmap_temporary_indexed(vaddr); +} + +static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot) { preempt_disable(); - return kmap_atomic_pfn_prot(pfn, kmap_prot); + return kmap_temporary_page_prot(page, prot); } static inline void *kmap_atomic(struct page *page) @@ -112,9 +131,10 @@ static inline void *kmap_atomic(struct p return kmap_atomic_prot(page, kmap_prot); } -static inline void __kunmap_atomic(void *addr) +static inline void *kmap_atomic_pfn(unsigned long pfn) { - kumap_atomic_indexed(addr); + preempt_disable(); + return kmap_temporary_pfn_prot(pfn, kmap_prot); } /* declarations for linux/mm/highmem.c */ @@ -177,6 +197,22 @@ static inline void kunmap(struct page *p #endif } +static inline void *kmap_temporary_page(struct page *page) +{ + pagefault_disable(); + return page_address(page); +} + +static inline void *kmap_temporary_page_prot(struct page *page, pgprot_t prot) +{ + return kmap_temporary_page(page); +} + +static inline void *kmap_temporary_pfn(unsigned long pfn) +{ + return kmap_temporary_page(pfn_to_page(pfn)); +} + static inline void *kmap_atomic(struct page *page) { preempt_disable(); @@ -194,12 +230,8 @@ static inline void *kmap_atomic_pfn(unsi return kmap_atomic(pfn_to_page(pfn)); } -static inline void __kunmap_atomic(void *addr) +static inline void __kunmap_temporary(void *addr) { - /* - * Mostly nothing to do in the CONFIG_HIGHMEM=n case as kunmap_atomic() - * handles preemption - */ #ifdef ARCH_HAS_FLUSH_ON_KUNMAP kunmap_flush_on_unmap(addr); #endif @@ -217,10 +249,16 @@ static inline void __kunmap_atomic(void #define kunmap_atomic(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ - __kunmap_atomic(addr); \ + __kunmap_temporary(addr); \ preempt_enable(); \ } while (0) +#define kunmap_temporary(addr) \ + do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_temporary(addr); \ + } while (0) + /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage static inline void clear_user_highpage(struct page *page, unsigned long vaddr) --- a/mm/highmem.c +++ b/mm/highmem.c @@ -432,7 +432,7 @@ static pte_t *kmap_get_pte(void) return __kmap_pte; } -static void *__kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +static void *do_kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pte_t pteval, *kmap_pte = kmap_get_pte(); unsigned long vaddr; @@ -451,14 +451,14 @@ static void *__kmap_atomic_pfn_prot(unsi return (void *)vaddr; } -void *kmap_atomic_pfn_prot(unsigned long pfn, pgprot_t prot) +void *__kmap_temporary_pfn_prot(unsigned long pfn, pgprot_t prot) { pagefault_disable(); - return __kmap_atomic_pfn_prot(pfn, prot); + return do_kmap_temporary_pfn_prot(pfn, prot); } -EXPORT_SYMBOL(kmap_atomic_pfn_prot); +EXPORT_SYMBOL(__kmap_temporary_pfn_prot); -void *kmap_atomic_page_prot(struct page *page, pgprot_t prot) +void *__kmap_temporary_page_prot(struct page *page, pgprot_t prot) { void *kmap; @@ -471,11 +471,11 @@ void *kmap_atomic_page_prot(struct page if (kmap) return kmap; - return __kmap_atomic_pfn_prot(page_to_pfn(page), prot); + return do_kmap_temporary_pfn_prot(page_to_pfn(page), prot); } -EXPORT_SYMBOL(kmap_atomic_page_prot); +EXPORT_SYMBOL(__kmap_temporary_page_prot); -void kunmap_atomic_indexed(void *vaddr) +void kunmap_temporary_indexed(void *vaddr) { unsigned long addr = (unsigned long) vaddr & PAGE_MASK; pte_t *kmap_pte = kmap_get_pte(); @@ -503,7 +503,7 @@ void kunmap_atomic_indexed(void *vaddr) preempt_enable(); pagefault_enable(); } -EXPORT_SYMBOL(kunmap_atomic_indexed); +EXPORT_SYMBOL(kunmap_temporary_indexed); void kmap_switch_temporary(struct task_struct *prev, struct task_struct *next) { _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx