summaryrefslogtreecommitdiff
path: root/src/soc.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc.zig')
-rw-r--r--src/soc.zig15
1 files changed, 15 insertions, 0 deletions
diff --git a/src/soc.zig b/src/soc.zig
index f022b50..172966e 100644
--- a/src/soc.zig
+++ b/src/soc.zig
@@ -94,6 +94,21 @@ pub const rom = struct {
pub extern fn ets_printf(fmt: [*:0]const u8, ...) c_int;
pub extern fn ets_delay_us(us: u32) void;
+ /// Invalidate the caches. `map` selects which, from `rom/cache.h:228-236`:
+ /// L1 ICache0 = 1, ICache1 = 2, L1 DCache = 0x10, L2 = 0x20; `cache_all` is all four.
+ ///
+ /// This is not optional on a large image, and finding that out took a while. The second-stage
+ /// bootloader leaves cache lines behind that do not match the mapping it finally installs, so an
+ /// application can read its own `.rodata` and get someone else's bytes - deterministically,
+ /// which is what makes it look like anything other than a cache. Measured: a load at 0x40035a1c
+ /// returned `93 85 85 0f`, and after touching 512 KiB to evict the line the same load returned
+ /// `3c ee 08 40`, which is what the image holds there. `_start` calls this before it clears
+ /// `.bss`, so nothing of ours is in flight when the lines are dropped.
+ pub extern fn Cache_Invalidate_All(map: u32) c_int;
+
+ /// Every cache this chip has: L1 ICache0 | L1 ICache1 | L1 DCache | L2.
+ pub const cache_all: u32 = 0x33;
+
pub inline fn print(comptime fmt: [*:0]const u8, args: anytype) void {
_ = @call(.auto, ets_printf, .{fmt} ++ args);
}