Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions issues/two-amdvi-boots-in-a-kvm-suite-wrote-not-one-byte.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
status: open
kind: defect
opened: 2026-10-28
---

# Two amdvi boots in a KVM suite wrote not one byte

A full `cargo test --test toyos-build` at `0eb2c09d0` on a Linux x86_64 KVM
host went red on `amdvi_selftest` and `amdvi_firmware_left`, and on nothing
else. Both boots used `tests/images/testcases.toml`, finished building in the
same second and timed out together after 63 s. Both reported `the console
carried: nothing at all` and `uart: nothing at all`. So the 16550 file was
empty, without even the firmware's screen-clearing escapes that the netcase
boots in
`issues/a-netcase-boot-under-host-load-said-nothing-past-the-firmwares-screen-clears.md`
wrote. Both tests passed in that host's suites at `e4bdb0a5d` and `7745af98d`.
`7745af98d` differs from `0eb2c09d0` only in a host-side wait inside
`the_log_lands_on_the_boot_stick`. That suite ran alone on the host, and its
load during these boots was not recorded. Log:
https://github.com/ToyOSOrg/evidence/tree/d06821d0cb6e754f1fec16a5921bc4378d9ba600/pr-1107/r2

Not reduced: whether QEMU or the firmware ever ran in those boots. A QMP read
of a silent guest's registers would say. No `red-run-serial` file was empty,
so the empty 16550 files were not kept.

**Exit**: a silent boot's registers read, naming where it stopped, and the fix
at that cause. If it is the netcase boots' cause, fold this record into that one.

**Owner**: the orchestrator.
13 changes: 12 additions & 1 deletion tests/toyos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2954,7 +2954,12 @@ fn the_log_lands_on_the_boot_stick(test_config: &Path) -> Result<(), String> {
// power button is pressed, as the metal row's deadline finds it.
writeln!(qemu.stdin_mut(), "run {}", metal::STICK_LOAD_JOB).map_err(|e| e.to_string())?;
qemu.flush_stdin();
qemu::await_marker(&mut qemu, &mut console, "stick_load: line 1500 ", "the load to write the stick")?;
// Any line past the first 1500, not one exact line: logkeeper sheds its
// oldest console lines when the console falls behind the load.
let from = console.len();
qemu::await_guest(&mut qemu, &mut console, "the load to write the stick", |log| {
log[from..].lines().any(|l| stick_load_line(l).is_some_and(|n| n >= 1500))
})?;
qemu::QmpShutdown::open(qemu.qmp_socket(), qemu.budget(qemu::GUEST_QUIET)).power_button();
let by = qemu.budget(Duration::from_secs(60));
console.push_str(&qemu.await_exit(by)?);
Expand All @@ -2981,6 +2986,12 @@ fn the_log_lands_on_the_boot_stick(test_config: &Path) -> Result<(), String> {
usb_stopped_before_the_reset(&log, &console)
}

fn stick_load_line(line: &str) -> Option<u64> {
let (_, rest) = line.split_once("stick_load: line ")?;
let digits = rest.find(|c: char| !c.is_ascii_digit()).unwrap_or(rest.len());
rest[..digits].parse().ok()
}

/// usbd ended for the stop with every connected port's reset finished and its
/// controller halted and reset (its exit code, which the kernel records,
/// because its own line may reach no log), and it ended before the kernel's
Expand Down