implemented paging with Sv57

This commit is contained in:
Lorenzo Torres 2026-02-01 15:53:02 +01:00
parent 4341e1dce2
commit 31a0fd5202
4 changed files with 125 additions and 7 deletions

View file

@ -1,5 +1,6 @@
const std = @import("std"); const std = @import("std");
const Fdt = @This(); const Fdt = @This();
const isa = @import("riscv/isa.zig");
pub const MAGIC = 0xd00dfeed; pub const MAGIC = 0xd00dfeed;
@ -592,6 +593,25 @@ pub fn memory(self: *const Fdt) ?Node {
return null; 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 { pub fn cpus(self: *const Fdt) ?Node {
return self.findNode("/cpus"); return self.findNode("/cpus");
} }

View file

@ -40,11 +40,6 @@ export fn kmain(hartid: u64, fdt_ptr: *const anyopaque) callconv(.c) noreturn {
debug.print("booting hydra...\n", .{}); 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().?; const memory = fdt.memory().?;
var reg_iter = Fdt.parseReg(memory.getProperty("reg").?.data, root.addressCells(), root.sizeCells()); var reg_iter = Fdt.parseReg(memory.getProperty("reg").?.data, root.addressCells(), root.sizeCells());
const reg = reg_iter.next().?; 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", .{}); debug.print("memory allocator initialized.\n", .{});
const allocator = buddy.allocator(); 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) { while (true) {
asm volatile ("wfi"); asm volatile ("wfi");

92
src/riscv/PageTable.zig Normal file
View file

@ -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 = &current_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),
};
}

View file

@ -1,7 +1,9 @@
pub const PageTable = @import("PageTable.zig");
pub const Satp = packed struct { pub const Satp = packed struct {
pub const Mode = enum(u4) { pub const Mode = enum(u4) {
bare = 0, bare = 0,
sv38 = 8, sv39 = 8,
sv48 = 9, sv48 = 9,
sv57 = 10, sv57 = 10,
sv64 = 11, sv64 = 11,
@ -17,6 +19,7 @@ pub inline fn write_satp(satp: Satp) void {
: :
: [val] "r" (satp), : [val] "r" (satp),
); );
asm volatile ("sfence.vma");
} }
pub inline fn read_satp() Satp { pub inline fn read_satp() Satp {