[aarch64-port-dev ] RFC: Use __clear_cache to do cache flushing

Edward Nevill ed at camswl.com
Wed Apr 2 16:59:34 UTC 2014


Hi,

The current implementation of cache flushing/invalidation assumes that the line size is 64 bytes. This is not necessarily the case.

To do this properly we would have to read CTR_EL0. Added to this is the complexity that the D cache and I cache may have different line sizes, so we must be careful to use the D cache line size when flushing the D cache and the I cache line size when invalidating the I cache.

I think it would be much better all around if we just used the gcc intrinsic __clear_cache to do this as in the patch below.

Comments?

Ed.

--- CUT HERE ---
exporting patch:
# HG changeset patch
# User Edward Nevill edward.nevill at linaro.org
# Date 1396457502 -3600
#      Wed Apr 02 17:51:42 2014 +0100
# Node ID 080aebbebb5386e29298abfd5da240f7588ecbc0
# Parent  273f8f0e7109ba0abe8f3697f2f48e34afe0d2f3
Use gcc __clear_cache instead of doing it ourselves

diff -r 273f8f0e7109 -r 080aebbebb53 src/cpu/aarch64/vm/icache_aarch64.cpp
--- a/src/cpu/aarch64/vm/icache_aarch64.cpp	Wed Apr 02 11:41:48 2014 +0100
+++ b/src/cpu/aarch64/vm/icache_aarch64.cpp	Wed Apr 02 17:51:42 2014 +0100
@@ -29,41 +29,10 @@
 #include "runtime/icache.hpp"
 
 extern void aarch64TestHook();
-extern "C" void setup_arm_sim();
 
-#define __ _masm->
-
-void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) {
-
+void ICacheStubGenerator::generate_icache_flush(
+  		ICache::flush_icache_stub_t* flush_icache_stub) {
   aarch64TestHook();
-
-  StubCodeMark mark(this, "ICache", "flush_icache_stub");
-
-  address entry = __ pc();
-
-  // generate a c stub prolog which will bootstrap into the ARM code
-  // which follows, loading the 3 general registers passed by the
-  // caller into the first 3 ARM registers
-
-#ifdef BUILTIN_SIM
-  __ c_stub_prolog(3, 0, MacroAssembler::ret_type_integral);
-#endif
-
-  Register start = r0, lines = r1, auto_magic = r2;
-
-  // First flush the dcache
-  __ generate_flush_loop(&Assembler::dc, start, lines);
-
-  __ dsb(Assembler::SY);
-
-  // And then the icache
-  __ generate_flush_loop(&Assembler::ic, start, lines);
-
-  // the stub is supposed to return the 3rd argument
-  __ mov(r0, auto_magic);
-  __ ret(r30);
-
-  *flush_icache_stub =  (ICache::flush_icache_stub_t)entry;
+  // Give anyone who calls this a surprise
+  *flush_icache_stub = (ICache::flush_icache_stub_t)NULL;
 }
-
-#undef __
diff -r 273f8f0e7109 -r 080aebbebb53 src/cpu/aarch64/vm/icache_aarch64.hpp
--- a/src/cpu/aarch64/vm/icache_aarch64.hpp	Wed Apr 02 11:41:48 2014 +0100
+++ b/src/cpu/aarch64/vm/icache_aarch64.hpp	Wed Apr 02 17:51:42 2014 +0100
@@ -27,16 +27,19 @@
 #ifndef CPU_AARCH64_VM_ICACHE_AARCH64_HPP
 #define CPU_AARCH64_VM_ICACHE_AARCH64_HPP
 
-// Interface for updating the instruction cache.  Whenever the VM modifies
-// code, part of the processor instruction cache potentially has to be flushed.
+// Interface for updating the instruction cache.  Whenever the VM
+// modifies code, part of the processor instruction cache potentially
+// has to be flushed.
 
 class ICache : public AbstractICache {
  public:
-  enum {
-    stub_size      = 128, // Size of the icache flush stub in bytes
-    line_size      = 64, // Icache line size in bytes
-    log2_line_size = 6   // log2(line_size)
-  };
+  static void initialize() {}
+  static void invalidate_word(address addr) {
+	__clear_cache((char *)addr, (char *)(addr + 3));
+  }
+  static void invalidate_range(address start, int nbytes) {
+	__clear_cache((char *)start, (char *)(start + nbytes));
+  }
 };
 
 #endif // CPU_AARCH64_VM_ICACHE_AARCH64_HPP
--- CUT HERE ---




More information about the aarch64-port-dev mailing list