aboutsummaryrefslogtreecommitdiffstats
path: root/mm/highmem.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2020-11-18 20:48:44 +0100
committerThomas Gleixner <tglx@linutronix.de>2020-11-24 14:42:09 +0100
commitf3ba3c710ac5a30cd058615a9eb62d2ad95bb782 (patch)
tree1678112f3c1f9793ac5551679cfe2a275a270543 /mm/highmem.c
parentsched: highmem: Store local kmaps in task struct (diff)
downloadlinux-dev-f3ba3c710ac5a30cd058615a9eb62d2ad95bb782.tar.xz
linux-dev-f3ba3c710ac5a30cd058615a9eb62d2ad95bb782.zip
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
Diffstat (limited to 'mm/highmem.c')
-rw-r--r--mm/highmem.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/mm/highmem.c b/mm/highmem.c
index d1ef06aa6de6..83f9660f168f 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);