hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-12 04:08:33 +0200
committerhachem <im@hachem.wtf>2026-09-12 04:09:21 +0200
commit4f540af34d7a88547d60bed7bd28850e6d0e18ab (patch)
tree2b98bc0010a00822169459ef0d37f2ddda6f3b99 /boot
parentc34524767c9eac650f16dbe9059c24af2acd1397 (diff)
feat: BAREEE METTALLLLLL REVOOOOO
Diffstat (limited to 'boot')
-rw-r--r--boot/boot.zig19
-rw-r--r--boot/heap.zig4
-rw-r--r--boot/idt.zig7
-rw-r--r--boot/limine.zig14
4 files changed, 41 insertions, 3 deletions
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