base: bump gitlink for acpid bounded S5 + reset-reg/8042 reboot (task 7)
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
=== TASK 7: acpid bounded S5 + FADT reset-register reboot + 8042 fallback ===
|
||||
Date: 2026-08-05
|
||||
Plan: .omo/plans/ryzen-7000-x670e-compat.md @ line 173
|
||||
|
||||
=== FILES CHANGED ===
|
||||
|
||||
1. local/sources/base/drivers/acpid/src/acpi.rs
|
||||
- Made GenericAddressStructure fields `pub` (address_space, bit_width,
|
||||
bit_offset, access_size, address) for FADT reset_reg access.
|
||||
- Added associated constants: GAS_SYSTEM_MEMORY(0), GAS_SYSTEM_IO(1),
|
||||
GAS_PCI_CONFIG(2) — ACPI 6.5 Table 5.1 address space IDs.
|
||||
- Added S5 bounded-delay constants: S5_BOUNDED_DELAY_MS=5000,
|
||||
S5_POLL_INTERVAL_MS=100, S5_MAX_ITERATIONS=50.
|
||||
- Replaced infinite spin loop (was acpi.rs:1226-1230) in
|
||||
set_global_s_state(5) with bounded 5-second wait (50 iterations
|
||||
of 100ms sleeps). After expiry, executes the NAMED terminal
|
||||
fallback chain via acpi_reboot_inner().
|
||||
- Non-S5 states (S3 suspend) retain existing spin behavior.
|
||||
- Added fn s5_bounded_wait_and_fallback() — 5s wait + log + fallback.
|
||||
- Added pub fn acpi_reboot() — public API for kstop reason=4 reboot.
|
||||
- Added fn acpi_reboot_inner() — shared logic: FADT reset_reg →
|
||||
8042 pulse → halt.
|
||||
- Added fn try_fadt_reset_reg() — writes reset_value to reset_reg
|
||||
per GAS address_space (System I/O supported; System Memory and
|
||||
PCI Config Space logged as not-yet-implemented, returning false).
|
||||
- Copy packed-struct fields to locals before referencing (fixes
|
||||
E0793 "reference to packed field is unaligned").
|
||||
- Added #[doc(hidden)] test helper functions:
|
||||
* gas_address_space_is_resettable()
|
||||
* gas_address_space_name()
|
||||
- Added module-level pub enum FallbackStage { Pm1Write, FadtResetReg,
|
||||
I8042Pulse, TerminalHalt }.
|
||||
- Added const fn fallback_chain_for_state() — pure function enumerating
|
||||
the ordered fallback stages for S5 vs reboot.
|
||||
- Added free fn i8042_pulse_reset() -> ! — 8042 keyboard-controller
|
||||
reset pulse (write 0xFE to port 0x64 after waiting for input buffer
|
||||
empty). Includes cfg-gated arch support, bounded port polling
|
||||
(up to 10,000 iterations), and terminal halt with `cli; hlt`.
|
||||
- Added #[cfg(test)] mod tests with 16 unit tests covering:
|
||||
GAS classification, fallback chain ordering, bounded-delay parameters,
|
||||
ACPI spec constant values, and fallback stage discriminant uniqueness.
|
||||
|
||||
2. local/sources/base/drivers/acpid/src/main.rs
|
||||
- Added `let mut reboot_requested = false;` before the main event loop.
|
||||
- Added kstop reason=4 dispatch: sets reboot_requested=true, mounted=false.
|
||||
- Post-loop: dispatches to acpi_context.acpi_reboot() when
|
||||
reboot_requested, otherwise acpi_context.set_global_s_state(5).
|
||||
- Existing kstop/shutdown eventing (reason=1→shutdown, reason=2→s2idle
|
||||
wake, reason=3→s3 wake, power-button→mounted=false) is preserved
|
||||
unchanged.
|
||||
|
||||
3. local/sources/base/drivers/acpid/tests/fallback_chain_standalone.rs (NEW)
|
||||
- Standalone host-runnable test harness for the pure decision-logic
|
||||
functions. No Redox syscall dependencies — compiles and runs on
|
||||
the Linux host with `rustc --test`.
|
||||
|
||||
=== FALLBACK CHAIN DESIGN ===
|
||||
|
||||
S5 shutdown (set_global_s_state(5)):
|
||||
1. PM1a/PM1b write (SLP_EN | SLP_TYPa/b) — existing code, unchanged.
|
||||
2. BOUNDED 5-second wait (50 × 100ms sleeps).
|
||||
3. If still alive → log.error("S5 bounded wait expired — executing fallback chain")
|
||||
4. FADT reset_reg/reset_value write (System I/O address space only;
|
||||
System Memory and PCI Config logged as not-yet-implemented).
|
||||
5. If reset_reg absent/fails → 8042 keyboard-controller pulse
|
||||
(write 0xFE to port 0x64 after waiting for input buffer empty).
|
||||
6. If 8042 fails → log.error("ALL RESET MECHANISMS FAILED") + cli; hlt.
|
||||
NEVER an unbounded silent spin.
|
||||
|
||||
Reboot (acpi_reboot(), called from kstop reason=4 or S5 fallback):
|
||||
1. FADT reset_reg/reset_value write.
|
||||
2. 8042 keyboard-controller pulse (0x64/0xFE).
|
||||
3. Terminal halt (cli; hlt).
|
||||
|
||||
Both paths share the same fallback mechanism (acpi_reboot_inner).
|
||||
|
||||
=== LOG LINE FORMATS (distinct, greppable) ===
|
||||
|
||||
S5 attempt:
|
||||
log::warn!("Sleep S5 with ACPI outw(0x{:X}, 0x{:X})", state, port_a, val_a);
|
||||
|
||||
Bounded-wait expiry:
|
||||
log::error!("acpid: S5 bounded wait expired ({} ms) — machine did not power off; executing fallback chain", S5_BOUNDED_DELAY_MS);
|
||||
|
||||
FADT reset_reg attempt:
|
||||
log::warn!("acpid: attempting FADT reset_reg reboot: addr_space={} addr={:#x} value={:#x} bit_width={} bit_offset={}", ...);
|
||||
|
||||
FADT reset_reg unavailable (address zero):
|
||||
log::warn!("acpid: FADT reset_reg address is zero — reset register not available");
|
||||
|
||||
FADT reset_reg unsupported address space:
|
||||
log::error!("acpid: FADT reset_reg is System Memory at {:#x} — MMIO reset not yet implemented", ...);
|
||||
log::error!("acpid: FADT reset_reg is PCI Config Space at {:#x} — PCI config reset not yet implemented", ...);
|
||||
log::error!("acpid: FADT reset_reg has unknown address space {} — cannot reset", ...);
|
||||
|
||||
8042 pulse attempt:
|
||||
log::warn!("acpid: sending 8042 keyboard-controller reset pulse (port 0x64, value 0xFE)");
|
||||
|
||||
8042 transition:
|
||||
log::warn!("acpid: FADT reset_reg did not reboot; trying 8042 keyboard-controller pulse");
|
||||
|
||||
Terminal halt:
|
||||
log::error!("acpid: ALL RESET MECHANISMS FAILED (PM1, FADT reset_reg, 8042) — halting system");
|
||||
|
||||
=== HOST-RUNNABLE UNIT TESTS (16/16 GREEN) ===
|
||||
|
||||
Command:
|
||||
rustc --test local/sources/base/drivers/acpid/tests/fallback_chain_standalone.rs \
|
||||
-o /tmp/acpid-fallback-test && /tmp/acpid-fallback-test
|
||||
|
||||
Output:
|
||||
running 16 tests
|
||||
test reboot_fallback_chain_without_reset_reg ... ok
|
||||
test gas_address_space_unknown_is_not_resettable ... ok
|
||||
test s5_fallback_chain_with_reset_reg ... ok
|
||||
test gas_address_space_pci_config_is_resettable ... ok
|
||||
test gas_constants_match_acpi_spec ... ok
|
||||
test reboot_fallback_chain_with_reset_reg ... ok
|
||||
test s5_bounded_delay_is_exactly_5_seconds ... ok
|
||||
test gas_address_space_system_io_is_resettable ... ok
|
||||
test s5_always_includes_pm1_write_first ... ok
|
||||
test fallback_stages_have_distinct_discriminants ... ok
|
||||
test all_chains_end_with_terminal_halt ... ok
|
||||
test gas_address_space_system_memory_is_resettable ... ok
|
||||
test s5_max_iterations_is_50 ... ok
|
||||
test s5_fallback_chain_without_reset_reg ... ok
|
||||
test s5_iterations_times_interval_equals_delay ... ok
|
||||
test s5_poll_interval_is_100ms ... ok
|
||||
|
||||
test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||
|
||||
Test coverage:
|
||||
- GAS address space classification (System I/O, System Memory, PCI Config, Unknown)
|
||||
- GAS address space naming
|
||||
- S5 fallback chain with reset_reg: [Pm1Write, FadtResetReg, I8042Pulse, TerminalHalt]
|
||||
- S5 fallback chain without reset_reg: [Pm1Write, I8042Pulse, TerminalHalt]
|
||||
- Reboot fallback chain with reset_reg: [FadtResetReg, I8042Pulse, TerminalHalt]
|
||||
- Reboot fallback chain without reset_reg: [I8042Pulse, TerminalHalt]
|
||||
- S5 always starts with Pm1Write
|
||||
- Every chain always terminates in TerminalHalt (no unbounded spin)
|
||||
- Bounded delay = exactly 5 seconds
|
||||
- Poll interval = exactly 100ms
|
||||
- Max iterations = 50 (5000/100)
|
||||
- Iterations × interval = delay (sanity check)
|
||||
- GAS constants match ACPI 6.5 Table 5.1: 0=SysMem, 1=SysIO, 2=PCIConfig
|
||||
- Fallback stage discriminants are all unique
|
||||
|
||||
=== QEMU VERIFICATION COMMANDS ===
|
||||
|
||||
The orchestrator runs these after a canonical build of redbear-mini:
|
||||
|
||||
# 1. Happy: S5 shutdown exits QEMU cleanly
|
||||
./local/scripts/build-redbear.sh redbear-mini
|
||||
qemu-system-x86_64 -cdrom build/x86_64/redbear-mini.iso -m 1024 \
|
||||
-nographic -serial stdio
|
||||
# Inside guest: poweroff
|
||||
# Expected: QEMU exits cleanly (no hang). Serial log shows:
|
||||
# "Sleep S5 with ACPI outw(...)"
|
||||
# (no "S5 bounded wait expired" in normal case)
|
||||
|
||||
# 2. Happy: reboot re-enters firmware boot
|
||||
# Inside guest: (reboot; not yet wired through kernel kstop reason=4;
|
||||
# scheduler may reboot via 8042 directly)
|
||||
# Expected: QEMU resets and re-enters firmware boot
|
||||
|
||||
# 3. Forced-failure QA (QA-only test build, NOT shipped):
|
||||
# Point SLP_TYP at an invalid value so the firmware ignores the PM1
|
||||
# write. Builds a test ISO where the S5 path writes an invalid PM1
|
||||
# value, then:
|
||||
# qemu-system-x86_64 -cdrom build/x86_64/redbear-mini-qa.iso \
|
||||
# -m 1024 -nographic -serial stdio
|
||||
# # Inside guest: poweroff
|
||||
# # Expected serial log:
|
||||
# # "Sleep S5 with ACPI outw(...)"
|
||||
# # (5 second pause)
|
||||
# # "S5 bounded wait expired (5000 ms) — machine did not power off; executing fallback chain"
|
||||
# # "attempting FADT reset_reg reboot: ..."
|
||||
# # (machine resets instead of spinning — QEMU restarts)
|
||||
# # If reset_reg also absent/fails:
|
||||
# # "sending 8042 keyboard-controller reset pulse (port 0x64, value 0xFE)"
|
||||
# # If 8042 also fails:
|
||||
# # "ALL RESET MECHANISMS FAILED (PM1, FADT reset_reg, 8042) — halting system"
|
||||
# # (machine halts, QEMU sits idle — operator sees the error)
|
||||
|
||||
# 4. Verify cargo check is clean (no errors, warnings from our code only)
|
||||
cd local/sources/base && cargo check -p acpid
|
||||
# Expected: zero errors
|
||||
|
||||
# 5. Standalone decision-logic tests (host-runnable)
|
||||
rustc --test local/sources/base/drivers/acpid/tests/fallback_chain_standalone.rs \
|
||||
-o /tmp/acpid-fallback-test && /tmp/acpid-fallback-test
|
||||
# Expected: 16/16 passed
|
||||
|
||||
=== KSTOP REASON CODES (current state) ===
|
||||
|
||||
0 = idle (no event)
|
||||
1 = shutdown (S5) → set_global_s_state(5) with bounded fallback
|
||||
2 = s2idle wake → exit_s2idle() (unchanged)
|
||||
3 = s3 wake → wake_from_sleep_state(3) (unchanged)
|
||||
4 = reboot → acpi_reboot() [NEW — requires kernel kstop_set_reason(4);
|
||||
fallback path: FADT reset_reg → 8042 → halt]
|
||||
|
||||
The kernel side (local/sources/kernel/src/scheme/acpi.rs) defines reason codes
|
||||
0-3; reason=4 (reboot) needs to be added by the kernel agent. Until then,
|
||||
the unknown/reason=4 path falls through to shutdown, preserving existing
|
||||
behavior. When the kernel adds `kstop_set_reason(4)`, the acpid dispatch
|
||||
will immediately route it to `acpi_reboot()`.
|
||||
|
||||
=== DESIGN NOTES ===
|
||||
|
||||
- The \_S5 AML evaluation path, GPE/EC handling, \_PTS/\_SST calls, and
|
||||
PM1a/PM1b write logic are all preserved unchanged. Only the post-write
|
||||
behavior changed.
|
||||
- The kstop/shutdown eventing (power button → mounted=false → S5 shutdown)
|
||||
is preserved unchanged.
|
||||
- No unwrap()/expect() in daemon code — all error paths use log::error!
|
||||
or log::warn!.
|
||||
- The 8042 pulse function is a free function (not &self method) because
|
||||
it is the terminal fallback that does not depend on any ACPI state.
|
||||
- FADT reset_reg System Memory and PCI Config address spaces are logged
|
||||
as not-yet-implemented; only System I/O is functional. The X670E
|
||||
desktop target uses System I/O reset registers (0xCF9 is common).
|
||||
- As required, NO unbounded silent spin remains anywhere in the S5 path.
|
||||
+1
-1
Submodule local/sources/base updated: 7fce9aa585...3da0fe7ac4
Reference in New Issue
Block a user