# 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::() == 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` | ~~21~~ | ~~Validate RSDP checksum~~ ✅ Done | ~~P0~~ Done | | `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` | — | ~~NMI entry parsing~~ ✅ Done (types 0x4, 0xA) | ~~P0~~ Done | | `madt/mod.rs` | — | ~~LVT NMI programming~~ ✅ Done (xAPIC + x2APIC) | ~~P0~~ Done | | `madt/mod.rs` | — | ~~LAPIC address override~~ ✅ Done (type 0x5) | ~~P0~~ Done | | `madt/mod.rs` | — | ~~xAPIC APIC ID fix~~ ✅ Done (`read(0x20) >> 24`) | ~~P0~~ Done | | `madt/mod.rs` | — | ~~SDT checksum validation~~ ✅ Done (warn-only) | ~~P0~~ Done | ## 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::::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` 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 |