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

Andrew Haley aph at redhat.com
Thu Apr 3 09:57:21 UTC 2014


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:

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

Fix your indentation in icache_aarch64.hpp.

Andrew.


diff -r 780ed75ea21a src/cpu/aarch64/vm/icache_aarch64.cpp
--- a/src/cpu/aarch64/vm/icache_aarch64.cpp	Tue Apr 01 12:22:23 2014 -0400
+++ b/src/cpu/aarch64/vm/icache_aarch64.cpp	Thu Apr 03 05:52:33 2014 -0400
@@ -33,6 +33,27 @@

 #define __ _masm->

+int ICache::line_size = 64;
+int ICache::log2_line_size = 6;
+static int dcache_line_size = 64;
+
+class InitICache {
+public:
+  InitICache() {
+#ifndef BUILTIN_SIM
+    unsigned int cache_info = 0;
+    /* CTR_EL0 [3:0] contains log2 of icache line size in words.
+       CTR_EL0 [19:16] contains log2 of dcache line size in words.  */
+    asm volatile ("mrs\t%0, ctr_el0":"=r" (cache_info));
+    ICache::log2_line_size = (cache_info & 0xF) + 2;
+    ICache::line_size = 1 << ICache::log2_line_size;
+    dcache_line_size = 4 << ((cache_info >> 16) & 0xF);
+#endif
+  }
+};
+
+static InitICache nothing; // Call the constructor
+
 void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) {

   aarch64TestHook();
@@ -52,12 +73,12 @@
   Register start = r0, lines = r1, auto_magic = r2;

   // First flush the dcache
-  __ generate_flush_loop(&Assembler::dc, start, lines);
+  __ generate_flush_loop(&Assembler::dc, start, lines, dcache_line_size);

   __ dsb(Assembler::SY);

   // And then the icache
-  __ generate_flush_loop(&Assembler::ic, start, lines);
+  __ generate_flush_loop(&Assembler::ic, start, lines, ICache::line_size);

   // the stub is supposed to return the 3rd argument
   __ mov(r0, auto_magic);
diff -r 780ed75ea21a src/cpu/aarch64/vm/icache_aarch64.hpp
--- a/src/cpu/aarch64/vm/icache_aarch64.hpp	Tue Apr 01 12:22:23 2014 -0400
+++ b/src/cpu/aarch64/vm/icache_aarch64.hpp	Thu Apr 03 05:52:33 2014 -0400
@@ -34,9 +34,8 @@
  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 int line_size, log2_line_size; // Icache line size in bytes
 };

 #endif // CPU_AARCH64_VM_ICACHE_AARCH64_HPP
diff -r 780ed75ea21a src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Tue Apr 01 12:22:23 2014 -0400
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp	Thu Apr 03 05:52:33 2014 -0400
@@ -2889,7 +2889,8 @@
   }
 }

-void MacroAssembler::generate_flush_loop(flush_insn flush, Register start, Register lines) {
+void MacroAssembler::generate_flush_loop(flush_insn flush, Register start, Register lines,
+					 int line_size) {
   Label again, exit;

   assert_different_registers(start, lines, rscratch1, rscratch2);
@@ -2901,7 +2902,7 @@
   bind(again);
   (this->*flush)(rscratch1);
   sub(rscratch2, rscratch2, 1);
-  add(rscratch1, rscratch1, ICache::line_size);
+  add(rscratch1, rscratch1, line_size);
   cbnz(rscratch2, again);
   bind(exit);
 }
diff -r 780ed75ea21a src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Tue Apr 01 12:22:23 2014 -0400
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp	Thu Apr 03 05:52:33 2014 -0400
@@ -1362,7 +1362,8 @@
   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);
+  void generate_flush_loop(flush_insn flush, Register start, Register lines,
+			   int line_size);

   // Used by aarch64.ad to control code generation
   static bool use_acq_rel_for_volatile_fields();



More information about the aarch64-port-dev mailing list