12 KiB
ACPI Fixes — P0 Phase Tracker
Numbering note: "P0" refers to the historical hardware-enablement phase (ACPI boot), not the v2.0 desktop plan phases in
local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md.
Status of ACPI fixes for AMD bare metal boot. Cross-referenced with
HARDWARE.md crash reports and kernel/acpid source TODOs.
This file is the historical P0 bring-up ledger. The forward-looking ownership, robustness, and
validation plan now lives in local/docs/ACPI-IMPROVEMENT-PLAN.md.
P0 ACPI boot-baseline work is materially complete for the historical boot goal. It should not be read as release-grade ACPI completeness; ownership cleanup, sleep-state support, and bounded bare-metal validation still remain open. Kernel patch is 574 lines, base/acpid patch is 558 lines.
Where this historical ledger differs from the current source tree, prefer
local/docs/ACPI-IMPROVEMENT-PLAN.md. In particular, do not read older references here to
typed acpid startup hardening as proof that current-tree boot-path hardening is already complete.
Do not use this file as the current boot-wiring authority either: initfs lifecycle, hwd →
acpid ad hoc spawning, explicit RSDP_ADDR forwarding plus x86 BIOS AML fallback, weak legacy
fallback, and provisional /scheme/acpi/power semantics are tracked in
local/docs/ACPI-IMPROVEMENT-PLAN.md.
Crash Reports
| Hardware | Symptom | Root Cause | Status |
|---|---|---|---|
| Framework Laptop 16 (AMD 7040) | Crash on boot | Unimplemented ACPI function (jackpot51/acpi#3) | ✅ Fixed for the historical boot-baseline path (RSDP/SDT checksums, MADT NMI types, FADT parse, related bring-up fixes). acpid startup hardening still remains open in the current tree. |
| Lenovo ThinkCentre M83 | Aml(NoCurrentOp) panic at acpid acpi.rs:256 |
AML interpreter encounters unsupported opcode | Under investigation (upstream AML issue; not resolved by P0 work) |
| HP Compaq nc6120 | Crash after kernel::acpi prints APIC info |
xAPIC APIC ID read returned raw value, caused page fault on Intel | ✅ Fixed (xAPIC id() now shifts read(0x20) >> 24) |
Known Missing ACPI Table Parsers
| Table | Location | Status | Impact |
|---|---|---|---|
| DSDT (Differentiated System Description Table) | Parsed by acpi crate AML interpreter |
Working | Platform-specific device config via AML bytecode |
| SSDT (Secondary System Description Table) | Parsed by acpi crate AML interpreter |
Working | Secondary AML tables (hotplug, etc.) |
| FACP/FADT | ✅ Full parse in acpid | ✅ Done | PM registers, reset register, sleep states, \_S5 |
| IVRS (AMD-Vi IOMMU) | Removed from acpid stub path | Handled by iommu daemon path |
ACPI-side broken stub removed; runtime AMD-Vi handling now lives in the separate daemon |
| MCFG (PCI Express config space) | Removed (broken stub) | ✅ Handled by pcid | pcid /config endpoint provides direct PCI config space access |
| DBG2 (Debug port) | Not implemented | Low | Serial debug port discovery |
| BGRT (Boot graphics) | Not implemented | Low | Boot logo preservation |
| FPDT (Firmware perf data) | Not implemented | Low | Boot performance metrics |
IVRS was previously listed as "implemented" but the acpid stub was broken, so it was removed from
acpid. AMD-Vi runtime handling now lives in the separate iommu daemon path rather than in acpid.
MCFG is now handled by pcid's /config endpoint (P1 complete) which provides direct PCI config space
access.
Implemented ACPI Tables
| Table | Kernel | Userspace (acpid) | Notes |
|---|---|---|---|
| RSDP | acpi/rsdp.rs |
N/A | Signature + checksum validated (ACPI 1.0 + 2.0+ extended) |
| RSDT/XSDT | acpi/rsdt.rs, acpi/xsdt.rs |
N/A | Root table pointer iteration + SDT checksum validation |
| MADT (APIC) | acpi/madt/ |
N/A | xAPIC + x2APIC (type 0x9) + NMI (0x4, 0xA) + address override (0x5) |
| HPET | acpi/hpet.rs |
N/A | Assumes single HPET |
| DMAR (Intel VT-d) | N/A | acpi/dmar/ (present, not wired) |
DMAR parsing code remains in dmar/mod.rs but is not initialized at acpid startup. Ownership is still transitional/orphaned from acpid, not cleanly transferred to a real Intel runtime owner. Iterator bug fixed, re-enabled, safe on AMD (early return) |
| FADT | N/A | acpi.rs |
Full: PM1a/b CNT, reset register, \_S5 sleep types, GenericAddress I/O |
| Power Methods | N/A | acpi.rs |
\_PS0/\_PS3/\_PPC AML evaluation for device power control |
| SPCR | acpi/spcr.rs |
N/A | ARM64 serial console |
| GTDT | acpi/gtdt.rs |
N/A | ARM64 timers |
| Embedded Controller (EC) | N/A | ec.rs |
Byte-wide and widened accesses (u16/u32/u64) via byte-transaction sequences; timeout on each byte |
| AML Mutexes | N/A | aml_physmem.rs |
Real tracked state with handle-based acquire/release; not a placeholder |
Shutdown via kstop |
scheme/acpi.rs registers /scheme/kernel.acpi/kstop |
main.rs opens kstop and subscribes via RawEventQueue |
Kernel-to-userspace shutdown signal; redbear-sessiond listens on kstop for D-Bus PrepareForShutdown |
ACPI MADT Entry Types
All MADT entry types parsed by the kernel. The MADT loop in x86.rs dispatches
each type to the appropriate handler.
| Type | Name | Struct | Size | Kernel Action |
|---|---|---|---|---|
| 0x0 | Processor Local APIC | MadtLocalApic |
8 bytes | AP boot via SIPI |
| 0x1 | I/O APIC | MadtIoApic |
12 bytes | Enumerated |
| 0x2 | Interrupt Source Override | MadtIntSrcOverride |
10 bytes | IRQ remapping |
| 0x4 | Local APIC NMI | MadtLocalApicNmi |
4 bytes | LVT NMI programming (xAPIC 0x350/0x360) |
| 0x5 | LAPIC Address Override | MadtLapicAddressOverride |
10 bytes | Logged (64-bit address) |
| 0x9 | Local x2APIC | MadtLocalX2Apic |
16 bytes | AP boot via x2APIC ICR (MSR) |
| 0xA | Local x2APIC NMI | MadtLocalX2ApicNmi |
10 bytes | x2APIC LVT NMI MSR (0x835/0x836) |
All structs include compile-time size assertions (assert!(size_of::<T>() == N))
to catch ABI mismatches early.
Kernel ACPI TODOs
From recipes/core/kernel/source/src/acpi/:
| File | Line | TODO | Priority |
|---|---|---|---|
mod.rs |
132 | Don't touch ACPI tables in kernel? (move to userspace) | Future |
mod.rs |
147 | Enumerate processors in userspace | Future |
mod.rs |
154 | Let userspace setup HPET | Future |
rsdp.rs |
|||
hpet.rs |
56 | Assumes only one HPET | Low |
spcr.rs |
38,86,100,110 | Optional fields, more interrupt types | ARM64 only |
madt/mod.rs |
134 | Optional field in ACPI 6.5 (trbe_interrupt) | Low |
madt/mod.rs |
— | ||
madt/mod.rs |
— | ||
madt/mod.rs |
— | ||
madt/mod.rs |
— | read(0x20) >> 24) |
|
madt/mod.rs |
— |
ACPID (Userspace) TODOs — UPSTREAM, NOT AMD-FIRST P0/P1
These are pre-existing upstream acpid issues. They are NOT part of the AMD-first P0/P1 scope. They exist in mainline Redox acpid and affect all platforms, not just AMD.
| File | Line | TODO | Priority | Scope | Status |
|---|---|---|---|---|---|
acpi.rs |
266 | Use parsed tables for rest of acpid | Upstream | Mainline acpid improvement | Open |
acpi.rs |
643 | Handle SLP_TYPb for sleep states | Upstream | Mainline power management | Open (known gap) |
aml_physmem.rs |
418,423,428 | Mutex create/acquire/release | Upstream | Mainline AML interpreter | Partially addressed — real tracked state implemented, not placeholder |
ec.rs |
193+ (8 occurrences) | Proper error types | Upstream | Mainline EC handler | Partially addressed — widened accesses implemented via byte transactions |
dmar/mod.rs |
7 | Move DMAR to separate driver | Upstream | Mainline driver refactor | Partially addressed — DMAR module present but not wired into startup; ownership remains transitional/orphaned rather than cleanly moved |
main.rs |
— | Startup panic/expect handling | Local | Boot-path hardening | Open — active current-tree acpid still contains panic/expect startup paths; see Wave 1 in local/docs/ACPI-IMPROVEMENT-PLAN.md |
P0 Fixes Applied
Kernel ACPI (local/patches/kernel/redox.patch — 574 lines)
| # | Fix | Description |
|---|---|---|
| 1 | xAPIC APIC ID fix | id() returns read(0x20) >> 24 for xAPIC mode (was raw, caused Intel page fault) |
| 2 | x2APIC MADT type 0x9 | MadtLocalX2Apic struct + AP boot via ICR with universal startup algorithm |
| 3 | ICR pending wait | Pre/post wrmsr PENDING bit check for x2APIC set_icr() |
| 4 | ICR constants | ICR_INIT_ASSERT (0x4500), ICR_STARTUP (0x4600) with bit-layout comments |
| 5 | MADT entry length guard | entry_len < 2 returns None (prevents infinite loop on malformed tables) |
| 6 | RSDP checksum validation | ACPI 1.0 + 2.0+ extended checksum |
| 7 | SDT checksum validation | validate_checksum() method + warn-only on failure |
| 8 | CPUID arch split | Separate x86/x86_64 cpuid functions |
| 9 | Memory alignment | find_free_near_aligned() with power-of-two assert |
| 10 | Trampoline W+X | Documented limitation (code must be writable + executable during AP init) |
| 11 | MADT type 0x4 (Local APIC NMI) | MadtLocalApicNmi struct (4 bytes), compile-time size assertion |
| 12 | MADT type 0x5 (LAPIC Address Override) | MadtLapicAddressOverride struct (10 bytes), logged |
| 13 | MADT type 0xA (x2APIC NMI) | MadtLocalX2ApicNmi struct (10 bytes), compile-time size assertion |
| 14 | LVT NMI programming | set_lvt_nmi() method for xAPIC (0x350/0x360) and x2APIC (0x835/0x836 MSRs) |
| 15 | NMI processing in x86.rs | LocalApicNmi, LocalX2ApicNmi, LapicAddressOverride handling in MADT loop |
| 16 | AP startup timeout | 100M-iteration bounded waits prevent infinite hang |
| 17 | Second SIPI | Universal Startup Algorithm compliance (Intel spec requires two SIPIs) |
Userspace Acpid (local/patches/base/redox.patch — 558 lines)
| # | Fix | Description |
|---|---|---|
| 1 | DMAR iterator fix | type_bytes renamed to len_bytes bug fix + len < 4 guard |
| 2 | DMAR parser/runtime safety fixes | Iterator/length guards were repaired so the DMAR carrier no longer crashes merely by existing; this does not mean active acpid startup ownership was re-established |
| 3 | DMAR not wired into acpid startup | DMAR module present in dmar/mod.rs but not imported or called from main.rs; this removes active startup ownership from acpid, but does not yet establish a clean Intel runtime owner |
| 4 | FADT shutdown | acpi_shutdown() using PM1a/PM1b CNT_BLK writes with \_S5 sleep types |
| 5 | FADT reboot | acpi_reboot() using ACPI reset register via GenericAddress |
| 6 | Keyboard controller fallback | Pio::<u8>::new(0x64).write(0xFE) when reset_reg unavailable |
| 7 | Power methods | evaluate_acpi_method(), device_power_on() (\_PS0), device_power_off() (\_PS3), device_get_performance() (\_PPC) |
| 8 | GenericAddress rename | GenericAddressStructure renamed to GenericAddress with is_empty(), write_u8() |
| 9 | Reboot wiring | reboot_requested flag in main.rs, scheme path detection |
| 10 | ivrs/mcfg removed | Broken stub references eliminated (deferred to P2+, handled by pcid) |
| 11 | Historical startup-hardening direction | Earlier patch work attempted StartupError-style handling, but active current-tree acpid still requires Wave 1 boot-path hardening; do not treat startup hardening as complete from this ledger alone |
| 12 | AML mutex real state | AmlMutexState with handle-based create/acquire/release; FxHashMap<Handle, bool> tracking; poisoned-state recovery |
| 13 | EC widened accesses | read_bytes/write_bytes implement u16/u32/u64 via per-byte transactions; ensure_access bounds-checks against u8 addressable range |
| 14 | kstop shutdown eventing | main.rs opens /scheme/kernel.acpi/kstop and subscribes via RawEventQueue; redbear-sessiond reads kstop and emits D-Bus PrepareForShutdown signal |