Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: mm: Add support for flushing HugeTLB pages.

On ARM we use the __flush_dcache_page function to flush the dcache
of pages when needed; usually when the PG_dcache_clean bit is unset
and we are setting a PTE.

A HugeTLB page is represented as a compound page consisting of an
array of pages. Thus to flush the dcache of a HugeTLB page, one must
flush more than a single page.

This patch modifies __flush_dcache_page such that all constituent
pages of a HugeTLB page are flushed.

Signed-off-by: Steve Capper <steve.capper@linaro.org>
Reviewed-by: Will Deacon <will.deacon@arm.com>

+15 -10
+15 -10
arch/arm/mm/flush.c
··· 17 17 #include <asm/highmem.h> 18 18 #include <asm/smp_plat.h> 19 19 #include <asm/tlbflush.h> 20 + #include <linux/hugetlb.h> 20 21 21 22 #include "mm.h" 22 23 ··· 169 168 * coherent with the kernels mapping. 170 169 */ 171 170 if (!PageHighMem(page)) { 172 - __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); 171 + size_t page_size = PAGE_SIZE << compound_order(page); 172 + __cpuc_flush_dcache_area(page_address(page), page_size); 173 173 } else { 174 - void *addr; 175 - 174 + unsigned long i; 176 175 if (cache_is_vipt_nonaliasing()) { 177 - addr = kmap_atomic(page); 178 - __cpuc_flush_dcache_area(addr, PAGE_SIZE); 179 - kunmap_atomic(addr); 180 - } else { 181 - addr = kmap_high_get(page); 182 - if (addr) { 176 + for (i = 0; i < (1 << compound_order(page)); i++) { 177 + void *addr = kmap_atomic(page); 183 178 __cpuc_flush_dcache_area(addr, PAGE_SIZE); 184 - kunmap_high(page); 179 + kunmap_atomic(addr); 180 + } 181 + } else { 182 + for (i = 0; i < (1 << compound_order(page)); i++) { 183 + void *addr = kmap_high_get(page); 184 + if (addr) { 185 + __cpuc_flush_dcache_area(addr, PAGE_SIZE); 186 + kunmap_high(page); 187 + } 185 188 } 186 189 } 187 190 }