From 3f791778391db52fc82b0020a3cbdda369f06d5a Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Tue, 18 Mar 2025 09:31:13 +0200 Subject: [PATCH] aarch64: physical memory setup --- output.log | 8 +++ src/arch/aarch64/boot.zig | 46 +++++++++++-- src/arch/riscv64/boot.zig | 25 +------ src/util/dtb.zig | 133 +++++++++++++++++++++++++++----------- 4 files changed, 148 insertions(+), 64 deletions(-) create mode 100644 output.log diff --git a/output.log b/output.log new file mode 100644 index 0000000..fff21f0 --- /dev/null +++ b/output.log @@ -0,0 +1,8 @@ +Hello, dtb is at 0x48000000 +Memory: 'memory@40000000', base 0x40000000, size 0x10000000 +Reserved: 'kernel', base 0x40080000, size 0x1d000 +Reserved: 'fdt', base 0x48000000, size 0x100000 +Reserved: 'page-array', base 0x4009d000, size 0x100000 +Available memory: 253 MiB, page array mem.phys.Page@4009d000 +QEMU: Terminated + \ No newline at end of file diff --git a/src/arch/aarch64/boot.zig b/src/arch/aarch64/boot.zig index f3df362..5b7a9df 100644 --- a/src/arch/aarch64/boot.zig +++ b/src/arch/aarch64/boot.zig @@ -1,8 +1,11 @@ const kernel = @import("../../kernel.zig"); const vmm = @import("vmm.zig"); +const dtb = @import("../../util/dtb.zig"); const arch = kernel.arch; +const mem = kernel.mem; const log = kernel.debug.log; +const physMemory = mem.phys; extern const __aa64_bsp_stack_top: u8; @@ -22,6 +25,15 @@ fn relocAddressToUpper(ptr: *const anyopaque) usize { } } +fn relocAddressToLower(ptr: *const anyopaque) usize { + const p = @intFromPtr(ptr); + if (p >= vmm.KERNEL_VIRTUAL_BASE) { + return p - vmm.KERNEL_VIRTUAL_BASE; + } else { + return p; + } +} + fn aa64BspUpperEntry(realAddress: u64) callconv(.C) noreturn { // Relocate the kernel yet again const relaStart = relocAddressToUpper(&__rela_start); @@ -33,7 +45,12 @@ fn aa64BspUpperEntry(realAddress: u64) callconv(.C) noreturn { arch.barrier(.acq_rel); log.setWriteFn(&earlyDebugPrint); - log.info("Hello, dtb is at 0x{x}", .{ gDtbAddress }); + log.info("Hello, dtb is at 0x{x}", .{gDtbAddress}); + + mem.PhysicalAddress.gVirtualizeBase = 0; + mem.PhysicalAddress.gVirtualizeSize = 16 << 30; + + setupMemoryFromFdt(realAddress); arch.halt(); } @@ -53,6 +70,8 @@ pub export fn aa64BspLowerEntry(realAddress: u64, dtbAddress: u64) callconv(.C) extern const __rela_start: u8; extern const __rela_end: u8; +extern var __kernel_start: u8; +extern var __kernel_end: u8; export fn aa64RelocateKernel(imageBase: usize, relaStart: usize, relaEnd: usize) void { const elf = @import("std").elf; @@ -79,10 +98,27 @@ inline fn longJump(pc: usize, sp: usize, a0: usize) noreturn { \\ mov sp, %[sp] \\ br %[pc] : - : [sp]"r"(sp), - [pc]"r"(pc), - [a0]"{x0}"(a0), - :"memory" + : [sp] "r" (sp), + [pc] "r" (pc), + [a0] "{x0}" (a0), + : "memory" ); unreachable; } + +fn setupMemoryFromFdt(realAddress: usize) void { + _ = realAddress; + + const kernelStart = relocAddressToLower(&__kernel_start); // 0 + const kernelEnd = relocAddressToLower(&__kernel_end); // whatever + + const fdt = dtb.Fdt.fromPhysicalAddress(.{ .raw = gDtbAddress }) catch |err| { + log.panic("Cannot initialize raw DTB: {}", .{err}); + }; + fdt.addPhysicalMemoryToSystem(); + + physMemory.addReservedRegion("kernel", kernelStart, kernelEnd - kernelStart); + physMemory.addReservedRegion("fdt", gDtbAddress, vmm.L3.align_up(fdt.bytes.len)); + + physMemory.init(); +} diff --git a/src/arch/riscv64/boot.zig b/src/arch/riscv64/boot.zig index 2ec9efd..6dedbbd 100644 --- a/src/arch/riscv64/boot.zig +++ b/src/arch/riscv64/boot.zig @@ -14,8 +14,6 @@ const log = debug.log; const arch = kernel.arch; extern const __rv64_bsp_stack_top: u8; -extern const __kernel_start: u8; -extern const __kernel_end: u8; var gDtbAddress: usize = 0; var gBspHartId: u32 = 0; @@ -81,6 +79,8 @@ extern var __tdata_start: u8; extern var __tdata_end: u8; extern var __tbss_start: u8; extern var __tbss_end: u8; +extern var __kernel_start: u8; +extern var __kernel_end: u8; fn setupPerCpu() void { // Assume .tbss follows .tdata @@ -131,29 +131,10 @@ fn setupMemoryFromFdt(realAddress: usize) void { const kernelStart = @intFromPtr(&__kernel_start); const kernelEnd = @intFromPtr(&__kernel_end); - var cells: [2]u64 = undefined; - const fdt = dtb.Fdt.fromPhysicalAddress(.{ .raw = gDtbAddress }) catch |err| { log.panic("Cannot initialize raw DTB: {}", .{err}); }; - - var memoryRegions = fdt.memoryRegionIterator(); - - while (memoryRegions.next()) |region| { - physMemory.addMemoryRegion(region.name, region.base, region.size); - } - const reservedRegions = fdt.rootNode().child("reserved-memory"); - if (reservedRegions) |resv| { - var children = resv.children(); - while (children.next()) |region| { - if (region.property("reg")) |reg| { - // TODO #address-cells, #size-cells - if (reg.readCells(0, &cells, &.{ 2, 2 })) { - physMemory.addReservedRegion(region.name, cells[0], cells[1]); - } - } - } - } + fdt.addPhysicalMemoryToSystem(); physMemory.addReservedRegion("kernel", kernelStart - (vmm.KERNEL_VIRTUAL_BASE + vmm.L1.offset(realAddress)) + realAddress, kernelEnd - kernelStart); physMemory.addReservedRegion("fdt", gDtbAddress, vmm.L3.align_up(fdt.bytes.len)); diff --git a/src/util/dtb.zig b/src/util/dtb.zig index c1470d5..536fa14 100644 --- a/src/util/dtb.zig +++ b/src/util/dtb.zig @@ -2,6 +2,8 @@ const mem = @import("../mem.zig"); const log = @import("../debug.zig").log; const std = @import("std"); +const physMemory = mem.phys; + const fdt_header = extern struct { magic: u32, totalsize: u32, @@ -359,50 +361,107 @@ pub const Fdt = struct { return @ptrCast(raw[0..len]); } - pub fn dump(self: *const @This()) void { - const root = self.rootNode(); + pub fn addPhysicalMemoryToSystem(self: *const @This()) void { + var memoryRegions = self.memoryRegionIterator(); var cells: [2]u64 = undefined; - if (root.child("reserved-memory")) |resv| { - var regions = resv.children(); - while (regions.next()) |region| { + + while (memoryRegions.next()) |region| { + physMemory.addMemoryRegion(region.name, region.base, region.size); + } + const reservedRegions = self.rootNode().child("reserved-memory"); + if (reservedRegions) |resv| { + var children = resv.children(); + while (children.next()) |region| { if (region.property("reg")) |reg| { + // TODO #address-cells, #size-cells if (reg.readCells(0, &cells, &.{ 2, 2 })) { - log.info("Reserved memory region {s}: base=0x{x}, size=0x{x}", .{ region.name, cells[0], cells[1] }); + physMemory.addReservedRegion(region.name, cells[0], cells[1]); } } } } - // var memIter = self.memoryRegionIterator(); - // while (memIter.next()) |region| { - // log.info("base=0x{x}, size=0x{x}", .{ region.base, region.size }); - // } + } - // var nodeIter = self.nodeIterator(); - // while (nodeIter.next()) |node| { - // for (0..node.depth) |_| { - // log.writeRaw(" "); - // } - // if (node.name.len == 0) { - // log.info("Root node, depth = {}", .{ node.depth }); - // } else { - // log.info("Node {s}, depth {}", .{ node.name, node.depth }); - // } - // var nodePropIter = node.propIterator(); - // while (nodePropIter.next()) |prop| { - // for (0..node.depth + 1) |_| { - // log.writeRaw(" "); - // } - // log.info("Prop {s}", .{ prop.name }); - // if (std.mem.eql(u8, prop.name, "compatible")) { - // var strings = prop.getStringArray(); - // while (strings.next()) |s| { - // for (0..node.depth + 2) |_| { - // log.writeRaw(" "); - // } - // log.info("= {s}", .{ s }); - // } - // } - // } - // } + fn dump_property(property: *const FdtNodeProp, depth: usize, allStrings: bool) void { + for (0..depth) |_| { + log.writeRaw(" "); + } + log.write("{s}", .{property.name}); + + if (std.mem.eql(u8, property.name, "#size-cells") // + or std.mem.eql(u8, property.name, "#address-cells") // + or std.mem.eql(u8, property.name, "#interrupt-cells") // + or std.mem.eql(u8, property.name, "phandle") // + or std.mem.eql(u8, property.name, "interrupt-parent") // + ) { + // Dump as a single cell + const v = property.getU32(0) orelse 0; + log.write(" = {}", .{v}); + } else if (allStrings // + or std.mem.eql(u8, property.name, "compatible") // + or std.mem.eql(u8, property.name, "model") // + or std.mem.endsWith(u8, property.name, "-names") // + or std.mem.endsWith(u8, property.name, "stdout-path") // + ) { + var v = property.getStringArray(); + var f = true; + while (v.next()) |s| { + if (f) { + log.writeRaw(" = "); + } else { + log.writeRaw(", "); + } + f = false; + log.write("\"{s}\"", .{s}); + } + } else { + // Dump the rest as a cell array + const len = property.lenU32(); + log.writeRaw(" = <"); + for (0..len) |i| { + if (i != 0) { + log.writeRaw(", "); + } + log.write("0x{x}", .{property.getU32Unchecked(i)}); + } + log.writeRaw(">"); + } + + log.writeRaw(";\r\n"); + } + + fn dump_node(node: *const FdtNode, depth: usize) void { + var anyProperties = false; + var firstChild = true; + + for (0..depth) |_| { + log.writeRaw(" "); + } + if (node.name.len != 0) { + log.write("{s} ", .{node.name}); + } + log.writeRaw("{\r\n"); + var properties = node.propIterator(); + const allStrings = std.mem.eql(u8, node.name, "aliases"); + while (properties.next()) |property| { + dump_property(&property, depth + 1, allStrings); + anyProperties = true; + } + var children = node.children(); + while (children.next()) |child| { + if (anyProperties and firstChild) { + log.writeRaw("\r\n"); + } + firstChild = false; + dump_node(&child, depth + 1); + } + for (0..depth) |_| { + log.writeRaw(" "); + } + log.write("}},\r\n", .{}); + } + + pub fn dump(self: *const @This()) void { + dump_node(&self.rootNode(), 0); } };