implemented paging with Sv57
This commit is contained in:
parent
4341e1dce2
commit
31a0fd5202
4 changed files with 125 additions and 7 deletions
20
src/Fdt.zig
20
src/Fdt.zig
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
src/main.zig
15
src/main.zig
|
|
@ -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
92
src/riscv/PageTable.zig
Normal 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 = ¤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),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue