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
+19 -15
View File
@@ -15,12 +15,16 @@
//! -> xkeyboard-config -> character -> key_press
const std = @import("std");
const runtime = @import("runtime");
const device = @import("driver");
const ipc = @import("ipc");
const process = @import("process");
const time = @import("time");
const input = @import("input");
const memory = @import("memory");
const logging = @import("logging");
const xkb = @import("xkeyboard-config");
const ps2 = @import("ps2-library.zig");
const scancode = @import("scancode.zig");
const device = runtime.device;
const ipc = runtime.ipc;
const input_protocol = @import("input-protocol");
/// Look up the ps2-bus service, retrying while the bus (which spawned us before
@@ -29,7 +33,7 @@ fn lookupBus() ?ipc.Handle {
var attempts: usize = 0;
while (attempts < 100) : (attempts += 1) {
if (ipc.lookup(.ps2_bus)) |handle| return handle;
runtime.system.sleep(50);
time.sleepMillis(50);
}
return null;
}
@@ -64,16 +68,16 @@ fn modifierWord(modifiers: scancode.ModifierSnapshot) u32 {
return word;
}
pub fn main(init: runtime.process.Init) void {
pub fn main(init: process.Init) void {
const hid = init.arguments.get(1).?;
if (hid.len == 0) {
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: no HID argument\n");
_ = logging.write("/system/drivers/ps2-bus/keyboard: no HID argument\n");
return;
}
std.log.info("starting for hid {s}", .{hid});
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: out of memory\n");
const buffer = memory.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = logging.write("/system/drivers/ps2-bus/keyboard: out of memory\n");
return;
};
if (device.findDeviceDescriptorByHid(buffer, hid) == null) {
@@ -90,33 +94,33 @@ pub fn main(init: runtime.process.Init) void {
// Attach to the bus: hand it our endpoint, and it forwards every byte the
// keyboard sends (it owns the controller; we own the decoding).
const bus = lookupBus() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: ps2-bus service unavailable\n");
_ = logging.write("/system/drivers/ps2-bus/keyboard: ps2-bus service unavailable\n");
return;
};
const endpoint = ipc.createIpcEndpoint() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: no endpoint\n");
_ = logging.write("/system/drivers/ps2-bus/keyboard: no endpoint\n");
return;
};
var attach = ps2.AttachRequest{ .device_type = @intFromEnum(ps2.DeviceType.keyboard) };
var attach_reply: [@sizeOf(ps2.AttachReply)]u8 = undefined;
const attached = ipc.callCap(bus, std.mem.asBytes(&attach), &attach_reply, endpoint) catch {
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: attach call failed\n");
_ = logging.write("/system/drivers/ps2-bus/keyboard: attach call failed\n");
return;
};
if (attached.len < @sizeOf(ps2.AttachReply) or
std.mem.bytesToValue(ps2.AttachReply, attach_reply[0..@sizeOf(ps2.AttachReply)]).status != @intFromEnum(ps2.AttachStatus.ok))
{
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: attach refused\n");
_ = logging.write("/system/drivers/ps2-bus/keyboard: attach refused\n");
return;
}
// Broadcast keyboard events through the input service so programs can listen
// for them (docs/input.md).
var source = runtime.input.connectSource() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: input service unavailable\n");
var source = input.connectSource() orelse {
_ = logging.write("/system/drivers/ps2-bus/keyboard: input service unavailable\n");
return;
};
_ = runtime.system.write("/system/drivers/ps2-bus/keyboard: ok\n");
_ = logging.write("/system/drivers/ps2-bus/keyboard: ok\n");
var decoder = scancode.Decoder{};
var state = scancode.KeyboardState{};
+19 -15
View File
@@ -15,11 +15,15 @@
//! -> movement -> motion (dx/dy, screen convention)
const std = @import("std");
const runtime = @import("runtime");
const device = @import("driver");
const ipc = @import("ipc");
const process = @import("process");
const time = @import("time");
const input = @import("input");
const memory = @import("memory");
const logging = @import("logging");
const ps2 = @import("ps2-library.zig");
const mouse_packet = @import("mouse-packet.zig");
const device = runtime.device;
const ipc = runtime.ipc;
const input_protocol = @import("input-protocol");
/// Look up the ps2-bus service, retrying while the bus (which spawned us before
@@ -28,7 +32,7 @@ fn lookupBus() ?ipc.Handle {
var attempts: usize = 0;
while (attempts < 100) : (attempts += 1) {
if (ipc.lookup(.ps2_bus)) |handle| return handle;
runtime.system.sleep(50);
time.sleepMillis(50);
}
return null;
}
@@ -42,17 +46,17 @@ fn buttonMask(packet: mouse_packet.Packet) u32 {
return mask;
}
pub fn main(init: runtime.process.Init) void {
pub fn main(init: process.Init) void {
const hid = init.arguments.get(1).?;
if (hid.len == 0) {
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: no HID argument\n");
_ = logging.write("/system/drivers/ps2-bus/mouse: no HID argument\n");
return;
}
std.log.info("starting for hid {s}", .{hid});
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: out of memory\n");
const buffer = memory.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = logging.write("/system/drivers/ps2-bus/mouse: out of memory\n");
return;
};
if (ps2.findMouseDescriptor(buffer) == null) {
@@ -63,33 +67,33 @@ pub fn main(init: runtime.process.Init) void {
// Attach to the bus: hand it our endpoint, and it forwards every byte the
// mouse sends (it owns the controller; we own the decoding).
const bus = lookupBus() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: ps2-bus service unavailable\n");
_ = logging.write("/system/drivers/ps2-bus/mouse: ps2-bus service unavailable\n");
return;
};
const endpoint = ipc.createIpcEndpoint() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: no endpoint\n");
_ = logging.write("/system/drivers/ps2-bus/mouse: no endpoint\n");
return;
};
var attach = ps2.AttachRequest{ .device_type = @intFromEnum(ps2.DeviceType.mouse) };
var attach_reply: [@sizeOf(ps2.AttachReply)]u8 = undefined;
const attached = ipc.callCap(bus, std.mem.asBytes(&attach), &attach_reply, endpoint) catch {
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: attach call failed\n");
_ = logging.write("/system/drivers/ps2-bus/mouse: attach call failed\n");
return;
};
if (attached.len < @sizeOf(ps2.AttachReply) or
std.mem.bytesToValue(ps2.AttachReply, attach_reply[0..@sizeOf(ps2.AttachReply)]).status != @intFromEnum(ps2.AttachStatus.ok))
{
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: attach refused\n");
_ = logging.write("/system/drivers/ps2-bus/mouse: attach refused\n");
return;
}
// Broadcast mouse events through the input service so programs can listen
// for them (docs/input.md).
var source = runtime.input.connectSource() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: input service unavailable\n");
var source = input.connectSource() orelse {
_ = logging.write("/system/drivers/ps2-bus/mouse: input service unavailable\n");
return;
};
_ = runtime.system.write("/system/drivers/ps2-bus/mouse: ok\n");
_ = logging.write("/system/drivers/ps2-bus/mouse: ok\n");
var assembler = mouse_packet.Assembler{};
var buttons: u32 = 0;
+35 -32
View File
@@ -10,11 +10,14 @@
//! MOU_ [acpi_device] hid=PNP0F13 (PS/2 Mouse)
//! - irq 0xc len 0x1
const std = @import("std");
const runtime = @import("runtime");
const device = @import("driver");
const ipc = @import("ipc");
const process = @import("process");
const service = @import("service");
const memory = @import("memory");
const logging = @import("logging");
const acpi_ids = @import("acpi-ids");
const ps2 = @import("ps2-library.zig");
const device = runtime.device;
const ipc = runtime.ipc;
/// Ask the device on `port` what it is, then spawn the matching driver from the
/// initial-ramdisk, handing it the device's HID as argv[1]. The driver is chosen
@@ -31,7 +34,7 @@ fn spawnIdentifiedDriver(controller: ps2.Controller, port: ps2.Port) ?ps2.Device
return null;
};
const hid = device_type.hid() orelse "";
if (runtime.system.spawnWithArguments(driver_name, &.{hid}) != null) {
if (process.spawnWithArguments(driver_name, &.{hid}) != null) {
std.log.info("port {s} is a {s}, spawned {s}", .{ @tagName(port), hid, driver_name });
return device_type;
}
@@ -83,8 +86,8 @@ fn handleAttach(message: []const u8, got: ipc.Received, out: []u8) usize {
}
pub fn main() void {
const buffer = runtime.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = runtime.system.write("/system/drivers/ps2-bus: out of memory\n");
const buffer = memory.allocator().alloc(device.DeviceDescriptor, 64) catch {
_ = logging.write("/system/drivers/ps2-bus: out of memory\n");
return;
};
@@ -96,16 +99,16 @@ pub fn main() void {
// is on which port is decided later by identify, not by this HID.
const maybe_controller_device_descriptor = device.findDeviceDescriptorByHid(buffer, acpi_ids.HardwareId.ps2_keyboard.hid());
if (maybe_controller_device_descriptor) |controller_device_descriptor| {
_ = runtime.system.write("/system/drivers/ps2-bus: found PS/2 controller\n");
_ = runtime.system.write("/system/drivers/ps2-bus: initializing controller\n");
_ = logging.write("/system/drivers/ps2-bus: found PS/2 controller\n");
_ = logging.write("/system/drivers/ps2-bus: initializing controller\n");
if (!device.claim(controller_device_descriptor.id)) {
_ = runtime.system.write("/system/drivers/ps2-bus: unable to claim controller \n");
_ = logging.write("/system/drivers/ps2-bus: unable to claim controller \n");
return;
}
const controller = ps2.Controller.init(controller_device_descriptor) orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: controller is missing its IO ports\n");
_ = logging.write("/system/drivers/ps2-bus: controller is missing its IO ports\n");
return;
};
maybe_controller = controller;
@@ -116,7 +119,7 @@ pub fn main() void {
controller.flushOutputBuffer();
const current = controller.readConfigurationByte() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: controller configuration timed out\n");
_ = logging.write("/system/drivers/ps2-bus: controller configuration timed out\n");
return;
};
@@ -125,49 +128,49 @@ pub fn main() void {
ps2.configuration_first_port_translation);
if (controller.writeConfigurationByte(update) == null) {
_ = runtime.system.write("/system/drivers/ps2-bus: controller configuration timed out\n");
_ = logging.write("/system/drivers/ps2-bus: controller configuration timed out\n");
return;
}
if (controller.performSelfTest()) |reply| {
if (reply != ps2.response_controller_test_passed) {
_ = runtime.system.write("/system/drivers/ps2-bus: perform controller self test failed\n");
_ = logging.write("/system/drivers/ps2-bus: perform controller self test failed\n");
return;
}
} else {
_ = runtime.system.write("/system/drivers/ps2-bus: controller self test timed out\n");
_ = logging.write("/system/drivers/ps2-bus: controller self test timed out\n");
return;
}
has_two_channels = controller.hasTwoChannels() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: controller channels timed out\n");
_ = logging.write("/system/drivers/ps2-bus: controller channels timed out\n");
return;
};
if (has_two_channels) {
_ = runtime.system.write("/system/drivers/ps2-bus: has two channels\n");
_ = logging.write("/system/drivers/ps2-bus: has two channels\n");
// keep the bus quiet until we have tested the ports and are ready to use them
controller.disablePort(.two);
} else {
_ = runtime.system.write("/system/drivers/ps2-bus: has one channel\n");
_ = logging.write("/system/drivers/ps2-bus: has one channel\n");
}
// interface tests: always test port 1, test port 2 only if it exists
const port_one_works = (controller.testPort(.one) orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: port 1 test timed out\n");
_ = logging.write("/system/drivers/ps2-bus: port 1 test timed out\n");
return;
}) == ps2.response_port_test_passed;
var port_two_works = false;
if (has_two_channels) {
port_two_works = (controller.testPort(.two) orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: port 2 test timed out\n");
_ = logging.write("/system/drivers/ps2-bus: port 2 test timed out\n");
return;
}) == ps2.response_port_test_passed;
}
if (!port_one_works and !port_two_works) {
_ = runtime.system.write("/system/drivers/ps2-bus: no usable ports\n");
_ = logging.write("/system/drivers/ps2-bus: no usable ports\n");
return;
}
@@ -181,16 +184,16 @@ pub fn main() void {
// abort bring-up of the other one
if (port_one_works) {
if (controller.resetDevice(.one)) |passed| {
if (!passed) _ = runtime.system.write("/system/drivers/ps2-bus: port 1 device reset failed\n");
if (!passed) _ = logging.write("/system/drivers/ps2-bus: port 1 device reset failed\n");
} else {
_ = runtime.system.write("/system/drivers/ps2-bus: port 1 device reset timed out\n");
_ = logging.write("/system/drivers/ps2-bus: port 1 device reset timed out\n");
}
}
if (port_two_works) {
if (controller.resetDevice(.two)) |passed| {
if (!passed) _ = runtime.system.write("/system/drivers/ps2-bus: port 2 device reset failed\n");
if (!passed) _ = logging.write("/system/drivers/ps2-bus: port 2 device reset failed\n");
} else {
_ = runtime.system.write("/system/drivers/ps2-bus: port 2 device reset timed out\n");
_ = logging.write("/system/drivers/ps2-bus: port 2 device reset timed out\n");
}
}
@@ -200,13 +203,13 @@ pub fn main() void {
if (port_one_works) port_device_types[@intFromEnum(ps2.Port.one)] = spawnIdentifiedDriver(controller, .one);
if (port_two_works) port_device_types[@intFromEnum(ps2.Port.two)] = spawnIdentifiedDriver(controller, .two);
} else {
_ = runtime.system.write("/system/drivers/ps2-bus: no PS/2 controller found\n");
_ = logging.write("/system/drivers/ps2-bus: no PS/2 controller found\n");
return;
}
const controller = maybe_controller.?;
const interrupt_index = maybe_interrupt_index orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: controller is missing its IRQ\n");
_ = logging.write("/system/drivers/ps2-bus: controller is missing its IRQ\n");
return;
};
@@ -214,11 +217,11 @@ pub fn main() void {
// well-known id so the children can find it, the way input subscribers find
// the input service.
const endpoint = ipc.createIpcEndpoint() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: no endpoint\n");
_ = logging.write("/system/drivers/ps2-bus: no endpoint\n");
return;
};
if (!ipc.register(.ps2_bus, endpoint)) {
_ = runtime.system.write("/system/drivers/ps2-bus: register failed\n");
_ = logging.write("/system/drivers/ps2-bus: register failed\n");
return;
}
@@ -227,7 +230,7 @@ pub fn main() void {
// let the controller raise them — an interrupt with nobody bound is lost.
controller.drainOutputBuffer();
if (!device.irqBind(controller.device_id, interrupt_index, endpoint)) {
_ = runtime.system.write("/system/drivers/ps2-bus: irq_bind failed\n");
_ = logging.write("/system/drivers/ps2-bus: irq_bind failed\n");
return;
}
@@ -246,21 +249,21 @@ pub fn main() void {
.gsi = descriptor.resources[auxiliary_index].start,
};
} else {
_ = runtime.system.write("/system/drivers/ps2-bus: auxiliary irq_bind failed\n");
_ = logging.write("/system/drivers/ps2-bus: auxiliary irq_bind failed\n");
}
}
}
}
var configuration = controller.readConfigurationByte() orelse {
_ = runtime.system.write("/system/drivers/ps2-bus: controller configuration timed out\n");
_ = logging.write("/system/drivers/ps2-bus: controller configuration timed out\n");
return;
};
if (port_device_types[@intFromEnum(ps2.Port.one)] != null) configuration |= ps2.Port.one.interruptBit();
if (maybe_auxiliary_interrupt != null) configuration |= ps2.Port.two.interruptBit();
_ = controller.writeConfigurationByte(configuration);
_ = runtime.system.write("/system/drivers/ps2-bus: ok\n");
_ = logging.write("/system/drivers/ps2-bus: ok\n");
// The forwarding loop: an IRQ1 notification drains the output buffer, routing
// each byte to the attached driver of the port it came from; a client message
+7 -7
View File
@@ -1,9 +1,9 @@
//! shared definitions between the different PS/2 drivers
const std = @import("std");
const runtime = @import("runtime");
const device = @import("driver");
const ipc = @import("ipc");
const time = @import("time");
const acpi_ids = @import("acpi-ids");
const device = runtime.device;
const system = runtime.system;
/// PS-2 io ports:
/// The PS/2 Controller itself uses 2 IO ports (usually, IO ports 0x60 and 0x64). Like many IO
@@ -114,16 +114,16 @@ pub const identify_mouse_scroll: u8 = 0x03; // mouse with scroll wheel
pub const identify_mouse_five_button: u8 = 0x04; // 5-button mouse
fn waitReadable(id: u64, cmd_index: u64, wait_timeout_nanoseconds: u64) bool {
const deadline = system.clock() + wait_timeout_nanoseconds;
while (system.clock() < deadline) {
const deadline = time.clock() + wait_timeout_nanoseconds;
while (time.clock() < deadline) {
if (status(id, cmd_index) & status_output_buffer_full != 0) return true; // OBF set -> data ready
}
return false;
}
fn waitWritable(id: u64, cmd_index: u64, wait_timeout_nanoseconds: u64) bool {
const deadline = system.clock() + wait_timeout_nanoseconds;
while (system.clock() < deadline) {
const deadline = time.clock() + wait_timeout_nanoseconds;
while (time.clock() < deadline) {
if (status(id, cmd_index) & status_input_buffer_full == 0) return true; // IBF clear -> ok to write
}
return false; // timed out