Files
RedBear-OS/local/docs/LOWLEVEL-INFRASTRUCTURE-REASSESSMENT-AND-PLAN.md
T
vasilito e22ae71cb5 LOWLEVEL plan v1.1: comprehensive Linux 7.1 cross-reference audit
Cross-referenced every stub/gap claim in v1.0 against actual code and
Linux 7.1 reference (local/reference/linux-7.1/). Four parallel audits.

Key corrections to v1.0:
- kernel/src/arch/x86_shared/sleep.rs:257-276 does NOT exist; real PCI
  stubs are in acpid/aml_physmem.rs:375-398 (root cause: pcid never
  sends fd to acpid)
- EHCI is ALREADY implemented (1538+ lines); the stubs are OHCI and UHCI
- aml_physmem.rs:195, :274 line numbers were wrong; actual stubs at
  :213-232 (map_physical_region panic) and :241-280 (read returns 0)
- MSI stub at irq.rs:231 was fixed 2026-06-08 (this audit's first task)

New gaps added (v1.1):
- Gap 11: IOMMU daemon->kernel IRQ integration missing (kernel has
  set_iommu_remapping_active() but daemon never calls it)
- Gap 12: MSI multi-vector not exposed (blocks xhcid, nvmed, ixgbed,
  redox-drm)

Other corrections:
- DMAR init should move to iommu daemon, not acpid
- >255 CPU ID is a panic (u8::try_from().expect()), not deferred
- hwd legacy backend stub is acceptable (graceful no-op fallback)

Added new sections:
- Section 13: Concrete Fix List (v1.1, ready to execute) with exact
  file paths, line numbers, current code, target code, Linux reference
- Section 14: v1.1 Audit Methodology documenting the cross-reference
  approach

All execution plan phases updated with corrected tasks, owners, and
verification gates.
2026-06-08 18:43:22 +03:00

1018 lines
58 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Red Bear OS — Low-Level Infrastructure Reassessment & Updated Plan
**Version**: 1.1 (2026-06-08) — comprehensive code audit against Linux 7.1 reference
**Supersedes**: Fragmentary assessments in `COMPREHENSIVE-SYSTEM-ASSESSMENT-AND-IMPROVEMENT-PLAN.md` §2–§4 for ACPI/IRQ/PCI/driver topics
**Canonical adjacent plans** (remain authoritative for subsystem detail):
- `ACPI-IMPROVEMENT-PLAN.md` — ACPI waves W0W7
- `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` — PCI/IRQ/MSI-X waves W1W6
- `BOOT-PROCESS-HARDWARE-DETECTION-PLAN.md` — Boot detection waves W0W6
- `SMP-SCHEDULER-IMPROVEMENT-PLAN.md` — SMP bottlenecks B1B7
- `local/reference/linux-7.1/` — Linux 7.1 reference source for cross-validation
---
## 1. Executive Summary
This document is a **code-grounded reassessment** of four interdependent low-level subsystems: ACPI/acpid, IRQ/PCI, enumeration/driver binding, and driver infrastructure. It is based on direct source inspection (file paths and line numbers provided throughout), cross-referenced against existing plans.
### Bottom-line verdict
| Subsystem | Verdict | Blocking Bare Metal? |
|-----------|---------|---------------------|
| **ACPI boot** | Boot-baseline complete, not release-grade | Partial — shutdown timing fragile |
| **ACPI shutdown** | S5 derivation works, timing-dependent on PCI | Yes — pre-PCI shutdown degrades weakly |
| **ACPI thermal/fan** | Discovery exists, no runtime backend | No — thermal safety gap |
| **ACPI C-states** | Discovery exists, **no kernel cpuidle** | **Yes** — root cause of heat |
| **IRQ delivery** | Architecturally strong, QEMU-proven only | Partial — no HW validation |
| **MSI/MSI-X** | Code complete, **IOMMU validation stubbed** | **Yes**`iommu_validate_msi_irq()` returns `true` |
| **PCI enumeration** | Userspace-only (correct), pcid complete | No |
| **Driver binding** | Manual class-code matching, no ACPI _HID/_CID | Partial — limited device coverage |
| **redox-driver-sys** | Production quality, zero stubs | No |
| **linux-kpi** | **Verified real** for Wi-Fi: 2770 lines Rust impl, no stubs | No |
| **GPU drivers** | Compile-only, synthetic EDID everywhere | **Yes** — no real display detection |
| **Wi-Fi** | Compile+host-test only, **linux-kpi wireless layer verified real** | Yes — no HW validation; linux-kpi headers/impl sufficient for driver compilation |
| **USB** | xhcid only, no EHCI/UHCI/OHCI | **Yes** — legacy USB keyboards unreachable |
### What changed since last assessment (2026-05-20)
1. **Critical stub discovered**: `iommu_validate_msi_irq()` at `kernel/src/scheme/irq.rs:231` unconditionally returns `true` — this was not flagged as a blocking item in the IRQ enhancement plan (all 6 waves marked "complete").
2. **Critical stub discovered**: `aml_physmem.rs:195` and `:274` fabricate zero values on physical memory access failure — affects all AML runtime evaluation.
3. **Dual AML interpreter architecture** identified as a maintenance risk — kernel `acpi_ext` crate and userspace `acpi` crate parse DSDT/SSDT independently.
4. **APIC timer disabled** (`local_apic.rs:81`) — not flagged in any existing plan as a blocker.
5. **Synthetic EDID used in all GPU drivers** — blocks real display detection on bare metal.
6. **40 total TODOs** in ACPI code (16 kernel + 24 userspace) — higher than previously documented.
7. **linux-kpi wireless layer verified real** (2026-06-08): Comprehensive code audit confirmed all Wi-Fi headers (`cfg80211.h`, `mac80211.h`, `netdevice.h`, `skbuff.h`) are real implementations backed by 2770 lines of Rust code (`wireless.rs` 1002 lines, `mac80211.rs` 959 lines, `net.rs` 809 lines). No TODO/FIXME/STUB markers found in wireless code. The `amdgpu_stubs.h` stub file is GPU-specific and does not affect Wi-Fi.
### What changed in v1.1 (2026-06-08) — Linux 7.1 cross-reference audit
8. **`kernel/src/arch/x86_shared/sleep.rs:257276` does not exist**: The kernel has no `sleep.rs` file. The sleep path is entirely in userspace (`acpid`). The actual PCI config access stubs are in `acpid/src/aml_physmem.rs:375398` (read_pci_u8/u16/u32, write_pci_u8/u16/u32) where `pci_fd` is always `None` because `pcid` never sends its fd to `acpid`. The fix is to wire pcid's fd to acpid via the `RegisterPci` scheme handle, not to modify a non-existent kernel file.
9. **EHCI is already implemented** (2026-06-08): `local/recipes/drivers/ehcid/source/src/main.rs` is 1538+ lines with full EHCI spec implementation (device enumeration, control/bulk/interrupt transfers, DMA, port reset). The plan's "no EHCI driver" gap was inaccurate. The actual stubs are **OHCI** (`ohcid/source/src/main.rs:1634`, ~19 lines) and **UHCI** (`uhcid/source/src/main.rs:1634`, ~19 lines) — both just log BAR reads and enter a sleep loop with no enumeration, no transfers, no port management.
10. **MSI/MSI-X stub FIXED** (2026-06-08): The `iommu_validate_msi_irq()` blind `true` return at `kernel/src/scheme/irq.rs:231` was replaced with proper IOMMU remapping state tracking. Now uses `IOMMU_REMAPPING_ACTIVE: AtomicBool` + public `set_iommu_remapping_active()` API. The kernel trusts the IOMMU hardware (when active) to validate interrupt remapping. The daemon→kernel coordination is not yet wired (Gap 11).
11. **IOMMU daemon→kernel IRQ integration missing** (2026-06-08): The kernel now has `set_iommu_remapping_active()` but the `iommu` daemon never calls it. The MSI validation gate works correctly once the daemon writes to a new `/scheme/irq/remapping` file. Spec: kernel adds `Handle::RemappingControl` + write handler; daemon writes `"1"` after `INIT_UNITS` succeeds and IRTE tables are set up.
12. **MSI multi-vector allocation is a real blocker** (2026-06-08): `pci_allocate_interrupt_vector` in `pcid/src/driver_interface/irq_helpers.rs:307` only allocates single vectors. xhcid (USB 3.0), nvmed (NVMe), ixgbed (10GbE), and redox-drm (GPU) all need multiple vectors. `allocate_aligned_interrupt_vectors` already supports `count` parameter; the fix is to expose it. `multi_message_enable` field in MSI capability is always set to `Some(0)` (single vector).
13. **>255 CPU truncation is a panic** (2026-06-08): `irq_helpers.rs:89` `u8::try_from(cpu_id).expect("usize cpu ids not implemented yet")` panics for CPU IDs > 255. Must be converted to `io::Error` return. The x2APIC path supports 32-bit APIC IDs. Not a blocker for current hardware (AMD Threadripper 128-thread = 128 CPUs) but must be fixed before >256 CPU systems are tested.
14. **DMAR init should move to iommu daemon** (2026-06-08): The 533 lines of Intel VT-d parsing in `acpid/src/acpi/dmar/mod.rs` (`Dmar::init()` at line 55) only log register values without initializing hardware. The `acpi.rs:545` call is commented out. Per microkernel design, DMAR init belongs in the `iommu` daemon, not acpid. Linux 7.1 reference: `drivers/iommu/intel/dmar.c` (intel-iommu init pattern).
15. **APIC timer disabled confirmed** (2026-06-08): `local_apic.rs:81` `//self.setup_timer();``setup_timer()` method does not exist despite the call being commented out. All timer infrastructure (LVT timer, divider config, count registers) is present but unconnected. Re-enabling requires: implement `setup_timer()` (TSC deadline mode for modern CPUs, periodic with divide-by-16 fallback), add PM-timer/TSC-based calibration, wire into init sequence. Safe on QEMU; needs calibration on bare metal.
---
## 2. ACPI / acpid Reassessment
### 2.1 Architecture
The ACPI subsystem has **three operational levels**:
```
Bootloader → KernelArgs.hwdesc_base (RSDP pointer)
Kernel ACPI (src/acpi/ + src/scheme/acpi.rs + src/arch/x86_shared/sleep.rs)
├── RSDP→RSDT/XSDT→SDT enumeration (MADT, SRAT, SLIT, HPET)
├── Export via /scheme/kernel.acpi/{rxsdt, kstop, sleep}
└── Kernel-side AML interpreter (acpi_ext crate) for S3/S5 sleep
Userspace acpid (drivers/acpid/src/)
├── Reads rxsdt, loads SDTs from physical memory
├── Userspace AML interpreter (acpi crate) — SEPARATE from kernel's
├── Exports /scheme/acpi/{dmi, tables, symbols, thermal, fan, cstates}
└── Shutdown via kstop pipe + PM1a/PM1b write
```
### 2.2 What Is Working
| Component | File | Evidence |
|-----------|------|----------|
| RSDP discovery + dual checksum | `acpi/rsdp.rs` | ACPI 1.0 + 2.0+ validation, 62 lines |
| MADT parsing (10 entry types) | `acpi/madt/mod.rs` | Types 0x00xA + aarch64 GICC/GICD, 340 lines |
| x2APIC support | `acpi/madt/mod.rs` | Types 0x9/0xA, `P20P22` patches |
| IOAPIC init from MADT | `device/ioapic.rs` | GSI resolution, source overrides, affinity, 502 lines |
| LAPIC/x2APIC | `device/local_apic.rs` | MSR + MMIO dual path, 312 lines |
| SRAT/SLIT NUMA | `acpi/srat.rs`, `acpi/slit.rs` | Affinity + distance matrix |
| HPET timer | `acpi/hpet.rs` | Init from ACPI tables |
| Kernel scheme export | `scheme/acpi.rs` | rxsdt, kstop, sleep — 398 lines |
| acpid SDT loading | `acpid/src/acpi.rs:162217` | Page-span handling, PhysmapGuard |
| acpid FADT parsing | `acpid/src/acpi.rs:9651122` | ACPI 2.0 extended fields |
| acpid EC handler | `acpid/src/ec.rs` | Full protocol (RD_EC/WR_EC/BE_EC/BD_EC/QR_EC), 317 lines |
| acpid S5 derivation | `acpid/src/acpi.rs:754813` | FADT + AML \__S5, cached |
| acpid DMI | `acpid/src/dmi.rs` | SMBIOS 32/64-bit entry points, 350 lines |
| acpid thermal/fan/cstate discovery | `thermal.rs`, `fan.rs`, `cstate.rs` | AML-backed \__TZ, \__PR namespace |
| hwd ACPI backend | `hwd/backend/acpi.rs` | \__CID/\__HID device discovery, 119 lines |
### 2.3 Critical Stubs
| Location | Line | Issue | Severity |
|----------|------|-------|----------|
| `acpid/src/aml_physmem.rs` | 195 | `read_phys_or_fault()` returns `T::zero()` on failure — **fabricates data** | 🔴 CRITICAL |
| `acpid/src/aml_physmem.rs` | 274 | `map_physical_region()` falls back to **zero page** on failure — writes lost | 🔴 CRITICAL |
| `kernel/src/arch/x86_shared/sleep.rs` | 257276 | `read_pci_u8/u16/u32` always return **0**; `write_pci_*` are no-ops | 🔴 CRITICAL |
| `kernel/src/arch/x86_shared/sleep.rs` | 275 | `nanos_since_boot()` returns **0** — broken AML timing | 🟠 HIGH |
| `kernel/src/arch/x86_shared/sleep.rs` | 294298 | `acquire()`/`release()` for AML mutexes are **no-ops** | 🟠 HIGH |
| `acpid/src/acpi.rs` | 545 | `Dmar::init(&this)` **commented out** — "TODO (hangs on real hardware)" | 🟠 HIGH |
| `hwd/backend/legacy.rs` | 13 | `LegacyBackend::probe()` is a **TODO no-op** | 🟠 HIGH |
| `acpid/src/acpi.rs` | 820822 | `set_global_s_state(state)` returns `Ok` for any state != 5 | 🟡 MEDIUM |
### 2.4 Architectural Risks
1. **Dual AML interpreters**: Kernel `sleep.rs` uses `acpi_ext` crate; userspace `acpid` uses `acpi` crate. They parse the same DSDT/SSDT independently with different handler implementations. Bug fixes in one do not affect the other.
2. **RSDP_ADDR contract**: acpid AML init requires `RSDP_ADDR` environment variable (from `hwd` via `KernelArgs.hwdesc_base`). x86 has BIOS fallback; non-x86 paths are unresolved.
3. **S5 derivation timing**: Depends on AML readiness which depends on PCI registration. Pre-PCI shutdown falls back gracefully but the degraded contract is weak.
4. **DMAR orphaned**: 533 lines of Intel VT-d parsing code exist but are not wired into startup.
### 2.5 TODO Inventory
- **Kernel ACPI**: 16 TODOs (`madt` arch variants, `hpet` x86 assumption, `spcr` type support, `scheme/acpi` context switch, `gtdt`)
- **Userspace acpid**: 24 TODOs (`acpi.rs`: 10, `dmar/`: 9, `main.rs`: 3, `scheme.rs`: 1, `aml_physmem.rs`: 1)
- **Total**: 40 TODOs
### 2.6 Alignment with ACPI-IMPROVEMENT-PLAN.md
| Wave | Plan Status | Code Reality | Delta |
|------|-------------|--------------|-------|
| W0 Contracts | ~80% | Truth statement accurate | — |
| W1 Startup hardening | ~60% | P19 patch removed panic-grade expects; remaining `expect()` in firmware-origin paths | Underdocumented |
| W2 AML ordering/shutdown | ~50% | S5 derivation improved (P24); explicit error types exist; timing still coupled to PCI | Underdocumented |
| W3 Honest power surface | Open | Battery/AC probing exists but not trustworthy; thermal/fan discovery real but no backend action | — |
| W4 Physmem/EC/fault handling | ~40% | **Two critical stubs at lines 195, 274 not flagged in plan** | **New finding** |
| W5 Ownership cleanup | Open | DMAR still orphaned; dual interpreters unresolved | — |
| W6 Consumer integration | ~60% | kstop→sessiond path works | — |
| W7 Validation closure | Open | No bare-metal validation matrix executed | — |
---
## 3. IRQ / PCI Reassessment
### 3.1 Architecture
```
PCI Device → MSI/MSI-X message (address 0xFEE0_0xxx + data)
APIC (local or I/O) → Vector delivery to target CPU
Kernel IDT → generic_irq handler (vec 32255)
scheme/irq.rs → irq_trigger(irq, token)
├── iommu_validate_msi_irq(irq) ← STUB: returns true unconditionally
├── increment COUNTS[irq]
├── walk HANDLES for matching fd
└── trigger EVENT_READ
Userspace driver → IrqHandle::wait() returns with count
```
### 3.2 What Is Working
| Component | File | Evidence |
|-----------|------|----------|
| IDT (256 entries) | `arch/x86_shared/idt.rs` | 224 generic vectors, legacy IRQ bindings, IPI handlers, 374 lines |
| 8259 PIC | `arch/x86_shared/device/pic.rs` | Master/slave init, mask, ack, ISR query, 98 lines |
| I/O APIC | `arch/x86_shared/device/ioapic.rs` | MADT-parsed, GSI resolution, affinity reprogramming, 502 lines |
| LAPIC/x2APIC | `arch/x86_shared/device/local_apic.rs` | MMIO + MSR dual path, IPI, EOI, ESR, 312 lines |
| IRQ dispatch | `arch/x86_shared/interrupt/irq.rs` | PIC/APIC switching, spurious accounting, 352 lines |
| IRQ scheme | `scheme/irq.rs` | Registration, delivery, affinity, per-CPU listing, 650 lines |
| MSI kernel code | `arch/x86_shared/device/msi.rs` | Message composition, validation, capability parsing, 183 lines |
| Vector allocator | `arch/x86_shared/device/vector.rs` | CAS bitmap for 224 vectors, 53 lines |
| redox-driver-sys IRQ | `redox-driver-sys/src/irq.rs` | MSI-X table mapping, vector allocation, affinity, 491 lines, **zero TODOs** |
| redox-driver-sys PCI | `redox-driver-sys/src/pci.rs` | Config space, BAR probing, MSI-X enable, 1446 lines, **zero TODOs** |
| pcid daemon | `drivers/pcid/src/` | Enumeration, scheme:pci, driver spawn, ~1400 lines total |
| driver-manager | `driver-manager/src/main.rs` | PciBus + AcpiBus binding, boot timeline, 553 lines |
### 3.3 Critical Stubs
| Location | Line | Issue | Severity |
|----------|------|-------|----------|
| `kernel/src/scheme/irq.rs` | 231 | `iommu_validate_msi_irq(_irq) -> bool { true }`**zero IOMMU validation** | 🔴 CRITICAL |
| `kernel/src/arch/x86_shared/device/local_apic.rs` | 81 | `//self.setup_timer();`**APIC timer disabled** | 🟠 HIGH |
| `kernel/src/arch/x86_shared/interrupt/irq.rs` | 307 | `println!("Local apic timer interrupt");` — debug artifact | 🟡 MEDIUM |
| `kernel/src/arch/x86_shared/device/ioapic.rs` | 329331 | `.unwrap()` on cpuid — panic risk | 🟡 MEDIUM |
| `drivers/pcid/src/driver_interface/irq_helpers.rs` | — | "FIXME for cpu_id >255 need IOMMU IRQ remapping" | 🟠 HIGH |
| `drivers/pcid/src/driver_interface/irq_helpers.rs` | — | "FIXME allow allocating multiple interrupt vectors" | 🟠 HIGH |
### 3.4 Patch-Backed Code
The following kernel code does **not exist in upstream** — it is entirely Red Bear patches:
- `msi.rs` (+183 lines) — added by `P8-msi.patch` (281 lines, 12 hunks)
- `vector.rs` (+53 lines) — added by `P8-msi.patch`
- IOAPIC affinity — `P9-ioapic-irq-affinity.patch`
- IRQ affinity wiring — `P10-irq-affinity-wiring.patch`
- x2APIC ICR fix — `P20-x2apic-icr-mode-fix.patch`
- x2APIC SMP fix — `P21-x2apic-smp-fix.patch`
- x2APIC MADT fallback — `P22-x2apic-madt-fallback.patch`
**Risk**: If upstream kernel rebases, these patches must be rebased. The MSI/MSI-X subsystem is entirely patch-dependent.
### 3.5 Alignment with IRQ Enhancement Plan
The plan reports all 6 Waves as **✅ Complete**. Code inspection confirms the Waves addressed panic hardening and code quality. However, **6 priority areas remain entirely open** and the plan does not flag:
- `iommu_validate_msi_irq()` stub (CRITICAL — not mentioned)
- APIC timer disabled (not mentioned)
- Single-vector-per-device limit (mentioned as FIXME but not prioritized)
---
## 4. Enumeration / Driver Binding Reassessment
### 4.1 Current Flow
```
pcid enumerates PCI bus → /scheme/pci/{segment}--{bus}--{device}.{function}/
driver-manager (or pcid-spawner legacy) reads /scheme/pci/
For each device: query config space (vendor, device, class, subclass)
Match against driver config (PCI class/vendor/device ID lookup)
Spawn driver daemon with PCID_CLIENT_CHANNEL env var
Driver opens /scheme/pci/{addr}/config and /scheme/irq/{irq}
```
### 4.2 Limitations
1. **No ACPI _HID/_CID matching**: Non-PCI devices (ACPI-enumerated GPIO, I2C, etc.) are not bound through the driver-manager.
2. **No modalias generation**: Drivers are matched by simple class-code or vendor/device ID — no automatic alias generation from PCI class/subclass/prog-if.
3. **LegacyBackend is a stub**: `hwd/backend/legacy.rs:13` — "TODO: handle driver spawning from legacy backend" — any non-ACPI, non-DTB platform gets no hardware discovery.
4. **Initfs transitional**: `hwd` and `acpid` live on initfs boot path, not under stable rootfs service contract.
### 4.3 Alignment with Boot-Process-Hardware-Detection-Plan.md
| Wave | Plan Status | Code Reality |
|------|-------------|--------------|
| W0 Boot stage definitions | ✅ Done | Config-only |
| W1 ACPI bus in driver-manager | ✅ Done | `AcpiBus` exists |
| W2 Resource parser (_CRS, _PRT) | ✅ Done | Parsed |
| W2b ACPI device binding | ✅ Done | Wired |
| W2c GPIO/I2C configs | Partial | Runtime _CRS evaluation **not started** |
| W3 Service rewiring | ✅ Done | Stage targets wired |
| W4 Dead /etc/pcid.d/ removal | ✅ Done | Removed |
| W5 Deferred probing | ✅ Already had | Scheme-aware |
| W6 USB topology enumeration | **Not started** | Depends on xHCI IRQ stability |
---
## 5. Driver Infrastructure Reassessment
### 5.1 redox-driver-sys
**Status: ✅ Production quality, zero stubs, zero TODOs**
- **Schemes**: memory (physical mapping, cache type control), irq (registration, wait, affinity), pci (enumeration, config space, BARs, MSI-X)
- **Quirks**: 3-layer (compiled-in 11 entries + TOML runtime + DMI/SMBIOS 8 rules), 22 PCI flags, 21 USB flags
- **MSI-X**: Full `MsixTable` with validated x86 message programming, vector allocation, CPU round-robin
- **DMA**: `DmaBuffer` (phys-contiguous), `IommuDmaAllocator` (MAP/UNMAP protocol)
- **Tests**: 30+ unit tests in `pci.rs`
### 5.2 linux-kpi
**Status: ✅ Structurally complete for GPU + Wi-Fi, 119 tests passing, zero stubs**
- **17 Rust modules**, **32 C headers**
- **Full implementations**: pci (777 lines), net (809), wireless (1002), mac80211 (959), irq (228), firmware (277), drm_shim (374)
- **No `todo!()`/`unimplemented!()`** in any audited module
- **C header coverage**: pci.h, skbuff.h, interrupt.h, firmware.h, netdevice.h, ieee80211.h, nl80211.h, cfg80211.h, mac80211.h, drm*.h, atomic.h, spinlock.h, mutex.h, workqueue.h, timer.h, wait.h, list.h, slab.h, mm.h, io.h, types.h, errno.h, compiler.h, export.h, printk.h, module.h, refcount.h, jiffies.h, kernel.h, idr.h, bug.h
### 5.3 firmware-loader
**Status: ✅ Production quality**
- `scheme:firmware` daemon with `SchemeSync` impl
- MANIFEST generation (BLAKE3), `--probe`, `--request-nowait`
- Path traversal prevention, 64MB blob cap, cache with source signature validation
- AMD GPU: 17 firmware keys expected; Intel: per-generation DMC firmware
### 5.4 GPU Drivers
| Driver | Status | Key Gap |
|--------|--------|---------|
| redox-drm (AMD) | 🟡 Compiles, 616 lines | `synthetic_edid()` fallback — no real DDC/I²C |
| redox-drm (Intel) | 🟡 Compiles, 693 lines | `synthetic_edid()` fallback — no real DDC/I²C |
| redox-drm (VirtIO) | 🟡 Compiles | `synthetic_edid()` fallback |
| amdgpu (C port) | 🟡 Compiles, ~1487 lines | Hardcoded 4 connector descriptors, no real HPD |
**All three GPU drivers use `synthetic_edid()`** at `redox-drm/src/kms/connector.rs:35` — a hardcoded 128-byte EDID 1.4 block for 1920×1080@60Hz. This blocks real display detection on bare metal.
### 5.5 Wi-Fi
**Status: 🟡 Compiles + host-tested, zero hardware validation**
- `redbear-iwlwifi`: C transport layer (~2450 lines) + Rust daemon (~1550 lines)
- 8 host tests pass
- Commands time out without real firmware — by design
- No Intel Wi-Fi device ever exercised
### 5.6 USB
**Status: 🟡 xhcid builds + QEMU proofs pass, bare-metal incomplete**
- xhcid: Red Bear patched, QEMU IRQ delivery proven
- usbscsid: USB mass storage with inline quirks (214 storage quirks)
- usbhubd: Hub port management
- **Gap**: No EHCI, UHCI, or OHCI drivers — legacy USB keyboards on companion controllers are unreachable on bare metal
---
## 6. Cross-Cutting Critical Gaps (Updated Priority)
### Gap 1 — IOMMU MSI Validation (CRITICAL)
**File**: `kernel/src/scheme/irq.rs:231`
```rust
fn iommu_validate_msi_irq(_irq: u8) -> bool {
true
}
```
Every MSI/MSI-X interrupt bypasses IOMMU remapping validation. This is a security and correctness gap. The hook exists but has zero logic.
**Root cause**: IOMMU daemon (`iommu`) provides AMD-Vi runtime but no Intel VT-d. The validation function needs remapping table data from the IOMMU daemon, or validation must move to userspace via a scheme call.
**Action**: Implement real validation against IOMMU remapping tables, or explicitly document that MSI/MSI-X without IOMMU is only safe on trusted buses.
### Gap 2 — AML Physical Memory Stubs (CRITICAL)
**Files**: `acpid/src/aml_physmem.rs:195`, `:274`
- `read_phys_or_fault()` returns `T::zero()` on failure — fabricates data
- `map_physical_region()` falls back to zero page — silent data loss
**Impact**: Any AML method accessing a physical memory region that fails to map will see fabricated zeroes. This can cause:
- Incorrect battery/thermal readings
- Silent EC communication failures
- Wrong power state transitions
**Action**: Propagate `Result<T>` errors to AML evaluation callers instead of fabricating values.
### Gap 3 — AML PCI Access Stubs in acpid (CRITICAL, corrected v1.1)
**Files**: `acpid/src/aml_physmem.rs:375398` (NOT `kernel/src/arch/x86_shared/sleep.rs:257276` which does not exist)
- `read_pci_u8/u16/u32` and `write_pci_u8/u16/u32` in `AmlPhysMemHandler`
- When `pci_fd` is `None` (always, currently): `read_pci()` logs error, returns untouched `value` array (all zeros from `let mut value = [0u8]`); `write_pci()` silently does nothing
- Root cause: `pcid` never sends its PCI scheme fd to `acpid` via the `RegisterPci` scheme handle (scheme.rs:447480)
**Impact**: Any AML method that accesses PCI config space (OpRegion with `ACPI_ADR_SPACE_PCI_CONFIG`) gets fabricated zero data. S5 shutdown works by accident because `set_global_s_state(5)` writes to PM1a port directly, but `\_PTS`, `\_WAK`, and any PCI-dependent `\_S5` methods get wrong data.
**Action**: Wire pcid's PCI scheme fd to acpid:
1. `pcid` opens `/scheme/acpi/register_pci` and sends its pci scheme fd via `on_sendfd` on startup
2. `acpid` scheme stores the fd in `AmlPhysMemHandler::pci_fd`
3. `aml_eval()` in `acpi.rs:394` passes `self.pci_fd.as_ref()` to `aml_context_mut` instead of `None`
### Gap 4 — APIC Timer Disabled (HIGH)
**File**: `kernel/src/arch/x86_shared/device/local_apic.rs:81`
- `//self.setup_timer();` — the method `setup_timer()` does not exist; all timer infrastructure (LVT timer, divider config, count registers) is present but unconnected
- System uses PIT fallback for all timer interrupts
**Impact**: No per-CPU timer interrupts (all CPUs share PIT on BSP), no TSC deadline mode for modern CPUs, potential timer skew on SMP, root cause of heat on bare metal.
**Action** (per Linux 7.1 `arch/x86/kernel/apic/apic.c:277321`):
1. Implement `setup_timer()` method: TSC deadline mode for modern CPUs (Intel Haswell+, AMD Zen+), periodic with divide-by-16 fallback
2. Add PM-timer or TSC-based calibration (Linux: `lapic_cal_handler`)
3. Wire into `init_ap()` after `setup_error_int()`
4. Calibrate against PIT initially, switch to TSC-deadline or APIC periodic after calibration
### Gap 5 — Synthetic EDID in All GPU Drivers (HIGH)
**File**: `redox-drm/src/kms/connector.rs:3584`
- All three drivers (AMD, Intel, VirtIO) use hardcoded EDID via `synthetic_edid()`
- No real DDC/I²C display detection
**Impact**: Display will not work on bare metal with non-1080p panels, multi-monitor setups, or displays with non-standard timings.
**Action** (per Linux 7.1 `drivers/gpu/drm/drm_edid.c` and `drm_dp_helper.c`):
1. Implement I²C-over-AUX infrastructure in redox-drm for DisplayPort connectors (DDC address 0x50)
2. Replace `synthetic_edid()` with real EDID fetch via AUX CH
3. Keep fallback to standard CEA/CTA modes if AUX CH fails (not a single hardcoded mode)
4. For HDMI/VGA: implement separate DDC I²C bus access paths
### Gap 6 — Dual AML Interpreters (HIGH)
**Files**: `kernel` uses `acpi_ext` crate (kernel-side); `acpid/src/acpi.rs` uses `acpi` crate (userspace)
- Two independent parsers for the same DSDT/SSDT
- Different handler implementations
- Bug fixes in one do not affect the other
**Impact**: Maintenance risk, correctness divergence, two surfaces for AML security issues.
**Action**: Converge on a single canonical interpreter. Recommendation: userspace (acpid) since all drivers are userspace per project model. The kernel `sleep.rs` path was expected but doesn't exist in this codebase — the actual AML eval path is entirely in acpid. Future kernel S3 support should delegate to userspace.
### Gap 7 — No OHCI/UHCI Drivers (HIGH, corrected v1.1)
**Files**:
- `local/recipes/drivers/ohcid/source/src/main.rs:1634` — STUB: reads PCI BAR, enters sleep loop
- `local/recipes/drivers/uhcid/source/src/main.rs:1634` — STUB: reads I/O port BAR, enters sleep loop
- `local/recipes/drivers/ehcid/source/src/main.rs`**ALREADY IMPLEMENTED** (1538+ lines, full EHCI spec) — NOT a gap
**Impact**: Legacy USB keyboards on companion controller paths unreachable on bare metal. Only xHCI-native USB devices work, plus EHCI-native ones.
**Action** (per Linux 7.1 `drivers/usb/host/ohci-hcd.c` and `uhci-hcd.c`):
1. **OHCI first** (MMIO-based, simpler than UHCI): 34 weeks
- HCCA (Host Controller Communications Area) for interrupt transfers
- Control/bulk/isochronous transfer descriptors
- Frame list management (1024 entries)
- Port power and reset control
2. **UHCI second** (I/O port-based, more complex): 34 weeks
- Transfer descriptors (QTD) and queue heads (QH)
- Frame list pointer register in MMIO space
- Port reset and suspend control
### Gap 8 — No C-State Kernel Backend (HIGH)
**Impact**: CPUs run at full frequency constantly on bare metal. Thermal throttling only. Root cause of heat on AMD64.
**Action** (per Linux 7.1 `drivers/idle/intel_idle.c` and `arch/x86/include/asm/mwait.h`):
1. Kernel: add `mwait()`/`mwaitx()` helper functions + C-state hint MSR read/write
2. ACPI: parse `_CST` in acpid, expose C-state info via `scheme:cpuidle`
3. Implement idle loop using MWAIT with sub-state hints (Linux pattern: `intel_idle.c:67107` idle_cpu struct)
4. Optional: `cpuidled` daemon to coordinate C-state selection
### Gap 9 — DMAR Init in Wrong Owner (MEDIUM, corrected v1.1)
**Files**:
- `acpid/src/acpi/dmar/mod.rs:7` — TODO comment: "Move this code to a separate driver as well?"
- `acpid/src/acpi/dmar/mod.rs:5590``Dmar::init()` only logs register values, never initializes hardware
- `acpid/src/acpi.rs:545``Dmar::init(&this)` call commented out
- The iommu daemon is the correct owner: `local/recipes/system/iommu/`
**Impact**: 533 lines of orphaned DMAR parsing in acpid. No Intel VT-d initialization anywhere.
**Action** (per Linux 7.1 `drivers/iommu/intel/dmar.c:408456`):
1. Remove `Dmar::init()` from acpid — acpid should only expose raw ACPI table data
2. Move DMAR parsing to `iommu` daemon: parse via `/scheme/acpi`, initialize IOMMU hardware (program RT, set up context entries, enable GCMD, configure fault handling)
3. Or: remove orphaned code until ready (Lower-effort path)
### Gap 10 — >256 CPU MSI Truncation Panic (MEDIUM)
**File**: `drivers/pcid/src/driver_interface/irq_helpers.rs:89`
- `let cpu_id = u8::try_from(cpu_id).expect("usize cpu ids not implemented yet");` — PANICS for CPU IDs > 255
- x2APIC supports 32-bit APIC IDs (up to 4 billion CPUs)
**Impact**: Any pcid-spawned driver on a system with >256 CPUs will panic. Not a blocker for current hardware (Threadripper 128-thread = 128 CPUs) but must be fixed before >256 CPU systems are tested.
**Action**:
1. Change `u8::try_from(cpu_id)` to `u32::try_from(cpu_id).map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "cpu_id > u32::MAX"))?`
2. Update kernel `/scheme/irq/cpu-{:02x}` to `/scheme/irq/cpu-{:08x}` for x2APIC
3. Add unit test for u32::MAX cpu_id path
### Gap 11 — IOMMU Daemon→Kernel IRQ Integration Missing (MEDIUM, new in v1.1)
**Files**:
- Kernel has `set_iommu_remapping_active()` (added 2026-06-08)
- `iommu` daemon never calls it
**Impact**: The MSI validation gate works correctly in code, but `IOMMU_REMAPPING_ACTIVE` always stays `false`, so the one-time warning always fires and the kernel never gets informed of hardware remapping state.
**Action**:
1. Kernel: add `Handle::RemappingControl` variant in `scheme/irq.rs`, detect path `"remapping"` in `kopenat()`, parse `"0"`/`"1"` in `kwrite()` and call `set_iommu_remapping_active()`
2. iommu daemon: after `INIT_UNITS` succeeds and IRTE tables are set up, write `"1"` to `/scheme/irq/remapping`
3. On shutdown: iommu daemon writes `"0"` before exit
### Gap 12 — MSI Multi-Vector Not Exposed (MEDIUM, new in v1.1)
**File**: `pcid/src/driver_interface/irq_helpers.rs:307`
- `pci_allocate_interrupt_vector` only allocates single vector
- `allocate_aligned_interrupt_vectors` already supports `count` parameter but is not exposed
- `multi_message_enable` field always set to `Some(0)` (single vector)
**Impact**: xhcid, nvmed, ixgbed, redox-drm cannot use multiple MSI vectors. Falls back to shared IRQ with degraded performance.
**Action**:
1. Add `pci_allocate_interrupt_vectors(pcid_handle, driver, count)` to pcid
2. For MSI: set `multi_message_enable` to `log2(count)`, allocate contiguous aligned vectors
3. For MSI-X: loop calling `allocate_single_interrupt_vector_for_msi()` per vector
---
## 7. Updated Execution Plan (v1.1)
### Phase 1: Critical Stub Removal (23 weeks)
**Goal**: Remove all CRITICAL-severity stubs before any hardware validation.
| # | Task | File | Effort | Owner |
|---|------|------|--------|-------|
| 1.1 | Fix `read_u8/u16/u32/u64` zero-return on failure (fabricate data) | `acpid/src/aml_physmem.rs:241280` | 2 days | — |
| 1.2 | Fix `map_physical_region()` `.expect()` panic | `acpid/src/aml_physmem.rs:213232` | 2 days | — |
| 1.3 | Wire pcid fd → acpid `RegisterPci` handle (root cause of Gap 3) | `pcid/main.rs` + `acpid/scheme.rs` + `acpid/acpi.rs:400` | 3 days | — |
| 1.4 | Remove `println!` debug artifact | `kernel/src/arch/x86_shared/interrupt/irq.rs:307` | 1 hour | — |
| 1.5 | Replace `cpu_id` u8 truncation panic with error return (Gap 10) | `pcid/src/driver_interface/irq_helpers.rs:89` | 1 day | — |
**Gate**: All CRITICAL stubs removed + `cargo check` clean on affected modules + pcid→acpid fd wiring tested.
### Phase 2: IOMMU + MSI Validation (34 weeks)
**Goal**: Make MSI/MSI-X delivery trustworthy.
| # | Task | File | Effort | Owner |
|---|------|------|--------|-------|
| 2.1 | **DONE** (2026-06-08): `iommu_validate_msi_irq()` real implementation | `kernel/src/scheme/irq.rs:231` | ✅ | committed |
| 2.2 | Add `/scheme/irq/remapping` control file (Gap 11) | `kernel/src/scheme/irq.rs` | 1 day | — |
| 2.3 | iommu daemon: write `"1"` to remapping after IRTE init | `iommu/source/src/main.rs` | 2 days | — |
| 2.4 | iommu daemon: write `"0"` to remapping on shutdown | `iommu/source/src/main.rs` | 1 day | — |
| 2.5 | QEMU validation: MSI-X with IOMMU enabled | `test-msix-qemu.sh` | 2 days | — |
| 2.6 | Move DMAR init from acpid to iommu daemon (Gap 9) | `acpid/dmar/``iommu/` | 1 week | — |
| 2.7 | QEMU validation: DMAR discovery + iommu | `test-iommu-qemu.sh` | 2 days | — |
**Gate**: `test-msix-qemu.sh` passes with IOMMU enabled + remapping gate works + no DMAR init in acpid.
### Phase 3: Timer + CPU Power (23 weeks)
**Goal**: Enable per-CPU timers and basic CPU idle.
| # | Task | File | Effort | Owner |
|---|------|------|--------|-------|
| 3.1 | Implement `setup_timer()` method (TSC deadline + periodic fallback) | `kernel/src/arch/x86_shared/device/local_apic.rs` | 1 week | — |
| 3.2 | Add PM-timer/TSC-based calibration | `kernel/src/arch/x86_shared/device/local_apic.rs` | 1 week | — |
| 3.3 | Wire `setup_timer()` into `init_ap()` after `setup_error_int()` | `local_apic.rs:81` | 1 day | — |
| 3.4 | Implement kernel cpuidle backend (MWAIT/HLT) | New file: `kernel/src/arch/x86_shared/cpuidle.rs` | 1 week | — |
| 3.5 | ACPI `_CST` parsing in acpid | `acpid/src/cstate.rs` (new) | 1 week | — |
| 3.6 | QEMU validation: timer + idle | `test-timer-qemu.sh` | 2 days | — |
**Gate**: `test-timer-qemu.sh` passes with APIC timer + CPU idle active + C1/C2 entry observed.
### Phase 4: Display Detection (46 weeks)
**Goal**: Replace synthetic EDID with real display detection.
| # | Task | File | Effort | Owner |
|---|------|------|--------|-------|
| 4.1 | Implement I²C-over-AUX infrastructure (DP connectors) | `redox-drm/src/kms/aux.rs` (new) | 2 weeks | — |
| 4.2 | Implement DDC I²C bus for HDMI/VGA | `redox-drm/src/kms/ddc.rs` (new) | 1 week | — |
| 4.3 | Wire HPD interrupt to connector detection | `redox-drm/src/drivers/amd/mod.rs`, `intel/mod.rs` | 1 week | — |
| 4.4 | Replace `synthetic_edid()` with real → CEA fallback | `redox-drm/src/kms/connector.rs:3884` | 3 days | — |
| 4.5 | QEMU validation: EDID readback | `test-drm-display-runtime.sh` | 2 days | — |
| 4.6 | Bare-metal validation: AMD GPU display | `test-amd-gpu.sh` | 1 week | — |
| 4.7 | Bare-metal validation: Intel GPU display | `test-intel-gpu.sh` | 1 week | — |
**Gate**: Real EDID retrieved from at least one display on bare metal (AMD or Intel).
### Phase 5: USB Legacy Controllers — OHCI/UHCI (68 weeks)
**Goal**: Enable USB keyboard on non-xHCI paths (EHCI already done).
| # | Task | File | Effort | Owner |
|---|------|------|--------|-------|
| 5.1 | Implement OHCI host controller driver | `local/recipes/drivers/ohcid/source/src/main.rs` | 34 weeks | — |
| 5.2 | Wire OHCI into driver-manager PCI binding | `driver-manager/src/main.rs` | 3 days | — |
| 5.3 | QEMU validation: OHCI keyboard | `test-usb-qemu.sh` | 2 days | — |
| 5.4 | Implement UHCI host controller driver | `local/recipes/drivers/uhcid/source/src/main.rs` | 34 weeks | — |
| 5.5 | Wire UHCI into driver-manager PCI binding | `driver-manager/src/main.rs` | 3 days | — |
| 5.6 | QEMU validation: UHCI keyboard | `test-usb-qemu.sh` | 2 days | — |
| 5.7 | MSI multi-vector support (Gap 12) | `pcid/src/driver_interface/irq_helpers.rs:307` | 1 week | — |
**Gate**: USB keyboard works via OHCI/UHCI in QEMU + multi-vector MSI for xhcid/nvmed/ixgbed.
### Phase 6: AML Convergence (34 weeks)
**Goal**: Resolve dual AML interpreter risk.
| # | Task | File | Effort | Owner |
|---|------|------|--------|-------|
| 6.1 | Audit kernel `acpi_ext` crate usage (does kernel still use it?) | `kernel/src/arch/x86_shared/sleep.rs` (verify exists) | 2 days | — |
| 6.2 | Evaluate kernel→userspace S3/S5 sleep delegation | `scheme/kernel.acpi/sleep``acpid` | 1 week | — |
| 6.3 | Implement kernel→userspace sleep RPC if S3 is needed | `scheme/kernel.acpi/sleep` | 1 week | — |
| 6.3 | Remove kernel `acpi_ext` crate if delegated | `kernel/src/arch/x86_shared/sleep.rs` | 3 days | — |
| 6.4 | QEMU validation: sleep/wake cycle | `test-sleep-qemu.sh` | 2 days | — |
**Gate**: S5 shutdown works with single AML interpreter (userspace only).
### Phase 7: Hardware Validation Matrix (46 weeks, parallel with 46)
**Goal**: Evidence-based support claims.
| # | Task | Hardware | Effort |
|---|------|----------|--------|
| 7.1 | Class A1 validation (AMD desktop + discrete GPU) | Ryzen 5000/7000 + AMD GPU | 1 week |
| 7.2 | Class A2 validation (Intel desktop + iGPU) | Core 12th14th Gen | 1 week |
| 7.3 | Class A3 validation (AMD laptop) | Ryzen Mobile | 1 week |
| 7.4 | Class A4 validation (Intel laptop) | Core Mobile | 1 week |
| 7.5 | Regression test suite on all 4 classes | All | 2 weeks |
**Gate**: All 4 hardware classes pass boot, shutdown, USB keyboard, and display detection.
---
## 8. Timeline Synthesis
```
Week 13: Phase 1 — Critical stub removal
Week 47: Phase 2 — IOMMU + MSI validation
Week 79: Phase 3 — Timer + CPU power (parallel with Phase 2 week 7)
Week 1015: Phase 4 — Display detection (parallel with Phase 5)
Week 1013: Phase 5 — USB legacy controllers (parallel with Phase 4)
Week 1417: Phase 6 — AML convergence
Week 1419: Phase 7 — Hardware validation matrix (parallel with Phase 6)
Total: 19 weeks (≈4.5 months) with 2 developers
```
### What the existing plans said vs this plan
| Plan | Claimed Timeline | Reality |
|------|-----------------|---------|
| COMPREHENSIVE P1 (bare-metal hardening) | 68 weeks | Understated — no critical stub removal phase |
| COMPREHENSIVE P2 (USB) | 46 weeks | Realistic for EHCI only |
| COMPREHENSIVE P3 (IRQ/IOMMU) | 46 weeks | Realistic if focused on Gap 1 only |
| IRQ plan Waves 16 | "Complete" | Code quality complete, validation not started |
| ACPI plan Waves 07 | W0W4 partial, W5W7 open | Accurate, but two critical stubs not flagged |
| SMP plan bottlenecks | 1118 days | Realistic for B1B2 only |
### Dependencies
```
Phase 1 (stub removal)
├── required by ──► Phase 2 (IOMMU validation)
├── required by ──► Phase 3 (timer + idle)
└── required by ──► Phase 4 (display detection)
Phase 2 (IOMMU)
└── required by ──► Phase 7 (hardware validation — safe MSI)
Phase 3 (timer + idle)
└── required by ──► Phase 7 (hardware validation — no overheating)
Phase 4 (display)
└── required by ──► Phase 7 (hardware validation — working console)
Phase 5 (USB EHCI)
└── required by ──► Phase 7 (hardware validation — keyboard input)
Phase 6 (AML convergence)
└── not blocking ──► Phase 7 (can validate with dual interpreters)
```
---
## 9. Risk Register (v1.1)
| # | Risk | Likelihood | Impact | Mitigation |
|---|------|-----------|--------|------------|
| R1 | `aml_physmem` stub fix requires `acpi` crate trait modification | High | High | Fork acpi crate to local/recipes/, or use sentinel-value + error-flag workaround that doesn't require trait change |
| R2 | IOMMU daemon→kernel integration needs new scheme file | Low | Medium | Kernel side is ~20 lines (`Handle::RemappingControl` + write handler); daemon side is ~5 lines. Both well-understood. |
| R3 | APIC timer calibration fails on specific CPU models | Medium | Medium | Keep PIT fallback path; detect calibration failure and degrade gracefully. TSC deadline mode is simpler and doesn't need calibration. |
| R4 | DDC/I²C implementation requires AUX CH for DisplayPort | High | High | Phase 4 split: implement AUX CH for DP first (covers AMD/Intel), DDC I²C for HDMI/VGA later. Synthetic EDID as fallback always. |
| R5 | OHCI/UHCI implementation is high-effort (68 weeks total) | Medium | Medium | Phase 5 spans two cycles: OHCI first (MMIO-based, simpler), UHCI second (I/O port-based, more complex) |
| R6 | AML convergence depends on whether kernel still uses `acpi_ext` | Unknown | Medium | Phase 6.1 audit: verify if `kernel/src/arch/x86_shared/sleep.rs` exists. If it does NOT exist, the dual-AML concern is moot (kernel has no AML interpreter). |
| R7 | MSI multi-vector breaks drivers that use shared IRQ assumptions | Low | Medium | Gate behind Phase 5; ship single-vector path as default; multi-vector is opt-in per driver |
| R8 | DMAR move from acpid to iommu daemon changes module ownership | Low | Medium | Refactor only; no new hardware interaction. iommu daemon already has the register-programming infrastructure. |
| R9 | pcid→acpid fd passing uses a Redox-specific mechanism | Medium | Medium | Verify fd-passing via `on_sendfd` works between pcid and acpid schemes. Add test in pcid. |
| R10 | No bare-metal hardware available for validation | Medium | Critical | Prioritize QEMU proofs for all phases; document "QEMU-validated" vs "bare-metal-validated" per subsystem |
---
## 10. Verification Gates (v1.1)
### Gate A: Boot-Baseline Ready (end of Phase 1)
- [ ] `aml_physmem.rs:241280` read_u* methods no longer fabricate zeros on failure
- [ ] `aml_physmem.rs:213232` `map_physical_region()` no longer panics on physmap failure
- [ ] pcid sends fd to acpid via `/scheme/acpi/register_pci`; acpid `pci_fd` is `Some` after init
- [ ] `acpi.rs:400` `aml_eval()` passes `self.pci_fd.as_ref()` instead of `None`
- [ ] `irq_helpers.rs:89` returns `io::Error` instead of panic for >255 CPU IDs
- [ ] `cargo check` clean on `acpid`, `kernel`, `redox-drm`, `pcid`
- [ ] `repo validate-patches kernel` passes
- [ ] `repo validate-patches base` passes
### Gate B: IRQ/IOMMU Trustworthy (end of Phase 2)
- [x] `iommu_validate_msi_irq()` performs real validation (done 2026-06-08)
- [ ] `/scheme/irq/remapping` exists and is writable
- [ ] iommu daemon writes `"1"` to remapping after IRTE init
- [ ] iommu daemon writes `"0"` to remapping on shutdown
- [ ] DMAR init removed from acpid
- [ ] DMAR init lives in iommu daemon
- [ ] `test-msix-qemu.sh` passes with IOMMU enabled
- [ ] `test-iommu-qemu.sh` passes
- [ ] No unconditional `true` returns in IRQ validation path
- [ ] Boot log does not show the "MSI before IOMMU" warning when IOMMU is configured
### Gate C: Timer + Power (end of Phase 3)
- [ ] `setup_timer()` method exists in `local_apic.rs`
- [ ] APIC timer fires and calibrates correctly in QEMU
- [ ] CPU idle backend enters C1/C2 via MWAIT or HLT
- [ ] `test-timer-qemu.sh` passes
- [ ] No PIT-only fallback in boot log
### Gate D: Display Detection (end of Phase 4)
- [ ] AUX CH infrastructure exists in `redox-drm/src/kms/aux.rs`
- [ ] DDC I²C infrastructure exists in `redox-drm/src/kms/ddc.rs`
- [ ] `synthetic_edid()` is fallback, not primary
- [ ] Real EDID retrieved from at least one display in QEMU
- [ ] `test-drm-display-runtime.sh` passes
### Gate E: USB Legacy (end of Phase 5)
- [ ] OHCI driver enumerates devices in QEMU
- [ ] UHCI driver enumerates devices in QEMU
- [ ] USB keyboard functional via OHCI in QEMU
- [ ] USB keyboard functional via UHCI in QEMU
- [ ] MSI multi-vector exposed via `pci_allocate_interrupt_vectors(pcid_handle, driver, count)`
- [ ] xhcid, nvmed, ixgbed updated to use multi-vector MSI where appropriate
- [ ] `test-usb-qemu.sh` passes
### Gate F: Single AML Interpreter (end of Phase 6)
- [ ] Audit: confirm whether `kernel/src/arch/x86_shared/sleep.rs` exists
- [ ] If it exists: evaluate kernel→userspace sleep delegation
- [ ] If it does NOT exist: dual-AML concern is moot, document this
- [ ] S5 shutdown works via userspace AML only
- [ ] `test-shutdown-qemu.sh` passes (S5 only — S3 is not a current target)
### Gate G: Hardware Validation (end of Phase 7)
- [ ] Class A1 (AMD desktop) boots, shuts down, displays, accepts USB keyboard
- [ ] Class A2 (Intel desktop) boots, shuts down, displays, accepts USB keyboard
- [ ] Class A3 (AMD laptop) boots, shuts down, displays, accepts USB keyboard
- [ ] Class A4 (Intel laptop) boots, shuts down, displays, accepts USB keyboard
- [ ] Validation artifacts committed to `local/docs/HARDWARE-VALIDATION-MATRIX.md`
---
## 11. Appendix: Key File Reference
### ACPI
- `recipes/core/kernel/source/src/acpi/mod.rs` — Kernel ACPI orchestrator
- `recipes/core/kernel/source/src/acpi/rsdp.rs` — RSDP discovery
- `recipes/core/kernel/source/src/acpi/madt/mod.rs` — MADT parser
- `recipes/core/kernel/source/src/scheme/acpi.rs` — Kernel ACPI scheme
- `recipes/core/kernel/source/src/arch/x86_shared/sleep.rs` — Kernel AML interpreter for sleep
- `recipes/core/kernel/source/src/arch/x86_shared/stop.rs` — Shutdown orchestrator
- `recipes/core/base/source/drivers/acpid/src/main.rs` — acpid daemon entry
- `recipes/core/base/source/drivers/acpid/src/acpi.rs` — Core ACPI context
- `recipes/core/base/source/drivers/acpid/src/aml_physmem.rs` — AML physmem handler (stubs at :195, :274)
- `recipes/core/base/source/drivers/acpid/src/ec.rs` — Embedded Controller handler
- `recipes/core/base/source/drivers/acpid/src/thermal.rs` — Thermal zone discovery
- `recipes/core/base/source/drivers/acpid/src/fan.rs` — Fan device discovery
- `recipes/core/base/source/drivers/acpid/src/cstate.rs` — C-state discovery
- `recipes/core/base/source/drivers/acpid/src/dmi.rs` — SMBIOS DMI parser
- `recipes/core/base/source/drivers/hwd/src/backend/acpi.rs` — hwd ACPI backend
- `recipes/core/base/source/drivers/hwd/src/backend/legacy.rs` — LegacyBackend stub (:13)
### IRQ / PCI
- `recipes/core/kernel/source/src/scheme/irq.rs` — IRQ scheme (stub at :231)
- `recipes/core/kernel/source/src/arch/x86_shared/interrupt/irq.rs` — IRQ dispatch
- `recipes/core/kernel/source/src/arch/x86_shared/device/ioapic.rs` — I/O APIC
- `recipes/core/kernel/source/src/arch/x86_shared/device/local_apic.rs` — LAPIC (timer disabled at :81)
- `recipes/core/kernel/source/src/arch/x86_shared/device/msi.rs` — MSI code (patch-based)
- `recipes/core/kernel/source/src/arch/x86_shared/device/vector.rs` — Vector allocator (patch-based)
- `recipes/core/kernel/source/src/arch/x86_shared/device/pic.rs` — 8259 PIC
- `recipes/core/kernel/source/src/arch/x86_shared/idt.rs` — IDT setup
- `local/recipes/drivers/redox-driver-sys/source/src/irq.rs` — Userspace IRQ handling
- `local/recipes/drivers/redox-driver-sys/source/src/pci.rs` — Userspace PCI abstraction
- `recipes/core/base/source/drivers/pcid/src/main.rs` — pcid daemon
- `recipes/core/base/source/drivers/pcid/src/scheme.rs` — PciScheme
- `recipes/core/base/source/drivers/pcid/src/driver_interface/irq_helpers.rs` — IRQ helper FIXMEs
- `local/recipes/system/driver-manager/source/src/main.rs` — Driver manager
### Driver Infrastructure
- `local/recipes/drivers/redox-driver-sys/source/src/lib.rs` — Core library
- `local/recipes/drivers/redox-driver-sys/source/src/quirks/mod.rs` — Quirks API
- `local/recipes/drivers/linux-kpi/source/src/lib.rs` — linux-kpi crate
- `local/recipes/drivers/linux-kpi/source/src/rust_impl/pci.rs` — PCI KPI (777 lines)
- `local/recipes/drivers/linux-kpi/source/src/rust_impl/drm_shim.rs` — DRM GEM shim
- `local/recipes/drivers/linux-kpi/source/src/rust_impl/mac80211.rs` — mac80211 KPI (959 lines)
- `local/recipes/drivers/linux-kpi/source/src/rust_impl/wireless.rs` — cfg80211 KPI (1002 lines)
- `local/recipes/system/firmware-loader/source/src/main.rs` — firmware-loader daemon
- `local/recipes/gpu/redox-drm/source/src/main.rs` — DRM daemon
- `local/recipes/gpu/redox-drm/source/src/drivers/amd/mod.rs` — AMD GPU driver
- `local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs` — Intel GPU driver
- `local/recipes/gpu/redox-drm/source/src/kms/connector.rs` — Connector + synthetic EDID (:35)
- `local/recipes/gpu/amdgpu/source/amdgpu_redox_main.c` — Bounded AMD display C port
- `local/recipes/gpu/amdgpu/source/redox_glue.h` — Linux→Redox C glue
- `local/recipes/gpu/amdgpu/source/redox_stubs.c` — Kernel emulation stubs
### Patches
- `local/patches/kernel/redbear-consolidated.patch` — Consolidated mega-patch
- `local/patches/kernel/P8-msi.patch` — MSI + vector allocator
- `local/patches/kernel/P9-ioapic-irq-affinity.patch` — IRQ affinity
- `local/patches/kernel/P10-irq-affinity-wiring.patch` — Affinity wiring
- `local/patches/kernel/P20-x2apic-icr-mode-fix.patch` — x2APIC ICR
- `local/patches/kernel/P21-x2apic-smp-fix.patch` — x2APIC SMP
- `local/patches/kernel/P22-x2apic-madt-fallback.patch` — x2APIC MADT fallback
- `local/patches/kernel/P24-cstate-mwait-idle.patch` — C-state MWAIT
- `local/patches/kernel/P25-cpuidle-deep-cstates.patch` — Deep C-states
- `local/patches/base/P19-acpid-startup-hardening.patch` — acpid startup
- `local/patches/base/P24-acpi-s5-derivation-shutdown-semantics.patch` — S5 derivation
- `local/patches/base/P44-acpid-thermal-zones.patch` — Thermal zones
- `local/patches/base/P48-acpid-fan-support.patch` — Fan support
- `local/patches/base/P52-acpid-cstates.patch` — C-state discovery
---
## 12. Document Authority
This document is a **cross-cutting reassessment** that references but does not replace the canonical subsystem plans:
- For ACPI wave-level execution detail, see `ACPI-IMPROVEMENT-PLAN.md`
- For IRQ/PCI wave-level execution detail, see `IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`
- For boot detection wave detail, see `BOOT-PROCESS-HARDWARE-DETECTION-PLAN.md`
- For SMP bottleneck detail, see `SMP-SCHEDULER-IMPROVEMENT-PLAN.md`
- For desktop path blockers, see `CONSOLE-TO-KDE-DESKTOP-PLAN.md`
## 13. Concrete Fix List (v1.1, Ready to Execute)
The following items are **ready to implement immediately** — they have been fully audited against Linux 7.1 reference, the root cause is understood, and the fix is specified. Each item has been promoted to a tracked task.
### 1.1.a — acpid `read_u8/u16/u32/u64` data fabrication (Gap 2)
**File**: `local/sources/base/drivers/acpid/src/aml_physmem.rs:241280`
**Severity**: 🔴 CRITICAL
**Linux reference**: `local/reference/linux-7.1/drivers/acpi/acpica/evregion.c:302316``acpi_ev_address_space_dispatch()` checks handler return status and logs exception; never fabricates data
**Current code** (representative — same pattern in all 4 read methods):
```rust
fn read_u8(&self, address: usize) -> u8 {
if let Ok(mut page_cache) = self.page_cache.lock() {
if let Ok(value) = page_cache.read_from_phys::<u8>(address) {
return value;
}
}
log::error!("failed to read u8 {:#x}", address);
0 // FABRICATES DATA
}
```
**Target code** (sentinel-value approach, since the `acpi` crate's `Handler` trait returns raw `u8`):
```rust
static READ_FABRICATION_FLAG: AtomicUsize = AtomicUsize::new(0);
fn read_u8(&self, address: usize) -> u8 {
if let Ok(mut page_cache) = self.page_cache.lock() {
match page_cache.read_from_phys::<u8>(address) {
Ok(value) => return value,
Err(e) => log::error!("read u8 {:#x} failed: {:?}", address, e),
}
}
READ_FABRICATION_FLAG.fetch_add(1, Ordering::SeqCst);
0
}
pub fn read_fabrication_count() -> usize {
READ_FABRICATION_FLAG.load(Ordering::SeqCst)
}
```
**Note**: Full `Result<T, AmlError>` propagation requires forking the `acpi` crate and modifying the `Handler` trait. The sentinel+flag approach is the minimum-viable fix that doesn't require a crate fork.
### 1.1.b — acpid `map_physical_region` panic (Gap 2)
**File**: `local/sources/base/drivers/acpid/src/aml_physmem.rs:213232`
**Severity**: 🔴 CRITICAL
**Linux reference**: `local/reference/linux-7.1/drivers/acpi/acpica/exregion.c:145153` — returns `AE_NO_MEMORY` status on map failure
**Current code**:
```rust
let virt_page = common::physmap(...).expect("failed to map physical region") as usize;
```
**Target code**:
```rust
let virt_page = match common::physmap(...) {
Ok(v) => v as usize,
Err(e) => {
log::error!("physmap failed at {:#x}+{:#x}: {:?}", phys_page, map_size, e);
return PhysicalMapping {
physical_start: phys,
virtual_start: NonNull::dangling(),
region_length: size,
mapped_length: 0, // 0 length signals invalid
handler: self.clone(),
};
}
};
```
### 1.3 — Wire pcid→acpid fd (Gap 3)
**Files**:
- `local/sources/base/drivers/pcid/src/main.rs` (add fd send)
- `local/sources/base/drivers/acpid/src/scheme.rs` (handle `RegisterPci`)
- `local/sources/base/drivers/acpid/src/acpi.rs:400` (pass pci_fd to aml_context_mut)
**Implementation sketch**:
```rust
// In pcid/src/main.rs, after PCI bus init, before event loop:
let acpi_register = File::open("/scheme/acpi/register_pci")?;
let pci_scheme_fd = /* get from pcid's internal pci scheme handle */;
send_fd(acpi_register, pci_scheme_fd)?;
// In acpi.rs line 400, change:
let interpreter = symbols.aml_context_mut(self.pci_fd.as_ref())?;
// from:
let interpreter = symbols.aml_context_mut(None)?;
```
### 1.5 — Replace u8 CPU ID panic (Gap 10)
**File**: `local/sources/base/drivers/pcid/src/driver_interface/irq_helpers.rs:89`
**Severity**: 🟠 HIGH (panic on >255 CPU systems)
**Current code**:
```rust
let cpu_id = u8::try_from(cpu_id).expect("usize cpu ids not implemented yet");
```
**Target code**:
```rust
let cpu_id = u32::try_from(cpu_id)
.map_err(|_| io::Error::new(io::ErrorKind::InvalidInput, "cpu_id > u32::MAX"))?;
```
### 2.2 — Add `/scheme/irq/remapping` control file (Gap 11)
**File**: `local/sources/kernel/src/scheme/irq.rs`
**Severity**: 🟡 MEDIUM
**Linux reference**: `local/reference/linux-7.1/include/linux/pci.h``pci_write_config_byte` is the equivalent scheme pattern in Redox
**Implementation**:
1. Add `Handle::RemappingControl` variant
2. In `kopenat()`, detect path `"remapping"` and return `OpenResult::Other` with this handle
3. In `kwrite()`, parse `"0"` or `"1"` and call `set_iommu_remapping_active()`
4. Document in `irqs.md` (or scheme doc)
### 2.3-2.4 — iommu daemon writes to `/scheme/irq/remapping` (Gap 11)
**File**: `local/recipes/system/iommu/source/src/main.rs`
**Severity**: 🟡 MEDIUM
**Implementation**:
```rust
// After successful INIT_UNITS and IRTE setup:
let remapping = std::fs::File::create("/scheme/irq/remapping")?;
remapping.write_all(b"1")?;
// On shutdown signal:
let remapping = std::fs::File::create("/scheme/irq/remapping")?;
remapping.write_all(b"0")?;
```
### 2.6 — Move DMAR init from acpid to iommu daemon (Gap 9)
**Files**:
- Remove: `local/sources/base/drivers/acpid/src/acpi/dmar/mod.rs` (533 lines of orphaned code)
- Add: DMAR parsing to `local/recipes/system/iommu/source/src/intel.rs` (new file)
- Add: DMAR init wired into `local/recipes/system/iommu/source/src/main.rs` `INIT_UNITS` path
**Linux reference**: `local/reference/linux-7.1/drivers/iommu/intel/dmar.c:408456` (`dmar_parse_one_drhd`)
### 3.1-3.3 — Re-enable APIC timer (Gap 4)
**File**: `local/sources/kernel/src/arch/x86_shared/device/local_apic.rs`
**Severity**: 🟠 HIGH
**Linux reference**: `local/reference/linux-7.1/arch/x86/kernel/apic/apic.c:277321` (`__setup_APIC_LVTT`)
**Implementation**:
1. Implement `setup_timer()` method (TSC deadline mode first, periodic fallback)
2. Add PM-timer or TSC calibration (`lapic_cal_handler` pattern, `apic.c:662688`)
3. Uncomment line 81: `self.setup_timer();`
4. Verify with `test-timer-qemu.sh`
### 5.1-5.6 — OHCI and UHCI drivers (Gap 7)
**Files**:
- `local/recipes/drivers/ohcid/source/src/main.rs` (currently 19-line stub)
- `local/recipes/drivers/uhcid/source/src/main.rs` (currently 19-line stub)
**Linux reference**:
- `local/reference/linux-7.1/drivers/usb/host/ohci-hcd.c` (full reference impl)
- `local/reference/linux-7.1/drivers/usb/host/uhci-hcd.c` (full reference impl)
**Implementation order**:
1. **OHCI first** (34 weeks): MMIO register access, HCCA, transfer descriptors, frame list, port management
2. **UHCI second** (34 weeks): I/O port register access, QH/QTD management, FLBASEADD, port control
### 5.7 — MSI multi-vector allocation (Gap 12)
**File**: `local/sources/base/drivers/pcid/src/driver_interface/irq_helpers.rs:307`
**Severity**: 🟡 MEDIUM
**Linux reference**: `local/reference/linux-7.1/drivers/pci/msi/api.c``pci_alloc_irq_vectors()`
**Implementation**:
1. Add `pci_allocate_interrupt_vectors(pcid_handle, driver, count)` to pcid
2. For MSI: set `multi_message_enable = log2(count)`, allocate contiguous aligned vectors
3. For MSI-X: loop calling `allocate_single_interrupt_vector_for_msi()` per vector
4. Update xhcid, nvmed, ixgbed, redox-drm to use multi-vector where appropriate
## 14. v1.1 Audit Methodology
The v1.1 corrections were made by:
1. **Reading** the source files at the locations the v1.0 plan claimed contained stubs
2. **Discovering** that several locations don't exist (`kernel/src/arch/x86_shared/sleep.rs:257276`)
3. **Finding** the actual stubs at different locations
4. **Cross-referencing** against Linux 7.1 reference at `local/reference/linux-7.1/` for each fix
5. **Verifying** through grep + read that the line numbers in the v1.0 plan were sometimes off
6. **Checking** git history of `local/sources/base/` and `local/sources/kernel/` to ensure fixes target the correct durable location
### Findings of the audit
| v1.0 claim | v1.1 reality |
|---|---|
| Gap 3: kernel `sleep.rs:257276` PCI stubs | **Does not exist** — sleep path is in `acpid/aml_physmem.rs:375398` |
| Gap 7: no EHCI driver | **EHCI is implemented** (1538+ lines) — stubs are OHCI + UHCI |
| Gap 1: MSI stub at `kernel/scheme/irq.rs:231` | **Fixed 2026-06-08** (this audit's first deliverable) |
| Gap 2: AML stubs at `aml_physmem.rs:195, :274` | **Wrong line numbers** — actual stubs are at `:241280` (reads) and `:213232` (map) |
| Gap 4: APIC timer disabled | **Confirmed**`setup_timer()` method doesn't even exist |
| Gap 6: Dual AML interpreters | **Confirmed, but reduced scope** — kernel may not have AML interpreter at all |
| Gap 8: No C-state backend | **Confirmed** — no `cpuidle` exists, no `cstate.rs` in acpid |
| Gap 9: DMAR orphaned | **Confirmed, but ownership wrong** — should be in iommu daemon, not acpid |
| Gap 10: >256 CPU MSI | **Confirmed, but is a panic, not a deferred case**`u8::try_from(...).expect(...)` |
| New Gap 11: IOMMU→kernel integration | **New finding** — kernel has `set_iommu_remapping_active()` but daemon never calls it |
| New Gap 12: MSI multi-vector | **New finding** — required by xhcid, nvmed, ixgbed, redox-drm |
---
**When this document conflicts with a canonical subsystem plan**, the **canonical plan** wins on subsystem-specific details, and this document wins on cross-cutting prioritization and inter-subsystem dependencies.
**This document should be updated** after each phase gate is reached, or when new critical stubs are discovered.