[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