[ulib][zircon] Use template functions in zx_cache_flush
This reduces the repeated boilerplate loop code in the source but
still compiles down to the same thing as the old code.
Change-Id: Ib4f29f4e6c3da9235cd95a0ed69ca06f003cdf4d
diff --git a/system/ulib/zircon/zx_cache_flush.cpp b/system/ulib/zircon/zx_cache_flush.cpp
index eb2d2ef..5bc6748 100644
--- a/system/ulib/zircon/zx_cache_flush.cpp
+++ b/system/ulib/zircon/zx_cache_flush.cpp
@@ -7,6 +7,30 @@
#include <zircon/compiler.h>
#include "private.h"
+namespace {
+
+template<typename T>
+void for_each_cache_line(const void* addr, size_t len, uint32_t line_size,
+ T func) {
+ for (uintptr_t p = (uintptr_t)addr & -(uintptr_t)line_size;
+ p < (uintptr_t)addr + len;
+ p += line_size) {
+ func(p);
+ }
+}
+
+template<typename T>
+void for_each_dcache_line(const void* addr, size_t len, T func) {
+ for_each_cache_line(addr, len, DATA_CONSTANTS.dcache_line_size, func);
+}
+
+template<typename T>
+void for_each_icache_line(const void* addr, size_t len, T func) {
+ for_each_cache_line(addr, len, DATA_CONSTANTS.icache_line_size, func);
+}
+
+} // anonymous namespace
+
zx_status_t _zx_cache_flush(const void* addr, size_t len, uint32_t flags) {
if (flags == 0 || (flags & ~(ZX_CACHE_FLUSH_INSN | ZX_CACHE_FLUSH_DATA)))
return ZX_ERR_INVALID_ARGS;
@@ -18,37 +42,28 @@
#elif defined(__aarch64__)
if (flags & ZX_CACHE_FLUSH_DATA) {
- for (uintptr_t p = ((uintptr_t)addr &
- -((uintptr_t)DATA_CONSTANTS.dcache_line_size));
- p < (uintptr_t)addr + len;
- p += DATA_CONSTANTS.dcache_line_size) {
- // Clean data cache (dc) to point of coherency (cvac).
- __asm__ volatile("dc cvac, %0" :: "r"(p));
- }
+ for_each_dcache_line(addr, len, [](uintptr_t p) {
+ // Clean data cache (dc) to point of coherency (cvac).
+ __asm__ volatile("dc cvac, %0" :: "r"(p));
+ });
}
if (flags & ZX_CACHE_FLUSH_INSN) {
// If we didn't already clean the dcache all the way to the point
// of coherency, clean it the point to unification.
if (!(flags & ZX_CACHE_FLUSH_DATA)) {
- for (uintptr_t p = ((uintptr_t)addr &
- -((uintptr_t)DATA_CONSTANTS.dcache_line_size));
- p < (uintptr_t)addr + len;
- p += DATA_CONSTANTS.dcache_line_size) {
- // Clean data cache (dc) to point of unification (cvau).
- __asm__ volatile("dc cvau, %0" :: "r"(p));
- }
+ for_each_dcache_line(addr, len, [](uintptr_t p) {
+ // Clean data cache (dc) to point of unification (cvau).
+ __asm__ volatile("dc cvau, %0" :: "r"(p));
+ });
}
// Synchronize the dcache flush to before the icache flush.
__asm__ volatile("dsb ish");
- for (uintptr_t p = ((uintptr_t)addr &
- -((uintptr_t)DATA_CONSTANTS.icache_line_size));
- p < (uintptr_t)addr + len;
- p += DATA_CONSTANTS.icache_line_size) {
- // Clean instruction cache (ic) to point of unification (ivau).
- __asm__ volatile("ic ivau, %0" :: "r"(p));
- }
+ for_each_icache_line(addr, len, [](uintptr_t p) {
+ // Clean instruction cache (ic) to point of unification (ivau).
+ __asm__ volatile("ic ivau, %0" :: "r"(p));
+ });
// Synchronize the icache flush to before future instruction fetches.
__asm__ volatile("isb sy");
}