hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/boot/boot.zig
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-13 00:42:08 +0200
committerhachem <im@hachem.wtf>2026-09-13 00:42:08 +0200
commit3235f37882bc98965bbf72951355f55bee729788 (patch)
tree86809895dc1c026d2fc9d88ccbbc02259d476b2f /boot/boot.zig
parent86e8ef8bc1db2b6ae050bf6ddcf30eb86c853cd2 (diff)
feat: paging/VMM + GDT user segments + ring 3 ground work
Diffstat (limited to 'boot/boot.zig')
-rw-r--r--boot/boot.zig34
1 files changed, 34 insertions, 0 deletions
diff --git a/boot/boot.zig b/boot/boot.zig
index e6342ce..77e7bb6 100644
--- a/boot/boot.zig
+++ b/boot/boot.zig
@@ -6,6 +6,7 @@ const gdt = @import("gdt.zig");
const idt = @import("idt.zig");
const pmm = @import("pmm.zig");
const heap = @import("heap.zig");
+const vmm = @import("vmm.zig");
const keyboard = @import("keyboard.zig");
const bridge = @import("bridge");
@@ -85,6 +86,39 @@ export fn _start() callconv(.c) noreturn {
pmm.free(b);
pmm.free(c);
+ // this is just a VMM smoke test
+ // we map a fresh frame at an unused higher half address in the
+ // active address space, write a pattern, read it back through the mapping
+ {
+ const pml4 = vmm.activePml4();
+ const frame = pmm.alloc().?;
+ const test_virt: u64 = 0xffff_c000_0000_0000;
+ _ = vmm.map(pml4, test_virt, frame, vmm.WRITE);
+ const cell: *volatile u64 = @ptrFromInt(test_virt);
+ cell.* = 0xDEADBEEFCAFEBABE;
+ serial.write("vmm test: map+rw ");
+ serial.write(if (cell.* == 0xDEADBEEFCAFEBABE) "OK" else "FAIL");
+ serial.write(", translate ");
+ const back = vmm.translate(pml4, test_virt) orelse 0;
+ serial.write(if (back == frame) "OK\r\n" else "FAIL\r\n");
+
+ // create a separate address space, switch into it (the scary part -- a
+ // bad CR3 triple-faults), map a lower-half user page, read/write it,
+ // then switch back. if the kernel keeps running, address spaces work.
+ const as = vmm.createAddressSpace().?;
+ const user_frame = pmm.alloc().?;
+ const user_virt: u64 = 0x0000_0000_4000_0000; // 1 GiB, lower half (user)
+ _ = vmm.map(as, user_virt, user_frame, vmm.WRITE | vmm.USER);
+ vmm.loadPml4(as);
+ serial.write("vmm test: switched CR3 OK\r\n"); // reached => kernel still mapped
+ const ucell: *volatile u64 = @ptrFromInt(user_virt);
+ ucell.* = 0x1234_5678_9ABC_DEF0;
+ serial.write("vmm test: user page rw ");
+ serial.write(if (ucell.* == 0x123456789ABCDEF0) "OK\r\n" else "FAIL\r\n");
+ vmm.loadPml4(pml4); // back to the original address space
+ serial.write("vmm test: switched back OK\r\n");
+ }
+
// hand the kernel heap + raw framebuffer to revo and bring up the VM
const fb: ?bridge.Fb = if (framebuffer.get()) |s| .{
.ptr = s.address,