Repository navigation
AArch64 stage 5: PSCI resets and powers the machine off, behind one reset and power-off seam - #647
Conversation
Stage 5 of issues/kernel/toyos-runs-on-arm64.md owed SYSTEM_RESET, SYSTEM_OFF and CPU_OFF behind a reset and power-off seam that takes x86-64's reset register and PM1a out of drivers/acpi.rs, and the stop shown on eight CPUs ending in that power-off. Stage 4's remaining items wait on stage 6 (the HVF run), on metal, or on an ABI brief, so this is the first unblocked step whose exit is not met. The seam: kernel/src/power.rs keeps what every reset owes whatever the machine (the console's last drain, the xHCI stop before the register, the reboot refused without a reset); arch::power is the register write. x86-64's is the FADT's reset register and S5 through PM1a, moved as they were, both decoded in one place before the IDT loads; the PM1a decode used to run after gpt::init. Its I/O-port-space checks were dead on x86 and every arch::pio user was that code, so both pio modules go. AArch64's is PSCI (Arm DEN0022): SYSTEM_RESET, which asks no coordination of the other cores (5.12.2), so a wedge may call it; and SYSTEM_OFF, whose caller places every core in a known state first (5.10.1), by the specification's own recipe (5.10.3): an SGI asks every other CPU in the roster to stop its timer and call CPU_OFF, and the caller waits, bounded, for AFFINITY_INFO to answer each off before it calls SYSTEM_OFF. A CPU still on past the budget is named on the UART raw, since the console's last drain is behind the call. The conduit psci::init found is kept in one word, which smp::start and the reset both read. toyos-gicv3 gains the inverse of packed_affinity, which is how PSCI names a CPU. Tests: virt_smp and virt_el1_smp's case now ends with the job `shutdown`, and both judge the power-off: the stop's record names eight CPUs, `Shutting down.` is the last word, QEMU stops for guest-shutdown, and QEMU's own `arm_psci_call` trace (BootOptions::psci_trace) has every CPU but one call CPU_OFF once before the remaining one calls SYSTEM_OFF once, through SMC at EL2 and through HVC at EL1. virt_reboot (tests/virtrebootcase) judges one SYSTEM_RESET and guest-reset. machine_shutdown is x86-64's power-off, which no test judged by QEMU's stop reason before this moved it. toyos-checks' psci_power_off_judge refuses each way a trace falls short. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
|
Orchestrator runs at d1c216d (
|
|
Round 1 at
Net lines: +372 (686 added, 314 deleted).
BLOCKER
NOTE
REMOVE
P1 applies at --- a/kernel/src/actuator.rs
+++ b/kernel/src/actuator.rs
@@ -170 +170,6 @@
power_refused_once = "power-refused-once";
+
+ /// The roster's last two CPUs take the power-off's SGI and halt without
+ /// `CPU_OFF`, so PSCI answers them on for the whole budget. Judged by
+ /// `virt_off_names_the_cpus_left_on`.
+ power_off_spares_the_last_two = "power-off-spares-the-last-two";
--- a/kernel/src/arch/aarch64/power.rs
+++ b/kernel/src/arch/aarch64/power.rs
@@ -61,2 +61,5 @@ pub(super) fn cpu_off() -> ! {
irqchip::stop_timer();
+ if crate::actuator::power_off_spares_the_last_two() && percpu::cpu_id() + 2 >= crate::smp::cpu_count() {
+ cpu::halt()
+ }
if let Some(psci) = psci::conduit() {
--- a/tests/toyos.rs
+++ b/tests/toyos.rs
@@ const SCREEN_TESTS @@
("virt_reboot", Sched::Parallel, qemu::Profile::VirtEl2),
+ ("virt_off_names_the_cpus_left_on", Sched::Parallel, qemu::Profile::VirtEl2),
@@ fn ended_through_psci( @@
reason: &str,
trace: &Path,
+ said_after: impl FnOnce(&[(u64, u64)]) -> Vec<String>,
) -> Result<(String, Vec<(u64, u64)>), String> {
@@
let after: Vec<&str> = lines[at + 1..].iter().copied().filter(|l| !l.trim().is_empty()).collect();
- if !after.is_empty() {
- return Err(format!("{} line(s) after the boot's last word:\n {}", after.len(), after.join("\n ")));
- }
let traced = fs::read_to_string(trace).map_err(|e| format!("read the PSCI trace: {e}"))?;
- Ok((console, psci_calls(&traced)?))
+ let calls = psci_calls(&traced)?;
+ let want = said_after(&calls);
+ if !after.iter().map(|l| l.trim_end()).eq(want.iter().map(String::as_str)) {
+ return Err(format!("{} line(s) after the boot's last word, not {want:?}:\n {}", after.len(), after.join("\n ")));
+ }
+ Ok((console, calls))
}
@@ virt_smp and virt_reboot pass `|_| Vec::new()` as `said_after` @@
@@ fn psci_powered_off @@
-fn psci_powered_off(calls: &[(u64, u64)], cpus: u32) -> Result<u64, String> {
+fn psci_powered_off(calls: &[(u64, u64)], cpus: u32, left_on: &[u64]) -> Result<u64, String> {
@@
- let others: Vec<u64> = (0..u64::from(cpus)).filter(|&cpu| cpu != last).collect();
+ let others: Vec<u64> = (0..u64::from(cpus)).filter(|&cpu| cpu != last && !left_on.contains(&cpu)).collect();
@@ virt_smp and tests/checks.rs pass `&[]` as `left_on` @@
+/// `power-off-spares-the-last-two`: cpu6 and cpu7 halt on the power-off's SGI
+/// without `CPU_OFF`, so `AFFINITY_INFO` answers each on to the end of the
+/// budget. Each of them but the one powering off is named after the last
+/// word, in roster order, and nothing else is; every other CPU is off before
+/// the one `SYSTEM_OFF`.
+fn virt_off_names_the_cpus_left_on(profile: qemu::Profile) -> Result<(), String> {
+ let trace = common::lane::dir().join("virt_off_left_on.psci");
+ let _ = fs::remove_file(&trace);
+ let mut qemu = boot_virt_smp(BootOptions {
+ profile,
+ smp: VIRT_CPUS,
+ qmp: true,
+ kernel_features: ACTUATOR_KERNEL,
+ kernel_params: &["power-off-spares-the-last-two"],
+ psci_trace: Some(trace.clone()),
+ ..Default::default()
+ });
+ let mut stop = qemu::QmpShutdown::open(qemu.qmp_socket(), qemu.budget(qemu::GUEST_QUIET));
+ let serial = judge_virt_job(&mut qemu, "unmap_touch", UNMAP_TOUCH_SAID)?;
+ let spared = |calls: &[(u64, u64)]| -> Vec<u64> {
+ let last = calls.iter().find(|&&(function, _)| function == PSCI_SYSTEM_OFF).map(|&(_, cpu)| cpu);
+ (u64::from(VIRT_CPUS) - 2..u64::from(VIRT_CPUS)).filter(|&cpu| Some(cpu) != last).collect()
+ };
+ let named = |calls: &[(u64, u64)]| -> Vec<String> {
+ spared(calls)
+ .iter()
+ .map(|cpu| format!("power: cpu{cpu} is not off by PSCI's answer inside the budget; SYSTEM_OFF regardless"))
+ .collect()
+ };
+ let (_, calls) = ended_through_psci(&mut qemu, &mut stop, serial, SHUTTING_DOWN, "guest-shutdown", &trace, named)?;
+ let left_on = spared(&calls);
+ let last = psci_powered_off(&calls, VIRT_CPUS, &left_on)?;
+ eprintln!(" [virt] {left_on:?} left on and named; the rest CPU_OFF, then {last:#x} SYSTEM_OFF");
+ Ok(())
+}
@@ fn run_screen_test @@
"virt_reboot" => virt_reboot(profile),
+ "virt_off_names_the_cpus_left_on" => virt_off_names_the_cpus_left_on(profile),SEND BACK |
…d every refusal says its code The review of 647 at d1c216d upheld two BLOCKERs. This commit answers them and fixes the NOTEs. B1: m3, which takes any AFFINITY_INFO answer for OFF, stayed green. In every arm the other CPUs' CPU_OFF reached QEMU before the caller's SYSTEM_OFF, so no arm had a CPU that PSCI still answered ON at the power-off. virt_off_names_the_cpus_left_on is the review's P1 arm. Its actuator, power-off-spares-the-last-two, makes cpu6 and cpu7 halt on SGI_OFF without calling CPU_OFF. The console must then name each of them that is not the powering CPU, after the last word and in roster order, and nothing else. QEMU's trace must show every other CPU calling CPU_OFF before the one SYSTEM_OFF. The review's patch set kernel_features: ACTUATOR_KERNEL beside kernel_params. The harness's kernel_of refuses that pair, since a parameter already selects the test kernel, so the arm sets kernel_params only. The patch also left the new actuator dead on x86-64, whose kernel builds -Dwarnings. The x86 boot-actuators check failed on it with "function `power_off_spares_the_last_two` is never used". Both PSCI actuators now carry #[allow(dead_code)], with the reason at the site. actuator.rs is generic code, so a target_arch cfg may not go there. m3 is reshaped to fit the new match: an ON answer is taken for OFF. B2: the timer stop before CPU_OFF has no arm that can fail, and none is in reach. The gap is issues/kernel/nothing-fails-without-the-timer-stop-before-cpu-off.md. It records the owner and this exit: an AArch64 metal target where SGI_OFF lands on a CPU whose timer is armed. The owner's ruling that no ARM hardware is a target stands against that exit, and the issue says so. Its evidence is the deletion mutation's guest run, which is the orchestrator's. NOTEs: - x86-64: init_reset stays before percpu::init_bsp. init_off moves after it, so a fault in the DSDT checksum or the \_S5_ scan is reported. - AArch64: cpu_off no longer ends SGI_OFF. SGI_HALT is never ended either, so a refused CPU_OFF leaves the CPU halted at the SGI's running priority, with no pending kick to wake it. - Every PSCI refusal on the way out prints its code raw: SYSTEM_RESET or SYSTEM_OFF returning, a refused CPU_OFF, and AFFINITY_INFO refusing, which is now named at once instead of waited out. psci::Error::code undoes Error::of. - can_reset's no-PSCI arm is virt_reboot_refused_without_psci. With the actuator psci-withheld, psci::init keeps no conduit. The job reboot is then refused by name before anything is torn down and ends with exit 1, and the boot never says Rebooting. - The panic arm line promises "unless a key is pressed" only where the architecture's keyboard_controller::PANIC_KEYS says the panic path reads one. The same holds for reboot_now's "no key inside the bound". The held line and Bound::Held say "no reset", which is true on a machine without PSCI. panic_before_peripherals_reboots now refuses the new held text by a named constant. - find_s5_slp_typ moves into toyos-acpi as s5_slp_typ, answering S5. It refuses an \_S5_ value SLP_TYP's three bits cannot hold (S5::Wide). Its host tests are crafted AML in corpus.rs: - ZeroOp, OneOp and a BytePrefix constant; - \_S4_'s package ahead of \_S5_'s; - a two-byte PkgLength; - a wide value and a WordPrefix; - no package, a method named \_S5_, and a package cut by the table's end; - a package past the declared length. No fixture DSDT exists to test against: fixtures/qemu-11.1.1/SOURCE says that boot's DSDT "is not here". Two host mutations are red: PkgLength read as one byte, and the width refusal removed. - x86-64 refuses a PM1a_CNT_BLK past the 16-bit port space by name, and a zero one as no PM1a control block, where the old code narrowed the address to u16. - machine_reboot and machine_shutdown are one function, machine_stops. It takes the command, the decode line, the last word and the stop reason. REMOVEs: the list of PSCI's callers in aarch64 boot.rs, the init_power story in tests/common/power.rs and the clause citing it, and the track's drivers/acpi.rs:325,345 port-I/O citation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016t9wjdQkB8SH7bmfUoiy6L
Twenty-six landings since 08381fb. Seven files conflicted. Three of them are modify/delete in substance: #660 cut the guest suite to the tests only a booted machine answers and deleted what only the cut tests used, and this branch had modified what it deleted. kernel/src/actuator.rs: main's list, which #660 took 68 actuators out of, `power-refused-once` among them, plus this branch's two, `power-off-spares-the-last-two` and `psci-withheld`. kernel/src/arch/aarch64/irqchip.rs: `Intid::Off` follows `Halt`, and `LogNest`, which #660 deleted, is gone. `Storm` follows it unnumbered, and nothing reads its number. kernel/src/panic_reboot.rs: this branch's lines, through #675's `serial::panic_registers()` in place of `serial::panic_raw`. The arm line's three writes share one hold of the registers. kernel/src/syscall/machine.rs: main's deletion of `refused_once`, and this branch's `power::can_reboot()` and its refusal line. kernel/src/arch/aarch64/power.rs did not conflict and did not build: `serial::panic_raw` and `panic_raw_dec` are gone since #675. Each line is now written under one `panic_registers()` hold, as every fatal path on main writes, and the hold is dropped before a halt, because a CPU halted holding the registers costs every later line the whole bound. `reset` takes the registers only to say a refusal; the call itself still takes no lock. tests/common/power.rs: main's file. Every hunk this branch had there landed in code #660 deleted: - `machine_reboot` generalised into `machine_stops`: main cut the QEMU half of `machine_reboot` for its metal row, so the generalisation has one caller left, `machine_shutdown`, and is written as that. - the `init_power` story removed from `died_and_reset`, the `NO_RESET_HELD` refusal in `panic_before_peripherals_reboots`, and `acpi::reboot` renamed in `usb_reset_hands_devices_back`'s prose: all three tests are cut on main, and the track names them. What is added back is `machine_shutdown`, and `ended`, the wait both it and the virt tests make: the last word, QEMU's `SHUTDOWN` reason, then QEMU's exit. `SHUTTING_DOWN` is declared there once. tests/common/qemu.rs: main's file, plus `BootOptions::psci_trace`. Its refusal of a second `-D` log goes: main deleted `nvme_trace`, the only other one. Three things #660 deleted because only cut tests read them come back, because this branch's tests read them: `QmpShutdown` with `shutdown_reason`, `QemuInstance::await_exit` and `QemuInstance::budget`. tests/toyos.rs: main's file, plus this branch's hunks: - the three `virt_` registrations, without `Sched`, which is gone; - `machine_shutdown` in `MACHINE_TESTS`, with why only QEMU can be asked; `machine_reboot`'s QEMU registration and its `machine_stops` arm stay cut; - `judge_virt_job` by reference, `boot_virt_smp` by `BootOptions`, `virt_smp`'s power-off, `ended_through_psci` over `power::ended`, `psci_calls`, `psci_powered_off`, and the three new virt tests; - the `acpi::shutdown()` comment this branch renamed sat in a test main cut. Everything else merged without conflict. Built at this tree: `cargo run -- --build-only` EXIT=0, the same with `--arch aarch64` EXIT=0 and as the test kernel EXIT=0, and `cargo test --test toyos-build --no-run` EXIT=0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
…e crate reads no DSDT `machine_soft_off_decoded` is a metal row on the boot `machine_reboot` already rides: the kernel log off the T14's stick carries the PM1a control block's port and the `SLP_TYPa` its `\_S5_` names, or none of `init_off`'s refusals would have let it. This branch moved that decode after the IDT and into `toyos_acpi::s5_slp_typ`, and added two refusals of firmware values, a PM1a block past the port space and an `\_S5_` value wider than three bits. The T14's values have been through neither. QEMU's `machine_shutdown` judges q35's, and the write: a T14 that powered itself off never answers the metal loop again, so the power-off itself has no row. `toyos-acpi/tests/corpus.rs` still said that nothing in the crate reads what is inside a DSDT and that `find_s5_slp_typ` stays in the kernel, under a test named for two things the crate does not do. `s5_slp_typ` has been the crate's since bb355a4 and five corpus cases cover it. The statement and its half of the test go; both assertions it held are made elsewhere in the file (`hpet_base` answering `Absent` at two sites, a DSDT opening in `s5_of`). The test keeps the half that is true, under its name. The timer-stop issue is `kind: tooling`: it is an instrument that does not exist, and nothing in the kernel is broken. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
|
Guest runs and negative controls at
The host's one-minute load average ran from 12 to 43 across the script; no run was marked
The patches, each as
|
|
|
…et nothing judges The timer-stop issue owed its evidence a run. With the stop deleted from `cpu_off` at 94dea67, `cargo test --test toyos-build -- virt_` exits 0, 19 of 19, so the issue now says what was measured and where the patch and the run are. The review of d1c216d noted that an AArch64 panic now resets after its bound and nothing judges it. bb355a4 made the two lines it named true. The reset itself was never measured: one boot now has, `test-late-panic` on `virt` waited to QEMU's stop, and it ends 60.0 s after the arm line in one SYSTEM_RESET and a `guest-reset`. A standing row costs 60 s of a 45 s suite, the actuator that shortened the bound is gone since #660, and AArch64 has no metal, so the gap is an issue with that measurement as its evidence and the row as its exit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
The review of d1c216d asked for the S5 decode to be host-tested on QEMU's DSDT, and bb355a4 answered that no fixture held one: capturing it takes a boot, which was not an implementer's to run then. It is now. `fixtures/qemu-11.1.1/dsdt.bin` is the 8500 bytes a `Profile::Headless` guest of QEMU 11.1.1 held at 0x7f77a000, read by the monitor's `pmemsave` in a test added by a patch and removed after its run, so no byte came through the decoder. It is not the boot the other eight files came off: that one's firmware put the tables 0x400000 higher. Read beside them, this boot's MADT, HPET, DMAR and WAET are those files byte for byte, and its RSDP, XSDT, FADT and MCFG differ in address bytes and checksums alone, which `SOURCE` now says. `SOURCE` also loses its claim that nothing in the crate decodes a DSDT. `the_dsdt_names_the_sleep_type_that_powers_qemu_off` opens it at its own address and reads `S5::SlpTyp(0)`, the value that boot's kernel logged as `ACPI: PM1a=0x604 SLP_TYPa=0` and `machine_shutdown` powers QEMU off with. `\_S4_`'s package sits 14 bytes ahead of `\_S5_`'s there and names 2, so a scan that took the wrong package answers 2. `src/licence.rs` gains the file's row, as the other eight have one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
|
Two more patches, and the runs at the final head
|
|
T14 evidence at
|
|
Round 2 at Earlier BLOCKERs:
Net lines,
BLOCKER
NOTE
REMOVE
D1 passes diff --git a/kernel/src/arch/aarch64/power.rs b/kernel/src/arch/aarch64/power.rs
index 9bfeb6c..dc0ec82 100644
--- a/kernel/src/arch/aarch64/power.rs
+++ b/kernel/src/arch/aarch64/power.rs
@@ -91,6 +91,10 @@ pub(super) fn cpu_off() -> ! {
let Some(psci) = psci::conduit() else {
unreachable!("power: SGI_OFF is raised only by `off`, which holds a conduit")
};
+ let late = Deadline::at(crate::clock::now() + Duration::from_millis(200));
+ while !late.reached(crate::clock::now()) {
+ core::hint::spin_loop();
+ }
let refusal = psci.cpu_off();
let mut uart = serial::panic_registers();
uart.write(b"power: cpu");SEND BACK |
…illisecond `off` gave every other CPU 100 ms to take `SGI_OFF` and be off by `AFFINITY_INFO`, on a private `Budget` whose number was a choice. A vCPU its host serves late is slow and not dead: #670 moved `time::AP_START` off the same 100 ms on a recorded red. The wait now ends at `time::DEAF_CPU`'s span, the bound the tree already has for a CPU that does not take an interrupt, and declares nothing of its own. Its end stays a degraded answer and no panic: what keeps a CPU on may be firmware's refusal of `CPU_OFF`, and the machine was asked to end. The poll was a bare spin of firmware calls. At 100 ms `virt_off_names_the_cpus_left_on`'s trace was 6199064 bytes, 50812 calls; at five seconds that loop is fifty times it. `AFFINITY_INFO` is now asked again once per `ASK_AGAIN`, a 1 ms `Cadence`, as the xHCI port poll is paced: the same row's trace is 610488 bytes, 5004 calls, and the row says its count. Review of 17e6363, the rest: - `psci::Error::code` wrote `Error::of`'s table a second time for callers that print the number. `cpu_off`, `system_off`, `system_reset` and `affinity_info`'s refusal answer the `i32` the call returned. - `psci::init` runs first in `interrupts`, as x86-64's `init_reset` does, so a panic in the per-CPU block or the GIC's bring-up has a reset. - `virt_fatal_halts_the_others_first` is held to the armed line as a machine with a reset and no panic key says it, `panic: rebooting in 60 s, timed by`, where it took the held line too. The issue that records what stays unheld says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
|
Guest runs and negative controls at
The host's one-minute load average ran from 5 to 29 across them; no run was marked
The trace's size, by a probe that prints it, applied to
A second probe run at The patches, each as
|
|
|
#636 moved the five `virt_` probes out of the shipped toybox into `userland/kernelprobe`, and put two rulings in `reviewer.md`. One conflict, `tests/virtsmpcase/system.toml`, every hunk of both sides kept: - main's: `[programs.toybox]` became `[programs.kernelprobe]`, and `bin/unmap_touch` points at `/system/bin/kernelprobe`. Both taken. - this branch's: the header's second sentence, `shutdown` after `unmap_touch` in the job list, and `bin/shutdown` pointing at `/system/bin/toybox`. All three kept, and `[programs.toybox]` stays beside `[programs.kernelprobe]`, because `shutdown` is a shipped toybox applet and no probe. `tests/toyos.rs` merged without conflict: main's two hunks are a doc line and `virt_timer_preempts`'s arm, neither in a function this branch touches. `tests/virtrebootcase/system.toml` names toybox alone, for `reboot`, and is untouched. `cargo test --test toyos-build -- virt_` on the merged tree before this commit: exit 0, 19 of 19. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
|
The same controls at
The host's one-minute load average ran from 6 to 15 across the script; no run was marked |
|
Round 3 at Earlier BLOCKERs:
Net lines,
BLOCKER None. NOTE
REMOVE
LAND AFTER NAMED CHANGES |
`virt_smp`, `virt_reboot` and `virt_off_names_the_cpus_left_on` each removed their PSCI trace before the boot that writes it, and read no status. The file cannot be there: `lane::dir()` is under the directory `Run::begin` makes new for every process, and each trace name has one row. `the_others_halt_first`'s doc said the fatal CPU holds its panel. The only machine that row boots arms the reset, and a panic that holds is its red. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
No conflict. `src/build.rs` is the one file changed on both sides, in separate hunks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
Two conflicts. bootloader/src/main.rs: main's start_kernel takes no layout and a RootImage that is always there; the branch's side is the rename alone, entry_counter and root_read_ticks, on main's signature, handoff and call. tests/toyos.rs: main's cut of the guest suite (520c0d1) deleted the x86-64 guest test boot_from_power_on, its MACHINE_TESTS entry and comment, its run_machine_test arm and its judge; the guest-suite track owes it a metal row. The branch had changed all four. Hunk by hunk of the branch's side: - the SCREEN_TESTS row virt_boot_from_power_on: kept, in main's two-field shape; - the MACHINE_TESTS comment and the run_machine_test arm passing Arch::X86_64: gone with the test main deleted; - the run_screen_test arm virt_boot_from_power_on: kept; - LOADER_COUNTER, POWER_ON, COUNTER_BACKWARDS, GENERIC_TIMER_HZ and the judge: kept for the virt row, AArch64's alone. TSC_PERIOD, the Arch parameter, the x86-64 period arm and the IA32_TSC_ADJUST tail had the deleted test as their only caller and go with it. A refusal carries the serial it read, as the other virt rows' do. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
#647, #642 and #636's follow-up landed since the last merge. One conflict, in tests/toyos.rs: #647 made `boot_virt_smp` take a `BootOptions` and `judge_virt_job` borrow its guest, and this branch had added `virt_mask_windows` on the old shape. Main's shape is kept whole; `virt_mask_windows` names its kernel build in the options and lends its guest like the others. `tests/virtsmpcase` now ends in `shutdown`, which this test does not wait for: it judges once `unmap_touch` has ended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
No conflict: #647 touches tests/toyos.rs away from this branch's two hunks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
…'s line is main's again The named changes of #649's third review (comment 5960868119). tests/toyos.rs: the merge of dd87383 took a space out of a line of #647's in `virt_smp`. It is main's line again, so the file's diff against main is this branch's alone. The herd's defect: its own report at N = 256 read 1980239, 2 x 5075290 and 4725822 in this head's three T14 boots (comment 5960575031, readbacks 649-r6/), against 1032292, 2 x 519358 and 1175943 at 8b73eba. One reading a size is decided by which boot carried one of the machine's own events, so the exit takes the track's statistic: the median of at least five boots a size, the tail beside it. The roster's syscall counts are said of the fourteen boots they are the range of. The 9 ms defect: its first reading recurred in 2-report-halved inside the herd's own report, all eight CPUs at 2 x 5014552 to 2 x 5075290 with the shootdown line's max=10038us beside it and nmi=1; and cpu7's line of the first report read 11492028, 2 x 1308074 and 8456658, where the stop's kept lines read at most 1396887, 2 x 758960 and 1470910. The exit covers the one-CPU reading before the first job's exit as well. The spawning CPU's defect: cpu7's line of the herd's report read 1980239 in 1-head, 468787 past the 1511452 that boot's `pwd` report reads for an applet's spawn. No byte of an image moves: the three boots at 0aa8d4c stand for this head if its staged kernel is the one 1-head booted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
922 commits of main since 8ee3c51. What main deleted takes the branch's hunks on it with it, and what main changed under the branch is taken as main wrote it. Conflicts, per file: - tests/toyos.rs, tests/common/power.rs, tests/common/faults.rs, tests/common/qemu.rs: main's as written (#660 cut the guest suite to what only a booted machine answers, #625 deleted the tiers). The branch's hunks there had no home: its five `isa_` guest tests and `crash_report_reads_no_kernel_memory` with their helpers (`isa_ports`, `isa_verdict`, `isa_status_byte`, `wait_for_obf`), which stood on the tier tables, `Profile::MetalNoUsb`, `BootOptions::i8042`, `qmp_send_keys`, `logstream::stage` and the `i8042-fault` and `i8042-budget-expired` actuators, all gone; `panic_ignores_keys` and its edits to `panicked()`, `PANIC_REBOOTING` and `await_reset`, whose `panic_reboots` family main cut; and its deletions of `screen_pager_keys`, `screen_paged_scrollback` and `check_no_stale_cells`, which main had already deleted. The commit after this one puts the dropped tests' behaviours on main's tiers. `tests/toyos-rust-tests/src/bin/isa_grant.rs` goes with the harness that gave it its roles, and comes back there. - tests/test-durations: deleted by #639; the branch's two removed rows have no file. - src/sourcegate.rs: `ARCH_RULES` went with #624; the branch's row has no table. - issues/build/assembly-outside-an-arch-module-in-userland-and-guest-probes.md: main rewrote the one line the branch reworded. - kernel/src/sched/driver.rs: `irq_ring`'s `UserDev` arm went with #634, and `isa::drain_pending` with it. The row's handler posts its claim's watch itself (`IrqWatch::post_in_place`), and the first interrupt is announced at the holder's read, both as `pcidev` does on main. - kernel/src/arch/{x86_64,aarch64}/pio.rs: #647 deleted both, their `EXISTS` and `out*` being dead. They come back holding only what the `isa` claim needs of an architecture. - kernel/src/panic_reboot.rs: main's `PANIC_KEYS` goes with the key the panic path no longer reads, and the line it kept for a machine that reads none is the one line now ("the bound is over"); the reset is `power::reset_now` (#647) and the raw writes are under the console's registers (#675). - kernel/src/arch/x86_64/i8042/mod.rs, aarch64/keyboard_controller.rs: main's `poll_byte` and `PANIC_KEYS` go with the pager. - kernel/src/arch/x86_64/idt/mod.rs: `log_nest` went on main. - kernel/src/actuator.rs: main's cut of the i8042's actuators stands. - issues/kernel/the-kernel-is-small-interrupts-post-and-threads-wait.md: main's stage 6 with the branch's stage 7 after it, and main's three "#592's i8042 stage" read "stage 7.2". Stage 7.2 loses its clause about `i8042-trace` and `shell_type_once`, which main deleted. What the merge had to change beside them, to build and to stay true on main: - `kernel/src/device.rs`: `Isa` joins the classes whose `Claimed::Class` drop cancels nothing, a match main added. - The straddle actuator is the i8042 driver's own module (`i8042::straddle`), reached from `isa::claim` through one arch function, and it raises the driver's flood itself at each answered claim: main deleted `i8042-fault`, the flood the branch's test was staged with, and the guest's keys with it. `i8042-withheld` leaves the controller unprobed, where the branch used `i8042-budget-expired`. - `panic-reboot-fast` comes back, which main deleted with the tests that armed it: `screen_fatal_behind_a_painter` proved its CPU watches the reset bound by the pager's second page, and with no pager the reset is the proof. It runs on the profile whose keys reach the i8042 and presses one inside the bound, which is what `panic_ignores_keys` asserted. `Profile::Gop`, which nothing else boots, goes. - `screen_panic_muted` reads the arm line as it is now written. - main's `report_line` and `heartbeat` are gone, so nothing reads the i8042's status port off `IRQ_CPU` and the quarantine's doc says so. - The port grant's pure half is `toyos_userbound::port`: the bitmap as the processor reads it, which rows a switch opens and closes, and the decode of a refused `in` or `out`. A grantable port is a `u8`, so one past the bitmap is no row. `percpu` embeds the bitmap in the TSS and `pio` is what is left of the architecture. - A mint no longer clears the row's record: its release cleared it, and an interrupt taken with no claim on the row is the next holder's to read. - `toyos-tco`'s doc of the panic bound and the guest-suite track's two pager lines named what this branch deletes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm
The first owed item of stage 5 in
issues/kernel/toyos-runs-on-arm64.md:SYSTEM_RESET,SYSTEM_OFFandCPU_OFFbehind one reset and power-off seam, which takes x86-64's reset register and PM1a out ofdrivers/acpi.rs, and the stop shown on eight CPUs ending in that power-off. The stage's other items stay owed, and the track says which.What changed, per decision
The seam (
kernel/src/power.rs, new) holdscan_reboot,reboot,reset_nowandshutdown, which weredrivers::acpi's. It keeps what every end of the machine owes on either architecture: the console's last drain, the xHCI stop before the machine ends (the module's invariant moves with it), and a reboot refused on a machine without a reset.arch::powerdoes the write:can_reset,resetandoff.x86-64 (
arch/x86_64/power.rs, new):toyos_acpi::Tabledirectly, aspsci.rsdoes.init_resetstays beforepercpu::init_bsploads the IDT, so every reportable panic has a reset to write.init_offruns right afterinit_bsp, so a fault in the DSDT checksum or the\_S5_scan is reported. It used to run aftergpt::init.PM1a_CNT_BLKpast the 16-bit port space is refused by name, where it used to be narrowed to a different port. A zero one is "no PM1a control block".arch::pio, whose two port-space refusals were dead on x86-64. Bothpiomodules go, anddrivers::acpi::Table::openwith them.toyos-acpi(src/dsdt.rs, new):s5_slp_typanswersS5. It is the kernel's oldfind_s5_slp_typ, moved besidedsdt_address, and it now refuses a first element wider thanSLP_TYP's three bits (S5::Wide), which shifted into place would setSLP_ENand reserved bits.AArch64 (
arch/aarch64/power.rs, new;psci.rs):resetisSYSTEM_RESET, which asks nothing of the other CPUs (DEN0022 §5.12.2), so the wedge and panic paths may call it. The call takes no lock.offisSYSTEM_OFFby the specification's recipe (§5.10.1, §5.10.3): a new SGI,Off, is raised on every other roster CPU by name, as the kick is; each CPU that takes it stops its timer (§5.5.2) and callsCPU_OFF; the caller asksAFFINITY_INFOof each until it answers OFF, which is PSCI's word and not the kernel's; then it callsSYSTEM_OFF.time::DEAF_CPU's span, five seconds from the SGI: the bound the tree already has for a CPU that does not take an interrupt, and the one The boot CPU waits for an AP's echo as long as a dead CPU is: 5 s, not 100 ms #670 movedtime::AP_STARTto from 100 ms on a recorded red.offdeclares no bound of its own; it had a private 100 msBudget.CPU_OFF, firmware's word never panics this kernel, and the machine was asked to end. The reason is at the site.AFFINITY_INFOis asked again once a millisecond (ASK_AGAIN, aCadence), where it was a bare spin of firmware calls. PSCI has no notification for a CPU going off, so the answer is polled, paced asxhci::PORT_POLLpaces its port reads.SYSTEM_RESETorSYSTEM_OFFthat returns, a refusedCPU_OFF, and anAFFINITY_INFOrefusal, which is named at once and not waited out. The code is thei32the call returned;psci::Errorkeeps one table,of, forCPU_ONandPSCI_VERSION.serial::panic_registers()hold, as every fatal path writes since Fatal paths write the console UART only under its registers, whose lock knows which CPU's fatal path holds it #675, and the hold is dropped before a halt: a CPU halted holding the registers costs every later line the whole bound.SGI_OFFis never ended, asSGI_HALTis not. A refusedCPU_OFFleaves its CPU halted at the SGI's running priority, which a pending kick cannot get past.psci::initkeeps the conduit in oneAtomicU8, whichsmp::start,resetandoffall read.Platformloses its copy. It runs first inboot::interrupts, ahead of the per-CPU block and the GIC as x86-64'sinit_resetis ahead of the APIC and the IDT, so a panic in either's bring-up has a reset; it ran after both.initalready requires:CPU_OFF(0x8400_0002), SMC64AFFINITY_INFO(0xC400_0004),SYSTEM_OFF(0x8400_0008),SYSTEM_RESET(0x8400_0009).power-off-spares-the-last-two(cpu6 and cpu7 halt onSGI_OFFwithoutCPU_OFF) andpsci-withheld(psci::initkeeps no conduit). Both carry#[allow(dead_code)]with the reason at the site: x86-64 builds the accessors and reads neither, and atarget_archcfg may not go into genericactuator.rs.The panic path (
panic_reboot.rs):psci::initnow arms the reboot bound where it used to hold, becausecan_rebootis true there.arch::keyboard_controller::PANIC_KEYSsays the panic path reads a key. On AArch64 it reads none.Bound::Heldsay "no reset", which is true on a machine without PSCI.toyos-gicv3:unpacked_affinity, the inverse ofpacked_affinity, because PSCI names a CPU byMPIDR's fields where they stand.Tests
Guest, and why each is one. No type holds firmware's answer or what a booted kernel says, no host process executes
SMCorHVCor links the kernel's architecture module, and AArch64 has no metal: the track records the owner's ruling that no ARM hardware is a target. Each of the first four rows below judges what a PSCI provider did with a call the kernel made throughSMCorHVCfrom EL1; the rows after them say their own reason.virt_smp(VirtEl2, SMC) andvirt_el1_smp(VirtTcg, HVC), changed:tests/virtsmpcasenow ends with the jobshutdown, and after what they judged before, both judge the power-off. The stop's record names 8 CPUs,Shutting down.is the console's last line, QEMU'sSHUTDOWNreason isguest-shutdownand it exits 0, and QEMU's own trace of every PSCI call shows each of the seven other CPUs callCPU_OFFonce, all before the remaining CPU's oneSYSTEM_OFF, and noSYSTEM_RESET.virt_off_names_the_cpus_left_on(new): underpower-off-spares-the-last-two, each of cpu6 and cpu7 that is not the powering CPU is named after the last word, in roster order, and nothing else is; the trace has every other CPU callCPU_OFFbefore the oneSYSTEM_OFF. It waits the whole ofDEAF_CPU's span by construction, and its line says how many calls QEMU traced. The match onAFFINITY_INFO's answer alone could be lifted into a pure function and host-tested; that test would hold it against a model of PSCI its own author wrote, and would not hold the call's shape (function id,target_affinity, conduit) or the line reaching the UART after the console's last drain. Here QEMU's PSCI answers.virt_reboot(new,tests/virtrebootcase): the jobreboot.Rebooting.is the last line, QEMU stops forguest-reset, and the trace holds oneSYSTEM_RESETand neitherCPU_OFFnorSYSTEM_OFF. The runner's own deadline line is refused, since it reboots too.virt_reboot_refused_without_psci(new): underpsci-withheldthe same job is refused by name, "reboot: this machine has no reset this kernel performs — refused", before anything is torn down, it ends with exit 1, and the boot never saysRebooting.. Its kernel makes no PSCI call afterPSCI_VERSION: what it judges is the syscall's refusal on a kernel that kept no conduit, which is a booted kernel's answer to a process. No metal row can reach it: the actuator and the arm it stages are AArch64's.virt_fatal_halts_the_others_first, changed: the line it waits for past the stop ispanic: rebooting in 60 s, timed by, the arm line as a machine with a reset and no panic key says it, the 60 read fromtoyos_tco::PANIC_BOUND_MS. It took the held line too, so it stayed green on an AArch64 panic that holds or promises a key. The line is a booted AArch64 kernel's, on the one machine that architecture has.virt_failed_ap_leaves_no_holeboots the same case, so its guest now powers off after the job it judges. Its verdicts are unchanged.machine_shutdown(new, x86-64):run shutdownontests/testcases. The boot loggedACPI: PM1a=0x604 SLP_TYPa=0,Shutting down.is said, QEMU stops forguest-shutdownand exits 0, and nothing on the console is a kernel death. The decode is held by host tests (below). The write cannot be a metal row: the metal loop reaches the T14 oversshonce it is back from a reset (src/metal.rs,return_secs), a T14 that powered itself off never answers again, and nothing in the loop turns it on.machine_reboot's QEMU half stays cut, as #660 left it: its metal row holds it. The four tests that wait for a machine to end share one wait,power::ended: the last word, QEMU'sSHUTDOWNreason, then QEMU's exit.No row judges a duration.
virt_smpandvirt_el1_smpare red on a CPU named after the last word, which now takes one PSCI still answers on five seconds after its SGI: the span past which the TLB shootdown calls a CPU deaf and panics.virt_off_names_the_cpus_left_onis red on a line that is not one of the two the actuator arranges.Harness.
BootOptions::psci_trace(-trace arm_psci_call) is refused on anything but TCG's AArch64.QmpShutdown,QemuInstance::await_exitandQemuInstance::budgetcome back: #660 deleted them with the tests that read them, and these tests read them.Metal.
machine_soft_off_decoded(new) rides the bootmachine_rebootalready takes: the kernel log off the T14's stick carriesACPI: PM1a=, which none ofinit_off's refusals lets through.Host.
toyos-acpi/tests/corpus.rs, crafted AML:ZeroOp,OneOpand aBytePrefixconstant;\_S4_'s package ahead of\_S5_'s; a two-bytePkgLength; a wide value and aWordPrefix; no package, a method named_S5_, and a package cut by the table's end; a package past the declared length. The test that stated the crate reads nothing inside a DSDT loses that half and keeps its XSDT half under its own name.toyos-acpi/tests/fixtures.rs,the_dsdt_names_the_sleep_type_that_powers_qemu_off:s5_slp_typover QEMU 11.1.1's own DSDT answersSlpTyp(0).fixtures/qemu-11.1.1/dsdt.binis 8500 bytes read off guest memory by the monitor'spmemsave;SOURCEsays which boot, andsrc/licence.rshas its row.toyos-checks'psci_power_off_judgereads the trace line as QEMU 11.1.1 formats it, with and without the log backend'spid@time:head, and refuses every short trace: a CPU missing, a CPU twice, aCPU_OFFafter theSYSTEM_OFF, the power-off missing or doubled, a reset beside it, the powering CPU among those turned off, a CPU left on that calledCPU_OFF.toyos-gicv3'sunpacking_puts_each_field_back_and_no_flag.Gates
At
190edc726, which isde4e37b96less threelet _ = fs::remove_file(&trace);lines and one comment sentence intests/toyos.rs, on the development host, an Apple-silicon Mac with QEMU 11.1.1 (the twoProfile::Virtrows run under HVF, every othervirt_row under TCG by its profile, every x86-64 guest under TCG),git status --porcelain --ignore-submodules=noneempty before and after:cargo run -- --ci hostHost: 64 step(s), all green;clippy, warnings denied: cleancargo run -- --build-onlycargo run -- --build-only --arch aarch64cargo run -- --build-only --arch aarch64 --kernel-feature boot-actuators --kernel-feature test-actuatorscargo test --test toyos-build -- --listvirt_namescargo test --test toyos-build -- --metal --list50 registration(s) and 218 shared member(s) over 28 boot(s)cargo test --test toyos-build -- virt_19 passed, 19 total (17.1s); one-minute load average 9.8 after it, noINVLcargo test --test toyos-build25 passed, 25 total (22.1s); one-minute load average 14.8 after it, noINVLcargo test --test toyos-build -- --metal --metal-readback <dir> machine_2 passed, 0 failed, 1 boot(s)The four rows that no longer remove their trace before the boot that writes it each read it, in the
virt_run's words:No CI job ran at this head: the pull request is a draft, and
toolchain,hostandguesteach skip a draft.guest / suiteunder KVM, a required check besidehost, has not run this branch.The T14
One boot,
jobcase, at17e636323, run by the orchestrator: #647 (comment).toyos-metalexited 0 (t14-647-jobcase EXIT=0 (73s)in the orchestrator's summary); machine LENOVO 20W0003AMZ, BIOS N34ET71W (1.71).cargo test --test toyos-build -- --metal --metal-readback <dir> machine_over that boot's readback touches no machine and exits 0, at17e636323, atf4f6a453d, atde4e37b96and at190edc726, with the same words:machine_rebootholds the reset register's decode in the kernel log and the loader pass after the reset readingDONE: the T14 reset through the moved register and came back.machine_soft_off_decodedholdsACPI: PM1a=0x1804 SLP_TYPa=7. Seven is the top valueS5::Widelets through, and 0x1804 is inside the port space, so the T14's\_S5_and PM1a block have now been through both refusals. The T14 was not powered off: nothing turns it back on.tests/metal/:git status --porcelainwas empty after each run, and none printed anow recordsline (3 number(s) on LENOVO 20W0003AMZ, BIOS N34ET71W (1.71 ); 0 past its record). Nothing of it belongs in a commit.The x86-64 kernel that booted is still this head's.
git diff --name-only 17e636323 190edc726 -- kernel/ bootloader/ toyos-abi/ toyos/ toyos-acpi/ src/ system.toml:kernel/src/arch/mod.rscompilesarch/aarch64only undertarget_arch = "aarch64", so the x86-64 kernel is built from files unchanged since the boot.f4f6a453dchanged those three files,tests/toyos.rsand one issue file, and190edc726tests/toyos.rsalone. No boot of this head was staged.What did change in the
jobcaseimage came in with the merge and is #636's:userland/toybox, whoserebootapplet is the image's one job, lost its five probe applets touserland/kernelprobe. Neither judged row reads anything toybox says.Negative controls
At
de4e37b96, each applied as a checked patch, the named test run, the patch reversed in the same script, the tree clean after: #647 (comment). None was run again at190edc726. The same patches gave the same exits atf4f6a453d, before the merge; they, that run's words and the trace's measured sizes are #647 (comment), andn0is #647 (comment).d1CPU_OFF200 ms late (the review's)virt_virt_smp,virt_el1_smpandvirt_off_names_the_cpus_left_ongreend1on17e636323(run fromf4f6a453d)virt_m1CPU_OFFnever called on the SGIvirt_smpm2virt_smpm3AFFINITY_INFOanswer of ON taken for OFFvirt_off_names_the_cpus_left_onn0origin/main(kernel/,toyos-gicv3/,toyos-acpi/src; the two actuators stay declared; the same bytes againsta31eec595andb331934c9)virt_off_names_the_cpus_left_onm4offcallsSYSTEM_RESETvirt_smpguest-resetm5resetcallsSYSTEM_OFFvirt_rebootguest-shutdownm7can_resetanswers truevirt_reboot_refused_without_pscip1can_resetanswers false, so its panic holdsvirt_fatal_halts_the_others_firstp2PANIC_KEYSis true, so its panic promises a keyvirt_fatal_halts_the_others_firstc1AFFINITY_INFOasked of an affinity no CPU hasvirt_smppower: cpu1's AFFINITY_INFO answered -2; SYSTEM_OFF regardless, to cpu7'st0cpu_offvirt_94dea677c, which is the tracked issue's evidences2percpu::init_bspandirqchip::initpanic: rebooting in 60 s, timed by the counter frequency the CPU states, then oneSYSTEM_RESETandguest-reset60.0 s laters3psci::initback afterenable_interruptspanic: holding this panelAt earlier heads, over files unchanged since (
git diff --name-only 94dea677c 190edc726names nothing underkernel/src/arch/x86_64ortoyos-acpi/src, and neithertoyos-acpi/tests/corpus.rsnortests/common/power.rs;git diff --name-only 17e636323 190edc726names nothing undertoyos-acpi/); their patches and words are #647 (comment) and #647 (comment):m6(at94dea677c)offwrites no PM1amachine_shutdownh1(at94dea677c)PkgLengthread as one bytetoyos-acpi--test corpusa_two_byte_package_length_is_stepped_overh2(at94dea677c)toyos-acpi--test corpusan_s5_value_wider_than_slp_typ_is_refused_with_ith3(at17e636323)_S4_toyos-acpi--test fixturesSlpTyp(2), notSlpTyp(0)What the longer wait costs, measured by a probe that prints the trace's size; the patch is in the second comment above:
virt_off_left_on.psci17e636323: 100 ms, a bare spinde4e37b96:DEAF_CPU's span, asked each millisecondvirt_smp's trace is 3,172 bytes, 26 calls, on either head;virt_el1_smp's went from 248,880 bytes, 2,040 calls, to 3,050 bytes, 25 calls.Independent oracles
AFFINITY_INFO's answers (§5.7.1), the power-off recipe (§5.10.1, §5.10.3),SYSTEM_RESETasking nothing of other cores (§5.12.2) andCPU_OFF's caller duties (§5.5.2).SHUTDOWNreason, and its exit. It acted on 0x8400_0008 by powering off, on 0x8400_0009 by resetting and on 0x8400_0002 by turning the caller off, and it answered 0xC400_0004 OFF for each CPU that had calledCPU_OFF, ON for the two that had not, and -2 for an affinity no CPU has.s5_slp_typ.The merge of
origin/mainde4e37b96mergesb331934c9(#636), which moved the fivevirt_probes out of the shipped toybox intouserland/kernelprobe. One conflict,tests/virtsmpcase/system.toml:unmap_touchpoints atkernelprobeas main has it,shutdownstays a toybox applet, and the image names both programs. The merge commit's message accounts for every hunk of both sides.f4c04c52cmergeda31eec595. #660 had cut the guest suite and deleted what only the cut tests used, where this branch had modified it; #675 had replacedserial::panic_rawwithpanic_registers(). The merge commit's message accounts for every hunk of both sides in the seven conflicted files, and forarch/aarch64/power.rs, which did not conflict and did not build.Tracked, not fixed
issues/kernel/nothing-fails-without-the-timer-stop-before-cpu-off.md: no arm can fail on the timer stop beforeCPU_OFF, and none is in reach.t0is its evidence.issues/panic-path/nothing-judges-that-an-aarch64-panic-resets-at-its-bound.md: the reset at the end of an AArch64 panic's bound is measured by scouts only (s0in the earlier comment,s2in the table above), and no standing test waits the bound.virt_fatal_halts_the_others_firstholds the arm line.Net lines
git diff --shortstat origin/main...190edc726: 42 files, +1188 −354.kernel/+478 −301, the two pure crates'src/+56. The growth is AArch64's reset, power-off andCPU_OFF, which it did not have, and the seam's own 59 lines; x86-64's half moved.src/: +7.issues/: +89 −6.What I'm unsure of
DEAF_CPUis aTripwire, andofftakes its span without its panic.time::AP_STARTdoes the same and says so by being aBudget;offsays it in a comment and declares nothing. UsingAP_STARTitself would have typed it and misnamed it.ASK_AGAIN's wait being deleted, and that deletion was not run: the bare spin wrote 6 MB at 100 ms, so at this span it would write about fifty times that, which is an extrapolation.virt_off_names_the_cpus_left_onprints its call count and judges none: the bound on it is the span over the period, two kernel constants the harness cannot read.xhci::PORT_POLL's period.virt_off_names_the_cpus_left_oncosts five seconds of every suite run, the span it exists to wait out.jobcasereadback stands for its kernel; its toybox is Nothing ships for tests alone: the five virt probes leave the shipped toybox, and two owner rulings enter reviewer.md #636's.psci::inititself, or before it, still holds its panel:psci::initreads the FADT and calls firmware, and nothing ahead of it has a reset to offer.dsdt.binis not from the boot the other eight fixtures came off. Its boot's firmware put the tables 0x400000 lower. Four of that boot's tables are the committed files byte for byte and four differ in address bytes and checksums alone; the old boot's DSDT was never kept, so that the two DSDTs are equal is unmeasured beyond their length, 8500.machine_shutdowndrives the stdin path'srun shutdownontests/testcases, which nothing else in the guest suite does.Lockheld with interrupts open included. After the SGI the caller takes one lock, the UART's registers, which no CPU holds with interrupts open.PANIC_KEYSis true whether or not an i8042 answers. The poll reads port 0x60 either way.🤖 Generated with Claude Code
https://claude.ai/code/session_013UDZQ6fSKw14e4w2TKTRfm