---
xen/arch/arm/arm64/cache.S | 45 +++++++++++++++++++++++++++++++++++++++++++++
xen/include/asm-arm/page.h | 2 ++
2 files changed, 47 insertions(+)
diff --git a/xen/arch/arm/arm64/cache.S b/xen/arch/arm/arm64/cache.S
index eff4e16..bc5a8f7 100644
--- a/xen/arch/arm/arm64/cache.S
+++ b/xen/arch/arm/arm64/cache.S
@@ -30,6 +30,51 @@
.endm
/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register.
+ */
+ .macro icache_line_size, reg, tmp
+ mrs \tmp, ctr_el0 // read CTR
+ and \tmp, \tmp, #0xf // cache line size encoding
+ mov \reg, #4 // bytes per word
+ lsl \reg, \reg, \tmp // actual cache line size
+ .endm
+
+/*
+ * flush_icache_range(start,end)
+ *
+ * Ensure that the I and D caches are coherent within specified region.
+ * This is typically used when code has been written to a memory region,
+ * and will be executed.
+ *
+ * - start - virtual start address of region
+ * - end - virtual end address of region
+ */
+ENTRY(flush_icache_range)
+ dcache_line_size x2, x3
+ sub x3, x2, #1
+ bic x4, x0, x3
+1:
+ dc cvau, x4 // clean D line to PoU
+ add x4, x4, x2
+ cmp x4, x1
+ b.lo 1b
+ dsb ish
+
+ icache_line_size x2, x3
+ sub x3, x2, #1
+ bic x4, x0, x3
+1:
+ ic ivau, x4 // invalidate I line PoU
+ add x4, x4, x2
+ cmp x4, x1
+ b.lo 1b
+ dsb ish
+ isb
+ mov x0, #0
+ ret
+ENDPROC(flush_icache_range)
+
+/*
* __flush_dcache_area(kaddr, size)
*
* Ensure that the data held in the page kaddr is written back to the
diff --git a/xen/include/asm-arm/page.h b/xen/include/asm-arm/page.h
index 05d9f82..a94e826 100644
--- a/xen/include/asm-arm/page.h
+++ b/xen/include/asm-arm/page.h
@@ -328,6 +328,8 @@ static inline int clean_and_invalidate_dcache_va_range
return 0;
}
+int flush_icache_range(unsigned long start, unsigned long end);
+
/* Macros for flushing a single small item. The predicate is always
* compile-time constant so this will compile down to 3 instructions in
* the common case. */