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

Edward Nevill ed at camswl.com
Thu Apr 3 22:10:07 UTC 2014


Hi Andrew,

On Thu, 2014-04-03 at 10:57 +0100, Andrew Haley wrote:
> Hi,
> 
> On 04/02/2014 05:59 PM, Edward Nevill wrote:
> > 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?
> 
> Hmm.  I guess this is OK.  I am uncomfortable that this leaves
> ICache::line_size incorrectly defined, but maybe that doesn't matter.
> I have written a patch that correctly initializes
> ICache::line_size. as an alternative for you to consider.
> 
> If you decide to go with the GCC version, please:

Thanks for this. I think the GCC version offers a more generic solution to the problems with the existing code.

I do not believe that line_size is referenced anywhere outside the cache flushing code.


> Make sure you delete the enums for things that we know to be wrong
> like line_size and log2_line_size.

I have ensured that line_size, log2_line_size and stub_size do not appear in any aarch64 specific code.


I have deleted generate_icache_flush in macroAssembler_aarch64.{cpp,hpp} as it is no longer referenced and it references ICache::line_size which might cause confusion.


> Fix your indentation in icache_aarch64.hpp.

Fixed.

New patch below,

All the best,
Ed.


--- CUT HERE ---
exporting patch:
# HG changeset patch
# User Edward Nevill edward.nevill at linaro.org
# Date 1396561902 -3600
#      Thu Apr 03 22:51:42 2014 +0100
# Node ID 5a8c184c37d4fc7d6c91b9c79401bd7d8242f4e8
# Parent  273f8f0e7109ba0abe8f3697f2f48e34afe0d2f3
Use gcc __clear_cache instead of doing it ourselves

diff -r 273f8f0e7109 -r 5a8c184c37d4 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     Thu Apr 03 22: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 5a8c184c37d4 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     Thu Apr 03 22: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
diff -r 273f8f0e7109 -r 5a8c184c37d4 src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp     Wed Apr 02 11:41:48 2014 +0100
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp     Thu Apr 03 22:51:42 2014 +0100
@@ -2889,23 +2889,6 @@
   }
 }
 
-void MacroAssembler::generate_flush_loop(flush_insn flush, Register start, Register lines) {
-  Label again, exit;
-
-  assert_different_registers(start, lines, rscratch1, rscratch2);
-
-  cmp(lines, zr);
-  br(Assembler::LE, exit);
-  mov(rscratch1, start);
-  mov(rscratch2, lines);
-  bind(again);
-  (this->*flush)(rscratch1);
-  sub(rscratch2, rscratch2, 1);
-  add(rscratch1, rscratch1, ICache::line_size);
-  cbnz(rscratch2, again);
-  bind(exit);
-}
-
   bool MacroAssembler::use_acq_rel_for_volatile_fields() {
 #ifdef PRODUCT
     return false;
diff -r 273f8f0e7109 -r 5a8c184c37d4 src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp     Wed Apr 02 11:41:48 2014 +0100
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp     Thu Apr 03 22:51:42 2014 +0100
@@ -1361,9 +1361,6 @@
   address read_polling_page(Register r, address page, relocInfo::relocType rtype);
   address read_polling_page(Register r, relocInfo::relocType rtype);
 
-  typedef void (Assembler::* flush_insn)(Register Rt);
-  void generate_flush_loop(flush_insn flush, Register start, Register lines);
-
   // Used by aarch64.ad to control code generation
   static bool use_acq_rel_for_volatile_fields();
 };
--- CUT HERE ---




More information about the aarch64-port-dev mailing list