aarch64: physical memory setup

This commit is contained in:
2025-03-18 09:31:13 +02:00
parent dc7968f92f
commit 3f79177839
4 changed files with 148 additions and 64 deletions
+8
View File
@@ -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
+41 -5
View File
@@ -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();
}
+3 -22
View File
@@ -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));
+96 -37
View File
@@ -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);
}
};