aboutsummaryrefslogtreecommitdiffstats
path: root/lib/builtins/clear_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/builtins/clear_cache.c')
-rw-r--r--lib/builtins/clear_cache.c68
1 files changed, 16 insertions, 52 deletions
diff --git a/lib/builtins/clear_cache.c b/lib/builtins/clear_cache.c
index 76dc1968cc7e..80d3b2f9f17d 100644
--- a/lib/builtins/clear_cache.c
+++ b/lib/builtins/clear_cache.c
@@ -23,8 +23,10 @@ uintptr_t GetCurrentProcess(void);
#endif
#if defined(__FreeBSD__) && defined(__arm__)
-#include <machine/sysarch.h>
+// clang-format off
#include <sys/types.h>
+#include <machine/sysarch.h>
+// clang-format on
#endif
#if defined(__NetBSD__) && defined(__arm__)
@@ -32,54 +34,16 @@ uintptr_t GetCurrentProcess(void);
#endif
#if defined(__OpenBSD__) && defined(__mips__)
-#include <machine/sysarch.h>
+// clang-format off
#include <sys/types.h>
+#include <machine/sysarch.h>
+// clang-format on
#endif
#if defined(__linux__) && defined(__mips__)
#include <sys/cachectl.h>
#include <sys/syscall.h>
#include <unistd.h>
-#if defined(__ANDROID__) && defined(__LP64__)
-// clear_mips_cache - Invalidates instruction cache for Mips.
-static void clear_mips_cache(const void *Addr, size_t Size) {
- __asm__ volatile(
- ".set push\n"
- ".set noreorder\n"
- ".set noat\n"
- "beq %[Size], $zero, 20f\n" // If size == 0, branch around.
- "nop\n"
- "daddu %[Size], %[Addr], %[Size]\n" // Calculate end address + 1
- "rdhwr $v0, $1\n" // Get step size for SYNCI.
- // $1 is $HW_SYNCI_Step
- "beq $v0, $zero, 20f\n" // If no caches require
- // synchronization, branch
- // around.
- "nop\n"
- "10:\n"
- "synci 0(%[Addr])\n" // Synchronize all caches around
- // address.
- "daddu %[Addr], %[Addr], $v0\n" // Add step size.
- "sltu $at, %[Addr], %[Size]\n" // Compare current with end
- // address.
- "bne $at, $zero, 10b\n" // Branch if more to do.
- "nop\n"
- "sync\n" // Clear memory hazards.
- "20:\n"
- "bal 30f\n"
- "nop\n"
- "30:\n"
- "daddiu $ra, $ra, 12\n" // $ra has a value of $pc here.
- // Add offset of 12 to point to the
- // instruction after the last nop.
- //
- "jr.hb $ra\n" // Return, clearing instruction
- // hazards.
- "nop\n"
- ".set pop\n"
- : [ Addr ] "+r"(Addr), [ Size ] "+r"(Size)::"at", "ra", "v0", "memory");
-}
-#endif
#endif
// The compiler generates calls to __clear_cache() when creating
@@ -123,17 +87,7 @@ void __clear_cache(void *start, void *end) {
#elif defined(__linux__) && defined(__mips__)
const uintptr_t start_int = (uintptr_t)start;
const uintptr_t end_int = (uintptr_t)end;
-#if defined(__ANDROID__) && defined(__LP64__)
- // Call synci implementation for short address range.
- const uintptr_t address_range_limit = 256;
- if ((end_int - start_int) <= address_range_limit) {
- clear_mips_cache(start, (end_int - start_int));
- } else {
- syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
- }
-#else
syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE);
-#endif
#elif defined(__mips__) && defined(__OpenBSD__)
cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE);
#elif defined(__aarch64__) && !defined(__APPLE__)
@@ -173,6 +127,16 @@ void __clear_cache(void *start, void *end) {
for (uintptr_t line = start_line; line < end_line; line += line_size)
__asm__ volatile("icbi 0, %0" : : "r"(line));
__asm__ volatile("isync");
+#elif defined(__sparc__)
+ const size_t dword_size = 8;
+ const size_t len = (uintptr_t)end - (uintptr_t)start;
+
+ const uintptr_t mask = ~(dword_size - 1);
+ const uintptr_t start_dword = ((uintptr_t)start) & mask;
+ const uintptr_t end_dword = ((uintptr_t)start + len + dword_size - 1) & mask;
+
+ for (uintptr_t dword = start_dword; dword < end_dword; dword += dword_size)
+ __asm__ volatile("flush %0" : : "r"(dword));
#else
#if __APPLE__
// On Darwin, sys_icache_invalidate() provides this functionality