Rename the shared contract module danos -> system; QEMU logs to /var/log/system

The shared kernel<->user ABI contract (BootInformation, the SystemCall numbers,
DeviceDescriptor, page_size, ...) is now the `system` module at
system/system.zig, following the convention that a directory's root file takes
the directory's name.

One overlap to note: the runtime's syscall wrappers are already `runtime.system`,
so the single file that uses both the contract and those wrappers
(library/runtime/heap.zig) aliases the wrappers locally as `system_calls`. The
two are distinct (top-level `system` vs `runtime.system`); everywhere else the
contract is just `system`.

Also: the QEMU run's serial capture now lands in the FHS log location,
zig-out/var/log/system/serial0-<timestamp>.log — a stand-in for the kernel's own
logging system, which will eventually write there itself.

Suite 35/35 plus host tests green.
This commit is contained in:
Daniel Samson
2026-07-10 14:09:38 +01:00
parent 3d1de37d0e
commit d19a0ae38d
38 changed files with 202 additions and 198 deletions
+27 -27
View File
@@ -10,7 +10,7 @@
//! exception report the handler prints (which also reaches serial).
const std = @import("std");
const danos = @import("danos");
const system = @import("system");
const architecture = @import("architecture");
const devices_broker = @import("devices-broker.zig");
const platform = @import("platform");
@@ -153,7 +153,7 @@ fn powerTest(comptime action: enum { off, reboot }) void {
result();
}
const BootInformation = danos.BootInformation;
const BootInformation = system.BootInformation;
fn eql(a: []const u8, b: []const u8) bool {
return std.mem.eql(u8, a, b);
@@ -165,7 +165,7 @@ fn smoke(boot_information: *const BootInformation) void {
// The memory map has some usable RAM.
const mm = boot_information.memory_map;
const regions = @as([*]const danos.MemoryRegion, @ptrFromInt(danos.physicalToVirtual(mm.regions)))[0..mm.len];
const regions = @as([*]const system.MemoryRegion, @ptrFromInt(system.physicalToVirtual(mm.regions)))[0..mm.len];
var usable: u64 = 0;
for (regions) |r| {
if (r.kind == .usable) usable += r.pages;
@@ -177,7 +177,7 @@ fn smoke(boot_information: *const BootInformation) void {
const b = pmm.alloc();
check("alloc returns a frame", a != null);
check("alloc returns distinct frames", a != null and b != null and a.? != b.?);
check("frames are page-aligned", (a orelse 1) % danos.page_size == 0);
check("frames are page-aligned", (a orelse 1) % system.page_size == 0);
// Freeing restores the count.
const before = pmm.stats().free_frames;
@@ -187,7 +187,7 @@ fn smoke(boot_information: *const BootInformation) void {
// Paging is active on our own tables (the root is non-zero and page-aligned).
const root = architecture.activePageTable();
check("paging active (page-table root set)", root != 0 and root % danos.page_size == 0);
check("paging active (page-table root set)", root != 0 and root % system.page_size == 0);
result();
}
@@ -573,7 +573,7 @@ fn smpTest() void {
const tramp = architecture.trampolinePage();
check("trampoline frame reserved", tramp != 0);
if (tramp != 0) {
const bytes: [*]const u8 = @ptrFromInt(danos.physicalToVirtual(tramp));
const bytes: [*]const u8 = @ptrFromInt(system.physicalToVirtual(tramp));
var zeroed = true;
for (0..4096) |b| {
if (bytes[b] != 0) zeroed = false;
@@ -757,7 +757,7 @@ fn userMemTest() void {
var mapped: usize = 0;
while (mapped < npages) : (mapped += 1) {
frames[mapped] = pmm.alloc() orelse break;
architecture.mapUserPageInto(aspace, arena + mapped * danos.page_size, frames[mapped], true, false);
architecture.mapUserPageInto(aspace, arena + mapped * system.page_size, frames[mapped], true, false);
}
check("granted three user pages", mapped == npages);
@@ -765,13 +765,13 @@ fn userMemTest() void {
var translate_ok = true;
var rw_ok = true;
for (0..npages) |i| {
const va = arena + i * danos.page_size;
const va = arena + i * system.page_size;
const physical = architecture.translate(aspace, va) orelse {
translate_ok = false;
continue;
};
if (physical != frames[i]) translate_ok = false;
const p: [*]u8 = @ptrFromInt(danos.physicalToVirtual(physical));
const p: [*]u8 = @ptrFromInt(system.physicalToVirtual(physical));
p[0] = 0xA5;
if (p[0] != 0xA5) rw_ok = false;
}
@@ -780,7 +780,7 @@ fn userMemTest() void {
// Release them the way munmap does, then tear down the address space.
for (0..npages) |i| {
const va = arena + i * danos.page_size;
const va = arena + i * system.page_size;
if (architecture.translate(aspace, va)) |physical| {
architecture.unmapUserPageInto(aspace, va);
pmm.free(physical);
@@ -877,7 +877,7 @@ fn processTest(boot_information: *const BootInformation) void {
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(danos.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
const image = @as([*]const u8, @ptrFromInt(system.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
process.write_count = 0;
process.write_from_user = false;
@@ -928,7 +928,7 @@ fn initTest(boot_information: *const BootInformation) void {
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(danos.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
const image = @as([*]const u8, @ptrFromInt(system.physicalToVirtual(boot_information.init_base)))[0..boot_information.init_len];
process.write_count = 0;
const spawned = if (process.spawnProcess(image, 4)) true else |err| blk: {
log("DANOS-INIT-ERR: {s}\n", .{@errorName(err)});
@@ -962,7 +962,7 @@ fn initialRamdiskTest(boot_information: *const BootInformation) void {
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(danos.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const image = @as([*]const u8, @ptrFromInt(system.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const rd = initial_ramdisk.Reader.init(image) orelse {
check("initial_ramdisk image is valid", false);
result();
@@ -1006,7 +1006,7 @@ fn vfsTest(boot_information: *const BootInformation) void {
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(danos.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const image = @as([*]const u8, @ptrFromInt(system.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const rd = initial_ramdisk.Reader.init(image) orelse {
check("initial_ramdisk image is valid", false);
result();
@@ -1069,7 +1069,7 @@ fn hpetTest(boot_information: *const BootInformation) void {
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(danos.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const image = @as([*]const u8, @ptrFromInt(system.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const rd = initial_ramdisk.Reader.init(image) orelse {
check("initial_ramdisk image is valid", false);
result();
@@ -1113,14 +1113,14 @@ fn hpetRouteOk() bool {
/// The GSI discovery recorded for the HPET, from the same device table the driver saw.
fn hpetGsi() ?u32 {
var buffer: [16]danos.DeviceDescriptor = undefined;
var buffer: [16]system.DeviceDescriptor = undefined;
const n = @min(devices_broker.enumerate(&buffer), buffer.len);
for (buffer[0..n]) |d| {
if (d.class != @intFromEnum(danos.DeviceClass.timer)) continue;
if (d.parent != danos.no_parent) continue; // the block, not a comparator child
if (d.class != @intFromEnum(system.DeviceClass.timer)) continue;
if (d.parent != system.no_parent) continue; // the block, not a comparator child
for (0..d.resource_count) |j| {
const r = d.resources[j];
if (r.kind == @intFromEnum(danos.ResourceKind.irq)) return @intCast(r.start);
if (r.kind == @intFromEnum(system.ResourceKind.irq)) return @intCast(r.start);
}
}
return null;
@@ -1146,7 +1146,7 @@ fn busTest(boot_information: *const BootInformation) void {
result();
return;
}
const image = @as([*]const u8, @ptrFromInt(danos.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const image = @as([*]const u8, @ptrFromInt(system.physicalToVirtual(boot_information.initial_ramdisk_base)))[0..boot_information.initial_ramdisk_len];
const rd = initial_ramdisk.Reader.init(image) orelse {
check("initial_ramdisk image is valid", false);
result();
@@ -1181,7 +1181,7 @@ fn busTest(boot_information: *const BootInformation) void {
/// trusted and doesn't obey containment: a PCI function's BAR is not inside its host
/// bridge's `bus_range`, because a bus-number range isn't an address window.
fn childrenContained() bool {
var buffer: [64]danos.DeviceDescriptor = undefined;
var buffer: [64]system.DeviceDescriptor = undefined;
const n = @min(devices_broker.enumerate(&buffer), buffer.len);
const bus_id = hpetDeviceId() orelse return false;
@@ -1197,7 +1197,7 @@ fn childrenContained() bool {
for (0..p.resource_count) |j| {
const pr = p.resources[j];
if (pr.kind != r.kind) continue;
if (r.kind == @intFromEnum(danos.ResourceKind.irq)) {
if (r.kind == @intFromEnum(system.ResourceKind.irq)) {
if (pr.start == r.start) ok = true;
} else if (r.len != 0 and r.start >= pr.start and
r.start + r.len <= pr.start + pr.len) ok = true;
@@ -1210,13 +1210,13 @@ fn childrenContained() bool {
/// Device id of the HPET (the bus bus claims), from the same table drivers see.
fn hpetDeviceId() ?u64 {
var buffer: [64]danos.DeviceDescriptor = undefined;
var buffer: [64]system.DeviceDescriptor = undefined;
const n = @min(devices_broker.enumerate(&buffer), buffer.len);
for (buffer[0..n]) |d| {
if (d.class != @intFromEnum(danos.DeviceClass.timer)) continue;
if (d.parent != danos.no_parent) continue; // a comparator child, not the block
if (d.class != @intFromEnum(system.DeviceClass.timer)) continue;
if (d.parent != system.no_parent) continue; // a comparator child, not the block
for (0..d.resource_count) |j| {
if (d.resources[j].kind == @intFromEnum(danos.ResourceKind.memory)) return d.id;
if (d.resources[j].kind == @intFromEnum(system.ResourceKind.memory)) return d.id;
}
}
return null;
@@ -1310,7 +1310,7 @@ fn ioPassTest() void {
return;
};
// Map it the way mmio_map does (device grant), then tear the space down.
architecture.mapUserDeviceInto(aspace, process.device_arena_base, frame, danos.page_size);
architecture.mapUserDeviceInto(aspace, process.device_arena_base, frame, system.page_size);
architecture.destroyAddressSpace(aspace);
// The page tables were reclaimed; the device-granted frame must not have been.