From 31a0fd520202c9d1b94b8f69ce8a9a258ca7dc17 Mon Sep 17 00:00:00 2001 From: Lorenzo Torres Date: Sun, 1 Feb 2026 15:53:02 +0100 Subject: [PATCH] implemented paging with Sv57 --- src/Fdt.zig | 20 +++++++++ src/main.zig | 15 ++++--- src/riscv/PageTable.zig | 92 +++++++++++++++++++++++++++++++++++++++++ src/riscv/isa.zig | 5 ++- 4 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 src/riscv/PageTable.zig diff --git a/src/Fdt.zig b/src/Fdt.zig index c62a030..669d4ee 100644 --- a/src/Fdt.zig +++ b/src/Fdt.zig @@ -1,5 +1,6 @@ const std = @import("std"); const Fdt = @This(); +const isa = @import("riscv/isa.zig"); pub const MAGIC = 0xd00dfeed; @@ -592,6 +593,25 @@ pub fn memory(self: *const Fdt) ?Node { return null; } +pub fn mmuType(self: *const Fdt) isa.Satp.Mode { + var n = self.cpus().?.children(); + while (n.next()) |node| { + if (node.getProperty("mmu-type")) |mmu_type| { + if (std.mem.eql(u8, mmu_type.asString().?, "riscv,sv64")) { + return .sv64; + } else if (std.mem.eql(u8, mmu_type.asString().?, "riscv,sv57")) { + return .sv57; + } else if (std.mem.eql(u8, mmu_type.asString().?, "riscv,sv48")) { + return .sv48; + } else if (std.mem.eql(u8, mmu_type.asString().?, "riscv,sv39")) { + return .sv39; + } + } + } + + return .bare; +} + pub fn cpus(self: *const Fdt) ?Node { return self.findNode("/cpus"); } diff --git a/src/main.zig b/src/main.zig index e40ff07..8c6174e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -40,11 +40,6 @@ export fn kmain(hartid: u64, fdt_ptr: *const anyopaque) callconv(.c) noreturn { debug.print("booting hydra...\n", .{}); - var reservations = fdt.memoryReservations(); - - while (reservations.next()) |reservation| { - debug.print("0x{x}:0x{x}\n", .{reservation.address, reservation.size}); - } const memory = fdt.memory().?; var reg_iter = Fdt.parseReg(memory.getProperty("reg").?.data, root.addressCells(), root.sizeCells()); const reg = reg_iter.next().?; @@ -55,7 +50,15 @@ export fn kmain(hartid: u64, fdt_ptr: *const anyopaque) callconv(.c) noreturn { debug.print("memory allocator initialized.\n", .{}); const allocator = buddy.allocator(); - _ = allocator; + + var table = isa.PageTable.init(allocator) catch { @panic("Unable to create page table.\n"); }; + table.identityMap(allocator, memory_end) catch {}; + table.map(allocator, @intFromPtr(console.mmio), @intFromPtr(console.mmio), .{.read = 1, .write = 1, .execute = 1}) catch {}; + isa.write_satp(.{ + .ppn = @as(u44, @intCast(@intFromPtr(table) >> 12)), + .mode = .sv57, + }); + debug.print("loaded kernel page table.\n", .{}); while (true) { asm volatile ("wfi"); diff --git a/src/riscv/PageTable.zig b/src/riscv/PageTable.zig new file mode 100644 index 0000000..f539310 --- /dev/null +++ b/src/riscv/PageTable.zig @@ -0,0 +1,92 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const PageTable = @This(); +const debug = @import("../debug.zig"); + +const MEMORY_START = @extern([*]u8, .{.name = "__memory_start"}); + +pub const EntryFlags = packed struct { + valid: u1 = 1, + read: u1, + write: u1, + execute: u1 = 0, + user: u1 = 0, +}; + +pub const Entry = packed struct { + flags: EntryFlags, + global_mapping: u1 = 0, + ignored: u2 = 0, + rsw: u2 = 0, + ppn: u44, + reserved: u7 = 0, + pbmt: u2 = 0, + n: u1 = 0, +}; + +entries: [512]Entry, + +pub fn init(allocator: Allocator) !*PageTable { + const table = try allocator.create(PageTable); + for (&table.entries) |*entry| { + entry.* = @bitCast(@as(u64, 0x0)); + } + return table; +} + +pub fn identityMap(self: *PageTable, allocator: Allocator, memory_end: u64) !void { + const flags = EntryFlags{ + .valid = 1, + .read = 1, + .write = 1, + .execute = 1, + .user = 0, + }; + + var addr: u64 = 0x80000000; + while (addr < memory_end) : (addr += 0x1000) { + try self.map(allocator, addr, addr, flags); + } +} + +pub fn map(self: *PageTable, allocator: Allocator, virtual: u64, physical: u64, flags: EntryFlags) !void { + const PAGE_SIZE = 4096; + + if (virtual % PAGE_SIZE != 0 or physical % PAGE_SIZE != 0) { + return error.AddressNotAligned; + } + + const vpn = [5]u64{ + (virtual >> 12) & 0x1ff, + (virtual >> 21) & 0x1ff, + (virtual >> 30) & 0x1ff, + (virtual >> 39) & 0x1ff, + (virtual >> 48) & 0x1ff, + }; + + var current_table = self; + + var level: usize = 4; + while (level > 0) : (level -= 1) { + const index = vpn[level]; + var entry = ¤t_table.entries[index]; + + if (entry.flags.valid == 0) { + const new_table = try PageTable.init(allocator); + + const table_phys = @intFromPtr(new_table); + entry.* = .{ + .flags = .{ .valid = 1, .read = 0, .write = 0, .execute = 0, .user = 0 }, + .ppn = @truncate(table_phys >> 12), + }; + } + + const next_table_phys = @as(u64, entry.ppn) << 12; + current_table = @ptrFromInt(next_table_phys); + } + + current_table.entries[vpn[0]] = .{ + .flags = flags, + .ppn = @truncate(physical >> 12), + }; +} diff --git a/src/riscv/isa.zig b/src/riscv/isa.zig index e94f4ca..e58f0b2 100644 --- a/src/riscv/isa.zig +++ b/src/riscv/isa.zig @@ -1,7 +1,9 @@ +pub const PageTable = @import("PageTable.zig"); + pub const Satp = packed struct { pub const Mode = enum(u4) { bare = 0, - sv38 = 8, + sv39 = 8, sv48 = 9, sv57 = 10, sv64 = 11, @@ -17,6 +19,7 @@ pub inline fn write_satp(satp: Satp) void { : : [val] "r" (satp), ); + asm volatile ("sfence.vma"); } pub inline fn read_satp() Satp {