C2: migrate consumers off the runtime shim to direct concern-module imports

Every user binary and the two device-logic library modules (pci, usb) now
`@import` the concern modules directly instead of aliasing through `runtime`:

  runtime.ipc/process/time/service/input/block/display  -> @import("<module>")
  runtime.device / runtime.device_manager               -> @import("driver")
  runtime.fs                                             -> @import("file-system")
  runtime.Thread                                         -> @import("thread").Thread
  runtime.system.{write,writeRecord,klog*}              -> logging.*
  runtime.system.{sleep,timerOnce,wallClock,clock}     -> time.*
  runtime.system.{spawn*,kill,exit,yield,processes,...}-> process.*
  runtime.system.{mmap,munmap,PROT_*}                  -> memory.*
  runtime.dma.* / runtime.shared_memory.* / runtime.allocator -> memory.*

Each consumer keeps its own alias name (e.g. `const device = @import("driver")`),
so call sites are unchanged and there are no collisions with local `driver`
variables. build.zig now injects the concern modules into every user binary via
`default_imports`; pci/usb module import lists were updated to match.

The `runtime` and `system` shims remain for one more step (root.zig still uses
runtime); they are deleted in C5. Nothing but root.zig imports `runtime` now.

Verified: zig build, zig build test, and 17 QEMU cases (smoke, device-manager,
logger, fat-mount, fat-mutations, usb-storage, usb-hid, display-native,
virtio-gpu, input, thread-spawn, thread-mutex, process-kill, shared-memory,
driver-restart, acpi-ps2, pci-scan).
This commit is contained in:
Daniel Samson
2026-07-22 23:28:34 +01:00
parent dded46726b
commit 23bcd77c58
37 changed files with 783 additions and 692 deletions
+24 -19
View File
@@ -12,12 +12,17 @@
//! physical address, which the data stage DMAs straight to/from.
const std = @import("std");
const runtime = @import("runtime");
const ipc = @import("ipc");
const process = @import("process");
const service = @import("service");
const time = @import("time");
const device_manager = @import("driver");
const memory = @import("memory");
const logging = @import("logging");
const usb = @import("usb");
const scsi = @import("scsi.zig");
const bot = @import("bulk-only-transport.zig");
const block_protocol = @import("block-protocol");
const dma = runtime.dma;
var device_id: u64 = 0;
var device: usb.Device = undefined;
@@ -26,9 +31,9 @@ var bulk_out: usb.Endpoint = undefined;
// DMA buffers for the transport: the 31-byte CBW, the 13-byte CSW, and a page
// for the small command data (INQUIRY / READ CAPACITY / the self-check sector).
var command_wrapper: dma.Region = undefined;
var status_wrapper: dma.Region = undefined;
var command_data: dma.Region = undefined;
var command_wrapper: memory.DmaRegion = undefined;
var status_wrapper: memory.DmaRegion = undefined;
var command_data: memory.DmaRegion = undefined;
var next_tag: u32 = 1;
var block_size: u32 = 512;
@@ -68,26 +73,26 @@ fn transact(cdb: []const u8, direction_in: bool, data_physical: u64, data_length
/// Device-absent paths stay clean exits: nothing to serve, nothing to retry.
var bring_up_failed = false;
fn initialise(endpoint: runtime.ipc.Handle) bool {
fn initialise(endpoint: ipc.Handle) bool {
_ = endpoint;
if (runtime.device_manager.hello(.device, device_id) == null) return false;
if (device_manager.hello(.device, device_id) == null) return false;
device = usb.open(device_id) orelse {
std.log.info("could not open device {d}", .{device_id});
return false;
};
bulk_in = device.findEndpoint(usb.transfer_type_bulk, true) orelse {
_ = runtime.system.write("/system/drivers/usb-storage: no bulk-IN endpoint\n");
_ = logging.write("/system/drivers/usb-storage: no bulk-IN endpoint\n");
bring_up_failed = true;
return false;
};
bulk_out = device.findEndpoint(usb.transfer_type_bulk, false) orelse {
_ = runtime.system.write("/system/drivers/usb-storage: no bulk-OUT endpoint\n");
_ = logging.write("/system/drivers/usb-storage: no bulk-OUT endpoint\n");
bring_up_failed = true;
return false;
};
command_wrapper = dma.alloc(4096, dma.coherent) orelse return false;
status_wrapper = dma.alloc(4096, dma.coherent) orelse return false;
command_data = dma.alloc(4096, dma.coherent) orelse return false;
command_wrapper = memory.dmaAlloc(4096, memory.dma_coherent) orelse return false;
status_wrapper = memory.dmaAlloc(4096, memory.dma_coherent) orelse return false;
command_data = memory.dmaAlloc(4096, memory.dma_coherent) orelse return false;
// Bring the LUN up: wait for it to be ready (clearing the initial unit-attention
// with REQUEST SENSE), identify it, and read its capacity.
@@ -97,14 +102,14 @@ fn initialise(endpoint: runtime.ipc.Handle) bool {
if (transact(&ready, false, 0, 0)) break;
const sense = scsi.requestSense(18);
_ = transact(&sense, true, command_data.physical, 18);
runtime.system.sleep(50);
time.sleepMillis(50);
}
const inquiry = scsi.inquiry(36);
_ = transact(&inquiry, true, command_data.physical, 36);
const capacity_command = scsi.readCapacity10();
if (!transact(&capacity_command, true, command_data.physical, 8)) {
_ = runtime.system.write("/system/drivers/usb-storage: READ CAPACITY failed\n");
_ = logging.write("/system/drivers/usb-storage: READ CAPACITY failed\n");
bring_up_failed = true;
return false;
}
@@ -128,7 +133,7 @@ fn initialise(endpoint: runtime.ipc.Handle) bool {
/// Serve the block protocol: geometry, and whole-block read/write to/from the
/// caller's DMA buffer (named by physical address).
fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?runtime.ipc.Handle) usize {
fn onMessage(message: []const u8, reply: []u8, sender: u32, capability: ?ipc.Handle) usize {
_ = sender;
_ = capability;
if (message.len < block_protocol.request_size) return 0;
@@ -167,21 +172,21 @@ fn writeReply(reply: []u8, value: block_protocol.Reply) usize {
return bytes.len;
}
pub fn main(init: runtime.process.Init) void {
pub fn main(init: process.Init) void {
const argument = init.arguments.get(1) orelse {
_ = runtime.system.write("/system/drivers/usb-storage: missing device id (argv[1])\n");
_ = logging.write("/system/drivers/usb-storage: missing device id (argv[1])\n");
return;
};
device_id = std.fmt.parseInt(u64, argument, 10) catch {
std.log.info("malformed device id '{s}'", .{argument});
return;
};
runtime.service.run(block_protocol.message_maximum, .{
service.run(block_protocol.message_maximum, .{
.service = .block,
.init = initialise,
.on_message = onMessage,
});
// A failure exit (nonzero -> .aborted) tells the device manager to restart
// us with backoff; a clean return means there was nothing to serve.
if (bring_up_failed) runtime.system.exit(1);
if (bring_up_failed) process.exit(1);
}