From: Stefano Stabellini Date: Fri, 3 Mar 2017 01:15:26 +0000 (-0800) Subject: xen/arm: fix affected memory range by dcache clean functions X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~2569 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=caf053fb545329e58ac891d197f96503e3121049;p=xen.git xen/arm: fix affected memory range by dcache clean functions clean_dcache_va_range and clean_and_invalidate_dcache_va_range don't calculate the range correctly when "end" is not cacheline aligned. As a result, the last cacheline is not skipped. Fix the issue by aligning the start address to the cacheline size. In addition, make the code simpler and faster in invalidate_dcache_va_range, by removing the module operation and using bitmasks instead. Also remove the size adjustments in invalidate_dcache_va_range, because the size variable is not used later on. Signed-off-by: Stefano Stabellini Reviewed-by: Edgar E. Iglesias Reviewed-by: Julien Grall Tested-by: Edgar E. Iglesias --- diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h index 86de0b6e6d..4b46e8831c 100644 --- a/xen/include/asm-arm/page.h +++ b/xen/include/asm-arm/page.h @@ -291,24 +291,20 @@ extern size_t cacheline_bytes; static inline int invalidate_dcache_va_range(const void *p, unsigned long size) { - size_t off; const void *end = p + size; + size_t cacheline_mask = cacheline_bytes - 1; dsb(sy); /* So the CPU issues all writes to the range */ - off = (unsigned long)p % cacheline_bytes; - if ( off ) + if ( (uintptr_t)p & cacheline_mask ) { - p -= off; + p = (void *)((uintptr_t)p & ~cacheline_mask); asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p)); p += cacheline_bytes; - size -= cacheline_bytes - off; } - off = (unsigned long)end % cacheline_bytes; - if ( off ) + if ( (uintptr_t)end & cacheline_mask ) { - end -= off; - size -= off; + end = (void *)((uintptr_t)end & ~cacheline_mask); asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (end)); } @@ -322,9 +318,10 @@ static inline int invalidate_dcache_va_range(const void *p, unsigned long size) static inline int clean_dcache_va_range(const void *p, unsigned long size) { - const void *end; + const void *end = p + size; dsb(sy); /* So the CPU issues all writes to the range */ - for ( end = p + size; p < end; p += cacheline_bytes ) + p = (void *)((uintptr_t)p & ~(cacheline_bytes - 1)); + for ( ; p < end; p += cacheline_bytes ) asm volatile (__clean_dcache_one(0) : : "r" (p)); dsb(sy); /* So we know the flushes happen before continuing */ /* ARM callers assume that dcache_* functions cannot fail. */ @@ -334,9 +331,10 @@ static inline int clean_dcache_va_range(const void *p, unsigned long size) static inline int clean_and_invalidate_dcache_va_range (const void *p, unsigned long size) { - const void *end; + const void *end = p + size; dsb(sy); /* So the CPU issues all writes to the range */ - for ( end = p + size; p < end; p += cacheline_bytes ) + p = (void *)((uintptr_t)p & ~(cacheline_bytes - 1)); + for ( ; p < end; p += cacheline_bytes ) asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (p)); dsb(sy); /* So we know the flushes happen before continuing */ /* ARM callers assume that dcache_* functions cannot fail. */