linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "tip-bot2 for Thomas Gleixner" <tip-bot2@linutronix.de>
To: linux-tip-commits@vger.kernel.org
Cc: Thomas Gleixner <tglx@linutronix.de>,
	"Peter Zijlstra (Intel)" <peterz@infradead.org>,
	x86@kernel.org, linux-kernel@vger.kernel.org
Subject: [tip: core/mm] mm/highmem: Provide kmap_local*
Date: Tue, 24 Nov 2020 14:20:53 -0000	[thread overview]
Message-ID: <160622765305.11115.11767201930174930313.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20201118204007.468533059@linutronix.de>

The following commit has been merged into the core/mm branch of tip:

Commit-ID:     f3ba3c710ac5a30cd058615a9eb62d2ad95bb782
Gitweb:        https://git.kernel.org/tip/f3ba3c710ac5a30cd058615a9eb62d2ad95bb782
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 18 Nov 2020 20:48:44 +01:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Tue, 24 Nov 2020 14:42:09 +01:00

mm/highmem: Provide kmap_local*

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_local.*() functions can be invoked from both preemptible and
atomic context. kmap local sections disable migration to keep the resulting
virtual mapping address correct, but disable neither pagefaults nor
preemption.

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 on the implicit pagefault disable. Needs to be
done on a case by case basis.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20201118204007.468533059@linutronix.de

---
 include/linux/highmem-internal.h | 48 +++++++++++++++++++++++++++++++-
 include/linux/highmem.h          | 43 +++++++++++++++++-----------
 mm/highmem.c                     |  6 ++++-
 3 files changed, 81 insertions(+), 16 deletions(-)

diff --git a/include/linux/highmem-internal.h b/include/linux/highmem-internal.h
index c5a2217..1bbe96d 100644
--- a/include/linux/highmem-internal.h
+++ b/include/linux/highmem-internal.h
@@ -68,6 +68,26 @@ static inline void kmap_flush_unused(void)
 	__kmap_flush_unused();
 }
 
+static inline void *kmap_local_page(struct page *page)
+{
+	return __kmap_local_page_prot(page, kmap_prot);
+}
+
+static inline void *kmap_local_page_prot(struct page *page, pgprot_t prot)
+{
+	return __kmap_local_page_prot(page, prot);
+}
+
+static inline void *kmap_local_pfn(unsigned long pfn)
+{
+	return __kmap_local_pfn_prot(pfn, kmap_prot);
+}
+
+static inline void __kunmap_local(void *vaddr)
+{
+	kunmap_local_indexed(vaddr);
+}
+
 static inline void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
 	preempt_disable();
@@ -140,6 +160,28 @@ static inline void kunmap(struct page *page)
 #endif
 }
 
+static inline void *kmap_local_page(struct page *page)
+{
+	return page_address(page);
+}
+
+static inline void *kmap_local_page_prot(struct page *page, pgprot_t prot)
+{
+	return kmap_local_page(page);
+}
+
+static inline void *kmap_local_pfn(unsigned long pfn)
+{
+	return kmap_local_page(pfn_to_page(pfn));
+}
+
+static inline void __kunmap_local(void *addr)
+{
+#ifdef ARCH_HAS_FLUSH_ON_KUNMAP
+	kunmap_flush_on_unmap(addr);
+#endif
+}
+
 static inline void *kmap_atomic(struct page *page)
 {
 	preempt_disable();
@@ -181,4 +223,10 @@ do {								\
 	__kunmap_atomic(__addr);				\
 } while (0)
 
+#define kunmap_local(__addr)					\
+do {								\
+	BUILD_BUG_ON(__same_type((__addr), struct page *));	\
+	__kunmap_local(__addr);					\
+} while (0)
+
 #endif
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 7d098bd..f597830 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -60,24 +60,22 @@ static inline struct page *kmap_to_page(void *addr);
 static inline void kmap_flush_unused(void);
 
 /**
- * kmap_atomic - Atomically map a page for temporary usage
+ * kmap_local_page - Map a page for temporary usage
  * @page:	Pointer to the page to be mapped
  *
  * Returns: The virtual address of the mapping
  *
- * Side effect: On return pagefaults and preemption are disabled.
- *
  * Can be invoked from any context.
  *
  * Requires careful handling when nesting multiple mappings because the map
  * management is stack based. The unmap has to be in the reverse order of
  * the map operation:
  *
- * addr1 = kmap_atomic(page1);
- * addr2 = kmap_atomic(page2);
+ * addr1 = kmap_local_page(page1);
+ * addr2 = kmap_local_page(page2);
  * ...
- * kunmap_atomic(addr2);
- * kunmap_atomic(addr1);
+ * kunmap_local(addr2);
+ * kunmap_local(addr1);
  *
  * Unmapping addr1 before addr2 is invalid and causes malfunction.
  *
@@ -88,10 +86,26 @@ static inline void kmap_flush_unused(void);
  * virtual address of the direct mapping. Only real highmem pages are
  * temporarily mapped.
  *
- * While it is significantly faster than kmap() it comes with restrictions
- * about the pointer validity and the side effects of disabling page faults
- * and preemption. Use it only when absolutely necessary, e.g. from non
- * preemptible contexts.
+ * While it is significantly faster than kmap() for the higmem case it
+ * comes with restrictions about the pointer validity. Only use when really
+ * necessary.
+ *
+ * On HIGHMEM enabled systems mapping a highmem page has the side effect of
+ * disabling migration in order to keep the virtual address stable across
+ * preemption. No caller of kmap_local_page() can rely on this side effect.
+ */
+static inline void *kmap_local_page(struct page *page);
+
+/**
+ * kmap_atomic - Atomically map a page for temporary usage - Deprecated!
+ * @page:	Pointer to the page to be mapped
+ *
+ * Returns: The virtual address of the mapping
+ *
+ * Effectively a wrapper around kmap_local_page() which disables pagefaults
+ * and preemption.
+ *
+ * Do not use in new code. Use kmap_local_page() instead.
  */
 static inline void *kmap_atomic(struct page *page);
 
@@ -101,12 +115,9 @@ static inline void *kmap_atomic(struct page *page);
  *
  * Counterpart to kmap_atomic().
  *
- * Undoes the side effects of kmap_atomic(), i.e. reenabling pagefaults and
+ * Effectively a wrapper around kunmap_local() which additionally undoes
+ * the side effects of kmap_atomic(), i.e. reenabling pagefaults and
  * preemption.
- *
- * Other than that a NOOP for CONFIG_HIGHMEM=n and for mappings of pages
- * in the low memory area. For real highmen pages the mapping which was
- * established with kmap_atomic() is destroyed.
  */
 
 /* Highmem related interfaces for management code */
diff --git a/mm/highmem.c b/mm/highmem.c
index d1ef06a..83f9660 100644
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -453,6 +453,11 @@ void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t prot)
 	unsigned long vaddr;
 	int idx;
 
+	/*
+	 * Disable migration so resulting virtual address is stable
+	 * accross preemption.
+	 */
+	migrate_disable();
 	preempt_disable();
 	idx = arch_kmap_local_map_idx(kmap_local_idx_push(), pfn);
 	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
@@ -522,6 +527,7 @@ void kunmap_local_indexed(void *vaddr)
 	current->kmap_ctrl.pteval[kmap_local_idx()] = __pte(0);
 	kmap_local_idx_pop();
 	preempt_enable();
+	migrate_enable();
 }
 EXPORT_SYMBOL(kunmap_local_indexed);
 

  reply	other threads:[~2020-11-24 14:20 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-18 19:48 [patch V4 0/8] mm/highmem: Preemptible variant of kmap_atomic & friends Thomas Gleixner
2020-11-18 19:48 ` [patch V4 1/8] mm/highmem: Provide and use CONFIG_DEBUG_KMAP_LOCAL Thomas Gleixner
2020-11-24 14:20   ` [tip: core/mm] " tip-bot2 for Thomas Gleixner
2020-11-18 19:48 ` [patch V4 2/8] mm/highmem: Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP Thomas Gleixner
2020-11-18 21:13   ` Linus Torvalds
2020-11-19  8:46     ` Mel Gorman
2020-11-19 17:19       ` Linus Torvalds
2020-11-24 14:20   ` [tip: core/mm] " tip-bot2 for Thomas Gleixner
2020-11-18 19:48 ` [patch V4 3/8] x86: Support kmap_local() forced debugging Thomas Gleixner
2020-11-24 14:20   ` [tip: core/mm] " tip-bot2 for Thomas Gleixner
2021-01-06 23:01   ` [BUG] from " Steven Rostedt
2021-01-07  1:03     ` Linus Torvalds
2021-01-07  1:16       ` Steven Rostedt
2021-01-07  1:49       ` Steven Rostedt
2021-01-07  1:49       ` Jakub Kicinski
2021-01-07  2:11         ` Willem de Bruijn
2021-01-07  4:44           ` Willem de Bruijn
2021-01-07 19:47             ` Linus Torvalds
2021-01-07 20:52               ` Steven Rostedt
2021-01-07 21:07                 ` Willem de Bruijn
2020-11-18 19:48 ` [patch V4 4/8] sched: Make migrate_disable/enable() independent of RT Thomas Gleixner
2020-11-19  9:38   ` Mel Gorman
2020-11-19 11:14     ` Peter Zijlstra
2020-11-19 12:14       ` Mel Gorman
2020-11-19 14:17         ` Steven Rostedt
2020-11-19 17:23       ` Linus Torvalds
2020-11-19 18:28         ` Peter Zijlstra
2020-11-20  1:33           ` Thomas Gleixner
2020-11-20  9:29             ` Peter Zijlstra
2020-11-22 23:16               ` Andy Lutomirski
2020-11-23 21:15                 ` Thomas Gleixner
2020-11-23 21:25                   ` Thomas Gleixner
2020-11-23 22:07                     ` Andy Lutomirski
2020-11-23 23:10                       ` Thomas Gleixner
2020-11-24 10:29   ` [tip: sched/core] " tip-bot2 for Thomas Gleixner
2020-11-18 19:48 ` [patch V4 5/8] sched: highmem: Store local kmaps in task struct Thomas Gleixner
2020-11-19 11:33   ` Peter Zijlstra
2020-11-19 11:51   ` Peter Zijlstra
2020-11-19 12:12     ` Peter Zijlstra
2020-11-19 14:11       ` Thomas Gleixner
2020-11-24 14:20   ` [tip: core/mm] " tip-bot2 for Thomas Gleixner
2020-11-18 19:48 ` [patch V4 6/8] mm/highmem: Provide kmap_local* Thomas Gleixner
2020-11-24 14:20   ` tip-bot2 for Thomas Gleixner [this message]
2020-11-18 19:48 ` [patch V4 7/8] io-mapping: Provide iomap_local variant Thomas Gleixner
2020-11-24 14:20   ` [tip: core/mm] " tip-bot2 for Thomas Gleixner
2020-11-18 19:48 ` [patch V4 8/8] x86/crashdump/32: Simplify copy_oldmem_page() Thomas Gleixner
2020-11-24 14:20   ` [tip: core/mm] " tip-bot2 for Thomas Gleixner
2020-11-24  8:03 ` [patch V4 0/8] mm/highmem: Preemptible variant of kmap_atomic & friends Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=160622765305.11115.11767201930174930313.tip-bot2@tip-bot2 \
    --to=tip-bot2@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).