Skip to content

Commit 7929eb9

Browse files
Nicolas PitreRussell King
authored andcommitted
ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() with highmem
Let's suppose a highmem page is kmap'd with kmap(). A pkmap entry is used, the page mapped to it, and the virtual cache is dirtied. Then kunmap() is used which does virtually nothing except for decrementing a usage count. Then, let's suppose the _same_ page gets mapped using kmap_atomic(). It is therefore mapped onto a fixmap entry instead, which has a different virtual address unaware of the dirty cache data for that page sitting in the pkmap mapping. Fortunately it is easy to know if a pkmap mapping still exists for that page and use it directly with kmap_atomic(), thanks to kmap_high_get(). And actual testing with a printk in the added code path shows that this condition is actually met *extremely* frequently. Seems that we've been quite lucky that things have worked so well with highmem so far. Cc: stable@kernel.org Signed-off-by: Nicolas Pitre <nico@marvell.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
1 parent c47a830 commit 7929eb9

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

arch/arm/mm/highmem.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,16 @@ void *kmap_atomic(struct page *page, enum km_type type)
4040
{
4141
unsigned int idx;
4242
unsigned long vaddr;
43+
void *kmap;
4344

4445
pagefault_disable();
4546
if (!PageHighMem(page))
4647
return page_address(page);
4748

49+
kmap = kmap_high_get(page);
50+
if (kmap)
51+
return kmap;
52+
4853
idx = type + KM_TYPE_NR * smp_processor_id();
4954
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
5055
#ifdef CONFIG_DEBUG_HIGHMEM
@@ -80,6 +85,9 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
8085
#else
8186
(void) idx; /* to kill a warning */
8287
#endif
88+
} else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) {
89+
/* this address was obtained through kmap_high_get() */
90+
kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)]));
8391
}
8492
pagefault_enable();
8593
}

0 commit comments

Comments
 (0)