From 4f540af34d7a88547d60bed7bd28850e6d0e18ab Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 12 Sep 2026 04:08:33 +0200 Subject: feat: BAREEE METTALLLLLL REVOOOOO --- boot/boot.zig | 19 ++++++++++++++++++- boot/heap.zig | 4 ++-- boot/idt.zig | 7 +++++++ boot/limine.zig | 14 ++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) (limited to 'boot') diff --git a/boot/boot.zig b/boot/boot.zig index 933065c..1f50d83 100644 --- a/boot/boot.zig +++ b/boot/boot.zig @@ -6,21 +6,32 @@ const gdt = @import("gdt.zig"); const idt = @import("idt.zig"); const pmm = @import("pmm.zig"); const heap = @import("heap.zig"); +const bridge = @import("bridge"); // We need a panic handler otherwise zig won't be happy, // std usually formats a message through std.Io.Writer which // emits SSE instructions which I haven't enabled. Ours // dumps the message to serial, then halts. pub const panic = std.debug.FullPanic(struct { - fn halt(msg: []const u8, _: ?usize) noreturn { + fn halt(msg: []const u8, ret_addr: ?usize) noreturn { serial.init(); serial.write("\r\n!!! uhhhh engine kaput : "); serial.write(msg); + if (ret_addr) |ra| { + serial.write("\r\n at "); + serial.writeHex(ra); + } serial.write("\r\n"); while (true) asm volatile ("hlt"); } }.halt); +// std.debug.print (revo hits it on a few error paths) defaults to a threaded +// stderr IO that doesn't exist on freestanding and won't even compile. This +// just points it to the custom one we wrote in bridge tthat uses the serial +// console and shit +pub const std_options_debug_io: std.Io = bridge.debug_io; + // Check `linker.ld` export var base_revision: limine.BaseRevision linksection(".limine_requests") = limine.BaseRevision.init(3); export var requests_start: limine.RequestsStartMarker linksection(".limine_requests_start") = .{}; @@ -31,6 +42,9 @@ export var requests_end: limine.RequestsEndMarker linksection(".limine_requests_ export var hhdm_request: limine.HhdmRequest linksection(".limine_requests") = .{}; export var memmap_request: limine.MemoryMapRequest linksection(".limine_requests") = .{}; +// 4 MiB stack +export var stack_size_request: limine.StackSizeRequest linksection(".limine_requests") = .{ .stack_size = 4 * 1024 * 1024 }; + // ENTRY(_start) export fn _start() callconv(.c) noreturn { serial.init(); @@ -70,6 +84,9 @@ export fn _start() callconv(.c) noreturn { pmm.free(b); pmm.free(c); + // hand the kernel heap to revo and we're gucci + bridge.run(heap.allocator(), serial.write); + if (framebuffer.get()) |screen| { // XOR texture var y: usize = 0; diff --git a/boot/heap.zig b/boot/heap.zig index 2f4e74b..3fd9f8c 100644 --- a/boot/heap.zig +++ b/boot/heap.zig @@ -10,9 +10,9 @@ const std = @import("std"); const pmm = @import("pmm.zig"); const serial = @import("serial.zig"); -// 4 MiB. +// 32 MiB. // NOTE: bump if the VM needs more -const HEAP_PAGES: usize = 1024; +const HEAP_PAGES: usize = 8192; var fba: std.heap.FixedBufferAllocator = undefined; diff --git a/boot/idt.zig b/boot/idt.zig index adff4b3..127fd8e 100644 --- a/boot/idt.zig +++ b/boot/idt.zig @@ -140,6 +140,13 @@ export fn exceptionHandler(frame: *Frame) callconv(.c) noreturn { serial.write(" cs="); writeHex(frame.cs); serial.write("\r\n rflags="); writeHex(frame.rflags); serial.write(" rsp="); writeHex(frame.rsp); + // page faults stash the offending address in CR2 + if (frame.vector == 14) { + const cr2 = asm volatile ("mov %%cr2, %[out]" + : [out] "=r" (-> u64), + ); + serial.write("\r\n cr2="); writeHex(cr2); + } serial.write("\r\n"); while (true) asm volatile ("hlt"); } diff --git a/boot/limine.zig b/boot/limine.zig index 914aca8..f1ed158 100644 --- a/boot/limine.zig +++ b/boot/limine.zig @@ -66,6 +66,20 @@ pub const FramebufferRequest = extern struct { response: ?*FramebufferResponse = null, }; +// ask limine for a bigger bootstrap stack than its ~64 KiB default cause +// revo's VM init builds a large struct on the stack and runs a fat recursive +// descent parser to register its stdlib, which page faults the machine +pub const StackSizeResponse = extern struct { + revision: u64, +}; + +pub const StackSizeRequest = extern struct { + id: [4]u64 = requestId(0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d), + revision: u64 = 0, + response: ?*StackSizeResponse = null, + stack_size: u64, +}; + // HHDM = higher-half direct map, limine linearly maps ALL of physical memory // starting at `offset`, so any physical address p is reachable at p + offset // This is how we touch physical frames without setting up our own page tables -- cgit v1.3