M2 step 3: route every physical dereference through the physmap

paging.init now builds the physmap (physToVirt(phys)) alongside the low
identity map, so both addressing modes resolve during the transition.
tableAt (the page-table walk hinge), the pmm bitmap, the framebuffer,
LAPIC/IOAPIC/HPET/PM-timer/SPCR MMIO, the ACPI table walk, AML
OperationRegions, the ACPI power registers, the user-ELF frame fills,
and the AP trampoline arm/disarm all reach physical memory through the
physmap. Hal.mapMmio now maps into the physmap and returns the virtual
address, so the device layer never learns the layout. boot_info and its
pointees are converted at kmain entry. The kernel still links and runs
low; identity is the safety net until it's removed. Suite 27/27.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Samson
2026-07-08 22:41:42 +01:00
co-authored by Claude Fable 5
parent 75bc429aa1
commit 724de7bbd0
16 changed files with 143 additions and 59 deletions
+13 -12
View File
@@ -147,7 +147,7 @@ var aml_block_count: usize = 0;
fn addAmlBlock(sdt_phys: u64) void {
if (aml_block_count >= aml_block_phys.len or sdt_phys == 0) return;
const h: *const SystemDescriptorTableHeader = @ptrFromInt(sdt_phys);
const h: *const SystemDescriptorTableHeader = @ptrFromInt(danos.physToVirt(sdt_phys));
if (h.length <= @sizeOf(SystemDescriptorTableHeader)) return;
aml_block_phys[aml_block_count] = sdt_phys + @sizeOf(SystemDescriptorTableHeader);
aml_block_len[aml_block_count] = h.length - @sizeOf(SystemDescriptorTableHeader);
@@ -376,14 +376,14 @@ pub fn discover(rsdp_phys: u64, dt: *DeviceTree, hal: Hal) !void {
dsdt_phys = 0;
aml_block_count = 0;
const rsdp: *const RootSystemDescriptionPointer = @ptrFromInt(rsdp_phys);
const rsdp: *const RootSystemDescriptionPointer = @ptrFromInt(danos.physToVirt(rsdp_phys));
if (!std.mem.eql(u8, &rsdp.signature, "RSD PTR ")) return error.BadRsdpSignature;
// Revision 0 checksums only the first 20 bytes (the v1.0 RSDP).
if (!checksumOk(@ptrFromInt(rsdp_phys), 20)) return error.BadRsdpChecksum;
if (!checksumOk(@ptrFromInt(danos.physToVirt(rsdp_phys)), 20)) return error.BadRsdpChecksum;
if (rsdp.revision >= 2) {
const xsdp: *const ExtendedSystemDescriptorPointer = @ptrFromInt(rsdp_phys);
if (!checksumOk(@ptrFromInt(rsdp_phys), xsdp.length)) return error.BadXsdpChecksum;
const xsdp: *const ExtendedSystemDescriptorPointer = @ptrFromInt(danos.physToVirt(rsdp_phys));
if (!checksumOk(@ptrFromInt(danos.physToVirt(rsdp_phys)), xsdp.length)) return error.BadXsdpChecksum;
try walkRoot(u64, xsdp.extended_system_descriptor_table_address, dt, hal);
} else {
try walkRoot(u32, rsdp.root_system_description_table_address, dt, hal);
@@ -393,7 +393,7 @@ pub fn discover(rsdp_phys: u64, dt: *DeviceTree, hal: Hal) !void {
// read the sleep types from it.
var blocks: [aml_block_phys.len][]const u8 = undefined;
for (0..aml_block_count) |i| {
blocks[i] = @as([*]const u8, @ptrFromInt(aml_block_phys[i]))[0..aml_block_len[i]];
blocks[i] = @as([*]const u8, @ptrFromInt(danos.physToVirt(aml_block_phys[i])))[0..aml_block_len[i]];
}
const active = blocks[0..aml_block_count];
if (aml.parse(dt.allocator, active)) |pr| {
@@ -412,11 +412,11 @@ pub fn discover(rsdp_phys: u64, dt: *DeviceTree, hal: Hal) !void {
/// Walk the RSDT (Entry = u32) or XSDT (Entry = u64): validate it, then dispatch
/// each SDT it points at. A bad individual table is skipped, not fatal.
fn walkRoot(comptime Entry: type, root_phys: u64, dt: *DeviceTree, hal: Hal) !void {
const header: *const SystemDescriptorTableHeader = @ptrFromInt(root_phys);
if (!checksumOk(@ptrFromInt(root_phys), header.length)) return error.BadRootChecksum;
const header: *const SystemDescriptorTableHeader = @ptrFromInt(danos.physToVirt(root_phys));
if (!checksumOk(@ptrFromInt(danos.physToVirt(root_phys)), header.length)) return error.BadRootChecksum;
const count = (header.length - @sizeOf(SystemDescriptorTableHeader)) / @sizeOf(Entry);
const base: [*]const u8 = @ptrFromInt(root_phys);
const base: [*]const u8 = @ptrFromInt(danos.physToVirt(root_phys));
const entries: [*]align(1) const Entry = @ptrCast(base + @sizeOf(SystemDescriptorTableHeader));
for (entries[0..count]) |ent| {
@@ -427,7 +427,7 @@ fn walkRoot(comptime Entry: type, root_phys: u64, dt: *DeviceTree, hal: Hal) !vo
/// Dispatch a single SDT on its signature.
fn handleTable(dt: *DeviceTree, hal: Hal, sdt_phys: u64) !void {
const header: *const SystemDescriptorTableHeader = @ptrFromInt(sdt_phys);
const header: *const SystemDescriptorTableHeader = @ptrFromInt(danos.physToVirt(sdt_phys));
const sig = header.signature;
if (std.mem.eql(u8, &sig, &APIC)) {
try parseMadt(dt, header);
@@ -1080,8 +1080,9 @@ fn pciConfigPtr(alloc: McfgAllocation, hal: Hal, bus: u8, dev: u8, func: u8) [*]
(@as(u64, bus - alloc.start_bus) << 20) +
(@as(u64, dev) << 15) +
(@as(u64, func) << 12);
hal.mapMmio(phys, phys, true); // identity-map this config page (writable)
return @ptrFromInt(phys);
// Map the config page (writable, for BAR sizing) and use the virtual
// address the HAL hands back.
return @ptrFromInt(hal.mapMmio(phys, danos.page_size, true));
}
/// Read a little-endian integer at `off` from a (possibly unaligned) byte pointer.