docs+code: spell out aspace/vaddr/paddr per coding standards

Expand the abbreviations flagged in docs/coding-standards.md (names spelled
out in full unless an acronym) across the kernel, runtime, ABI, tests, and
docs:

  aspace -> address_space  (AspaceRef -> AddressSpaceRef, retainAspace ->
           retainAddressSpace, loaded_aspace -> loaded_address_space, the
           liveAspaceCount/aspaceDestroyCount test hooks, etc.)
  vaddr  -> virtual_address
  paddr  -> physical_address

The kernel test case and its serial markers are renamed to match:
aspace-refcount -> address-space-refcount (kernel dispatch string and
test/qemu_test.py case name kept in sync). Prose in docs uses the natural
"address space"/"virtual address"; backticked field/identifier references
use the code spelling.

Also expand the bare "AS" abbreviation in three ABI comments and reframe the
set_thread_pointer ABI/handler docs to lead with the arch-neutral concept
(user-space TLS thread pointer; x86_64 IA32_FS_BASE, aarch64 TPIDR_EL0)
rather than x86 FS-first, matching scheduler.zig's existing framing.

Foreign ABI names preserved: the ELF p_vaddr field and mmap/mmio remain.

Verified: zig build, zig build test, and the full 25-case QEMU guardrail
suite all green.
This commit is contained in:
2026-07-21 01:45:47 +01:00
parent 6101e429ba
commit 28b3635979
18 changed files with 232 additions and 231 deletions
+42 -42
View File
@@ -139,8 +139,8 @@ pub fn run(case: []const u8, boot_information: *const BootInformation) void {
userPfTest();
} else if (eql(case, "fault-recovery")) {
faultRecoveryTest(boot_information);
} else if (eql(case, "aspace-refcount")) {
aspaceRefcountTest(boot_information);
} else if (eql(case, "address-space-refcount")) {
addressSpaceRefcountTest(boot_information);
} else if (eql(case, "thread-spawn")) {
threadSpawnTest(boot_information);
} else if (eql(case, "thread-join")) {
@@ -920,12 +920,12 @@ fn userMemTest() void {
log("DANOS-TEST-BEGIN: usermem\n", .{});
const base_free = pmm.stats().free_frames;
const aspace = architecture.createAddressSpace() orelse {
const address_space = architecture.createAddressSpace() orelse {
check("created a fresh address space", false);
result();
return;
};
check("created a fresh address space", aspace != 0);
check("created a fresh address space", address_space != 0);
// Grant three pages into the arena, mapped RW + NX (the mmap contract).
const npages = 3;
@@ -934,7 +934,7 @@ fn userMemTest() void {
var mapped: usize = 0;
while (mapped < npages) : (mapped += 1) {
frames[mapped] = pmm.alloc() orelse break;
architecture.mapUserPageInto(aspace, arena + mapped * abi.page_size, frames[mapped], true, false);
architecture.mapUserPageInto(address_space, arena + mapped * abi.page_size, frames[mapped], true, false);
}
check("granted three user pages", mapped == npages);
@@ -943,7 +943,7 @@ fn userMemTest() void {
var rw_ok = true;
for (0..npages) |i| {
const va = arena + i * abi.page_size;
const physical = architecture.translate(aspace, va) orelse {
const physical = architecture.translate(address_space, va) orelse {
translate_ok = false;
continue;
};
@@ -958,13 +958,13 @@ fn userMemTest() void {
// Release them the way munmap does, then tear down the address space.
for (0..npages) |i| {
const va = arena + i * abi.page_size;
if (architecture.translate(aspace, va)) |physical| {
architecture.unmapUserPageInto(aspace, va);
if (architecture.translate(address_space, va)) |physical| {
architecture.unmapUserPageInto(address_space, va);
pmm.free(physical);
}
}
check("munmap unmapped every grant", architecture.translate(aspace, arena) == null);
architecture.destroyAddressSpace(aspace);
check("munmap unmapped every grant", architecture.translate(address_space, arena) == null);
architecture.destroyAddressSpace(address_space);
check("no frames leaked (free count restored)", pmm.stats().free_frames == base_free);
result();
@@ -1132,12 +1132,12 @@ fn dmaTest() void {
// Map the run into a fresh address space as coherent DMA and translate each page
// back: the same physical run, in order — proving contiguity and the mapping.
const aspace = architecture.createAddressSpace().?;
architecture.mapUserDmaInto(aspace, process.dma_arena_base, phys, frames * abi.page_size);
const address_space = architecture.createAddressSpace().?;
architecture.mapUserDmaInto(address_space, process.dma_arena_base, phys, frames * abi.page_size);
var mapped_ok = true;
for (0..frames) |i| {
const va = process.dma_arena_base + i * abi.page_size;
const got = architecture.translate(aspace, va) orelse {
const got = architecture.translate(address_space, va) orelse {
mapped_ok = false;
break;
};
@@ -1147,7 +1147,7 @@ fn dmaTest() void {
// Teardown must reclaim the DMA RAM (the leaves carry no device_grant, so
// freeSubtree frees them as ordinary frames) — a driver that just dies leaks none.
architecture.destroyAddressSpace(aspace);
architecture.destroyAddressSpace(address_space);
for (0..2) |i| pmm.free(low + i * abi.page_size);
check("no frames leaked after DMA teardown", pmm.stats().free_frames == base_free);
result();
@@ -1379,9 +1379,9 @@ fn spawnFaultingProcess() ?u32 {
const flags = sync.enter();
defer sync.leave(flags);
const aspace = architecture.createAddressSpace() orelse return null;
const address_space = architecture.createAddressSpace() orelse return null;
const code_frame = pmm.alloc() orelse {
architecture.destroyAddressSpace(aspace);
architecture.destroyAddressSpace(address_space);
return null;
};
// Fill through the physmap (the user mapping is read-only); pad with int3 so a
@@ -1389,17 +1389,17 @@ fn spawnFaultingProcess() ?u32 {
const code: [*]u8 = @ptrFromInt(boot_handoff.physicalToVirtual(code_frame));
@memset(code[0..abi.page_size], 0xCC);
@memcpy(code[0..blob.len], blob);
architecture.mapUserPageInto(aspace, process.code_virtual, code_frame, false, true); // RO + X
architecture.mapUserPageInto(address_space, process.code_virtual, code_frame, false, true); // RO + X
const stack_frame = pmm.alloc() orelse {
architecture.destroyAddressSpace(aspace); // frees code_frame too — it's mapped
architecture.destroyAddressSpace(address_space); // frees code_frame too — it's mapped
return null;
};
architecture.mapUserPageInto(aspace, process.stack_base_virtual, stack_frame, true, false); // RW + NX
architecture.mapUserPageInto(address_space, process.stack_base_virtual, stack_frame, true, false); // RW + NX
// Supervised by the calling test task, so exitReasonOf can read the verdict.
const id = scheduler.spawnUserLocked(aspace, process.code_virtual, process.stack_base_virtual + abi.page_size, 0, 4, "fault-probe", scheduler.currentId(), null) orelse {
architecture.destroyAddressSpace(aspace);
const id = scheduler.spawnUserLocked(address_space, process.code_virtual, process.stack_base_virtual + abi.page_size, 0, 4, "fault-probe", scheduler.currentId(), null) orelse {
architecture.destroyAddressSpace(address_space);
return null;
};
return id;
@@ -1460,11 +1460,11 @@ fn faultRecoveryTest(boot_information: *const BootInformation) void {
/// address spaces returns to baseline while destructions advance by exactly that many.
/// This is the foundation threads (shared address spaces) build on: the refactor must be
/// invisible while every space still has exactly one task.
fn aspaceRefcountTest(boot_information: *const BootInformation) void {
fn addressSpaceRefcountTest(boot_information: *const BootInformation) void {
_ = boot_information;
log("DANOS-TEST-BEGIN: aspace-refcount\n", .{});
const base_live = scheduler.liveAspaceCount();
const base_destroyed = scheduler.aspaceDestroyCount();
log("DANOS-TEST-BEGIN: address-space-refcount\n", .{});
const base_live = scheduler.liveAddressSpaceCount();
const base_destroyed = scheduler.addressSpaceDestroyCount();
const rounds: u32 = 5;
var killed: u32 = 0;
var round: u32 = 0;
@@ -1480,11 +1480,11 @@ fn aspaceRefcountTest(boot_information: *const BootInformation) void {
if (process.fault_kill_count >= 1) killed += 1;
}
check("all probes spawned and were killed", killed == rounds);
check("live address-space count returned to baseline", scheduler.liveAspaceCount() == base_live);
check("each address space destroyed exactly once", scheduler.aspaceDestroyCount() == base_destroyed + rounds);
if (killed == rounds and scheduler.liveAspaceCount() == base_live and
scheduler.aspaceDestroyCount() == base_destroyed + rounds)
log("aspace-refcount: spaces released to baseline ok\n", .{});
check("live address-space count returned to baseline", scheduler.liveAddressSpaceCount() == base_live);
check("each address space destroyed exactly once", scheduler.addressSpaceDestroyCount() == base_destroyed + rounds);
if (killed == rounds and scheduler.liveAddressSpaceCount() == base_live and
scheduler.addressSpaceDestroyCount() == base_destroyed + rounds)
log("address-space-refcount: spaces released to baseline ok\n", .{});
result();
}
@@ -1509,7 +1509,7 @@ fn threadSpawnTest(boot_information: *const BootInformation) void {
check("thread-test spawned", spawnNamed(rd, "thread-test"));
// Wait for the service's verdict marker (it polls shared memory the worker wrote).
const ok_marker = "thread-test: child ran in shared aspace ok";
const ok_marker = "thread-test: child ran in shared address space ok";
const fail_marker = "thread-test: FAIL";
scheduler.setPriority(1);
const deadline = architecture.millis() + 12000;
@@ -1740,7 +1740,7 @@ fn threadAllocTest(boot_information: *const BootInformation) void {
}
scheduler.setPriority(4);
check("concurrent heap allocation stayed corruption-free (shared heap + per-aspace arena)", bufferHas(ok_marker) and !bufferHas(fail_marker));
check("concurrent heap allocation stayed corruption-free (shared heap + per-address-space arena)", bufferHas(ok_marker) and !bufferHas(fail_marker));
result();
}
@@ -3289,20 +3289,20 @@ fn ioPassTest() void {
log("DANOS-TEST-BEGIN: iopass\n", .{});
const base_free = pmm.stats().free_frames;
const aspace = architecture.createAddressSpace() orelse {
const address_space = architecture.createAddressSpace() orelse {
check("created a fresh address space", false);
result();
return;
};
const frame = pmm.alloc() orelse {
architecture.destroyAddressSpace(aspace);
architecture.destroyAddressSpace(address_space);
check("allocated a frame to grant", false);
result();
return;
};
// Map it the way mmio_map does (device grant, strong-uncacheable), then tear the space down.
architecture.mapUserDeviceInto(aspace, process.device_arena_base, frame, abi.page_size, false);
architecture.destroyAddressSpace(aspace);
architecture.mapUserDeviceInto(address_space, process.device_arena_base, frame, abi.page_size, false);
architecture.destroyAddressSpace(address_space);
// The page tables were reclaimed; the device-granted frame must not have been.
check("device-granted frame survived teardown (not reclaimed as RAM)", pmm.stats().free_frames == base_free - 1);
@@ -3354,26 +3354,26 @@ fn displayTest(boot_information: *const BootInformation) void {
// space, and confirm the leaf's cache type. We never run this space (no CR3 load) —
// we only read back the page-table entries — so aliasing the same physical page at
// two cache types below is inert.
const aspace = architecture.createAddressSpace() orelse {
const address_space = architecture.createAddressSpace() orelse {
check("created a fresh address space", false);
result();
return;
};
defer architecture.destroyAddressSpace(aspace);
defer architecture.destroyAddressSpace(address_space);
const page_base = fb.base & ~@as(u64, abi.page_size - 1);
architecture.mapUserDeviceInto(aspace, process.device_arena_base, page_base, abi.page_size, true);
architecture.mapUserDeviceInto(address_space, process.device_arena_base, page_base, abi.page_size, true);
check(
"the framebuffer maps write-combining (PAT entry 4: PAT bit set, PCD/PWT clear)",
architecture.userLeafIsWriteCombining(aspace, process.device_arena_base) == true,
architecture.userLeafIsWriteCombining(address_space, process.device_arena_base) == true,
);
// Regression guard: the strong-uncacheable default is still that, so WC is a real
// choice the flag makes, not the only behaviour.
architecture.mapUserDeviceInto(aspace, process.device_arena_base + abi.page_size, page_base, abi.page_size, false);
architecture.mapUserDeviceInto(address_space, process.device_arena_base + abi.page_size, page_base, abi.page_size, false);
check(
"a register window still maps strong-uncacheable",
architecture.userLeafIsWriteCombining(aspace, process.device_arena_base + abi.page_size) == false,
architecture.userLeafIsWriteCombining(address_space, process.device_arena_base + abi.page_size) == false,
);
log("display: mapped {d}x{d} pitch {d} (write-combining)\n", .{ fb.width, fb.height, fb.pitch });