| ... | ... | @@ -26,6 +26,10 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void { |
| 26 | 26 | .mips, .mipsel, .mips64, .mips64el => true, |
| 27 | 27 | else => false, |
| 28 | 28 | }; |
| 29 | const riscv = switch (arch) { |
| 30 | .riscv32, .riscv64 => true, |
| 31 | else => false, |
| 32 | }; |
| 29 | 33 | const powerpc64 = switch (arch) { |
| 30 | 34 | .powerpc64, .powerpc64le => true, |
| 31 | 35 | else => false, |
| ... | ... | @@ -41,32 +45,42 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void { |
| 41 | 45 | if (x86) { |
| 42 | 46 | // Intel processors have a unified instruction and data cache |
| 43 | 47 | // so there is nothing to do |
| 48 | exportIt(); |
| 44 | 49 | } else if (os == .windows and (arm32 or arm64)) { |
| 45 | | @compileError("TODO"); |
| 50 | // TODO |
| 46 | 51 | // FlushInstructionCache(GetCurrentProcess(), start, end - start); |
| 52 | // exportIt(); |
| 47 | 53 | } else if (arm32 and !apple) { |
| 48 | | if (os == .freebsd or os == .netbsd) { |
| 49 | | // struct arm_sync_icache_args arg; |
| 50 | | // |
| 51 | | // arg.addr = (uintptr_t)start; |
| 52 | | // arg.len = (uintptr_t)end - (uintptr_t)start; |
| 53 | | // |
| 54 | | // sysarch(ARM_SYNC_ICACHE, &arg); |
| 55 | | @compileError("TODO: implement for NetBSD/FreeBSD"); |
| 56 | | } else if (os == .linux) { |
| 57 | | const result = std.os.linux.syscall3(.cacheflush, start, end, 0); |
| 58 | | std.debug.assert(result == 0); |
| 59 | | } else { |
| 60 | | @compileError("no __clear_cache implementation available for this target"); |
| 54 | switch (os) { |
| 55 | .freebsd, .netbsd => { |
| 56 | var arg = arm_sync_icache_args{ |
| 57 | .addr = start, |
| 58 | .len = end - start, |
| 59 | }; |
| 60 | const result = sysarch(ARM_SYNC_ICACHE, @ptrToInt(&arg)); |
| 61 | std.debug.assert(result == 0); |
| 62 | exportIt(); |
| 63 | }, |
| 64 | .linux => { |
| 65 | const result = std.os.linux.syscall3(.cacheflush, start, end, 0); |
| 66 | std.debug.assert(result == 0); |
| 67 | exportIt(); |
| 68 | }, |
| 69 | else => {}, |
| 61 | 70 | } |
| 62 | 71 | } else if (os == .linux and mips) { |
| 63 | | @compileError("TODO"); |
| 64 | | //const uintptr_t start_int = (uintptr_t)start; |
| 65 | | //const uintptr_t end_int = (uintptr_t)end; |
| 66 | | //syscall(__NR_cacheflush, start, (end_int - start_int), BCACHE); |
| 72 | const flags = 3; // ICACHE | DCACHE |
| 73 | const result = std.os.linux.syscall3(.cacheflush, start, end - start, flags); |
| 74 | std.debug.assert(result == 0); |
| 75 | exportIt(); |
| 67 | 76 | } else if (mips and os == .openbsd) { |
| 68 | | @compileError("TODO"); |
| 77 | // TODO |
| 69 | 78 | //cacheflush(start, (uintptr_t)end - (uintptr_t)start, BCACHE); |
| 79 | // exportIt(); |
| 80 | } else if (os == .linux and riscv) { |
| 81 | const result = std.os.linux.syscall3(.riscv_flush_icache, start, end - start, 0); |
| 82 | std.debug.assert(result == 0); |
| 83 | exportIt(); |
| 70 | 84 | } else if (arm64 and !apple) { |
| 71 | 85 | // Get Cache Type Info. |
| 72 | 86 | // TODO memoize this? |
| ... | ... | @@ -105,8 +119,9 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void { |
| 105 | 119 | } |
| 106 | 120 | } |
| 107 | 121 | asm volatile ("isb sy"); |
| 122 | exportIt(); |
| 108 | 123 | } else if (powerpc64) { |
| 109 | | @compileError("TODO"); |
| 124 | // TODO |
| 110 | 125 | //const size_t line_size = 32; |
| 111 | 126 | //const size_t len = (uintptr_t)end - (uintptr_t)start; |
| 112 | 127 | // |
| ... | ... | @@ -121,8 +136,9 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void { |
| 121 | 136 | //for (uintptr_t line = start_line; line < end_line; line += line_size) |
| 122 | 137 | // __asm__ volatile("icbi 0, %0" : : "r"(line)); |
| 123 | 138 | //__asm__ volatile("isync"); |
| 139 | // exportIt(); |
| 124 | 140 | } else if (sparc) { |
| 125 | | @compileError("TODO"); |
| 141 | // TODO |
| 126 | 142 | //const size_t dword_size = 8; |
| 127 | 143 | //const size_t len = (uintptr_t)end - (uintptr_t)start; |
| 128 | 144 | // |
| ... | ... | @@ -132,13 +148,26 @@ pub fn clear_cache(start: usize, end: usize) callconv(.C) void { |
| 132 | 148 | // |
| 133 | 149 | //for (uintptr_t dword = start_dword; dword < end_dword; dword += dword_size) |
| 134 | 150 | // __asm__ volatile("flush %0" : : "r"(dword)); |
| 151 | // exportIt(); |
| 135 | 152 | } else if (apple) { |
| 136 | 153 | // On Darwin, sys_icache_invalidate() provides this functionality |
| 137 | 154 | sys_icache_invalidate(start, end - start); |
| 138 | | } else { |
| 139 | | @compileError("no __clear_cache implementation available for this target"); |
| 155 | exportIt(); |
| 140 | 156 | } |
| 141 | 157 | } |
| 142 | 158 | |
| 159 | const linkage = if (std.builtin.is_test) std.builtin.GlobalLinkage.Internal else std.builtin.GlobalLinkage.Weak; |
| 160 | |
| 161 | inline fn exportIt() void { |
| 162 | @export(clear_cache, .{ .name = "__clear_cache", .linkage = linkage }); |
| 163 | } |
| 164 | |
| 143 | 165 | // Darwin-only |
| 144 | 166 | extern fn sys_icache_invalidate(start: usize, len: usize) void; |
| 167 | // BSD-only |
| 168 | const arm_sync_icache_args = extern struct { |
| 169 | addr: usize, // Virtual start address |
| 170 | len: usize, // Region size |
| 171 | }; |
| 172 | const ARM_SYNC_ICACHE = 0; |
| 173 | extern "c" fn sysarch(number: i32, args: usize) i32; |