pci-bus registers and reports what it scans (M19.2)
Each function is registered under the bridge with the config-space slice and BARs sized by the same all-ones probe the kernel uses — byte-for-byte equal descriptors, so the idempotent register returns the kernel's existing node ids during coexistence instead of duplicating the tree. The bridge gained the 16-bit io_port aperture that functions' I/O BARs need to pass containment. Reports carry the registered device_id, and the pci-scan scenario drills a forced restart: kill the enumerator after its reports, watch the respawn re-scan, and assert the broker's PCI node count never grew. The usb-restart test trigger is pinned to the xHCI reporter (pci-bus racing it to two reports used to steal the kill). Harness hardening: failing cases preserve their serial logs; the heavy scenarios run at 150s.
This commit is contained in:
@@ -108,6 +108,7 @@ var manager_endpoint: runtime.ipc.Handle = 0;
|
||||
var test_restart_mode = false;
|
||||
var test_usb_restart_mode = false;
|
||||
var test_usb_killed = false;
|
||||
var test_pci_restart_mode = false;
|
||||
var test_kill_pid: u32 = 0;
|
||||
var test_kill_due_ns: u64 = 0;
|
||||
|
||||
@@ -400,13 +401,32 @@ fn onChildAdded(message: []const u8, reply: []u8, sender: u32) usize {
|
||||
}
|
||||
const report_reply = protocol.ReportReply{ .status = status };
|
||||
@memcpy(reply[0..@sizeOf(protocol.ReportReply)], std.mem.asBytes(&report_reply));
|
||||
if (test_pci_restart_mode and !test_usb_killed) {
|
||||
if (driverByProcess(sender)) |driver| {
|
||||
if (std.mem.eql(u8, driver.name(), "pci-bus") and childCountOf(sender) >= 3) {
|
||||
// The pci restart drill: kill the enumerator after it has
|
||||
// reported; the respawn must re-register without duplicates
|
||||
// (M19.0 idempotence, proven end to end by pci-scan).
|
||||
test_usb_killed = true;
|
||||
test_kill_pid = sender;
|
||||
test_kill_due_ns = system.clock() + 1_000_000_000;
|
||||
_ = system.timerOnce(manager_endpoint, 1100);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (test_usb_restart_mode and !test_usb_killed and childCountOf(sender) >= 2) {
|
||||
// Delayed, not immediate: the device-list scenario's subscriber needs a
|
||||
// window to enumerate and subscribe before the events start.
|
||||
test_usb_killed = true;
|
||||
test_kill_pid = sender;
|
||||
test_kill_due_ns = system.clock() + 2_000_000_000;
|
||||
_ = system.timerOnce(manager_endpoint, 2100);
|
||||
// Only the xHCI reporter is the drill's victim — pci-bus also reports
|
||||
// now, and whichever finishes second must not trigger the kill.
|
||||
if (driverByProcess(sender)) |driver| {
|
||||
if (std.mem.eql(u8, driver.name(), "usb-xhci-bus")) {
|
||||
// Delayed, not immediate: the device-list scenario's subscriber
|
||||
// needs a window to enumerate and subscribe before the events.
|
||||
test_usb_killed = true;
|
||||
test_kill_pid = sender;
|
||||
test_kill_due_ns = system.clock() + 2_000_000_000;
|
||||
_ = system.timerOnce(manager_endpoint, 2100);
|
||||
}
|
||||
}
|
||||
}
|
||||
return @sizeOf(protocol.ReportReply);
|
||||
}
|
||||
@@ -476,6 +496,7 @@ pub fn main(init: runtime.process.Init) void {
|
||||
if (init.arguments.get(1)) |mode| {
|
||||
test_restart_mode = std.mem.eql(u8, mode, "test-restart");
|
||||
test_usb_restart_mode = std.mem.eql(u8, mode, "test-usb-restart");
|
||||
test_pci_restart_mode = std.mem.eql(u8, mode, "test-pci-restart");
|
||||
}
|
||||
runtime.service.run(protocol.message_maximum, .{
|
||||
.service = .device_manager,
|
||||
|
||||
Reference in New Issue
Block a user