sylveos

Toy Operating System
Log | Files | Refs

commit bb0addad903bc4ffb19bee59f33dd6760152e342
parent 6d2fe46133dbd3d4b2ffbac18a8fac5c4ad03314
Author: Sylvia Ivory <git@sivory.net>
Date:   Fri, 13 Mar 2026 13:04:06 -0700

Remap regions

Diffstat:
Mboot/root.zig | 2+-
Mpi/interrupts.zig | 5++++-
Mpi/pt.zig | 8++++++++
Mpi/root.zig | 21+++++++++++++++++++--
Msylveos/memory.zig | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msylveos/root.zig | 34+++++++++++++++++++---------------
6 files changed, 120 insertions(+), 30 deletions(-)

diff --git a/boot/root.zig b/boot/root.zig @@ -22,7 +22,7 @@ export const _start = make(kmain, abort)._start; export fn kmain() void { // We don't return so we can modify SP - // pi.set_sp(@ptrFromInt(pi.get_stack_address())); + pi.set_sp(@ptrFromInt(pi.get_stack_address())); uart.initialize(921600, .Gpio14, .Gpio15) catch {}; diff --git a/pi/interrupts.zig b/pi/interrupts.zig @@ -3,6 +3,7 @@ const switching = @import("./switching.zig"); const system = @import("./system.zig"); const PSR = @import("./psr.zig").PSR; const mem = @import("./mem.zig"); +const pi = @import("./root.zig"); const BASE_ADDRESS: usize = mem.BASE_ADDRESS + 0xB200; @@ -210,7 +211,7 @@ fn create_trampoline(name: []const u8, offset: []const u8, ret: []const u8) []co name ++ ":\n" ++ " ldr sp, " ++ name ++ "_data\n" ++ " b " ++ name ++ "_skip\n" ++ - " " ++ name ++ "_data: .word 0x09000000\n" ++ + " " ++ name ++ "_data: .word 0\n" ++ " " ++ name ++ "_skip:\n" ++ " push {r0-r12, lr}\n" ++ " sub lr, lr, #" ++ offset ++ "\n" ++ @@ -270,6 +271,8 @@ pub fn setup_exception_vector(base_address: u32) void { mem.put_u32(@ptrFromInt(exception_vector), @intFromPtr(&fast_interrupt)); + rewrite_stacks(pi.get_interrupt_stack_address()); + // We've just inserted _new_ code system.flush_self_modifying_code(); } diff --git a/pi/pt.zig b/pi/pt.zig @@ -76,6 +76,14 @@ pub fn set(pt: []mmu.FirstLevelDescriptor, va: u32, pa: u32, attr: pinned.Pinned return &pt[index]; } +pub fn remove(pt: []mmu.FirstLevelDescriptor, va: u32) !void { + const index = va >> 20; + + pt[index] = fault_page; + + mmu.sync_pte(); +} + pub fn get(pt: []mmu.FirstLevelDescriptor, va: u32) !?*mmu.FirstLevelDescriptor { const index = va >> 20; const page = &pt[index]; diff --git a/pi/root.zig b/pi/root.zig @@ -42,11 +42,28 @@ extern const __stack_end__: u32; extern const __int_stack_start__: u32; extern const __int_stack_end__: u32; +// Things might get a bit fucky +var STACK_ADDRESS: u32 = 0; +var INT_STACK_ADDRESS: u32 = 0; pub inline fn get_stack_address() u32 { - return std.mem.alignForward(u32, @intFromPtr(&__stack_end__), 1024 * 1024); + if (STACK_ADDRESS == 0) { + STACK_ADDRESS = std.mem.alignForward(u32, @intFromPtr(&__stack_end__), 1024 * 1024); + } + + return STACK_ADDRESS; +} +pub inline fn update_stack_address(address: u32) void { + STACK_ADDRESS = address; } pub inline fn get_interrupt_stack_address() u32 { - return std.mem.alignForward(u32, @intFromPtr(&__int_stack_end__), 1024 * 1024); + if (INT_STACK_ADDRESS == 0) { + INT_STACK_ADDRESS = std.mem.alignForward(u32, @intFromPtr(&__int_stack_end__), 1024 * 1024); + } + + return INT_STACK_ADDRESS; +} +pub inline fn update_interrupt_stack_address(address: u32) void { + INT_STACK_ADDRESS = address; } pub inline fn cycle_counter_init() void { diff --git a/sylveos/memory.zig b/sylveos/memory.zig @@ -14,6 +14,11 @@ extern const __program_end__: u32; extern const __heap_start__: u32; pub const Region = struct { + var PROGRAM_START: ?u32 = null; + var PROGRAM_END: ?u32 = null; + var HEAP_START: ?u32 = null; + var HEAP_END: ?u32 = null; + start: u32, end: u32, size: u32, @@ -32,21 +37,36 @@ pub const Region = struct { } pub fn program() Region { - const program_start = std.mem.alignBackward(u32, @intFromPtr(&__program_start__), MB); - const program_end = std.mem.alignForward(u32, @intFromPtr(&__program_end__), MB); + if (PROGRAM_START == null) { + PROGRAM_START = std.mem.alignBackward(u32, @intFromPtr(&__program_start__), MB); + } + + if (PROGRAM_END == null) { + PROGRAM_END = std.mem.alignForward(u32, @intFromPtr(&__program_end__), MB); + } + + return Region.init(PROGRAM_START orelse unreachable, PROGRAM_END orelse unreachable); + } - return Region.init(program_start, program_end); + pub fn update_program_address(start: u32, end: u32) void { + PROGRAM_START = start; + PROGRAM_END = end; + } + + pub fn update_heap_address(start: u32, end: u32) void { + HEAP_START = start; + HEAP_END = end; } pub fn stack() Region { const stack_end = pi.get_stack_address(); - const stack_start = stack_end - MB; + const stack_start = if (stack_end > io().start) io().end else stack_end - MB; return Region.init(stack_start, stack_end); } pub fn stack_boot() Region { - const stack_end: u32 = 0x8000000; + const stack_end: u32 = 0x0800_0000; const stack_start = stack_end - MB; return Region.init(stack_start, stack_end); @@ -54,7 +74,7 @@ pub const Region = struct { pub fn interrupt_stack() Region { const int_stack_end = pi.get_interrupt_stack_address(); - const int_stack_start = int_stack_end - MB; + const int_stack_start = @max(int_stack_end - MB, stack().end); return Region.init(int_stack_start, int_stack_end); } @@ -75,11 +95,24 @@ pub const Region = struct { } pub fn heap() Region { - const memory_end = memory().end; - const heap_start = std.mem.alignBackward(u32, @intFromPtr(&__heap_start__), MB); - const heap_end = std.mem.alignBackward(u32, memory_end, MB); + if (HEAP_START == null) { + HEAP_START = std.mem.alignBackward(u32, @intFromPtr(&__heap_start__), MB); + } - return Region.init(heap_start, heap_end); + if (HEAP_END == null) { + const memory_end = memory().end; + HEAP_END = std.mem.alignBackward(u32, memory_end, MB); + } + + return Region.init(HEAP_START orelse unreachable, HEAP_END orelse unreachable); + } + + pub fn unmap(self: *const Region, pt: []mmu.FirstLevelDescriptor) !void { + const size = (self.end / MB) - (self.start / MB); + + for (0..size) |offset| { + try page_table.remove(pt, self.start + offset * MB); + } } pub fn map_to(self: *const Region, pt: []mmu.FirstLevelDescriptor, to: u32, attr: pinned.PinnedAttribute) !void { @@ -95,7 +128,7 @@ pub const Region = struct { } }; -pub fn print_regions() void { +pub fn print_regions_physical() void { const memory = Region.memory(); const program = Region.program(); const stack = Region.stack(); @@ -122,6 +155,31 @@ pub fn print_regions() void { }); } +pub fn print_regions_virtual() void { + const program = Region.program(); + const stack = Region.stack(); + const int_stack = Region.interrupt_stack(); + const heap = Region.heap(); + const io = Region.io(); + + uart.print( + \\ Virtual Memory Layout: + \\ HEAP: 0x{X:0>8} - 0x{X:0>8} ({Bi}) + \\ BCM2835 IO: 0x{X:0>8} - 0x{X:0>8} ({Bi}) + \\ KERNEL STACK: 0x{X:0>8} - 0x{X:0>8} ({Bi}) + \\KERNEL INTERRUPT STACK: 0x{X:0>8} - 0x{X:0>8} ({Bi}) + \\ KERNEL: 0x{X:0>8} - 0x{X:0>8} ({Bi}) + \\ + \\ + , .{ + heap.start, heap.end, heap.size, + io.start, io.end, io.size, + stack.start, stack.end, stack.size, + int_stack.start, int_stack.end, int_stack.size, + program.start, program.end, program.size, + }); +} + pub fn get_allocator() std.mem.Allocator { const heap = Region.heap(); diff --git a/sylveos/root.zig b/sylveos/root.zig @@ -13,7 +13,7 @@ const Region = memory.Region; // The whole point of this code is to relocate the kernel into the high addresses pub fn main() !void { - memory.print_regions(); + memory.print_regions_physical(); // Now it's time for the fun // We want to copy the kernel's code to high address space @@ -69,20 +69,17 @@ pub fn main() !void { mmu.enable(); pi.interrupts.disable_interrupts(); - pi.switching.jump(kernel_relocation + new_main_offset, kernel_relocation); + pi.switching.jump(kernel_relocation + new_main_offset, kernel_relocation - (memory.MB / 2)); } fn new_main() noreturn { const base_address = Region.io().end + memory.MB; - const stack = base_address; - const interrupt_stack = base_address - (memory.MB / 2); + // Keep interrupt stack on top of normal stack + const stack = base_address - (memory.MB / 2); + const interrupt_stack = base_address; - uart.print( - \\new_main: 0x{X:8>0} - \\ stack: 0x{X:8>0} - \\ - \\ - , .{ @intFromPtr(&new_main), stack }); + var page_table_raw: [*]mmu.FirstLevelDescriptor = @ptrFromInt(base_address - memory.MB); + const pt = page_table_raw[0..4096]; // Now we need to: // 1. Load the new exception handler @@ -98,11 +95,18 @@ fn new_main() noreturn { interrupts.rewrite_stacks(interrupt_stack); interrupts.enable_interrupts(); - uart.print( - \\interrupts: 0x{X:8>0} - \\ stack: 0x{X:8>0} - \\ - , .{ base_address, interrupt_stack }); + Region.interrupt_stack().unmap(pt) catch {}; + Region.stack_boot().unmap(pt) catch {}; + Region.stack().unmap(pt) catch {}; + + uart.print("Remapping regions\n\n", .{}); + + pi.update_stack_address(stack); + pi.update_interrupt_stack_address(interrupt_stack); + Region.update_program_address(base_address, base_address + memory.MB); + Region.update_heap_address(0, Region.memory().end - memory.MB * 2); + + memory.print_regions_virtual(); pi.reboot(); }