mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
arm: introduce invalidate_dcache_va_range
Take care of handling non-cacheline aligned addresses and sizes. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Reviewed-by: Julien Grall <julien.grall@linaro.org> Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
71d64afe3e
commit
09146ae71b
3 files changed
+38
No files matched your search
@@ -19,6 +19,9 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
|
||||
: : "r" (pte.bits), "r" (p) : "memory");
|
||||
}
|
||||
|
||||
/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
|
||||
#define __invalidate_dcache_one(R) STORE_CP32(R, DCIMVAC)
|
||||
|
||||
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
|
||||
#define __clean_dcache_one(R) STORE_CP32(R, DCCMVAC)
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
|
||||
: : "r" (pte.bits), "r" (p) : "memory");
|
||||
}
|
||||
|
||||
/* Inline ASM to invalidate dcache on register R (may be an inline asm operand) */
|
||||
#define __invalidate_dcache_one(R) "dc ivac, %" #R ";"
|
||||
|
||||
/* Inline ASM to flush dcache on register R (may be an inline asm operand) */
|
||||
#define __clean_dcache_one(R) "dc cvac, %" #R ";"
|
||||
|
||||
|
||||
@@ -268,6 +268,38 @@ extern size_t cacheline_bytes;
|
||||
/* Functions for flushing medium-sized areas.
|
||||
* if 'range' is large enough we might want to use model-specific
|
||||
* full-cache flushes. */
|
||||
|
||||
static inline int invalidate_dcache_va_range(const void *p, unsigned long size)
|
||||
{
|
||||
size_t off;
|
||||
const void *end = p + size;
|
||||
|
||||
dsb(sy); /* So the CPU issues all writes to the range */
|
||||
|
||||
off = (unsigned long)p % cacheline_bytes;
|
||||
if ( off )
|
||||
{
|
||||
p -= off;
|
||||
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 )
|
||||
{
|
||||
end -= off;
|
||||
size -= off;
|
||||
asm volatile (__clean_and_invalidate_dcache_one(0) : : "r" (end));
|
||||
}
|
||||
|
||||
for ( ; p < end; p += cacheline_bytes )
|
||||
asm volatile (__invalidate_dcache_one(0) : : "r" (p));
|
||||
|
||||
dsb(sy); /* So we know the flushes happen before continuing */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int clean_dcache_va_range(const void *p, unsigned long size)
|
||||
{
|
||||
const void *end;
|
||||
|
||||