MIPS/compiler_rt: use synci to flush icache on r6
syscall makes it failed to build on mips64 for mipsel: ``` compiler-rt/lib/builtins/clear_cache.c:97:3: error: call to undeclared function 'syscall'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); ``` In this patch, we use `rdhwr` to get synci_step. If synci_step is zero, it means that the hardware will maintain the coherence. We need to do nothing. Then for r6+, `synci` is required to keep icache global. So we can use `synci` to flush icache. The ISA documents ask a `sync` and a `jr.hb` after `synci`. For pre-r6, we can use cacheflush libc function, which is same on Linux and FreeBSD. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D135565
This commit is contained in:
committed by
Fangrui Song
parent
32a2af44e1
commit
674a17e9bb
@@ -93,12 +93,29 @@ void __clear_cache(void *start, void *end) {
|
|||||||
#endif
|
#endif
|
||||||
#elif defined(__linux__) && defined(__loongarch__)
|
#elif defined(__linux__) && defined(__loongarch__)
|
||||||
__asm__ volatile("ibar 0");
|
__asm__ volatile("ibar 0");
|
||||||
#elif defined(__linux__) && defined(__mips__)
|
#elif defined(__mips__)
|
||||||
const uintptr_t start_int = (uintptr_t)start;
|
const uintptr_t start_int = (uintptr_t)start;
|
||||||
const uintptr_t end_int = (uintptr_t)end;
|
const uintptr_t end_int = (uintptr_t)end;
|
||||||
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
|
uintptr_t synci_step;
|
||||||
#elif defined(__mips__) && defined(__OpenBSD__)
|
__asm__ volatile("rdhwr %0, $1" : "=r"(synci_step));
|
||||||
cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
|
if (synci_step != 0) {
|
||||||
|
#if __mips_isa_rev >= 6
|
||||||
|
for (uintptr_t p = start_int; p < end_int; p += synci_step)
|
||||||
|
__asm__ volatile("synci 0(%0)" : : "r"(p));
|
||||||
|
|
||||||
|
// The last "move $at, $0" is the target of jr.hb instead of delay slot.
|
||||||
|
__asm__ volatile(".set noat\n"
|
||||||
|
"sync\n"
|
||||||
|
"addiupc $at, 12\n"
|
||||||
|
"jr.hb $at\n"
|
||||||
|
"move $at, $0\n"
|
||||||
|
".set at");
|
||||||
|
#else
|
||||||
|
// Pre-R6 may not be globalized. And some implementations may give strange
|
||||||
|
// synci_step. So, let's use libc call for it.
|
||||||
|
cacheflush(start, end_int - start_int, BCACHE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#elif defined(__aarch64__) && !defined(__APPLE__)
|
#elif defined(__aarch64__) && !defined(__APPLE__)
|
||||||
uint64_t xstart = (uint64_t)(uintptr_t)start;
|
uint64_t xstart = (uint64_t)(uintptr_t)start;
|
||||||
uint64_t xend = (uint64_t)(uintptr_t)end;
|
uint64_t xend = (uint64_t)(uintptr_t)end;
|
||||||
|
|||||||
Reference in New Issue
Block a user