commit 9f3a50f47df68a52adf217b63253305298d91460
parent ad80f6ddfb0d3eb655413a166fa15fab1b19d1f8
Author: Sylvia Ivory <git@sivory.net>
Date: Tue, 20 Jan 2026 20:28:28 -0800
Improve kmain
Diffstat:
7 files changed, 59 insertions(+), 38 deletions(-)
diff --git a/build.zig b/build.zig
@@ -68,14 +68,13 @@ fn add_exe_real(exe_name: []const u8, path: std.Build.LazyPath, b: *std.Build) !
const boot = b.createModule(.{
.root_source_file = path,
.target = b.resolveTargetQuery(target),
- .optimize = .ReleaseSmall,
+ .optimize = .ReleaseSafe,
.unwind_tables = .none,
.single_threaded = true,
.error_tracing = false,
.link_libc = false,
.no_builtin = true,
});
- boot.addAssemblyFile(b.path("start.s"));
boot.addImport("pi", pi);
const exe = b.addExecutable(.{
diff --git a/fake-pi/root.zig b/fake-pi/root.zig
@@ -75,10 +75,6 @@ export fn put_u32(address: *u32, value: u32) void {
}
}
-// TODO; these should not be here ideally as they only relate to test-runner
-// but there is a chance we mess up stdout if we don't have it here...
-export fn nop() void {}
-
export fn delay_cycles(cycles: u32) void {
trace("delaying {} cycles\n", .{cycles});
}
diff --git a/linker.ld b/linker.ld
@@ -1,40 +1,43 @@
-/*
- * this is a trivial "linker script" given to the linker
- * and is used to control how the program is linked together.
- *
- * the main important thing for us is that we want the program
- * to be linked starting at 0x8000. the reason: by default the
- * pi-install bootloader will copy the program it receives
- * to address 0x8000 and jump to it.
- */
+OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
/* link the code first at 0x8000. */
.text 0x8000 : {
+ __code_start__ = .;
+ KEEP(*(.kmain))
*(.text*)
+ __code_end__ = .;
. = ALIGN(8);
}
/* read-only data */
.rodata : {
+ . = ALIGN(4);
*(.rodata*)
- . = ALIGN(8);
}
/* rw data */
.data : {
+ __data_start__ = .;
*(.data*)
. = ALIGN(8);
+ __data_end__ = .;
}
/* 0 data */
.bss : {
+ . = ALIGN(4);
+ __bss_start__ = .;
*(.bss*)
+ *(COMMON)
. = ALIGN(8);
+ __bss_end__ = .;
}
- /* discard debug info so the .lists are smaller */
+ . = ALIGN(16);
+ __heap_start__ = .;
+
/DISCARD/ : { *(.debug*) }
/DISCARD/ : { *(.comment*) }
/DISCARD/ : { *(*.attributes*) }
diff --git a/pi/root.zig b/pi/root.zig
@@ -1,5 +1,4 @@
pub const mem = @import("./mem.zig");
-pub extern fn nop() void;
pub inline fn cycle_counter_init() void {
const in: u32 = 1;
diff --git a/src/main.zig b/src/main.zig
@@ -1 +1,3 @@
-pub fn main() !void {}
+pub fn main() !void {
+ return error.Oops;
+}
diff --git a/src/root.zig b/src/root.zig
@@ -1,15 +1,50 @@
const std = @import("std");
const uart = @import("devices/mini-uart.zig");
-const fake_main = @import("main.zig").main;
+const user_main = @import("main.zig").main;
-export fn abort() noreturn {
- @branchHint(.cold);
- while (true) {}
+extern const __bss_start__: usize;
+extern const __bss_end__: usize;
+
+fn zero_bss() void {
+ for (__bss_start__..__bss_end__) |b| {
+ // Force a write
+ const ptr: *volatile u8 = @ptrFromInt(b);
+ ptr.* = 0;
+ }
+}
+
+noinline fn kmain() void {
+ zero_bss();
+
+ uart.initialize(115200, .Gpio14, .Gpio15) catch {};
+
+ user_main() catch |e| {
+ if (uart.is_initialized()) {
+ var buffer: [1024]u8 = undefined;
+ const slice = std.fmt.bufPrint(&buffer, "main: {t}\n", .{e}) catch {
+ uart.write_slice("failed to print error\n");
+ abort();
+ };
+ uart.write_slice(slice);
+ }
+ };
+}
+
+export fn _start() linksection(".kmain") callconv(.naked) noreturn {
+ asm volatile (
+ \\ mov sp, 0x800000
+ \\ bl %[kmain:P]
+ \\ bl %[abort:P]
+ :
+ : [kmain] "X" (&kmain),
+ [abort] "X" (&abort),
+ );
}
-pub export fn kmain() void {
- _ = fake_main() catch {};
+noinline fn abort() noreturn {
+ @branchHint(.cold);
+ while (true) {}
}
fn panic_handler(msg: []const u8, trace_addr: ?usize) noreturn {
diff --git a/start.s b/start.s
@@ -1,13 +0,0 @@
-.global _start
-.type _start, function
-.align 8
-_start:
- mov sp, 0x800000
- bl kmain
- bl abort
-
-.global nop
-.type nop, function
-.align 8
-nop:
- bx lr