Skip to content

Commit 2a656ca

Browse files
committed
mm/highmem: Take kmap_high_get() properly into account
kunmap_local() warns when the virtual address to unmap is below PAGE_OFFSET. This is correct except for the case that the mapping was obtained via kmap_high_get() because the PKMAP addresses are right below PAGE_OFFSET. Cure it by skipping the WARN_ON() when the unmap was handled by kunmap_high(). Fixes: 298fa1a ("highmem: Provide generic variant of kmap_atomic*") Reported-by: [email protected] Reported-by: Marek Szyprowski <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Marek Szyprowski <[email protected]> Tested-by: Sebastian Andrzej Siewior <[email protected]> Cc: Andrew Morton <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 13f876b commit 2a656ca

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

mm/highmem.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -426,12 +426,15 @@ static inline void *arch_kmap_local_high_get(struct page *page)
426426
#endif
427427

428428
/* Unmap a local mapping which was obtained by kmap_high_get() */
429-
static inline void kmap_high_unmap_local(unsigned long vaddr)
429+
static inline bool kmap_high_unmap_local(unsigned long vaddr)
430430
{
431431
#ifdef ARCH_NEEDS_KMAP_HIGH_GET
432-
if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP))
432+
if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
433433
kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
434+
return true;
435+
}
434436
#endif
437+
return false;
435438
}
436439

437440
static inline int kmap_local_calc_idx(int idx)
@@ -491,10 +494,14 @@ void kunmap_local_indexed(void *vaddr)
491494

492495
if (addr < __fix_to_virt(FIX_KMAP_END) ||
493496
addr > __fix_to_virt(FIX_KMAP_BEGIN)) {
494-
WARN_ON_ONCE(addr < PAGE_OFFSET);
495-
496-
/* Handle mappings which were obtained by kmap_high_get() */
497-
kmap_high_unmap_local(addr);
497+
/*
498+
* Handle mappings which were obtained by kmap_high_get()
499+
* first as the virtual address of such mappings is below
500+
* PAGE_OFFSET. Warn for all other addresses which are in
501+
* the user space part of the virtual address space.
502+
*/
503+
if (!kmap_high_unmap_local(addr))
504+
WARN_ON_ONCE(addr < PAGE_OFFSET);
498505
return;
499506
}
500507

0 commit comments

Comments
 (0)