884f9e8e0d
Plan v3.1 records the completed P0/LDR/P2 work program and the operator-ratified cutover (driver-manager owns the boot path in all redbear-* configs; pcid-spawner gated as fallback). Assessment § 11 documents the OS-services integration: init ConditionPathExists gate, live driver-params bridge, udev-shim driver-binding gap (P3), and the correct absence of D-Bus (bridge-on-demand pattern).
2120 lines
121 KiB
Markdown
2120 lines
121 KiB
Markdown
# Red Bear OS — `pci-spawner` → `driver-manager` Migration Plan
|
||
|
||
**Document status:** v3.1 canonical planning authority (supersedes v3.0 with the completed P0/LDR/P2 implementation and the operator-ratified cutover: driver-manager now owns the boot path in all `redbear-*` configs; pcid-spawner is gated as the fallback)
|
||
**Generated:** 2026-07-20
|
||
**Toolchain:** Rust nightly-2026-05-24 (edition 2024)
|
||
**Architecture:** Microkernel OS in Rust (Redox fork)
|
||
**Cross-reference baseline:** Linux kernel 7.1 at commit `ab9de95c9` (`local/reference/linux-7.1/`), CachyOS (`local/reference/cachyos/` — linux-cachyos `0001-cachyos-base-all.patch` 6.17.9 + desktop ISO 260628)
|
||
**Assessment:** `local/docs/evidence/driver-manager/ASSESSMENT-2026-07-22.md` (findings B1–G10, § 11 services integration)
|
||
|
||
**v3.1 status update over v3.0 (implementation + cutover round, 2026-07-23):**
|
||
|
||
The v3.0 work program is implemented and the operator has ratified the
|
||
cutover: **driver-manager owns the boot path in every `redbear-*`
|
||
config; pcid-spawner is retired from configs and gated behind
|
||
`/etc/driver-manager.d/disabled` as the operator fallback (never
|
||
deleted).** Future OS development is based on driver-manager.
|
||
|
||
Completed items:
|
||
|
||
- **P0-1 ✅ Claim-via-channel collapse.** `probe()` does a single
|
||
`PciFunctionHandle::connect_by_path()`; `ENOLCK` → next candidate;
|
||
`enable_device` + `into_inner_fd` → `PCID_CLIENT_CHANNEL`.
|
||
`claim_pci_device`/`open_pcid_channel` deleted; `SpawnedDriver` holds
|
||
the channel fd (claim lifetime == child lifetime).
|
||
- **P0-2 ✅ Orphan patches resolved.** bind-scheme + uevent-fix moved to
|
||
`local/patches/legacy-superseded-2026-07-22/` with a SUPERSEDED.md
|
||
audit entry; aer-scheme retained as the P2-1 producer blueprint.
|
||
- **P0-3 ✅ Advisory theater stripped.** `modern_tech.rs` and `exec.rs`
|
||
deleted; the useful parts correctly wired as spawn env hints
|
||
(`REDBEAR_DRIVER_IOMMU_GROUP` / `REDBEAR_DRIVER_NUMA_NODE` /
|
||
`REDBEAR_DRIVER_MSIX_VECTORS`); redox-driver-core C/P-state
|
||
coordinators removed (no consumers).
|
||
- **LDR-2 ✅ Spawned-mode `pci_register_driver`.** linux-kpi honors
|
||
`PCID_CLIENT_CHANNEL` (probe only the granted device; never
|
||
enumerate). Standalone mode retained for CLI tools.
|
||
- **LDR-3 ✅ iwlwifi onboarded.** `--daemon` mode (honors
|
||
`PCID_DEVICE_PATH`, full-init, resident) + `70-wifi.toml` staged;
|
||
`--import-linux-ids` wires linux_loader into production
|
||
(Linux `id_table` → `[[driver.match]]` TOML).
|
||
- **LDR-4 ✅ Verified convergent.** redox-drm already honors the pcid
|
||
handoff; no changes needed.
|
||
- **LDR-5 ✅ linux-kpi API completion.** Real MSI/MSI-X via
|
||
pcid_interface (vector allocation + table programming; linux-kpi owns
|
||
the channel in linux-kpi daemons), `pci_request_regions`,
|
||
`pcie_capability_read/write_*`, `pci_set_power_state` /
|
||
`pci_save_state` / `pci_restore_state`. C header synced.
|
||
- **P2-2 ✅ Operator surface.** Scheme endpoints `bind`, `unbind`,
|
||
`new_id`, `remove_id`, `driver_override`, `rescan`; DeviceManager
|
||
gained Tier-1 `driver_override` precedence + `bind_device`.
|
||
- **P2-3 ✅ Success trigger.** A successful bind immediately retries
|
||
deferred probes (Linux `driver_deferred_probe_trigger`), in
|
||
`run_enumeration` and the scheme bind handler.
|
||
- **Cutover ✅.** init learned `ConditionPathExists` (with `!`
|
||
negation — the C0 dormancy was a parser-rejection accident);
|
||
driver-manager services run by default in init.d/init.initfs.d and
|
||
all `redbear-*` configs; pcid-spawner services gated to
|
||
`/etc/driver-manager.d/disabled`. `make lint-config` clean.
|
||
- **Services integration ✅ (assessment § 11).** driver-params bridge
|
||
verified live; udev-shim driver-binding view noted as a P3 gap;
|
||
D-Bus correctly absent (bridge-on-demand pattern documented).
|
||
|
||
Open items (unchanged): **P0-4** QEMU runtime gate (build running;
|
||
first boot with driver-manager owning the path), **P2-1** pcid
|
||
producers (AER registers, pciehp slot events), **P3** policy/hygiene
|
||
(quirk phases, AER recovery actions, per-vendor firmware packaging,
|
||
udev-shim driver-binding view, dep-crate warnings, stale-tree cleanup).
|
||
|
||
**v3.0 status update over v2.2 (the assessment round):**
|
||
|
||
v3.0 records the first *runtime-grade* audit of the migration. Three
|
||
parallel codebase audits (pcid layer, linux-kpi binding model, Linux 7.1
|
||
PCI core) plus a full first-hand review of every driver-manager source
|
||
file found that the v1.3–v2.2 "Done" claims were compile-grade, and that
|
||
three of them are **broken at runtime**. The full evidence register
|
||
(B1–G10) is in the assessment doc; the corrections and the resulting
|
||
work program follow.
|
||
|
||
**Corrections to earlier rounds (stale claims removed):**
|
||
|
||
1. **The `<addr>/bind` claim endpoint does not exist.** Earlier rounds
|
||
marked "D1 C4 BAR request ✅ Done — `claim_pci_device` via
|
||
`<addr>/bind`" (and the § diagram "claims devices via `<addr>/bind`").
|
||
pcid exposes only `channel` and `config` per device; the patches that
|
||
would add `/bind` (`local/patches/base/P3-pcid-bind-scheme.patch`,
|
||
`P3-pcid-aer-scheme.patch`, `P3-pcid-uevent-format-fix.patch`) are
|
||
orphaned — never committed to `submodule/base`, and the cookbook does
|
||
not apply patches for `path =` fork recipes. At runtime, every probe
|
||
would fail `ENOENT` and defer-retry forever, binding nothing.
|
||
**Resolution: P0-1 below — the separate claim endpoint is dropped in
|
||
favor of pcid's existing channel exclusivity (`ENOLCK`), the model
|
||
pcid-spawner has always used.** The orphaned patches are resolved per
|
||
the orphan-patch decision tree (bind-scheme: SUPERSEDED by the
|
||
channel model; aer-scheme: kept as the P2-1 producer blueprint).
|
||
2. **The pciehp and AER listeners are inert.** v1.9/v2.0 marked them
|
||
done; in fact nothing in the tree produces `/scheme/pci/pciehp` or
|
||
`/scheme/acpi/aer`, and both readers fail-soft on missing files.
|
||
Device add/remove is covered by the 250 ms hotplug enumeration poll
|
||
(which works). The listeners are restated as *parsers ready,
|
||
producers pending* (P2-1).
|
||
3. **`exclusive_with` is not "the CachyOS pattern."** CachyOS solves
|
||
two-drivers-one-device by *probe-time* deferral (its 6.17.9 patch
|
||
makes ahci return `-ENODEV` on remapped-NVMe controllers so
|
||
`intel-nvme-remap` binds instead) and by *userspace* modprobe.d
|
||
blacklists. Match-time `exclusive_with` is a third, complementary
|
||
mechanism — a superset, retained. The plan text is corrected.
|
||
4. **`modern_tech` "wired" was advisory theater.** Bind/unbind emit
|
||
hardcoded C/P-state constants into JSON files nothing reads, and the
|
||
MSI-X proposal is computed at spawn and discarded. P0-3 strips it to
|
||
the honest core.
|
||
5. **"8 QEMU-functional test scripts" was aspirational.** The scripts
|
||
exist; no driver-manager QEMU boot has ever been run. Runtime
|
||
validation is now a hard gate (P0-4) and the D5 audit grades
|
||
capabilities *runtime* as well as *compile*.
|
||
|
||
**v3.0 work program (the tracks):**
|
||
|
||
| Track | Items | Goal |
|
||
|---|---|---|
|
||
| **P0 — Correctness blockers** | P0-1 claim-via-channel collapse · P0-2 restate pciehp/AER + resolve orphaned patches · P0-3 strip modern_tech + delete exec.rs · P0-4 runtime validation gate (QEMU) | Make the existing D-phase true at runtime |
|
||
| **LDR — Linux-Driver-Reuse** | LDR-1 unified claim model · LDR-2 spawned-mode `pci_register_driver` · LDR-3 iwlwifi onboarding · LDR-4 amdgpu path convergence · LDR-5 linux-kpi API completion | The critical goal: reuse Linux drivers |
|
||
| **P2 — Operator & event surface** | P2-1 pcid producers (AER registers, pciehp slot events) · P2-2 scheme write endpoints (`bind`/`unbind`/`new_id`/`remove_id`/`driver_override`/`rescan`) · P2-3 trigger-based deferred retry | Linux-grade operability |
|
||
| **P3 — Policy & hygiene** | quirk pass phases (early/runtime) · AER recovery actions (`pci_ers_result` mapping) · per-vendor firmware packaging · dep-crate warnings + stale-tree cleanup | Long-term evolution |
|
||
|
||
**P0 — Correctness blockers (preconditions for everything else):**
|
||
|
||
- **P0-1 Collapse claim into the channel open.** Replace
|
||
`claim_pci_device()` + `open_pcid_channel()` with a single
|
||
`PciFunctionHandle::connect_by_path()`: `ENOLCK` → "already claimed →
|
||
next candidate" (mirrors Linux's probe-time `-EBUSY`/`-ENODEV`
|
||
handoff), then `enable_device()` and `into_inner_fd()` →
|
||
`PCID_CLIENT_CHANNEL`. Claim lifetime == channel fd lifetime == child
|
||
lifetime — exactly correct, pcid-spawner-proven, zero pcid fork
|
||
changes. The exclusive_with check moves *after* the channel open
|
||
(claim-then-check, as in v2.1–v2.2, with close-on-defer).
|
||
- **P0-2 Restate pciehp/AER; resolve orphaned patches.** Plan text
|
||
corrected above. `P3-pcid-bind-scheme.patch` → SUPERSEDED (channel
|
||
model); `P3-pcid-aer-scheme.patch` → retained as the P2-1 producer
|
||
blueprint; `P3-pcid-uevent-format-fix.patch` → split: AER parts with
|
||
the producer work, uevent stub dropped (polling is the accepted v1
|
||
model). Move superseded files per the orphan-patch decision tree.
|
||
- **P0-3 Strip modern_tech to the honest core; delete exec.rs.** Remove
|
||
the constant C/P-state JSON writers (no consumers); pass the MSI-X
|
||
proposal to the child as `REDBEAR_DRIVER_MSIX_VECTORS=<n>` (same
|
||
env-hint channel as the quirk hints) or drop it until a consumer
|
||
exists. Delete `exec.rs` (dead `spawn_driver` with
|
||
`#[allow(dead_code)]`).
|
||
- **P0-4 Runtime validation gate.** Boot `redbear-mini` in QEMU with
|
||
driver-manager enabled in place of pcid-spawner (C-phase dry run):
|
||
e1000 binds through the real claim path, `/bound` reports it,
|
||
heartbeat counters move, deferred drivers retry and bind. Until this
|
||
passes, no capability is "Done" — the D5 audit gains a Runtime column.
|
||
|
||
**LDR — Linux-Driver-Reuse track (the critical goal):**
|
||
|
||
*One ownership model:* driver-manager owns enumeration, matching,
|
||
policy, claiming, and spawning for **native and Linux-port daemons
|
||
alike**; linux-kpi is the in-process Linux API surface *inside* the
|
||
spawned daemon, never a second enumerator.
|
||
|
||
- **LDR-1 Unified claim model.** All device binding flows through
|
||
driver-manager's match→claim→spawn. linux-kpi never opens
|
||
`/scheme/pci/` for binding decisions.
|
||
- **LDR-2 Spawned-mode `pci_register_driver`.** When
|
||
`PCID_CLIENT_CHANNEL` is present, linux-kpi skips enumeration, wraps
|
||
the granted channel, matches only the device it was spawned for, and
|
||
calls the C probe for exactly that device. Standalone
|
||
self-enumeration mode remains for CLI tools. This eliminates the
|
||
double-claim risk class (assessment B2).
|
||
- **LDR-3 redbear-iwlwifi onboarding.** Generate its driver-manager TOML
|
||
from the iwlwifi `id_table` via `linux_loader` (un-`cfg(test)` the
|
||
pipeline: `linux_loader → TOML → /lib/drivers.d/`); spawn it as a
|
||
daemon under the unified claim; retire its manual `/scheme/pci/`
|
||
scanning CLI path for the auto-bind case.
|
||
- **LDR-4 amdgpu path convergence.** Keep redox-drm as the spawned
|
||
daemon (its FFI into `libamdgpu_dc_redox.so` is legitimate
|
||
in-process composition, not a second claim system — but its PCI open
|
||
must go through the granted channel, not `PciDevice::open_location`
|
||
on its own enumeration).
|
||
- **LDR-5 linux-kpi API completion (priority order).** (a) real MSI/MSI-X
|
||
via `pcid_interface::enable_feature` (replace synthetic
|
||
`allocate_vectors`); (b) `pci_request_regions`/`pci_release_regions`
|
||
as BAR-mapping claims over the channel; (c) `pcie_capability_read/
|
||
write_*` via channel config R/W (exists in pcid_interface); (d) power
|
||
state (`pci_save_state`/`restore_state`/`set_power_state` via PMCSR);
|
||
(e) `pci_reset_function` (FLR) if pcid grows the hook.
|
||
|
||
**P2 — Operator & event surface:**
|
||
|
||
- **P2-1 pcid producers.** Per-device AER register files from the
|
||
retained aer-scheme blueprint; pciehp slot-status events (the five
|
||
hardware-defined bits ABP/PFD/PDC/DLLSC/CC) produced by pcid polling
|
||
the slot status register.
|
||
- **P2-2 Scheme write endpoints.** `/bind`, `/unbind`, `/new_id`,
|
||
`/remove_id`, `/driver_override`, `/rescan` on the driver-manager
|
||
scheme — the Linux sysfs operator surface, scheme-shaped. dynids are
|
||
already implemented in redox-driver-core; this exposes them.
|
||
`driver_override` adds Linux's Tier-1 match precedence.
|
||
- **P2-3 Trigger-based deferred retry.** Retry deferred probes on (a)
|
||
any successful bind (mirrors `driver_deferred_probe_trigger`), (b)
|
||
dependency-scheme arrival (watch `/scheme/` for the named scheme in
|
||
"dependency scheme not ready" deferrals), (c) firmware-loader
|
||
readiness for `NEED_FIRMWARE` deferrals. Blind 250 ms polling becomes
|
||
the fallback, not the mechanism.
|
||
|
||
**P3 — Policy & hygiene:** quirk pass phases (early pre-BAR vs runtime —
|
||
Linux has 8 `pci_fixup_pass` phases; we need at least the early/runtime
|
||
split for pre-BAR quirks); AER recovery actions wired to drivers
|
||
(`pci_ers_result` 6-state mapping over scheme IPC); per-vendor firmware
|
||
packaging mirroring linux-firmware splits; dependency-crate warnings
|
||
(libredox, pcid `Option::insert`, redox-driver-sys `Once`/`vendor`);
|
||
remove the stale `local/recipes/drivers/redox-driver-core/src/`
|
||
duplicate tree (live tree is `source/src/`); fold the concurrent path's
|
||
double bus enumeration into one pass.
|
||
|
||
**v2.2 status update over v2.1:**
|
||
|
||
v2.2 records the ninth round of D-phase work, fixing defects found by the
|
||
first full `x86_64-unknown-redox` compile of the v2.1 tree and by a
|
||
dead-code/warning sweep:
|
||
|
||
- **Concurrent probe path is now real** (`redox-driver-core`). The
|
||
`ConcurrentDeviceManager` previously returned a synthetic
|
||
`ProbeResult::Bound` from `run_probe` without ever calling
|
||
`Driver::probe()` — on any bus with ≥ 4 unbound devices (the production
|
||
`max_concurrent_probes = 4` config) this reported bindings with no
|
||
driver spawned and bypassed `exclusive_with`, quirks, and the
|
||
blacklist. `DeviceManager` now stores drivers as `Arc<dyn Driver>`;
|
||
concurrent jobs carry priority-ordered candidate lists (static match
|
||
table **and** dynids); workers invoke the real `probe()` with
|
||
serial-equivalent per-device semantics (Bound → claim + record,
|
||
Deferred → enqueue, Fatal → stop, NotSupported → next candidate) and
|
||
apply bound/deferred state in the worker. Three new tests cover real
|
||
probe invocation, candidate fallback, and deferred enqueue.
|
||
- **Redox-target build errors fixed** (`driver-manager`). `SchemeSync::write`
|
||
now matches the redox-scheme trait (`buf: &[u8]`); the `/modalias`
|
||
write stores the looked-up driver name per-handle and a subsequent
|
||
read returns it. `O_WRONLY`/`O_RDWR` come from `syscall::flag`
|
||
(usize) instead of `libc` (i32).
|
||
- **Double-claim bug fixed.** `probe()` claimed the PCI device twice
|
||
(once before the `exclusive_with` check, once before spawn); since
|
||
pcid binds are exclusive, the second claim would always fail
|
||
`EALREADY` on real hardware and no device would ever bind. The probe
|
||
now claims once and threads the same handle through to spawn.
|
||
- **Driver registry wired.** `set_registered_drivers()` is now called at
|
||
startup — previously the registry stayed empty, making the
|
||
`exclusive_with` check and the `/modalias` lookup silent no-ops.
|
||
- **Real signal handlers.** `SIGCHLD` and `SIGHUP` handlers are now
|
||
actually installed via `libc::signal` inside `spawn_reaper_thread` /
|
||
`spawn_reload_worker`. The previous `install_handler` /
|
||
`install_sighup_handler` bodies were empty placeholders, so the
|
||
reaper and the blacklist reload never fired in production.
|
||
- **Heartbeat counters wired.** `record_bound` / `record_spawned` /
|
||
`record_deferred` / `record_on_error` are called from the enumerate
|
||
path; `record_bound` / `record_unbound` from the hotplug loop. The
|
||
heartbeat JSON no longer publishes permanent zeros.
|
||
- **AER routing wired.** The unified event listener calls
|
||
`route_to_driver` per AER event against a live bound-device snapshot
|
||
(new `bound_device_pairs()` scheme accessor) and logs the decided
|
||
`RecoveryAction`.
|
||
- **Dead code removed or test-gated.** The superseded standalone
|
||
pciehp/AER listener threads, the single-variant `ProbeOutcome` enum,
|
||
`SharedBlacklist::len`/`snapshot`, the placeholder install functions,
|
||
the heartbeat `cv`/`stop` machinery, and `set_reload_flag` are gone;
|
||
`end_to_end_test`, `linux_loader`, `set_reap_flag`, `compute_modalias`,
|
||
and `policy::SharedBlacklist::snapshot` are `#[cfg(test)]`-gated;
|
||
`compute_match_modalias` / `lookup_modalias` are
|
||
`#[cfg(any(target_os = "redox", test))]` (their only production caller
|
||
is the redox-only scheme server).
|
||
- **Zero warnings.** `driver-manager` compiles warning-free on the host
|
||
and on the `x86_64-unknown-redox` target (remaining warnings are
|
||
pre-existing in dependency crates: libredox, pcid, redox-driver-sys).
|
||
|
||
**v2.2 test totals:** 56 driver-manager + 33 redox-driver-core lib + 5
|
||
dynid integration = 94 tests, all passing. `repo cook driver-manager`
|
||
succeeds for `x86_64-unknown-redox` with zero crate-local warnings.
|
||
|
||
**§ 0.5 audit gate at v2.2:** 0 violations.
|
||
|
||
**v1.4 status update over v1.3:**
|
||
|
||
v1.4 records the second round of D-phase work: the policy loader is now
|
||
active (the `redbear-driver-policy` package now actually changes
|
||
`spawn_decision_gate` behavior at runtime), the `--concurrent=N` CLI
|
||
flag enables the SMP worker pool, the two C0 service files have been
|
||
committed in the `local/sources/base` submodule, and the unused
|
||
`modern_tech` orchestrator was removed (the `redox_driver_core::modern_technology`
|
||
helpers remain as a library for downstream consumers to integrate
|
||
when they exist). The § 0.5 audit gate still reports **0 violations
|
||
across 34 files**. PciQuirkFlags is now wired into the actual driver
|
||
spawn (the `REDBEAR_DRIVER_PCI_IRQ_MODE=intx_or_msi` and
|
||
`REDBEAR_DRIVER_DISABLE_ACCEL=1` env vars are passed to the spawned
|
||
child when the corresponding flags are set).
|
||
|
||
| Item | Status at v1.4 | Where |
|
||
|---|---|---|
|
||
| § 5.1 D0 foundation verified | ✅ Done | `cargo test` 33+3+16 = 52 tests passing |
|
||
| § 5.1 D1 C1 capability (`add_dynid`/`remove_dynid`) | ✅ Done | `redox-driver-core/src/{dynid,manager}.rs` |
|
||
| § 5.1 D1 C2 capability (`Driver::remove` + WAIT_FOR_REAPPEAR) | ✅ Done | `driver-manager/src/config.rs` (real SIGTERM+SIGKILL) |
|
||
| § 5.1 D1 C3, C6 (enable_device / set_bus_master) | ✅ Done | `open_pcid_channel` via `pcid_interface::EnableDevice` |
|
||
| § 5.1 D1 C4 (BAR request) | 🟡 Corrected at v3.0 | `<addr>/bind` never existed in pcid (see v3.0 correction 1); claim collapses into channel exclusivity per P0-1 |
|
||
| § 5.1 D1 C5, C7, C8, C12, C16, C17 (child-side) | ✅ Done | pre-existing driver daemons |
|
||
| § 5.1 D1 format coexistence | ✅ Done | `convert_legacy` function in config.rs |
|
||
| § 5.1 D1 SpawnDecision committee | ✅ Done | `spawn_decision_gate()` function |
|
||
| § 5.1 D1 policy blacklist | ✅ Done at v1.4 | `policy::Blacklist::load_dir()` + `blacklist_match()` consult at probe |
|
||
| § 5.2 D2.1 SMP concurrent probe | ✅ Done | `redox-driver-core/src/concurrent.rs` (worker pool) |
|
||
| § 5.2 D2.2 C-state / P-state advisors | ✅ Library only at v1.4 | `redox-driver-core/src/modern_technology.rs` (orchestrator removed) |
|
||
| § 5.2 D2.3 IOMMU + MSI-X + NUMA helpers | ✅ Library only at v1.4 | same module (combined surface) |
|
||
| § 5.2 D2.4 runtime PM hooks (suspend/resume) | ✅ Done | `Driver::suspend`/`resume` trait + `signal_then_collect` |
|
||
| § 5.2 D2.5 AER foundation (on_error) | ✅ Done | `Driver::on_error` + `ErrorSeverity` + `RecoveryAction` |
|
||
| § 5.2 D2.6 PciQuirkFlags integration (D4) | ✅ Done at v1.4 | `driver-manager/src/quirks.rs` (redox-driver-sys dep) + spawn-time env vars |
|
||
| § 5.2 D3 event-driven hotplug (polling fallback) | ✅ Done | hotplug poll reduced to 250ms; pcid event delivery is the next step |
|
||
| § 5.2 D4 audit-no-stubs.py + 8 test scripts | ✅ Done | 0 violations across 34 files |
|
||
| § 5.2 D4 redbear-driver-policy package | ✅ Done | `local/recipes/system/redbear-driver-policy/` |
|
||
| § 5.2 D4 --concurrent=N CLI flag | ✅ Done at v1.4 | `main.rs` parses arg, calls `ConcurrentDeviceManager::enumerate(cap)` |
|
||
| § 5.2 D5 audit document | ✅ Done | `local/docs/evidence/driver-manager/D5-AUDIT.md` |
|
||
| § 5.2 C0 dormant service files | ✅ Committed at v1.4 | `local/sources/base` submodule (commit `0407d9cc`) |
|
||
| **Operator ratification** | 🔴 Not yet | required before C1 begins |
|
||
|
||
**v1.4 test totals:** 52 tests across the three crates, all passing.
|
||
|
||
**§ 0.5 audit gate at v1.4:** 0 violations across 34 scanned files.
|
||
|
||
**v1.3 status update over v1.2:**
|
||
|
||
v1.3 records the **full D-phase implementation**: every D1–D4 deliverable
|
||
in the § 5.1 D-phase is now in source. The § 0.5 comprehensive-implementation
|
||
audit gate (`local/scripts/driver-manager-audit-no-stubs.py`) returns
|
||
**zero violations across 34 files**. The § 0.6 parallel-development
|
||
constraint is preserved — the migration is fully implemented but driver-manager
|
||
remains excluded from any boot path until operator ratification. See
|
||
`local/docs/evidence/driver-manager/D5-AUDIT.md` for capability-by-capability
|
||
status.
|
||
|
||
| Item | Status at v1.3 | Where |
|
||
|---|---|---|
|
||
| § 5.1 D0 foundation verified | ✅ Done | `cargo test` 28+5 + 3 + 13 = 49 tests passing |
|
||
| § 5.1 D1 C1 capability (`add_dynid`/`remove_dynid`) | ✅ Done | `redox-driver-core/src/{dynid,manager}.rs` |
|
||
| § 5.1 D1 C2 capability (`Driver::remove` + WAIT_FOR_REAPPEAR) | ✅ Done | `driver-manager/src/config.rs` (real SIGTERM+SIGKILL) |
|
||
| § 5.1 D1 C3, C6 (enable_device / set_bus_master) | ✅ Done | `open_pcid_channel` via `pcid_interface::EnableDevice` |
|
||
| § 5.1 D1 C4 (BAR request) | 🟡 Corrected at v3.0 | `<addr>/bind` never existed in pcid (see v3.0 correction 1); claim collapses into channel exclusivity per P0-1 |
|
||
| § 5.1 D1 C5, C7, C8, C12, C16, C17 (child-side) | ✅ Done | pre-existing driver daemons |
|
||
| § 5.1 D1 format coexistence | ✅ Done | `convert_legacy` function in config.rs |
|
||
| § 5.1 D1 SpawnDecision committee | ✅ Done | `spawn_decision_gate()` function |
|
||
| § 5.2 D2.1 SMP concurrent probe | ✅ Done | `redox-driver-core/src/concurrent.rs` (worker pool) |
|
||
| § 5.2 D2.2 C-state / P-state advisors | 🟡 Corrected at v3.0 | advisory theater (assessment G6) — P0-3 strips to honest core (MSI-X env hint or removal) |
|
||
| § 5.2 D2.3 IOMMU + MSI-X + NUMA helpers | ✅ Done | same module (combined surface) |
|
||
| § 5.2 D2.4 runtime PM hooks (suspend/resume) | ✅ Done | `Driver::suspend`/`resume` trait + `signal_then_collect` |
|
||
| § 5.2 D2.5 AER foundation (on_error) | ✅ Done | `Driver::on_error` + `ErrorSeverity` + `RecoveryAction` |
|
||
| § 5.2 D2.6 PciQuirkFlags integration (D4) | ✅ Done | `driver-manager/src/quirks.rs` (redox-driver-sys dep) |
|
||
| § 5.2 D3 event-driven hotplug (polling fallback) | ✅ Done | hotplug poll reduced to 250ms; pcid event delivery is the next step |
|
||
| § 5.2 D4 audit-no-stubs.py + 8 test scripts | ✅ Done | 0 violations across 34 files |
|
||
| § 5.2 D4 redbear-driver-policy package | ✅ Done | `local/recipes/system/redbear-driver-policy/` |
|
||
| § 5.2 D5 audit document | ✅ Done | `local/docs/evidence/driver-manager/D5-AUDIT.md` |
|
||
| § 5.2 C0 dormant service files | ✅ Done | `local/sources/base/init.{,initfs.d/}/*-manager.service` |
|
||
| **Operator ratification** | 🔴 Not yet | required before C1 begins |
|
||
|
||
**Test totals at v1.3:**
|
||
|
||
- `redox-driver-core`: 28 unit + 5 integration = 33 tests
|
||
- `redox-driver-pci`: 3 tests
|
||
- `driver-manager`: 13 unit tests
|
||
- **Total: 49 tests, all passing**
|
||
|
||
**§ 0.5 audit gate at v1.3:** 0 violations across 34 scanned files.
|
||
|
||
**v1.2 status update over v1.1:**
|
||
|
||
The § 0 strategic context and § 5 D/C phase structure are unchanged from v1.1.
|
||
This revision records what was **implemented** during the parallel-development
|
||
sprint (v1.1 → v1.2). See `local/docs/evidence/driver-manager/D5-AUDIT.md` for
|
||
the formal capability-by-capability audit.
|
||
|
||
| Item | Status at v1.2 | Where |
|
||
|---|---|---|
|
||
| § 5.1 D0 foundation verified | ✅ Done (v1.1) | redacted |
|
||
| § 5.1 D1 C1 capability (`add_dynid`/`remove_dynid`) | ✅ Done (v1.2) | `local/recipes/drivers/redox-driver-core/source/src/{dynid,manager}.rs` |
|
||
| § 5.1 D1 C2 capability (`Driver::remove` + WAIT_FOR_REAPPEAR) | ✅ Done (v1.2) | `local/recipes/system/driver-manager/source/src/config.rs` |
|
||
| § 5.1 D1 C3, C6 (enable_device / set_bus_master) | ✅ Covered (v1.2) | already in `open_pcid_channel` via `pcid_interface` |
|
||
| § 5.1 D1 C4 (BAR request explicitness) | ✅ Covered (v1.2) | already in `claim_pci_device` |
|
||
| § 5.1 D1 C5, C7, C8, C12, C16, C17 (child-side) | ✅ Done (pre-D1) | already in driver daemons |
|
||
| § 5.1 D1 format coexistence (legacy `[[drivers]]` + new `[[driver]]`) | ✅ Done (v1.2) | `local/recipes/system/driver-manager/source/src/config.rs::convert_legacy` |
|
||
| § 5.1 D1 SpawnDecision committee | ✅ Done (v1.2) | `local/recipes/system/driver-manager/source/src/config.rs::spawn_decision_gate` |
|
||
| § 5.2 D2 modern-tech surface (PM/AER/MSI-X/IOMMU/C-state/P-state) | 🟡 Partial (v1.2) | `Driver::suspend`/`resume`/`on_error` trait; `signal_then_collect`; SMP/IOMMU defer to D5 |
|
||
| § 5.2 D3 event-driven hotplug | 🟡 Polling fallback (v1.2) | `redox_driver-pci::subscribe_hotplug` returns `Unsupported` until pcid event delivery lands |
|
||
| § 5.2 D4 audit-no-stubs.py + 8 test scripts | ✅ Done (v1.2) | `local/scripts/driver-manager-audit-no-stubs.py`, `local/scripts/test-driver-manager-*.sh` |
|
||
| § 5.2 D4 redbear-driver-policy package | ✅ Done (v1.2) | `local/recipes/system/redbear-driver-policy/` |
|
||
| § 5.2 D5 audit document | ✅ Done (v1.2) | `local/docs/evidence/driver-manager/D5-AUDIT.md` |
|
||
| § 5.2 C0 dormant service files | ✅ Done (v1.2) | `local/sources/base/init.{,initfs.d/}/*-manager.service` |
|
||
|
||
**v1.1 additions over v1.0:**
|
||
|
||
- New `§ 0 Strategic Context` with six subsections (rationale, success criteria, upstream risk, modern tech surface, comprehensive principle, parallel development).
|
||
- Restructured `§ 5 Phased migration plan` into **D-Phase (parallel development)** and **C-Phase (cutover & validation)** tracks. The two tracks are sequential, not interleaved.
|
||
- The original P0–P6 dual-mode strategy is folded into the new structure. driver-manager is now **never enabled** until the D-phase feature-complete gate (D5) ratifies.
|
||
- Cross-referenced § 0 references in § 1, § 2, § 4, § 5, § 9.
|
||
|
||
---
|
||
|
||
## Title and intent
|
||
|
||
`pcid-spawner` is the current single-purpose daemon that reads `/etc/pcid.d/*.toml`,
|
||
walks `/scheme/pci/`, and forks driver daemons for matched devices. It is correct,
|
||
small (127 lines), and ships the boot-critical `00_pcid-spawner.service` plus the
|
||
initfs `40_pcid-spawner-initfs.service` unit. It cannot grow further without
|
||
becoming a different program: deferred-probe semantics, dependency graphs, runtime
|
||
hotplug, driver parameters, and a managed device tree all require the more capable
|
||
abstraction in `local/recipes/system/driver-manager/` (already drafted but not
|
||
wired).
|
||
|
||
`driver-manager` is the intended replacement. Its implementation is partial: the
|
||
abstract `redox-driver-core` machinery exists, the `DeviceManager` orchestrates
|
||
buses/drivers/binding, a `PciBus` enumerates `/scheme/pci`, deferred probing and
|
||
hotplug are sketched in `hotplug.rs`, and a `scheme:driver-manager` server exposes
|
||
read-only observability. The piece that has never landed is the integration:
|
||
package it, write `00_driver-manager.service`, retire `pcid-spawner` cleanly,
|
||
adopt the Linux-style capability split (C1–C18), and absorb the CachyOS policy
|
||
patterns that have proven necessary on AMD-first hardware.
|
||
|
||
This plan produces that migration **without losing any boot path**, honoring the
|
||
project's **never-delete, never-disable, fix-root-cause** policy
|
||
(`local/AGENTS.md` § COMPREHENSIVE IMPLEMENTATION POLICY). pcid-spawner stays
|
||
buildable and present in the tree at every phase; it is the safe fallback.
|
||
|
||
---
|
||
|
||
## 0. Strategic context
|
||
|
||
This section captures the **why**, **what done looks like**, **upstream
|
||
risk**, **modern-technology surface**, **comprehensiveness principle**, and
|
||
**parallel-development constraint** of the migration. Every later section
|
||
implements these principles — they are not aspirations, they are binding
|
||
constraints derived from `local/AGENTS.md` and the project's engineering
|
||
standards.
|
||
|
||
### 0.1 Rationale for driver-manager (why not extend pcid-spawner)
|
||
|
||
**Three converging forces make `pcid-spawner` insufficient as the long-term
|
||
driver spawner:**
|
||
|
||
1. **Architectural ceiling.** pcid-spawner is a 127-line single-purpose
|
||
launcher that enumerates PCI devices and forks drivers against a static
|
||
config table. It cannot grow to handle: deferred-probe semantics (driver
|
||
needs a scheme that is not yet registered); dependency-graph scheduling
|
||
(drivers depending on other drivers); runtime hotplug (PCIe native, USB,
|
||
Thunderbolt); driver parameter mutation (a userspace tool writing
|
||
`iwlwifi` parameters at runtime); AER error recovery; runtime-PM
|
||
suspend/resume. Adding any of these to a 127-line launcher requires
|
||
restructuring into a different program.
|
||
|
||
2. **Driver coverage roadmap.** Red Bear's planned driver surface grows from
|
||
17 to ~30+ daemons (per `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`). New
|
||
drivers — `amd-mp2-i2cd`, `intel-thc-hidd`, Wi-Fi (`iwlwifi`, `mt76`),
|
||
GPU backends (`redox-drm` AMD DC variant), Thunderbolt, NVMe namespaces —
|
||
each carry their own configuration model, dependency graph, and runtime
|
||
parameter surface. A per-driver ad-hoc spawner is no longer maintainable.
|
||
|
||
3. **Driver ecosystem contract demands.** Wi-Fi drivers need delayed probe
|
||
(firmware load + regulatory database check); I2C/audio controllers need
|
||
dependency-aware ordering (acpi → i2c → driver); GPU drivers need stable
|
||
device-id→driver binding with explicit version handling; hotplug events
|
||
require an event-driven loop, not a one-shot enumeration. pcid-spawner's
|
||
architecture cannot satisfy any of these contractually.
|
||
|
||
**What we lose by NOT moving to driver-manager:**
|
||
|
||
- The existing `redox-driver-core` framework (Bus/Driver/DeviceManager/
|
||
ProbeEvent/DriverMatch/DriverParams) becomes dead code.
|
||
- The hard-won work in `redox-driver-acpi`, `redox-driver-pci`, and
|
||
`local/recipes/system/driver-params/` becomes single-purpose.
|
||
- Wi-Fi, USB hotplug, AER, and runtime-PM work has to be re-architected
|
||
against a different manager primitive.
|
||
- The CachyOS-style policy layer (blacklist, autoload, ordering, options)
|
||
cannot live cleanly without a manager that reads `/etc/driver-manager.d/`.
|
||
|
||
**Why not just extend pcid-spawner:**
|
||
|
||
- pcid-spawner is 127 LOC doing exactly one thing. Adding deferred probing +
|
||
dependency graphs + hotplug + params + AER + PM grows it to thousands of
|
||
LOC with a fundamentally different architecture.
|
||
- The `redox-driver-core` framework already exists with the right trait
|
||
surface. Throwing it away to extend pcid-spawner would violate
|
||
`local/AGENTS.md` § LOCAL FORK SUPREMACY POLICY: "Red Bear adapts to
|
||
upstream, never throws away working code."
|
||
- The Linux-style capability split (C1–C18 in § 2.3) is the right design.
|
||
pcid-spawner implements none of C9, C11, C13–C18; bolting them on is more
|
||
work than building the manager they belong in.
|
||
|
||
**Why this is happening now:**
|
||
|
||
- The framework is already built (`local/recipes/system/driver-manager/` is a
|
||
compilable Rust crate at version `0.3.1` with 1250 LOC and a 783KB binary
|
||
artifact).
|
||
- The 17 drivers' Cargo manifests depend on `pcid_interface`
|
||
(`PciFunctionHandle::connect_default()`). They are already compatible with
|
||
the manager contract — no driver-code changes are required at any phase.
|
||
- Driver parameters and dependency gating are needed before Wi-Fi (per
|
||
`local/docs/WIFI-IMPLEMENTATION-PLAN.md`).
|
||
- USB hotplug (per `local/docs/USB-IMPLEMENTATION-PLAN.md`) needs the
|
||
manager's hotplug surface.
|
||
- AER recovery (per `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`)
|
||
needs the manager's `Driver::on_error` surface.
|
||
|
||
### 0.2 Success criteria (definition of done)
|
||
|
||
The migration is **complete** when ALL of the following hold simultaneously:
|
||
|
||
1. **Functional parity** with pcid-spawner, verified by
|
||
`local/scripts/test-driver-manager-parity.sh`: every device pcid-spawner
|
||
binds, driver-manager binds. No regression in driver set coverage.
|
||
|
||
2. **Linux 7.1 capability bridge complete.** All of C1–C18 are implemented
|
||
and tested, at the priority levels in § 2.3:
|
||
- P0 set: C1, C2, C3, C4, C5, C6, C7, C8, C12, C16
|
||
- P1 set: C9, C10, C11, C14, C17, C18
|
||
- P2 set: C13, C15
|
||
|
||
3. **Modern technology surface integrated** (§ 0.4):
|
||
- SMP-aware concurrent probe verified
|
||
- C-state and P-state coordination verified
|
||
- Runtime PM suspend/resume callback chain verified
|
||
- IOMMU group management verified
|
||
- AER error recovery verified
|
||
|
||
4. **Hotplug functional and event-driven** (not polling). Verified on QEMU
|
||
synthetic and at least one real-hardware hot-add scenario.
|
||
|
||
5. **Quirk policy honored.** `redox-driver-sys::PciQuirkFlags` consulted for
|
||
every bind/remove decision. `NO_MSIX`, `NO_PME`, `NEED_FIRMWARE`,
|
||
`DISABLE_ACCEL`, `FORCE_LEGACY_IRQ`, `NEED_IOMMU`, etc., all flow through
|
||
the manager.
|
||
|
||
6. **Hardware validation matrix passes** on:
|
||
- AMD Threadripper (canonical AMD-first profile)
|
||
- AMD Zen4 desktop
|
||
- Intel Alder Lake or later desktop
|
||
- At least one bus category each: storage (NVMe + AHCI), network
|
||
(e1000d + rtl8168d), USB (xhcid), GPU (Intel or AMD display path)
|
||
|
||
7. **30-day stability gate.** In production cutover (C4), the
|
||
`ConditionPathExists` guard on `00_pcid-spawner.service` has not fired
|
||
in 30 days of continuous operation.
|
||
|
||
8. **Regressions clean.** All of
|
||
`local/scripts/test-driver-manager-{parity,active,initfs,hotplug,pm,cutover}.sh`
|
||
pass on every release branch for the same 30-day window.
|
||
|
||
9. **No-deferred-comments cleanup.** The inline deferred comments in
|
||
`config/redbear-mini.toml:31` and `config/redbear-device-services.toml:9-13`
|
||
are removed (no longer accurate).
|
||
|
||
10. **Operator ratification.** Explicit human acknowledgement at each
|
||
C-phase boundary and at the final C4 transition.
|
||
|
||
### 0.3 Upstream risk — what if Redox upstream ships their own driver-manager
|
||
|
||
This is **not a remote possibility** — Redox upstream has been discussing
|
||
driver-manager-style architectures. Red Bear's response is encoded as policy
|
||
ahead of time.
|
||
|
||
**What Redox upstream's plan could look like:**
|
||
|
||
- A single-purpose scheme:pci consumer that spawns drivers against a config
|
||
table (very similar to pcid-spawner, the canonical upstream).
|
||
- A more capable per-bus spawner (closer to Red Bear's driver-manager).
|
||
- A kernel-side enumeration manager (drastic, unlikely in Redox's
|
||
microkernel model).
|
||
|
||
**Red Bear's response strategy:**
|
||
|
||
- Compare against the C1–C18 capability list (§ 2.3). A manager is "equivalent"
|
||
if it covers at least the P0 set of capabilities and exposes a compatible
|
||
driver handoff contract.
|
||
|
||
- **If upstream ships a fully equivalent manager**, evaluate migrating to
|
||
use theirs per `local/AGENTS.md` § LOCAL FORK SUPREMACY POLICY (Red Bear
|
||
adapts to upstream; never pins/holds back). This is the most likely
|
||
scenario for the long term.
|
||
|
||
- **If upstream ships a different approach** (per-bus spawning, a kernel-side
|
||
manager, a Lua-scripted policy layer), Red Bear's driver-manager becomes a
|
||
**Red Bear extension layer on top of the upstream primitive**, OR is
|
||
preserved as a local recipe that supplements the upstream manager rather
|
||
than replacing it. The decision is taken at the time based on coverage.
|
||
|
||
- **If upstream ships the equivalent manager within 6 months of our D5 gate**,
|
||
the migration plan is re-evaluated against theirs. The C-phases
|
||
(§ 5.2) become a no-op or a thin shim. pcid-spawner remains the
|
||
fallback regardless.
|
||
|
||
**Concrete protections already in the plan:**
|
||
|
||
- `00_driver-manager.service` is a service name, not a binary. Swapping the
|
||
`cmd=` to upstream's binary is a one-line change.
|
||
- The driver's runtime contract is `PCID_CLIENT_CHANNEL=<fd>` (preserved
|
||
from upstream Redox pcid-spawner). Any manager that delivers this env var
|
||
keeps drivers unmodified.
|
||
- The capability taxonomy (C1–C18) is a Red Bear design tool, not an
|
||
upstream commitment. We use it to evaluate upstream choices.
|
||
|
||
**What does NOT change:**
|
||
|
||
- `local/recipes/system/driver-manager/source/` is and remains a local
|
||
Red Bear crate, not an upstream-fork clone.
|
||
- The D-phase development continues regardless of upstream decisions.
|
||
- pcid-spawner stays as the safe fallback until C4.
|
||
|
||
### 0.4 Modern technology surface (SMP, S/P states, runtime PM, IOMMU, AER, hotplug, MSI-X, NUMA)
|
||
|
||
The driver-manager is **genuinely modern** by design. The technologies listed
|
||
below are integrated as **functional features** (not stubs):
|
||
|
||
1. **SMP awareness.**
|
||
- Manager enumeration runs single-threaded for race-free exploration
|
||
(correct — exploration must be deterministic).
|
||
- **Concurrent probe dispatch**: `max_concurrent_probes` is enforced
|
||
via a worker pool. Today it is policy metadata; in D2 it becomes
|
||
real concurrent dispatch via `std::thread::scope` or `rayon`.
|
||
- **Per-vector IRQ CPU affinity**: MSI-X vectors are bound to specific
|
||
CPUs based on topology (CPUID leaf `0Bh` for AMD, `0Fh` for Intel).
|
||
- Hotplug event loop is a separate thread; events post through a lockless
|
||
queue to the manager (no shared mutable state with the probe path).
|
||
|
||
2. **C-states (CPU idle states).**
|
||
- Manager exposes driver-bound/unbound events to `cpufreqd` /
|
||
`thermald`. Hotplug-removing a device → CPU may drop to a deeper
|
||
C-state.
|
||
- Manager signals probe-completion → CPU may return to its former
|
||
governor state.
|
||
- System-wide C-state transitions coordinated through
|
||
`redox-driver-acpi` (via scheme:acpi).
|
||
|
||
3. **P-states (CPU performance states).**
|
||
- On driver bind/unbound, manager publishes a P-state advisory via
|
||
`cpufreqd` socket or a `pstate` scheme.
|
||
- Cold-boot probe order is documented and P-state-aware: storage
|
||
drivers spawn first (high P-state by default), audio/USB spawn later
|
||
(low P-state allowed).
|
||
- Driver spawn during boot is gated on `cpufreqd` confirming P-state
|
||
is high enough for the driver to initialise (e.g., NVMe completion
|
||
timeouts require a high enough P-state).
|
||
|
||
4. **Runtime PM (per-driver).**
|
||
- `Driver::suspend()` / `Driver::resume()` callbacks are **fully
|
||
implemented** with real state save + power-down (default: real D3
|
||
transition through pcid; not `Ok(())`).
|
||
- PCIe D-state transitions (D0 ↔ D3hot ↔ D0) coordinated through pcid's
|
||
`SetPowerState` request via `PcidClient`.
|
||
- Hotplug-remove pre-empts runtime PM: the manager calls
|
||
`force_suspend()` before unbinding.
|
||
|
||
5. **IOMMU groups** (`local/recipes/system/iommu/`).
|
||
- Per-device group registration via the `iommu` scheme.
|
||
- DMA isolation enforcement: drivers cannot bypass their group's domain.
|
||
- Group-awareness for hotplug: a sibling device in the same group
|
||
must also be quiesced before removal.
|
||
|
||
6. **AER (PCI Express Advanced Error Recovery).**
|
||
- `Driver::on_error(severity)` callback is **fully implemented** with
|
||
severity dispatch (CORRECTABLE → log; NONFATAL → retry with masking;
|
||
FATAL → slot reset → config restore → re-bind).
|
||
- Manager registers with `pciehp` for hotplug events (Presence Detect
|
||
Changed, Data Link Layer State Changed, MRL Sensor Changed).
|
||
- Per-driver error recovery action: drivers implement `Driver::on_error`
|
||
for their specific hardware (NVMe reset, e1000 soft-reinit, etc.).
|
||
|
||
7. **MSI-X vector allocation.**
|
||
- `pci_alloc_irq_vectors()` semantics preserved (MSI-X preferred,
|
||
fallback to MSI, fallback to INTx; capability-aware honouring of
|
||
`PciQuirkFlags::NO_MSIX`).
|
||
- Per-vector fd returned to driver (each vector independently
|
||
reachable through `/scheme/irq`).
|
||
- Multiple MSI-X vectors per device (e.g., xHCI's 16-vector
|
||
interrupt setup).
|
||
|
||
8. **NUMA awareness** (when `local/recipes/system/numad/` is live).
|
||
- Driver's memory regions classified by NUMA node.
|
||
- `DmaBuffer::allocate(size, align, node_hint)` prefers same-node.
|
||
- Hot-add monitored for NUMA topology changes.
|
||
|
||
9. **Modern vendor-specific paths.**
|
||
- **AMD**: PSP firmware load (via `firmware-loader`), DCN hardware
|
||
blocks, GTT addressing, AMD-Vi IOMMU integration.
|
||
- **Intel**: GGTT setup, hot-plug through `pciehp`, MFG/RC6 power
|
||
management, IOMMU group isolation.
|
||
- Per-vendor path is a `redox-drm` backend (out of scope here); the
|
||
manager's runtime-PM / quirk / hotplug hooks are exercised by all of
|
||
them.
|
||
|
||
**Why these technologies, and why not others:**
|
||
|
||
- We do NOT adopt `cgroup-vram` (CachyOS extras) — Redox has no cgroups.
|
||
- We do NOT adopt `sched-ext` / `BORE` scheduler — kernel-side work, per
|
||
`local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` Phase T.
|
||
- We DO adopt CachyOS-style `modprobe.d` patterns (blacklist, options,
|
||
autoload) — see § 2.2. These translate cleanly to `/etc/driver-manager.d/`.
|
||
|
||
### 0.5 Comprehensive implementation principle (no stubs, comprehensive code only)
|
||
|
||
The driver-manager implementation is **comprehensive, systematic, methodical**.
|
||
`local/AGENTS.md` § STUB AND WORKAROUND POLICY — ZERO TOLERANCE applies
|
||
without exception. The principle is re-stated here in the specific form that
|
||
applies to driver-manager:
|
||
|
||
- **No stubs.** Every public API in `redox-driver-core::driver::Driver`,
|
||
`redox-driver-core::bus::Bus`, and `driver-manager::scheme::*` is fully
|
||
implemented. No `unimplemented!()`, no `todo!()`, no empty match arms
|
||
returning trivial defaults.
|
||
- **No `#ifdef`-guarded no-ops.** No Rust `cfg` gates that disable entire
|
||
feature paths.
|
||
- **No `LD_PRELOAD`-style tricks.** No override layer that hides
|
||
unimplemented features.
|
||
- **No `sed`/`awk` rewriting.** TOML config is parsed, not preprocessed.
|
||
|
||
**Per-method completeness requirements** (any violation blocks D5):
|
||
|
||
| Surface | Forbidden pattern | Required behaviour |
|
||
|---|---|---|
|
||
| `Driver::probe(info)` | `unimplemented!()` or `Ok(())` skip | Full match-table evaluation + dependency check + device claim + spawn |
|
||
| `Driver::remove(info)` | `_ => Ok(())` drop | Reclaim bind handle, terminate child via `SIGTERM`, refresh `scheme:driver-manager:/bound` |
|
||
| `Driver::suspend(info)` | `Ok(())` default | Real PCI D-state transition via pcid (`SetPowerState`), save config space, log |
|
||
| `Driver::resume(info)` | `Ok(())` default | Restore config space, walk IRQ vectors (re-arm MSI-X), signal ready |
|
||
| `Driver::on_error(info, severity)` | `Ok(())` or `Unsupported` | Severity dispatch: CORRECTABLE → log; NONFATAL → retry; FATAL → slot reset |
|
||
| `Driver::params()` | `DriverParams::default()` | Real parameter definitions (priority, debug, exclusive_with, runtime flags) |
|
||
| `Bus::enumerate_devices()` | `Ok(vec![])` skip | Walk scheme:pci config files, populate `DeviceInfo` with vendor/device/class/subclass/prog_if/revision/subsystem IDs |
|
||
| `Bus::subscribe_hotplug()` | `Err(BusError::Unsupported)` | Subscribe to `/scheme/pci/events` (or pcid uevent channel); return real `HotplugSubscription` |
|
||
| `Manager::enumerate()` | empty loop | Walk all buses, dispatch to drivers, emit `ProbeEvent`s with deferred support |
|
||
| `Manager::retry_deferred()` | no-op | Re-evaluate deferred queue, re-probe if dependencies now satisfied, emit events |
|
||
|
||
**Honest absence** vs. **stub** matters. If a feature is genuinely not
|
||
applicable (e.g., NUMA awareness on a non-NUMA system), the manager code
|
||
calls a runtime probe that returns an honest answer:
|
||
|
||
```rust
|
||
// PREFERRED (D4+):
|
||
if !query_numa_support() {
|
||
return BusError::Unsupported; // honest absence
|
||
}
|
||
|
||
// FORBIDDEN at any phase:
|
||
// if !query_numa_support() { return Ok(()) }
|
||
// if cfg!(...) { return BusError::Unsupported } else { return Ok(()) }
|
||
```
|
||
|
||
The result: type signatures are honest, runtime is honest, documentation is
|
||
honest. A driver receiving `Unsupported` knows to fall back to uniform memory
|
||
without assuming the manager is silently doing the right thing.
|
||
|
||
**Systematic** means the same architectural pattern applies across all bus
|
||
types (PCI, USB, ACPI, future platform), all driver types (storage, network,
|
||
GPU, USB, audio), and all capability surfaces (C1–C18). The `Driver` trait is
|
||
the single contract; the `Bus` trait is the single contract; the
|
||
`scheme:driver-manager:/<node>` filesystem is the single observability surface.
|
||
|
||
**Methodical** means the work unfolds in the D-phases of § 5.1 with
|
||
verifiable exit criteria. No phase skips ahead. No phase declares done with
|
||
deferred items. The audit script `local/scripts/driver-manager-audit-no-stubs.py`
|
||
(D4 deliverable) is the formal gatekeeper.
|
||
|
||
**Right-component implementation rule** (from `local/AGENTS.md` § STUB AND
|
||
WORKAROUND POLICY):
|
||
|
||
| Symptom | Wrong fix | Required fix |
|
||
|---|---|---|
|
||
| `eventfd()` not in relibc | Stub in libc wrapper | Implement in relibc proper |
|
||
| `Bus::subscribe_hotplug` not in pcid scheme | Stub the manager side | Implement event delivery in pcid scheme |
|
||
| TOML config gap | Accept both formats but emit empty drivers | Implement FULL conversion from legacy `pcid.d` to new `drivers.d` |
|
||
| Driver needs runtime PM | `suspend: fn() { Ok(()) }` default | Implement genuine D3 transition in pcid, expose via trait |
|
||
| AER not yet wired | Mark feature as `Unsupported` and ignore errors | Implement severity dispatch + recovery action in `Driver::on_error` |
|
||
| Hotplug loop is polling-only | Document as "future work" | Implement event subscription via `Bus::subscribe_hotplug()` |
|
||
| TOML `[[driver.match]]` field missing | Skip silently | Return `Err(format!("unsupported match field: {name}"))` from loader |
|
||
|
||
### 0.6 Parallel development constraint (built but not utilised until fully developed)
|
||
|
||
**The driver-manager is being implemented in parallel and not being utilized
|
||
before fully developed.** This is the **binding development model**.
|
||
|
||
**Current state (2026-07-20):**
|
||
|
||
- The local-recipe at `local/recipes/system/driver-manager/source/` accumulates
|
||
improvements in commits.
|
||
- `pcid-spawner` is the boot path in every `redbear-*.toml`.
|
||
- `driver-manager` is **NOT** added to any `[packages]` section.
|
||
- `driver-manager` does **NOT** have an `00_driver-manager.service`.
|
||
- `driver-manager`'s binary MAY be built locally (it is at 783KB), but it is
|
||
**NOT** shipped in any produced ISO or harddrive image.
|
||
- Inline deferred comments in `config/redbear-mini.toml:31` and
|
||
`config/redbear-device-services.toml:9-13` reflect this.
|
||
|
||
**Operational reality during D-Phase:**
|
||
|
||
- `local/recipes/system/driver-manager/source/` is committed to the current
|
||
branch as part of normal development.
|
||
- `config/redbear-*.toml` does not include `driver-manager = {}`.
|
||
- The ISO build (`./local/scripts/build-redbear.sh redbear-mini`) does not
|
||
include the driver-manager binary.
|
||
- Test scripts `local/scripts/test-driver-manager-{parity,active,...}.sh` are
|
||
written but not in the ISO; they run only on developer workstations and CI
|
||
runners.
|
||
- `local/scripts/TOOLS.md` and `local/AGENTS.md` continue to describe
|
||
driver-manager as "in development" until D5 ratifies.
|
||
|
||
**When does driver-manager become eligible for the boot path?**
|
||
|
||
When ALL of D0–D5 exit gates are satisfied (see § 5.1):
|
||
|
||
- D0 (foundation) complete
|
||
- D1 (Linux capability bridge) complete — all P0 capabilities of C1–C18
|
||
implemented and tested
|
||
- D2 (modern technology surface) complete — SMP, S/P states, runtime PM,
|
||
IOMMU groups, AER all implemented
|
||
- D3 (hotplug event-driven) complete
|
||
- D4 (quark integration + comprehensive audit) complete
|
||
- D5 (feature-complete gate) — formal audit confirms no stubs in § 0.5
|
||
matrix, **operator ratification received**
|
||
|
||
**Until then**, the parallel development continues without touching the live
|
||
boot path.
|
||
|
||
**Implications for the original P0–P6 phasing (v1.0 of this plan):**
|
||
|
||
The original plan's P0 (dual-mode observation) and P1 (rootfs active
|
||
driver-manager) are now folded into the C-phases (§ 5.2). The D-phases
|
||
describe the **pre-cutover work** (i.e., the parallel development the team is
|
||
currently doing). The C-phases describe the **post-completion cutover**. The
|
||
two are sequential, not interleaved.
|
||
|
||
This constraint is the **one operational reality** that separates this
|
||
migration from any ordinary refactor. A feature that is not fully complete is
|
||
NOT shipped; the build system does not "auto-enable" it; CI does not bundle
|
||
it. The first time driver-manager appears in a boot path is after D5 +
|
||
operator ratification. **No exceptions.**
|
||
|
||
---
|
||
|
||
## Position in the doc set
|
||
|
||
- This is the canonical planning authority for `pci-spawner` → `driver-manager`
|
||
migration beneath `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||
- It does NOT replace any subsystem-specific plan. It supersedes the inline
|
||
comment in `config/redbear-mini.toml` (line 31):
|
||
*"driver-manager requires driver config migration and is not yet ready"*
|
||
and the inline comment in `config/redbear-device-services.toml` (line 9-13):
|
||
*"driver-manager intentionally not included: it is the intended future
|
||
replacement for pcid-spawner but is not yet ready (driver config migration
|
||
pending) and was previously packaged-but-unused — its service launched
|
||
pcid-spawner instead of driver-manager."*
|
||
- Cross-references: `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`
|
||
(where pcid-spawner hardening currently lives),
|
||
`local/docs/QUIRKS-SYSTEM.md` + `QUIRKS-IMPROVEMENT-PLAN.md` (where the
|
||
driver-manager→redox-driver-sys quirks bridge is planned),
|
||
`local/docs/USB-IMPLEMENTATION-PLAN.md` (where the Bus trait is wired for USB),
|
||
`local/docs/WIFI-IMPLEMENTATION-PLAN.md` (where matching semantics live for
|
||
mac80211/cfg80211).
|
||
|
||
## Scope
|
||
|
||
**In scope:**
|
||
|
||
- Lifecycle and integration of the existing
|
||
`local/recipes/system/driver-manager/` crate to replace
|
||
`local/sources/base/drivers/pcid-spawner/`.
|
||
- Format migration of `/etc/pcid.d/*.toml` (legacy `pcid_interface::Config`) to
|
||
`/lib/drivers.d/*.toml` (driver-manager `DriverMatch`), plus a back-compat
|
||
loader that lets both formats coexist during transition.
|
||
- Init service rewrite: `00_pcid-spawner.service` (rootfs) →
|
||
`00_driver-manager.service` with `00_pcid-spawner.service` retained as a
|
||
fallback unit that runs only when `driver-manager` is absent on the initfs.
|
||
Initfs unit `40_pcid-spawner-initfs.service` is renamed to
|
||
`40_driver-manager-initfs.service` with the same blocking-oneshot contract.
|
||
- Linux 7.1 capability bridging: the manager exposes, and the spawned drivers
|
||
consume via PCID_CLIENT_CHANNEL env continuation, the capabilities C1–C18
|
||
(driver match, lifecycle, BAR mapping, IRQ vectors, runtime PM, AER error
|
||
recovery, etc.).
|
||
- CachyOS policy patterns: policy-layer TOML with blacklist/options/autoload,
|
||
driven by the manager (not by `modprobe` since Red Bear has no modules).
|
||
|
||
**Out of scope:**
|
||
|
||
- Adding USB / ACPI / platform buses to the device manager — those are in
|
||
`local/docs/USB-IMPLEMENTATION-PLAN.md` and follow once the PCI manager lands.
|
||
- Replacing `pcid` itself (the scheme:pci owner) — it stays the canonical PCI
|
||
scheme surface, just like Linux's `pci_bus_type` owning `/sys/bus/pci/devices/`.
|
||
- Replacing `redox-driver-sys` — driver-manager consumes it for the
|
||
hardware-quirks surface once Q3 lands (see `local/docs/QUIRKS-IMPROVEMENT-PLAN.md`
|
||
Task 2.1).
|
||
- Replacing the kernel — Redox's PCI scheme is userspace; the kernel's role
|
||
(memory/irq/acpi/dt/serio schemes, MMIO mapping, MSI/MSI-X vector delivery)
|
||
is unchanged.
|
||
|
||
## Policy constraints (binding)
|
||
|
||
Every step in this plan inherits the following constraints from
|
||
`local/AGENTS.md`:
|
||
|
||
1. **NEVER DELETE** a package, service, config, or patch. pcid-spawner stays.
|
||
2. **NEVER IGNORE** a package by `"ignore"`. driver-manager lands as additive.
|
||
3. **NEVER COMMENT OUT** a service or config entry to "fix" a build.
|
||
4. **ALWAYS FIX** the root cause when something breaks.
|
||
5. The migration is **operator-ratified**: each phase has an explicit exit gate
|
||
and is not closed until the gate is met AND human-acknowledged.
|
||
|
||
The durability rule applies: any source-tree edit during this migration is
|
||
mirrored into `local/patches/` or `local/sources/<component>/` in the same
|
||
work session. `local/patches/base/` and the fork `local/sources/base/` carry
|
||
the changes; `recipes/core/base/source/` is not the durable location.
|
||
|
||
---
|
||
|
||
## 1. Current state assessment
|
||
|
||
### 1.1 What pcid-spawner does today
|
||
|
||
**Source:** `local/sources/base/drivers/pcid-spawner/src/main.rs` (127 lines)
|
||
**Cargo:** `local/sources/base/drivers/pcid-spawner/Cargo.toml`
|
||
**Recipe:** `recipes/core/base/drivers/pcid-spawner/recipe.toml` (path-fork)
|
||
|
||
Single `main()` function with the following behaviour, ordered:
|
||
|
||
1. **Wait** for `/scheme/pci/` to appear (200 × 50ms retry, 10s total) — this
|
||
was added by Red Bear patch `local/patches/base/P4-pcid-spawner-pci-coordinate-env.patch`
|
||
alongside the PCI coordinate env vars.
|
||
2. **Load** merged driver configs via `config::config("pcid")` — concatenates
|
||
`/etc/pcid.d/*.toml` (rootfs) or `/scheme/initfs/etc/pcid.d/*.toml`
|
||
(`--initfs` mode) into one `Config` struct.
|
||
3. **Iterate** `/scheme/pci/` directory entries. For each:
|
||
- `PciFunctionHandle::connect_by_path(&device_path)` — opens the per-device
|
||
`channel` handle in `scheme:pci`. The handle is the **mutual-exclusion
|
||
lock**: pcid returns `ENOLCK` to any second opener. This is the only claim
|
||
mechanism.
|
||
- On `ENOLCK`: log debug, `continue`. On other errors: log error, `continue`.
|
||
The spawner never aborts on a single bad device.
|
||
- `config.match_function(&full_device_id)` — legacy matching (class →
|
||
subclass → interface → vendor/device, optional multi-vendor `ids` map,
|
||
optional device_id_range).
|
||
- On miss: log debug, `continue`.
|
||
4. **Enable** the PCI function (`handle.enable_device()`) — pcid writes the
|
||
command register to enable bus mastering + memory + IO.
|
||
5. **Build** `Command` from `driver.command`, resolving `program` either
|
||
absolute or prefixed `/usr/lib/drivers/<program>`.
|
||
6. **Pass** env vars to the child:
|
||
- `PCID_CLIENT_CHANNEL=<channel_fd>` — the bincode channel FD the driver
|
||
uses for `PciFunctionHandle::connect_default()` to reach pcid.
|
||
- `PCID_SEGMENT=<hex>` — added by Red Bear P4 patch.
|
||
- `PCID_BUS=<hex>` — added by Red Bear P4 patch.
|
||
- `PCID_DEVICE=<hex>` — added by Red Bear P4 patch.
|
||
- `PCID_FUNCTION=<dec>` — added by Red Bear P4 patch.
|
||
7. **Spawn** via `daemon::Daemon::spawn(command)` — parent blocks until the
|
||
child signals readiness. This is the **driver-ready handshake** and is
|
||
honoured by every existing driver daemon (`ahcid`, `e1000d`, `xhcid`, etc.).
|
||
8. **Close** the parent's copy of the channel FD.
|
||
|
||
### 1.2 What the existing driver-manager implements
|
||
|
||
**Source root:** `local/recipes/system/driver-manager/source/`
|
||
**Cargo:** `local/recipes/system/driver-manager/source/Cargo.toml` (Cat 1, version `0.3.1`)
|
||
**Recipe:** `local/recipes/system/driver-manager/recipe.toml` (template=cargo, path="source")
|
||
|
||
Five source files (`src/main.rs`, `config.rs`, `scheme.rs`, `hotplug.rs`,
|
||
`exec.rs`) totalling ~1250 lines. Built and present at
|
||
`recipes/system/driver-manager/target/x86_64-unknown-redox/stage/usr/bin/driver-manager`
|
||
(783KB ELF, dated 2026-07-19). Binary-store artifact cached in
|
||
`repo/x86_64-unknown-redox/driver-manager.pkgar`. **NOT** packaged into any
|
||
current `[packages]` section of `redbear-*.toml`.
|
||
|
||
| Area | Status | Notes |
|
||
|---|---|---|
|
||
| Compile | ✅ | Builds clean on x86_64-unknown-redox |
|
||
| Core abstraction | ✅ | `redox-driver-core` (Bus/Driver/DeviceManager/ProbeEvent/ManagerConfig/DriverParams/MatchTable/HotplugEvent) |
|
||
| PCI bus | ✅ | `redox-driver-pci::PciBus` reads `/scheme/pci` raw config space; class/subclass/program-if/subdevice IDs returned |
|
||
| TOML config loader | ✅ | `/lib/drivers.d/*.toml` (name, description, priority, command, match, depends_on) |
|
||
| Probe pipeline | ✅ | ProbeResult::Bound / NotSupported / Deferred / Fatal with retry queue |
|
||
| Deferred retry | 🟡 | 30 retries × 500ms; logs `deferred-retry-limit-reached` and exits 0 |
|
||
| Async probe | 🟡 | `ManagerConfig::async_probe = true` is set, but `thread::spawn(...).join()` is used immediately, making it actually synchronous |
|
||
| `max_concurrent_probes` | 🟡 | Stored as policy metadata; never enforced (all probes are serial) |
|
||
| Hotplug | 🟡 | `run_hotplug_loop()` polls every 2s; `Bus::subscribe_hotplug()` is hidden behind an unused `hotplug` feature flag |
|
||
| `scheme:driver-manager` | ✅ | Read-only `/devices`, `/bound`, `/events`, `/devices/<pci-addr>`, plus param persistence to `/tmp/redbear-driver-params/<addr>/{driver,enabled}` |
|
||
| Spawn via PCID_CLIENT_CHANNEL | 🟡 Corrected at v3.0 | `<addr>/bind` never existed in pcid; P0-1 collapses claim into the channel open (`ENOLCK` exclusivity) and passes `PCID_CLIENT_CHANNEL=<fd>` — the pcid-spawner model |
|
||
| Driver parameters | 🟡 | `Driver::params()` declared but driver-manager's own schema (`enabled`, `priority`) is parameter-only; runtime writes via `scheme:driver-params` (separate daemon `local/recipes/system/driver-params`) |
|
||
| Quirks integration | 🔴 | `redox-driver-sys` is **not** in the dep list; `pci_has_quirk` / `pci_get_quirk_flags` are NOT consulted |
|
||
| Service wiring | 🔴 | No `00_driver-manager.service` exists; absent from all `[packages]` sections |
|
||
| Tests | 🔴 | Zero driver-manager tests; 12 unit tests in `redox-driver-core` |
|
||
| Documentation | 🟡 | No dedicated doc; mentioned in `UPSTREAM-SYNC-PROCEDURE.md` § "driver-manager: Deferred" and `PACKAGE-BUILD-QUIRKS.md` § "driver-manager Removed During Sync" |
|
||
|
||
### 1.3 Service inventory that depends on pcid-spawner
|
||
|
||
**Service definitions:**
|
||
|
||
| Service | Mode | Flag | Where |
|
||
|---|---|---|---|
|
||
| `00_pcid-spawner.service` | `oneshot_async` | (none) | `local/sources/base/init.d/` |
|
||
| `40_pcid-spawner-initfs.service` | `oneshot` (blocking) | `--initfs` | `local/sources/base/init.initfs.d/` |
|
||
| `/etc/init.d/00_pcid-spawner.service` (override) | `oneshot_async` | (none) | `config/redbear-mini.toml` lines 575-583 |
|
||
| `00_base.target` `requires_weak` | — | — | `local/sources/base/init.d/00_base.target` |
|
||
|
||
**Service dependencies** (every service that references `00_pcid-spawner.service`):
|
||
|
||
| Config | Service referencing it | Reference role |
|
||
|---|---|---|
|
||
| `config/redbear-mini.toml` | `10_evdevd.service` | `requires_weak` |
|
||
| `config/redbear-mini.toml` | `20_udev-shim.service` | `requires_weak` |
|
||
| `config/redbear-mini.toml` | 11 other services | `requires_weak` |
|
||
| `config/redbear-full.toml` | `10_evdevd.service` | `requires_weak` |
|
||
| `config/redbear-full.toml` | `redox-drm` consumers | `requires_weak` |
|
||
| `config/redbear-greeter-services.toml` | `redbear-greeter` (seatd chain) | `requires_weak` |
|
||
| `config/redbear-device-services.toml` | explicit comment that driver-manager is deferred | — |
|
||
| `config/acid.toml` | acid test config | `requires_weak` |
|
||
| `config/redoxer.toml` | redoxer CI config | `requires_weak` |
|
||
|
||
Migrating this dependency graph without breaking any boot path requires
|
||
**keeping `00_pcid-spawner.service` available as a fallback** through P0–P2 and
|
||
**running both managers transiently during P3**.
|
||
|
||
### 1.4 Configuration surfaces
|
||
|
||
**Active now (legacy format):**
|
||
|
||
- `config/redbear-mini.toml:500-512` — `/etc/pcid.d/*.toml` overrides
|
||
(`ihdgd.toml`, `virtio-gpud.toml`, `00_text_mode_gpu_mask.toml`)
|
||
- `local/config/pcid.d/intel_gpu.toml` — Intel GPU match
|
||
- `local/config/pcid.d/amd_gpu.toml` — AMD GPU match
|
||
|
||
**Already drafted (driver-manager format, currently inert):**
|
||
|
||
- `config/redbear-device-services.toml:116-490` — full set of
|
||
`/lib/drivers.d/*.toml`:
|
||
- `00-storage.toml` (ahcid, ided, nvmed, virtio-blkd, usb-bot)
|
||
- `10-network.toml` (e1000d, rtl8168d, rtl8139d, ixgbed, virtio-netd)
|
||
- `20-usb.toml` (xhcid, ehcid, ohcid, uhcid, usbhubd)
|
||
- `30-graphics.toml` (vesad, virtio-gpud, redox-drm)
|
||
- `40-input.toml` (ps2d, usbhidd, intel-thc-hidd)
|
||
- `50-audio.toml` (ihdad, ac97d, sb16d)
|
||
- `70-usb-class.toml` (usbscsid, usbaudiod, redbear-ftdi)
|
||
|
||
**Decision-needed:** are these drafts correctly normalised for driver-manager's
|
||
TOML schema (`[driver]` with `match` tables, priority, depends_on)? **D1**
|
||
verifies them. Many entries will need editing to converge on a single matching
|
||
language.
|
||
|
||
### 1.5 Fork / source provenance
|
||
|
||
- `local/sources/base/` is the local fork of the `base` Redox upstream
|
||
submodule. It holds BOTH `drivers/pcid/` (the scheme:pci owner) AND
|
||
`drivers/pcid-spawner/` (the legacy spawner).
|
||
- `local/recipes/system/driver-manager/` is a **local recipe** (Cat 1 in-house
|
||
crate), not a submodule. It does NOT duplicate upstream code; it's a fresh
|
||
Red Bear creation. No `submodule/driver-manager` branch exists, no
|
||
`.gitmodules` entry, no need to create one (per `local/AGENTS.md` §
|
||
BRANCH AND SUBMODULE POLICY: "We don't create new branches/repos. We work on
|
||
existing submodules first. … A new submodule is only justified when the
|
||
component is large enough that submodule pinning provides real value over a
|
||
tracked tree or local recipe. driver-manager satisfies none of these").
|
||
- The 17 driver daemons under `local/sources/base/drivers/{storage,net,graphics,audio,usb}/`
|
||
each have `pcid = { path = "../../pcid" }` in their Cargo.toml. **They depend
|
||
on `pcid_interface` (a lib crate alongside pcid), NOT on the pcid-spawner
|
||
binary.** The runtime contract they honour is `PCID_CLIENT_CHANNEL=<fd>`, which
|
||
driver-manager preserves. No driver-binary changes are required.
|
||
|
||
---
|
||
|
||
## 2. Cross-reference: pcid-spawner vs driver-manager vs Linux 7.1 vs CachyOS
|
||
|
||
### 2.1 Linux 7.1 PCI driver model surface (`local/reference/linux-7.1/` at `ab9de95c9`)
|
||
|
||
| Subsystem | Linux source | Capability exposed |
|
||
|---|---|---|
|
||
| PCI bus type | `drivers/pci/pci-driver.c:1726-1742` (`pci_bus_type`), `include/linux/pci.h:1021-1154` (`pci_driver` + `pci_device_id` macros) | C1: id_table + match |
|
||
| Probe / remove | `drivers/pci/pci-driver.c:473-553` (`pci_device_probe` / `pci_device_remove` / `pci_device_shutdown`) | C2: device lifecycle |
|
||
| Module loading | `kernel/kmod.c:64-179` (`__request_module` → `call_modprobe`) + `drivers/pci/pci-driver.c:1587-1617` (`pci_uevent` with MODALIAS) | C1′: driver lookup with alias |
|
||
| Driver-core binding | `drivers/base/bus.c` (`bus_add_driver` / `bus_probe_device` / `device_attach` / `driver_attach`) | C2′: symmetric device/driver iteration |
|
||
| Sysfs surface | `drivers/pci/pci-sysfs.c` (`vendor`, `device`, `class`, `subsystem_*`, `resource`, `config`, `bind`, `unbind`, `new_id`, `remove_id`, `driver_override`) | C1 + C2 + C11 + observability |
|
||
| PCIe native hotplug | `drivers/pci/hotplug/pciehp_core.c:185-372` (`pciehp_probe` + presence/attention/MRL/DLLSC handlers) | C14: hotplug events |
|
||
| AER | `drivers/pci/pcie/aer.c:1203-1280` (`aer_recover_work_func` + `pcie_do_recovery`) + `include/linux/pcieport_if.h` (`pci_error_handlers`) | C13: error recovery |
|
||
| Runtime PM | `drivers/pci/pci-driver.c:1314-1440` (`pci_pm_runtime_*` + `pci_dev_pm_ops`) | C9 + C18: suspend/resume |
|
||
| IOMMU / DMA | `drivers/pci/pci-driver.c:1668-1711` (`pci_dma_configure`) + `drivers/iommu/iommu.c` (`iommu_device_use_default_domain`) | C15: DMA / IOMMU |
|
||
| MSI / MSI-X | `drivers/pci/msi/api.c:205-264` (`pci_alloc_irq_vectors_affinity`) + `include/linux/pci.h:1166-1168` (`pci_irq_vector`) | C7 + C8: vector allocation |
|
||
| BAR / MMIO | `drivers/pci/pci.c:2120-238, 3916-4172` (`pci_enable_device` / `pci_request_regions` / `pci_set_master` / `pci_ioremap_bar`) | C3 + C4 + C5 + C6: device + bar map |
|
||
| Power states | `include/linux/pci.h:183-188` (`PCI_D0..PCI_D3cold`) + `pci.h` `pci_set_power_state` | C9: power state control |
|
||
| Capabilities search | `drivers/pci/pci.c` (`pci_find_capability` / `pci_find_ext_capability`) | C16: capability iteration |
|
||
|
||
**Synthesis (cross-reference `pci_driver` ↔ `Driver` trait ↔ driver-manager):**
|
||
|
||
| Linux `pci_driver` member | Linux function | Redox current (`redox-driver-core`) | Redox pcid-spawner path | Gap to fill |
|
||
|---|---|---|---|---|
|
||
| `.probe` | `pci_device_probe` | `Driver::probe(&DeviceInfo) -> ProbeResult` | (deferred to child spawn) | async + retry + dependency-aware |
|
||
| `.remove` | `pci_device_remove` | `Driver::remove(&DeviceInfo) -> Result<(), DriverError>` | (no remove path at all) | full lifecycle |
|
||
| `.suspend` / `.resume` | `pci_pm_runtime_*` | `Driver::suspend() / resume()` (default Ok) | (no path) | graceful shutdown + wake |
|
||
| `.id_table` | `pci_match_device` | `Driver::match_table() -> &[DriverMatch]` | legacy `match_function()` | unify on `DriverMatch` |
|
||
| `.shutdown` | `pci_device_shutdown` | (not in trait) | (no path) | add to trait or handle via systemd |
|
||
| `.err_handler` | `pcie_do_recovery` | (not in trait) | (no path) | add `Driver::on_error()` |
|
||
| `.driver_managed_dma` | `iommu_device_use_default_domain` | (not in trait) | (no path) | add `Driver::dma_managed()` |
|
||
|
||
### 2.2 CachyOS pattern surface (CachyOS-Settings `master`)
|
||
|
||
| Pattern | CachyOS location | Red Bear equivalent |
|
||
|---|---|---|
|
||
| udev rule w/ subsystem match + sysfs write | `usr/lib/udev/rules.d/60-ioschedulers.rules` (HDD/SSD/NVMe scheduler assignment) | driver-manager scheme event `set_io_scheduler(dev, "bfq"\|"mq-deadline"\|"kyber")` |
|
||
| udev rule w/ `bind`/`unbind` lifecycle | `usr/lib/udev/rules.d/71-nvidia.rules` (NVIDIA PM lifecycle) | driver-manager `register_add_event` + `register_remove_event` matching on vendor + class |
|
||
| Cross-subsystem reaction (battery state → audio params) | `usr/lib/udev/rules.d/20-audio-pm.rules` (snd_hda_intel powersave) | driver-manager event filter `{AC=>BATT}` → action `set_param(driver, "power_save", value)` |
|
||
| Sentinel-based idempotency | `/run/udev/snd-hda-intel-powersave` | driver-manager in-memory `init_done: BTreeSet<(driver_name, param_set)>` |
|
||
| modprobe.d blacklist | `usr/lib/modprobe.d/blacklist.conf` (`blacklist iTCO_wdt`) | `/etc/driver-manager.d/00-blacklist.conf`: `[[blacklist]] module = "iTCO_wdt"` |
|
||
| modprobe.d options | `usr/lib/modprobe.d/amdgpu.conf` (`options amdgpu si_support=1`) | `/etc/driver-manager.d/50-amdgpu.conf`: `[amdgpu.params] si_support = true` |
|
||
| modules-load.d | `usr/lib/modules-load.d/ntsync.conf` (`ntsync`) | `/etc/driver-manager.d/autoload.d/ntsync.conf`: `module = "ntsync"` |
|
||
| Driver mutual exclusion (two drivers claim same PCI IDs) | `usr/lib/modprobe.d/amdgpu.conf` (`amdgpu` SI/CIK ↔ `radeon` SI/CIK off) | driver-manager priority + explicit `exclusive_with` field |
|
||
| Path-triggered (config change) service activation | `usr/lib/udev/rules.d/85-iw-regulatory.rules` + `cachyos-iw-set-regdomain.{path,service}` | driver-manager + scheme watcher over `/etc/driver-manager.d/` |
|
||
| Ramdisk driver manifest (mkinitcpio hook ordering) | `linux-cachyos` preset (`microcode`/`modconf`/`kms`/`block`/`filesystems`/`fsck`) | `/usr/lib/driver-manager.d/initfs.manifest` (`ramdisk_drivers = ["ahci", "nvme", "redoxfs"]`, ordered) |
|
||
| Cold-boot parameter injection (immutable module params) | `modprobe.d/options ...` | driver-manager `set_pre_spawn_param(driver, param, value)` recorded in `BOOT_TIMELINE` |
|
||
| Curated-policy-as-a-package (cachyos-settings) | `cachyos-settings` ARCH package | `redbear-driver-policy` local recipe (or `redbear-meta` extension) |
|
||
|
||
### 2.3 Capability table — what a full driver-manager must provide (C1–C18)
|
||
|
||
**Note:** the "Priority" column uses P0/P1/P2 as **capability-priority labels** —
|
||
*not* phase references. The P0/P1/P2 capability priorities pre-date the § 5 D/C
|
||
phase restructure. Capability priorities are:
|
||
|
||
- **P0** (capability priority) = blocker for desktop path
|
||
- **P1** (capability priority) = desktop-ready
|
||
- **P2** (capability priority) = production-grade
|
||
|
||
These priorities map onto specific phases in § 5.1 D-Phase (P0 set lands in
|
||
D1; P1 set lands in D2/D3; P2 set lands in D2/D4).
|
||
|
||
| # | Capability | Linux equivalent | driver-manager API | Priority | Notes |
|
||
|---|---|---|---|---|---|
|
||
| **C1** | ID-table match + dynamic ID add | `pci_match_device` + sysfs `new_id` / `remove_id` | `DeviceManager.register_driver()` + `match_table()` + `add_dynid()` | P0 | Already present in `redox-driver-core`. `add_dynid` not yet exposed in driver-manager; **D1** must wire it |
|
||
| **C2** | Device lifecycle (probe/remove) | `pci_device_probe` / `pci_device_remove` | `Driver::probe(&DeviceInfo)` + `Driver::remove(&DeviceInfo)` | P0 | Already present. driver-manager calls `Driver::probe` only after claim + dependency check |
|
||
| **C3** | Enable / disable device | `pci_enable_device` / `pci_disable_device` | `enable_device(pci_addr)` → pcid `EnableDevice` request | P0 | driver-manager must call pcid `EnableDevice` BEFORE spawning the child |
|
||
| **C4** | BAR request/release | `pci_request_regions` / `pci_release_regions` | channel open (exclusive `ENOLCK`) + BAR map via `pcid_interface::map_bar` | P0 | Resolved at v3.0: `<addr>/bind` never existed; claim == channel (P0-1) |
|
||
| **C5** | BAR map / unmap | `pci_ioremap_bar` / `pci_iounmap` | child `scheme:memory/physical@<wc\|wb\|uc>` via `redox_driver_sys::pci::PciDevice::map_bar` | P0 | Not a manager task — child uses `redox-driver-sys` directly |
|
||
| **C6** | Bus master on/off | `pci_set_master` / `pci_clear_master` | `set_bus_master(pci_addr, true)` | P0 | driver-manager sets on probe, clears on remove |
|
||
| **C7** | Allocate IRQ vectors | `pci_alloc_irq_vectors` | `pci_alloc_vectors(pci_addr, min, max, flags) -> vector_count` | P0 | driver-manager proposes; child daemon allocates via `PcidClient` |
|
||
| **C8** | Resolve vector → IRQ handle | `pci_irq_vector` | `pci_vector_handle(pci_addr, index) -> scheme:irq fd` | P0 | child uses `scheme:irq` directly |
|
||
| **C9** | Runtime PM | `pci_pm_runtime_*` | `set_power_state(pci_addr, D0\|D3hot\|D3cold)` | P1 | pcid `SetPowerState` request exists; driver-manager exposes it (lands in **D2**) |
|
||
| **C10** | Save/restore config space | `pci_save_state` / `pci_restore_state` | child uses `PcidClient::read_config()` | P1 | not a manager concern |
|
||
| **C11** | Driver override | sysfs `driver_override` | `set_driver_override(pci_addr, driver_name)` | P1 | driver-manager exposes it as a scheme op (writes `pci_addr/override`) — **D2** |
|
||
| **C12** | Config space read/write | `pci_read_config_*` | child uses `PcidClient::read_config() / write_config()` | P0 | not a manager concern |
|
||
| **C13** | AER error recovery | `pci_error_handlers` + `pcie_do_recovery` | `Driver::on_error(error_kind) -> RecoveryAction` | P2 | Lands in **D2** (AER recovery is part of the modern technology surface) |
|
||
| **C14** | Hotplug events (PDC / DLLSC / MRL) | `pciehp_*` | `manager.subscribe_hotplug() -> HotplugEvent` | P1 | Requires event-driven scheme:pci surface; **D3** delivers event-driven hotplug |
|
||
| **C15** | DMA mask / IOMMU | `dma_set_mask` + `iommu_device_use_default_domain` | `set_dma_mask(pci_addr, bits)` + `iommu_assign_group(pci_addr)` | P2 | iommu daemon present (`local/recipes/system/iommu/`); wiring lands in **D2** (modern tech surface) |
|
||
| **C16** | Find capabilities | `pci_find_capability` / `pci_find_ext_capability` | child uses `redox_driver_sys::pci::PciDevice::find_capability` | P0 | not a manager concern |
|
||
| **C17** | INTx on/off | `pci_intx` | child via `PcidClient` | P1 | not a manager concern |
|
||
| **C18** | System PM (suspend/resume) | `pci_pm_*` | `Driver::suspend() / resume()` callbacks via manager | P2 | driver-manager keeps a registry of bound drivers for the systemd-supervisor to call; **D2** |
|
||
|
||
**Source-of-truth invariant:** C7 (vector allocation) is implemented inside pcid
|
||
itself, not in driver-manager. driver-manager's role is to (a) call `enable_device`
|
||
through pcid before spawning, (b) hand the channel FD to the child, and (c) call
|
||
`remove` (which clears bus master + sends ULP/cleanup requests) when a device
|
||
disappears from hotplug. The same split holds for C5, C12, C16, C17: those are
|
||
the child's contract via `redox-driver-sys`.
|
||
|
||
### 2.4 boot-timeline and observability alignment
|
||
|
||
Note: the "Priority" column reuses P0/P1/P2 as capability-priority labels (the
|
||
same priority ladder used in § 2.3) — *not* phase references. Capacity
|
||
deliveries for these priorities land in the § 5 D-Phase track (P0 set in
|
||
D1; P1 set in D2/D3; P2 set in D4). AER-aware `reset` handling (P1 here)
|
||
is part of D2's modern-technology surface.
|
||
|
||
| Linux surface | driver-manager equivalent | Status | Priority |
|
||
|---|---|---|---|
|
||
| `dmesg` `pci ... BAR X set to ...` | `BOOT_TIMELINE_PATH = /tmp/redbear-boot-timeline.json` (already present) | ✅ exists | (D0) |
|
||
| `journalctl -k` | `scheme:driver-manager:/events` (read-only ring buffer, 256 lines) | ✅ exists | (D0) |
|
||
| `lspci -v` | `scheme:driver-manager:/devices/<addr>` (vendor / device / class / driver / enabled=true) | 🟡 partial | P0 |
|
||
| `lspci -vv -s ...` + `lspci -xxx -s ...` | not exposed | not yet | P0 |
|
||
| `find /sys/bus/pci/devices -name reset` | not exposed | not yet | P1 — needed for AER + reboot (**D2**) |
|
||
| `pci=nomsi` kernel cmdline | `REDBEAR_DRIVER_MANAGER_FLAGS=disable_msi` env | not yet | P1 |
|
||
| `pci=realloc=` | not exposed | not yet | P2 |
|
||
| `lspci -tv` (tree) | `scheme:driver-manager:/tree` (planned) | not yet | P2 |
|
||
|
||
---
|
||
|
||
## 3. Target architecture
|
||
|
||
### 3.1 Process model (post-migration)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ DRIVER-MANAGER (PID 1 child) │
|
||
│ ▸ Subscribes to /scheme/pci as a client │
|
||
│ ▸ Owns Driver trait objects from TOML │
|
||
│ ▸ Maintains Bus → Device → Driver graph │
|
||
│ ▸ Claims via channel open (ENOLCK) │
|
||
│ ▸ Spawns driver daemons with: │
|
||
│ PCID_CLIENT_CHANNEL=<fd> │
|
||
│ PCID_SEGMENT / PCID_BUS / PCID_DEVICE │
|
||
│ PCID_FUNCTION (Red Bear P4 contract) │
|
||
│ ▸ Registers scheme:driver-manager │
|
||
│ ▸ Writes /tmp/redbear-driver-params/... │
|
||
│ ▸ Writes /tmp/redbear-boot-timeline.json │
|
||
│ ▸ On hotplug (P1): detects add/remove │
|
||
│ ▸ On AER (P5): invokes error handler │
|
||
└───────────────────┬─────────────────────────┘
|
||
│
|
||
┌───────────────────────────┼──────────────────────────┐
|
||
▼ ▼ ▼
|
||
┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐
|
||
│ PCID │ │ SCHEME:PCI │ │ REDOX-DRIVER-SYS │
|
||
│ (Canonical PCI │ │ (per-device │ │ (registered │
|
||
│ scheme owner) │◀──│ channel+bind+ │ │ quirk surface) │
|
||
│ │ │ config+feature) │ │ /scheme:driver-sys│
|
||
└─────────┬──────────┘ └─────────┬──────────┘ └────────────────────┘
|
||
│ │
|
||
│ /scheme/memory │
|
||
│ /scheme/irq │
|
||
│ /scheme:acpi │
|
||
│ /scheme/iommu (P5) │
|
||
▼ ▼
|
||
─────────── KERNEL ───────────
|
||
```
|
||
|
||
### 3.2 New component list
|
||
|
||
| Component | Lives at | Source-of-truth | Phase |
|
||
|---|---|---|---|
|
||
| `driver-manager` daemon | `local/recipes/system/driver-manager/source/` | local recipe (Cat 1) | built in **D0–D5**, enabled at **C0** |
|
||
| `driver-manager-config` package | `local/recipes/system/driver-manager-config/` (NEW) | local recipe (Meta) | **D4** (policy layer) |
|
||
| `/etc/driver-manager.d/*.toml` configs | NEW dir, shipped by `driver-manager-config` | policy | **D4** |
|
||
| `/lib/drivers.d/*.toml` | NEW dir, per-config files | match tables | **D1** (format); **D4** (content) |
|
||
| `00_driver-manager.service` | `local/sources/base/init.d/` | service | **C0** (created dormant); **C3** (active) |
|
||
| `40_driver-manager-initfs.service` | `local/sources/base/init.initfs.d/` | service | **C0** (dormant); **C2** (active blocking) |
|
||
| `local/recipes/system/driver-params` | already exists; extends to consume `scheme:driver-manager` rather than its own bound-text-parsing | observer | **C1** (switch over) |
|
||
| `redbear-driver-policy` package | `local/recipes/system/redbear-driver-policy/` (NEW) | curated package | **D4** (created); **C3** (packaged) |
|
||
|
||
### 3.3 What changes for `pcid-spawner` (NOT deleted, demoted)
|
||
|
||
The v1.1 D/C phase restructure changes pcid-spawner's role as follows:
|
||
|
||
| Track / Phase | pcid-spawner state |
|
||
|---|---|
|
||
| **D-phase (D0–D5)** | **No change.** pcid-spawner remains the live boot path. driver-manager is being built locally but is NOT shipped, NOT packaged, NOT enabled. The boot path is identical to baseline. |
|
||
| **C0** | `00_pcid-spawner.service` gains `ConditionPathExists=!/etc/driver-manager.d/disabled`. Service is dormant by default. |
|
||
| **C1** | driver-manager runs in `--observe` mode (writes BOOT_TIMELINE, does NOT spawn). pcid-spawner is still the actual spawner. |
|
||
| **C2** | `40_driver-manager-initfs.service` becomes `oneshot` blocking in initfs; pcid-spawner initfs service becomes fallback only via `ConditionPathExists`. |
|
||
| **C3** | `00_driver-manager.service` becomes the primary rootfs spawner. `00_pcid-spawner.service` is retained as fallback only (idem for initfs variant). |
|
||
| **C4** | pcid-spawner source tree receives a final commit on the `submodule/base` branch documenting the maintenance-mode status. **Never deleted.** |
|
||
|
||
### 3.4 Wire-level contracts that MUST stay invariant
|
||
|
||
| Contract | Description | Invariant |
|
||
|---|---|---|
|
||
| **C-ENV-1** | `PCID_CLIENT_CHANNEL=<fd>` is passed to every spawned driver daemon | Preserved by `config.rs::probe()` already |
|
||
| **C-ENV-2** | `PCID_SEGMENT`/`PCID_BUS`/`PCID_DEVICE`/`PCID_FUNCTION` env vars (Red Bear P4) | Preserved — driver-manager's probe path must add them |
|
||
| **C-ENV-3** | Program resolution: absolute OR `/usr/lib/drivers/<name>` | Preserved — same prefix logic moves to driver-manager |
|
||
| **C-CHAN-1** | Per-device `channel` open in scheme:pci yields mutual-exclusion (ENOLCK to second opener) | Not the responsibility of driver-manager — that's pcid. driver-manager must use `bind` (NOT `channel`) so multi-driver retry can re-probe without consuming the lock. **Confirm with pcid that `bind` is also exclusive, or document the asymmetry.** |
|
||
| **C-CHAN-2** | Drivers call `PciFunctionHandle::connect_default()` and get a working bincode channel via the FD | Continues unchanged |
|
||
| **C-SVC-1** | Every service that previously `requires_weak=00_pcid-spawner.service` gains `requires_weak=00_driver-manager.service` as an alternative. Driver-manager has `requires_weak=00_pcid-spawner.service` for fallback coordination. | Provides fallback-safety |
|
||
| **C-DAEMON-1** | `daemon::Daemon::spawn()` blocks parent on child ready | driver-manager must use the same primitive to preserve the boot-order guarantee — ahcid/nvmed up before redoxfs mounts |
|
||
| **C-RECIPE-1** | `recipes/core/base/drivers/pcid-spawner/recipe.toml` keeps `path = "../../../local/sources/base/drivers/pcid-spawner"` | Never changes |
|
||
| **C-SCHEME-1** | `scheme:driver-manager` exposes: `/devices`, `/devices/<addr>`, `/bound`, `/events` (read-only) | Already present |
|
||
| **C-PARAM-1** | `driver-params` reads from `/scheme/driver-manager/bound` (instead of its current text-parsing of the bound file) | **C1** wiring |
|
||
|
||
### 3.5 Module / crate dependencies (target state)
|
||
|
||
```
|
||
recipes/system/driver-manager/source/Cargo.toml ─── D0 plus phase-by-phase additions
|
||
├── redox-driver-core (already: local/recipes/drivers/redox-driver-core)
|
||
├── redox-driver-pci (already: local/recipes/drivers/redox-driver-pci)
|
||
├── redox-driver-sys (NEW dep ─ added at D4; previously optional, now required)
|
||
├── pcid_interface (already: local/sources/base/drivers/pcid)
|
||
├── redox-scheme (already: local/sources/redox-scheme)
|
||
├── redox_syscall (already: local/sources/syscall, features=["std"])
|
||
├── log, toml, serde (already)
|
||
├── event-stream (NEW in D3 — for hotplug event consumption)
|
||
├── bitflags (NEW in D2 — for CapabilityFlag aggregation)
|
||
└── [patch.crates-io] (already: redox_syscall, libredox, redox-scheme)
|
||
```
|
||
|
||
`pcid-spawner` Cargo.toml is untouched (it stays in the base submodule fork for
|
||
fallback). No retroactive changes to `daemon::Daemon::spawn`,
|
||
`PciFunctionHandle::connect_default`, or any of the 17 driver daemons.
|
||
|
||
---
|
||
|
||
## 4. Critical risk register
|
||
|
||
| # | Risk | Severity | Mitigation |
|
||
|---|---|---|---|
|
||
| **R1** | Double-spawn race: driver-manager and pcid-spawner both spawn the same driver daemon | 🔴 BLOCKING | **C1** sequencing: driver-manager runs **only** in `--observe` mode first. The actual spawn is gated by `spawn_enabled` flag set by the C1 exit gate. `00_driver-manager.service` is dormant in C0; observable in C1; primary in C3. |
|
||
| **R2** | Driver daemon crashes after spawn, no one restarts it | 🔴 BLOCKING | driver-manager persists `bound_devices` map to `/tmp/redbear-driver-params/`. On `WAIT_FOR_REAPPEAR` per-driver (delivered in **D2**) the manager retries after a 5s backoff. systemd `Restart=` on the driver service files provides the surface-process fallback (**D4**). |
|
||
| **R3** | The match table migration misses a vendor/device pair | 🔴 BLOCKING | **D1** adds "no-match ↔ spin in driver-manager, no spawn" tests for the existing 17 drivers. **C1** runs **both** managers side-by-side and emits `unbound_device_addr=<addr>` lines to `BOOT_TIMELINE` for any device the new manager misses but pcid-spawner bound. |
|
||
| **R4** | The `bind` vs `channel` claim differs in exclusivity | 🟡 HIGH | **D1** step is a QEMU test that opens `bind` from one driver and `channel` from another; verifies the latter gets ENOLCK. Document the asymmetry. |
|
||
| **R5** | Initfs switchroot breaks (storage drivers must be ready before redoxfs mounts) | 🔴 BLOCKING | **C2** keeps `40_pcid-spawner-initfs.service` available (via `ConditionPathExists`). `40_driver-manager-initfs.service` is added in **observation** mode at **C0** and only switches on at **C2** once the storage path passes on at least 3 hardware configs (QEMU virtio + AMD NVMe + Intel SATA). |
|
||
| **R6** | `redox-driver-sys` quirks not consulted during spawn decisions | 🟡 MEDIUM | **D4** phase. Until then, the kernel-side MSI/MSI-X fallback in pcid remains authoritative. No regression on bare metal. |
|
||
| **R7** | Atomic patch governance failure: live source edit goes unmirrored | 🟡 (procedural) | Every source edit during this plan is committed to the `submodule/base` branch (for `pcid-spawner` edits) or as commits within `local/recipes/system/driver-manager/source/` (which is a local-recipe tree, not a fetched source tree). Per `local/AGENTS.md` DURABILITY POLICY. |
|
||
| **R8** | The new `scheme:driver-manager` collides with `scheme:driver-params` | 🟡 MEDIUM | C-PARAM-1 above resolves this: `driver-params` becomes a thin observer over `scheme:driver-manager:/bound`, no separate parsing path. Wired at **C1**. |
|
||
| **R9** | The migration leaves the repo in a state that cannot fall back | 🔴 BLOCKING | During **D-phase**, no boot path is affected (driver-manager is not in the system). During **C-phase**, both managers may run; pcid-spawner is the fallback at every cutover step (`ConditionPathExists=!/etc/driver-manager.d/disabled` gates it). **At no phase is the boot path single-point-of-failure.** |
|
||
| **R10** | The TOML match-table migration produces a silent NO-OP for an edge device (e.g., ID 0x1234:0x5678 not in any entry → driver never binds) | 🟡 HIGH | **D1** implements `missing_match = warn` so any unresolved match is logged. QEMU tests with the 17 known drivers verify each entry before **C3**. |
|
||
| **R11** | The `redox-driver-core` `DeviceManager::probe_device` locks the entire manager mutex for the duration of a probe, blocking `retry_deferred` for slow drivers | 🟡 MEDIUM | **D2** introduces per-driver `Mutex<DriverState>` for finer-grained concurrency; manager's outer mutex held only during dispatch. |
|
||
| **R12** | Device hot-add during switchroot causes race with pcid (which may re-enumerate) | 🟡 MEDIUM | Hotplug is **off** during initfs → rootfs transition. driver-manager starts in `--hotplug=off` until switchroot completes. |
|
||
| **R13** | D-phase work produces a stub or workaround instead of comprehensive code | 🔴 BLOCKING | **`local/scripts/driver-manager-audit-no-stubs.py`** (D4 deliverable) is the formal gatekeeper. Static analysis + QEMU integration test. Any D-phase work that violates § 0.5 fails the D4 audit and blocks D5 ratification. **No partial-credit D5 exit.** |
|
||
| **R14** | driver-manager enters a boot path before D5 ratification (i.e., someone packages it earlier than planned) | 🔴 BLOCKING | Build-system guard: `local/scripts/build-redbear.sh` and the cookbook CI refuse any commit that adds `driver-manager` to `[packages]` in `config/redbear-*.toml` during D-phase. Documented in § 0.6. |
|
||
|
||
### Out-of-scope (deferred to OTHER plans)
|
||
|
||
- USB / ACPI / platform buses → `local/docs/USB-IMPLEMENTATION-PLAN.md`, `local/docs/ACPI-IMPROVEMENT-PLAN.md`
|
||
- GPU render / DRM completion → `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md`
|
||
- Wi-Fi / Bluetooth → `local/docs/WIFI-IMPLEMENTATION-PLAN.md`, `BLUETOOTH-IMPLEMENTATION-PLAN.md`
|
||
- IRQ / MSI-X quality → `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md`
|
||
- IOMMU runtime proof → still QEMU-only per HardWARE matrix
|
||
- Replacement of `pcid` (the scheme:pci owner) — far future, no decision today
|
||
|
||
---
|
||
|
||
## 5. Phased migration plan
|
||
|
||
The migration has **two tracks** operating sequentially, not interleaved:
|
||
|
||
- **D-Phase (Parallel Development).** driver-manager is being built;
|
||
pcid-spawner remains the live boot system. No boot path is affected.
|
||
This phase starts at D0 (current state) and continues through D5
|
||
(feature-complete gate). The team's parallel development work lives here.
|
||
- **C-Phase (Cutover & Validation).** driver-manager is fully built; the
|
||
boot path is switched over from pcid-spawner to driver-manager in
|
||
stages. C0 starts only after D5 + operator ratification.
|
||
|
||
**Authority:** the § 0.6 Parallel Development constraint is binding.
|
||
driver-manager does NOT enter any boot path until D5 ratifies. The
|
||
original v1.0 P0–P6 dual-mode strategy is folded into the C-phases.
|
||
|
||
### 5.1 D-Phase — Parallel Development
|
||
|
||
**State during D-Phase:**
|
||
|
||
- pcid-spawner is the boot path in every `redbear-*.toml`.
|
||
- driver-manager is built locally (committed to
|
||
`local/recipes/system/driver-manager/source/`) but NOT shipped.
|
||
- driver-manager has no `00_driver-manager.service`.
|
||
- No files in `/etc/driver-manager.d/` are read by the live system.
|
||
- No `[packages]` entry contains `driver-manager`.
|
||
- The team's work is recorded in commits to the local recipe source.
|
||
|
||
#### Phase D0 — Foundation (current state)
|
||
|
||
**Status (2026-07-20):** partially complete.
|
||
|
||
**What exists:**
|
||
|
||
- `redox-driver-core` framework: `Bus` trait, `Driver` trait, `DeviceManager`,
|
||
`DriverMatch`, `DriverParams`, `ProbeEvent`, `ProbeResult`. Compiled with
|
||
12 unit tests.
|
||
- `redox-driver-pci::PciBus` reads `/scheme/pci/`, parses PCI config space,
|
||
returns `DeviceInfo` with vendor/device/class/subclass/prog_if/revision/
|
||
subsystem IDs.
|
||
- `local/recipes/system/driver-manager/source/src/{main.rs,config.rs,scheme.rs,hotplug.rs,exec.rs}`
|
||
— 1250 lines compiling to a 783KB ELF.
|
||
- `scheme:driver-manager` registered with `/devices`, `/bound`, `/events`,
|
||
`/devices/<addr>` paths (read-only).
|
||
- Boot timeline JSON at `/tmp/redbear-boot-timeline.json`.
|
||
|
||
**What does NOT yet exist** (D1–D5 work):
|
||
|
||
- Linux 7.x capability bridge: C9, C11, C13, C14, C15, C17, C18 are absent
|
||
- Modern technology surface integration (SMP-aware concurrent probe,
|
||
S/P-state hooks, runtime PM, AER)
|
||
- Event-driven hotplug (current code polls every 2s)
|
||
- Quirk integration with `redox-driver-sys` (no `redox-driver-sys` import
|
||
in `source/Cargo.toml`)
|
||
- Format-coexistence TOML loader (current loader only accepts new
|
||
`[[driver]]` format)
|
||
|
||
**Exit criteria for D0:**
|
||
|
||
1. `cargo build --release -p driver-manager` clean.
|
||
2. `cargo test -p redox-driver-core` 12/12 green.
|
||
3. `local/recipes/system/driver-manager/target/x86_64-unknown-redox/stage/usr/bin/driver-manager`
|
||
exists.
|
||
4. No `00_driver-manager.service` in any init.d.
|
||
5. No `driver-manager = {}` in any `[packages]` section.
|
||
|
||
#### Phase D1 — Linux 7.x capability bridge (target: 6–10 weeks)
|
||
|
||
**Preconditions:** D0 exit criteria met.
|
||
|
||
**Goal:** Implement every P0 capability from § 2.3 (C1, C2, C3, C4, C5, C6,
|
||
C7, C8, C12, C16).
|
||
|
||
**Deliverables:**
|
||
|
||
- `redox-driver-core::driver::Driver` trait gains full
|
||
`suspend()` / `resume()` / `on_error()` / `params()` implementations with
|
||
concrete behaviour (not stubs — see § 0.5).
|
||
- `redox-driver-core::bus::Bus` trait gains event-driven
|
||
`subscribe_hotplug()` implementation in `PciBus`.
|
||
- `local/recipes/system/driver-manager/src/manager-probe.rs` (new module)
|
||
handles the SpawnDecision committee (C2', C3, C4, C6).
|
||
- Format-coexistence TOML loader accepting both `[drivers]` (legacy
|
||
pcid-spawner) and `[[driver]]` (driver-manager) formats from the same
|
||
directory tree.
|
||
- New test script `local/scripts/test-driver-manager-parity.sh` (used in
|
||
C1, but drafted here).
|
||
|
||
**Exit criteria for D1:**
|
||
|
||
1. Every P0 capability of C1–C18 is implemented and unit-tested.
|
||
2. `local/scripts/test-driver-manager-parity.sh` returns identical bound
|
||
sets under both formats.
|
||
3. Integration test (QEMU + all 17 drivers) shows driver-manager can
|
||
shadow pcid-spawner exactly.
|
||
|
||
#### Phase D2 — Modern technology surface (target: 8–12 weeks)
|
||
|
||
**Preconditions:** D1 exit criteria met.
|
||
|
||
**Goal:** Integrate SMP-aware concurrent probe, C/P-state coordination,
|
||
runtime PM hooks, IOMMU groups, MSI-X vector allocation, AER recovery
|
||
(see § 0.4 for the full tech surface).
|
||
|
||
**Deliverables:**
|
||
|
||
- `redox-driver-core::manager::DeviceManager::probe_device` becomes truly
|
||
concurrent (`std::thread::scope` or `rayon`,
|
||
`max_concurrent_probes` enforced).
|
||
- MSI-X vector allocation with per-vector fds exposed via
|
||
`redox-driver-sys::irq::MsixTable`.
|
||
- Per-driver P-state advisory publisher (interacts with `cpufreqd`).
|
||
- C-state coordination hook with `cpufreqd` / `thermald`.
|
||
- IOMMU group registration via `local/recipes/system/iommu/`.
|
||
- D-state transitions (D0 ↔ D3hot ↔ D0) through pcid's
|
||
`SetPowerState` request.
|
||
|
||
**Exit criteria for D2:**
|
||
|
||
1. Concurrent probe dispatch verified (`max_concurrent_probes = 4` shows
|
||
4-way parallelism in QEMU timings).
|
||
2. Per-driver P-state advisory verified on real AMD/Intel hardware.
|
||
3. IOMMU-group-aware binding demonstrated on at least one QEMU +
|
||
vfio-passthrough run.
|
||
4. Runtime PM suspend/resume callback chain verified.
|
||
|
||
#### Phase D3 — Hotplug event-driven (target: 4–6 weeks)
|
||
|
||
**Preconditions:** D2 exit criteria met.
|
||
|
||
**Goal:** Replace polling-based hotplug with event-driven subscription.
|
||
|
||
**Deliverables:**
|
||
|
||
- `Bus::subscribe_hotplug()` returns `HotplugSubscription` mapping to a
|
||
real event fd (via `Bus::poll_hotplug_events()` or equivalent).
|
||
- `PciBus` consumes `/scheme/pci/events` (requires pcid scheme event
|
||
delivery — feature request to pcid maintainer).
|
||
- `Manager::hotplug_loop()` becomes event-driven, removing the 2-second
|
||
poll entirely.
|
||
|
||
**Exit criteria for D3:**
|
||
|
||
1. Hotplug event arrival latency < 200 ms on QEMU synthetic add/remove.
|
||
2. Real-hardware hotplug (PCIe Native or USB) verified on at least one
|
||
AMD and one Intel bare-metal target.
|
||
|
||
#### Phase D4 — Quirk integration + comprehensive audit (target: 6–8 weeks)
|
||
|
||
**Preconditions:** D3 exit criteria met.
|
||
|
||
**Goal:** Wire `redox-driver-sys::PciQuirkFlags` into bind/remove decisions;
|
||
complete feature audit confirming § 0.5 compliance.
|
||
|
||
**Deliverables:**
|
||
|
||
- `local/recipes/system/driver-manager/source/Cargo.toml` adds
|
||
`redox-driver-sys` as path dep.
|
||
- `manager-probe.rs` consults `PciQuirkFlags::NO_MSIX`, `NO_PME`,
|
||
`NEED_FIRMWARE`, `DISABLE_ACCEL`, etc., during spawn decisions.
|
||
- Audit script `local/scripts/driver-manager-audit-no-stubs.py` runs
|
||
against the source tree and confirms: every public trait method has a
|
||
concrete implementation, no `unimplemented!()`, no `todo!()`, no
|
||
`#[allow(dead_code)]` for production code paths, no `Ok(())` defaults in
|
||
trait methods that have a real responsibility (per § 0.5 matrix).
|
||
- Quirk policy delivered: `/etc/driver-manager.d/{00-blacklist.conf,
|
||
50-amdgpu.toml,autoload.d/ntsync.conf}` patterns work as designed.
|
||
|
||
**Exit criteria for D4:**
|
||
|
||
1. `driver-manager-audit-no-stubs.py` reports zero violations.
|
||
2. Quirk-driven spawn decisions match expected behaviour (e.g.,
|
||
`DISABLE_ACCEL` causes `redox-drm --no-render` to be invoked).
|
||
3. Hardware-validation-matrix AMD Threadripper + Intel Alder Lake both
|
||
pass.
|
||
|
||
#### Phase D5 — Feature-complete gate (audit before cutover)
|
||
|
||
**Preconditions:** D4 exit criteria met, **operator ratification**.
|
||
|
||
**Goal:** Formal declaration that driver-manager is feature-complete and
|
||
ready to cut over.
|
||
|
||
**Deliverables:**
|
||
|
||
- Audit document `local/docs/evidence/driver-manager/D5-AUDIT.md` listing
|
||
every C1–C18 capability with status (✅ Production / 🟡 Build-grade /
|
||
🔴 Not Implemented).
|
||
- Updated `local/docs/HARDWARE-VALIDATION-MATRIX.md` with driver-manager
|
||
rows.
|
||
- This document's `Last reviewed` line updated to the D5 completion date.
|
||
- Operator's written ratification (chat log, email, or commit message).
|
||
|
||
**Exit criteria for D5:**
|
||
|
||
1. Every entry on the C1–C18 table is at least 🟡 Build-grade.
|
||
2. The § 0.5 no-stub audit is clean (audit script returns 0).
|
||
3. Hardware validation matrix passes on at least one AMD and one Intel
|
||
profile with at least 3 driver categories each (storage, network,
|
||
GPU).
|
||
4. The § 0.2 success criteria 1–6 are met (criteria 7–10 are C-phase
|
||
criteria).
|
||
5. Operator has ratified in writing.
|
||
|
||
**At this point**, the D-phase work is **OVER**. The C-phase begins.
|
||
|
||
### 5.2 C-Phase — Cutover & Validation
|
||
|
||
The C-phase begins only after D5 ratifies. The cutover is sequential,
|
||
gated, and operator-ratified at every phase boundary. The cutover does
|
||
NOT require pcid-spawner to be removed — it stays as a `ConditionPathExists`
|
||
fallback.
|
||
|
||
#### Phase C0 — Service wiring (dormant service file)
|
||
|
||
**Preconditions:** D5 complete.
|
||
|
||
**Goal:** Add the dormant service file and `[packages]` entry. Driver-manager
|
||
remains inactive.
|
||
|
||
**Deliverables:**
|
||
|
||
- `local/sources/base/init.d/00_driver-manager.service` (NEW, dormant by
|
||
default — never auto-starts).
|
||
- `local/sources/base/init.initfs.d/40_driver-manager-initfs.service`
|
||
(NEW, dormant by default).
|
||
- `local/sources/base/init.d/00_pcid-spawner.service` gains
|
||
`ConditionPathExists=!/etc/driver-manager.d/disabled` (auto-skip when
|
||
driver-manager is operational; remains the actual spawner in C0).
|
||
- `config/redbear-{mini,full,grub,device-services,greeter-services}.toml`
|
||
add `driver-manager = {}` to `[packages]`.
|
||
- `[packages]` removal of `pcid-spawner` does NOT happen in C0.
|
||
|
||
**Acceptance test:**
|
||
|
||
```
|
||
[ BOOT ] init: 00_pcid-spawner.service running
|
||
[ BOOT ] init: 00_driver-manager.service skipped (dormant)
|
||
[ PASS ] C0: pcid-spawner still spawns; driver-manager binary present but inactive
|
||
```
|
||
|
||
**Exit criteria for C0:**
|
||
|
||
1. ISO boots identically to pre-C0 baseline.
|
||
2. `make lint-config` clean.
|
||
3. `scripts/validate-collision-log.sh` clean.
|
||
4. `driver-manager-audit-no-stubs.py` still clean.
|
||
|
||
#### Phase C1 — Dual-mode observation
|
||
|
||
**Preconditions:** C0 exit criteria met.
|
||
|
||
**Goal:** driver-manager runs in `--observe` mode (no spawn). Both managers
|
||
see the same devices. Parity confirmed before any actual spawn.
|
||
|
||
**Deliverables:**
|
||
|
||
- `00_driver-manager.service` runs in `--observe` mode (writes
|
||
BOOT_TIMELINE, no spawn).
|
||
- `00_pcid-spawner.service` is still the actual spawner.
|
||
- Both managers write parity data to their BOOT_TIMELINE files.
|
||
- `local/scripts/test-driver-manager-parity.sh` runs as a CI gate.
|
||
|
||
**Acceptance test:**
|
||
|
||
```
|
||
[ BOOT ] driver-manager: enumerate begin (observe)
|
||
[ BOOT ] driver-manager: enumeration complete: 17 bound (observe), 0 deferred
|
||
[ BOOT ] pcid-spawner: spawn e1000d for 0000:00:03.0
|
||
[ BOOT ] driver-manager: 17/17 binds agree with pcid-spawner
|
||
[ BOOT ] driver-manager: BOOT_TIMELINE written
|
||
[ PASS ] C1: parity clean
|
||
```
|
||
|
||
**Exit criteria for C1:**
|
||
|
||
1. `test-driver-manager-parity.sh` clean in 5 back-to-back QEMU runs.
|
||
2. Real-hardware parity verified on AMD Threadripper + Intel Alder Lake.
|
||
3. Both managers' BOOT_TIMELINE files match.
|
||
|
||
#### Phase C2 — Initfs switchover
|
||
|
||
**Preconditions:** C1 exit criteria met, **operator ratification**.
|
||
|
||
**Goal:** driver-manager becomes the initfs spawner (storage drivers).
|
||
|
||
**Deliverables:**
|
||
|
||
- `40_driver-manager-initfs.service` becomes `oneshot` (blocking) and
|
||
replaces `40_pcid-spawner-initfs.service` in initfs.
|
||
- pcid-spawner initfs service moves to
|
||
`ConditionPathExists=!/etc/driver-manager.d/initfs-active` fallback.
|
||
- `local/scripts/test-driver-manager-initfs.sh` clean.
|
||
|
||
**Acceptance test:**
|
||
|
||
```
|
||
[ INITFS ] driver-manager-initfs: storage drivers ready (ahcid/nvmed/virtio-blkd/ided)
|
||
[ INITFS ] redoxfs: mount /dev/redoxfs /scheme/root ✓
|
||
[ INITFS ] switchroot: /usr loaded
|
||
[ PASS ] C2: initfs path via driver-manager
|
||
```
|
||
|
||
**Exit criteria for C2:**
|
||
|
||
1. Initfs-only QEMU run completes with driver-manager and the switchroot
|
||
happens within 5 s.
|
||
2. AHCI + NVMe + virtio-blkd paths tested on at least one AMD and one
|
||
Intel system.
|
||
3. pcid-spawner-initfs fallback can be activated by deleting
|
||
`/etc/driver-manager.d/initfs-active`, and the boot still completes.
|
||
|
||
#### Phase C3 — Rootfs switchover
|
||
|
||
**Preconditions:** C2 exit criteria met, **operator ratification**.
|
||
|
||
**Goal:** driver-manager becomes the primary rootfs spawner.
|
||
|
||
**Deliverables:**
|
||
|
||
- `00_driver-manager.service` becomes the primary rootfs spawner.
|
||
- `00_pcid-spawner.service` is retained as fallback only.
|
||
- `local/scripts/test-driver-manager-active.sh` runs end-to-end.
|
||
- `driver-params` switches to consuming `scheme:driver-manager:/bound`.
|
||
|
||
**Acceptance test:**
|
||
|
||
```
|
||
[ BOOT ] driver-manager: registered scheme:driver-manager
|
||
[ BOOT ] driver-manager: load_all: 7 config files, 17 drivers registered
|
||
[ BOOT ] driver-manager: enumeration complete: 17 bound, 0 deferred
|
||
[ BOOT ] driver-manager: hotplug: starting event loop (event-driven)
|
||
[ PASS ] C3: driver-manager is the active rootfs spawner
|
||
```
|
||
|
||
**Exit criteria for C3:**
|
||
|
||
1. `test-driver-manager-active.sh` clean in 5 back-to-back QEMU runs.
|
||
2. driver-params via scheme:driver-manager produces correct driver list.
|
||
3. parity test (C1's) keeps reporting identical binds.
|
||
|
||
#### Phase C4 — Operator-ratified production cutover
|
||
|
||
**Preconditions:** C3 exit criteria met, **operator ratification**,
|
||
**two-week soak**, **three hardware reboots** with identical driver-bound
|
||
sets.
|
||
|
||
**Goal:** pcid-spawner moves to maintenance-mode fallback. Status rows
|
||
update.
|
||
|
||
**Deliverables:**
|
||
|
||
- pcid-spawner source tree receives a final commit on `submodule/base`
|
||
documenting the maintenance-mode status.
|
||
- `local/docs/UPSTREAM-SYNC-PROCEDURE.md` § "driver-manager: Deferred"
|
||
replaced with "driver-manager: production".
|
||
- README.md status row updates.
|
||
- `local/AGENTS.md` § PLANNING NOTES pointer updates.
|
||
- Inline deferred comments in `config/redbear-mini.toml:31` and
|
||
`config/redbear-device-services.toml:9-13` removed.
|
||
|
||
**Exit criteria for C4:**
|
||
|
||
1. Two-week soak completes with no `ConditionPathExists` guard firing.
|
||
2. Three consecutive bare-metal reboots produce identical driver-bound
|
||
sets.
|
||
3. Hardware validation matrix shows parity or improvement on every row.
|
||
4. Operator ratification documented in
|
||
`local/docs/evidence/driver-manager/C4-RATIFICATION.md`.
|
||
|
||
**At no point is pcid-spawner DELETED.** It moves to "always-shipped,
|
||
on-disk fallback" alongside `00_driver-manager.service`.
|
||
|
||
---
|
||
|
||
## 6. Per-phase dependency diagram
|
||
|
||
The D-phase and C-phase tracks are **sequential** under § 0.6's parallel
|
||
development constraint:
|
||
|
||
```
|
||
D-PHASE: Parallel Development C-PHASE: Cutover & Validation
|
||
(driver-manager being built; (driver-manager enabled;
|
||
pcid-spawner is the live system) pcid-spawner demoted to fallback)
|
||
|
||
D0 ─► D1 ─► D2 ─► D3 ─► D4 ─► D5 ─── operator ratification + feature-complete gate ─── C0 ─► C1 ─► C2 ─► C3 ─► C4
|
||
│ │ │ │ │ │ │ │ │ │ │
|
||
▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
|
||
fnd cap tech hp quk audit svc obs ifs rfs prod
|
||
frame bridge face ev int (no stubs) wir dual sw sw cut
|
||
present +PM ent- gra- + HW validate e mode itc itc over
|
||
+AER drive ted dom dor ove ove (op
|
||
+IOM (dor r r era
|
||
MU man (do (do tor
|
||
+MS t) t) t) ra
|
||
I-X tif
|
||
ied
|
||
)
|
||
|
||
│ │
|
||
└──── During D-phase, pcid-spawner remains the boot path. During C-phase, both
|
||
No boot path is changed. managers may run; pcid-spawner
|
||
is the fallback at every cutover step.
|
||
```
|
||
|
||
**Phase key:**
|
||
|
||
- D0: Foundation (current state)
|
||
- D1: Linux 7.x capability bridge (C1–C18 P0 set)
|
||
- D2: Modern technology surface (SMP, S/P states, runtime PM, IOMMU, AER, MSI-X)
|
||
- D3: Hotplug (event-driven)
|
||
- D4: Quirk integration + comprehensive audit (no stubs)
|
||
- D5: Feature-complete gate (operator ratification)
|
||
- C0: Service wiring (dormant service file)
|
||
- C1: Dual-mode observation
|
||
- C2: Initfs switchover
|
||
- C3: Rootfs switchover
|
||
- C4: Operator-ratified production cutover
|
||
|
||
The workstream structure deliberately mirrors `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`
|
||
(Phase 1–5) and `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` (Workstream A–E)
|
||
to keep the project's planning grammar consistent.
|
||
|
||
---
|
||
|
||
## 7. Test scripts (`local/scripts/`)
|
||
|
||
All scripts land in `local/scripts/` per project convention and follow the
|
||
existing naming (`test-X.sh` for shell, `test-X-y.sh` for variants).
|
||
Each script returns exit 0 on success, emits a `[PASS]` line, and writes a
|
||
log to `local/docs/evidence/driver-manager/`.
|
||
|
||
| Script | Phase (D / C) | Purpose | Exit code signal |
|
||
|---|---|---|---|
|
||
| `test-driver-manager-parity.sh` | **C1** (drafted in D1) | Both managers active, observation only; verify they agree on every device-id-to-driver mapping | 0 = same set bound |
|
||
| `test-driver-manager-active.sh` | **C3** | driver-manager primary; pcid-spawner fallback; verify all 17 drivers | 0 = all expected drivers present |
|
||
| `test-driver-manager-initfs.sh` | **C2** | initfs use only; verify storage drivers come up before redoxfs | 0 = redoxfs mounted |
|
||
| `test-driver-manager-hotplug.sh` | **D3** (gate) | Hotplug add/remove cycle; unbind/rebind sequence | 0 = unbind + rebind within budget |
|
||
| `test-driver-manager-pm.sh` | **D2** (gate) | Suspend/resume cycle, parameter write-through | 0 = clean suspend+resume |
|
||
| `test-driver-manager-cutover.sh` | **C4** | Final acceptance: identical driver set before/after cutover | 0 = no diff in bound-set logs |
|
||
| `driver-manager-audit-no-stubs.py` | **D4** (gate) | Static analysis that the source contains no `unimplemented!()`, no `todo!()`, no `Ok(())` trait-method defaults — per § 0.5 | 0 = no violations |
|
||
| `test-driver-manager-no-stubs-qemu.sh` | **D4** (gate) | QEMU run with synthesized edge-case devices exercising every P0 capability C1–C18 | 0 = every test bus emits one bind event |
|
||
|
||
---
|
||
|
||
## 8. Cross-cutting concerns
|
||
|
||
### 8.1 GPU / DRM
|
||
|
||
The `redox-drm` driver daemon currently relies on `PciFunctionHandle::connect_default()`
|
||
plus `redox-driver-sys::pci::PciDevice`. driver-manager must continue passing
|
||
`PCID_CLIENT_CHANNEL` for `redox-drm` to receive a working channel. The match
|
||
table that triggers `redox-drm` (`30-graphics.toml` already in
|
||
`config/redbear-device-services.toml`) is consumed by driver-manager; no driver
|
||
side changes. The `redox-driver-sys::PciQuirkFlags` policy is consulted in **D4**
|
||
(`NEED_FIRMWARE`, `DISABLE_ACCEL`, `NO_MSIX`). AMD-specific decisions live in
|
||
`local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` — the present plan does not
|
||
re-open those decisions, it only carries them into the manager's match-time
|
||
decision logic.
|
||
|
||
### 8.2 USB
|
||
|
||
`xhcid`, `ehcid`, `ohcid`, `uhcid`, `usbhubd`, `usbscsid`, `usbhidd`, `usbaudiod`
|
||
all spawn from `/lib/drivers.d/{20-usb,70-usb-class}.toml`. These TOMLs exist
|
||
in `config/redbear-device-services.toml` (lines 116-490) but are inert today.
|
||
driver-manager must wake them correctly during **C3**. The Bus trait will gain a
|
||
`UsbBus` in `local/docs/USB-IMPLEMENTATION-PLAN.md`; that is **out of scope**
|
||
for this migration.
|
||
|
||
### 8.3 Audio
|
||
|
||
`ihdad`, `ac97d`, `sb16d` are in `50-audio.toml`. These spawn late (no initfs
|
||
dependency); driver-manager handles them as ordinary bound drivers with
|
||
priority below storage/network. CachyOS's audio-power management patterns
|
||
(`20-audio-pm.rules`) are reflected in **D4**'s `depends_on` and `hotplug`
|
||
hooks for these drivers.
|
||
|
||
### 8.4 Storage init path
|
||
|
||
This is the highest-risk surface. `ahcid`, `ided`, `nvmed`, `virtio-blkd`,
|
||
`usbscsid`, `usb-bot` MUST be ready before redoxfs mounts. Phase **C2**'s initfs
|
||
migration has its own gate, and a fallback (`40_pcid-spawner-initfs.service`
|
||
via `ConditionPathExists`) is required at every C-phase before **C4**.
|
||
|
||
### 8.5 Cross-config consistency
|
||
|
||
The three compile targets (`redbear-mini`, `redbear-full`, `redbear-grub`) all
|
||
include init services that depend on `00_pcid-spawner.service`. All three need
|
||
the same `00_driver-manager.service` substitution. The change is mechanical
|
||
but must be applied to every `[service].requires_weak` reference and every
|
||
`[[files]]` install in the same PR. `make lint-config` enforces consistency.
|
||
|
||
### 8.6 Doc references
|
||
|
||
After **C3**:
|
||
|
||
- `local/AGENTS.md` § PLANNING NOTES gets a one-liner pointing here.
|
||
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` Phase 1 row updates from
|
||
"🟡 | in progress" to "🟡 | driver-manager parity accepted".
|
||
- `local/docs/PATCH-GOVERNANCE.md` § "Local recipe priority vs upstream WIP"
|
||
notes that `local/recipes/system/driver-manager` is the canonical owner.
|
||
- `local/docs/UPSTREAM-SYNC-PROCEDURE.md` § "driver-manager: Deferred"
|
||
replaced with "driver-manager: live (`00_driver-manager.service`)".
|
||
|
||
After **C4** (production cutover):
|
||
|
||
- README.md status row updates to ✅.
|
||
- `config/redbear-mini.toml:31` and
|
||
`config/redbear-device-services.toml:9-13` inline deferred comments are
|
||
removed (no longer accurate once driver-manager is live).
|
||
- `local/docs/UPSTREAM-SYNC-PROCEDURE.md` § "driver-manager: Deferred"
|
||
replaced with "driver-manager: production".
|
||
|
||
### 8.7 Branch / submodule policy
|
||
|
||
Per `local/AGENTS.md` § BRANCH AND SUBMODULE POLICY, no new submodule is created.
|
||
driver-manager stays a **local recipe** under `local/recipes/system/driver-manager/`.
|
||
This is preserved at every phase. The 9 declared submodules remain unchanged.
|
||
|
||
---
|
||
|
||
## 9. Appendices
|
||
|
||
### 9.1 File map (post-migration, target end state)
|
||
|
||
**Created (tracked):**
|
||
|
||
```
|
||
local/recipes/system/driver-manager/source/src/
|
||
├── main.rs (modified at D3, D4, C1, C3 across their phases)
|
||
├── config.rs (modified at D1 [format coexistence], D2 [PM hooks], D3 [event-driven], D4 [quirk integration])
|
||
├── scheme.rs (modified at D2 [PM scheme surface], D4 [quirk reporting])
|
||
├── hotplug.rs (rewritten at D3 — event-driven)
|
||
├── exec.rs (removed at D0; spawn was already inlined in config.rs::probe())
|
||
├── driver-probe.rs (NEW at D1 [SpawnDecision committee], evolves D2 [PM dispatch], D4 [AER routing])
|
||
└── errors.rs (NEW at D0 [error-tag normalisation], evolves D2 [PM error codes])
|
||
|
||
local/recipes/system/driver-manager/recipe.toml (no change)
|
||
local/recipes/system/driver-manager/source/Cargo.toml (deps added at D2 [bitflags], D3 [event-stream], D4 [redox-driver-sys])
|
||
|
||
local/sources/base/init.d/00_driver-manager.service (NEW dormant at C0; evolves C1, C3)
|
||
local/sources/base/init.initfs.d/40_driver-manager-initfs.service (NEW dormant at C0; becomes blocking at C2)
|
||
|
||
local/config/driver-manager.d/ (NEW at D4)
|
||
├── 00-blacklist.conf
|
||
├── autoload.d/ntsync.conf
|
||
├── 50-amdgpu.toml
|
||
└── initfs.manifest
|
||
|
||
local/scripts/test-driver-manager-{parity,active,initfs,hotplug,pm,cutover}.sh (one per phase — see § 7)
|
||
local/scripts/driver-manager-audit-no-stubs.py (NEW at D4; gates D5)
|
||
|
||
local/recipes/system/driver-params/source/src/main.rs (modified at C1 to consume scheme:driver-manager:/bound)
|
||
local/recipes/system/redbear-driver-policy/ (NEW at D4; curated policy package; packaged at C3)
|
||
```
|
||
|
||
**Modified (kept tracked):**
|
||
|
||
```
|
||
config/redbear-mini.toml (C0: driver-manager added to [packages]; superseded comments at C4)
|
||
config/redbear-full.toml (C0: same)
|
||
config/redbear-grub.toml (C0: same)
|
||
config/redbear-greeter-services.toml (C0: same)
|
||
config/redbear-device-services.toml (C0 + D4: driver-manager config inclusion)
|
||
|
||
local/docs/UPSTREAM-SYNC-PROCEDURE.md (§ driver-manager: Deferred -> live at C3; -> production at C4)
|
||
local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md (Phase 1 row update at C3)
|
||
local/docs/HARDWARE-VALIDATION-MATRIX.md (multiple rows updated at D5)
|
||
README.md (status row at C4)
|
||
AGENTS.md (no change beyond pointer)
|
||
local/AGENTS.md (PLANNING NOTES section gains pointer)
|
||
```
|
||
|
||
**Untouched (preserved for fallback throughout D/C phases and after C4):**
|
||
|
||
```
|
||
local/sources/base/drivers/pcid-spawner/ (entire tree — fallback for life)
|
||
local/sources/base/drivers/pcid/ (unchanged — still the scheme:pci owner)
|
||
local/sources/base/init.d/00_pcid-spawner.service (becomes dormant fallback service at C3)
|
||
local/sources/base/init.initfs.d/40_pcid-spawner-initfs.service (becomes dormant fallback at C2)
|
||
|
||
local/patches/base/ (all P-numbered patches preserved)
|
||
local/recipes/core/pcid-spawner/recipe.toml (path-fork unchanged)
|
||
recipes/core/base/drivers/pcid-spawner/ (path-fork path unchanged)
|
||
|
||
The 17 driver daemons' source trees and Cargo.tomls.
|
||
```
|
||
|
||
### 9.2 Environment variable contract (preserved)
|
||
|
||
| Var | Source | Consumer | Format |
|
||
|---|---|---|---|
|
||
| `PCID_CLIENT_CHANNEL` | pcid-spawner (legacy), driver-manager (new) | driver daemon via `PciFunctionHandle::connect_default()` | ASCII decimal fd |
|
||
| `PCID_SEGMENT` | both | driver daemon | 4-hex (e.g., `0000`) |
|
||
| `PCID_BUS` | both | driver daemon | 2-hex (e.g., `03`) |
|
||
| `PCID_DEVICE` | both | driver daemon | 2-hex (e.g., `0a`) |
|
||
| `PCID_FUNCTION` | both | driver daemon | decimal |
|
||
| `REDBEAR_DRIVER_MANAGER_ACTIVE` | env (env file) | driver-manager | `0` = observation; non-zero = spawn |
|
||
| `DRIVER_PARAMS_LOG` | existing | driver-params | one of `trace`/`debug`/`info`/`warn`/`error` |
|
||
| `DRIVER_PARAMS_BOUND_PATH` | existing | driver-params | path string |
|
||
| `INIT_NOTIFY` | init | driver-params, driver-manager (from C0 onwards) | int fd |
|
||
|
||
### 9.3 Capability-to-driver matrix
|
||
|
||
| Driver daemon | C3 enable | C4 bar request | C5 map | C6 bus master | C7 vectors | C12 config R/W | C16 caps | C17 INTx |
|
||
|---|---|---|---|---|---|---|---|---|
|
||
| `ahcid` | ✅ via PCID_CLIENT_CHANNEL | implicit via connect | driver-side via `redox-driver-sys` | yes | MSI via pcid client | yes | yes | yes |
|
||
| `ided` | same | same | same | yes | n/a | yes | yes | yes |
|
||
| `nvmed` | same | same | same | yes | MSI-X | yes | yes | yes |
|
||
| `virtio-blkd` | same | same | same | yes | n/a | yes | yes | yes |
|
||
| `e1000d` | same | same | same | yes | MSI via `redox-driver-sys` | yes | yes | yes |
|
||
| `rtl8168d` | same | same | same | yes | MSI | yes | yes | yes |
|
||
| `rtl8139d` | same | same | same | yes | INTx | yes | yes | yes |
|
||
| `ixgbed` | same | same | same | yes | MSI-X | yes | yes | yes |
|
||
| `virtio-netd` | same | same | same | yes | n/a | yes | yes | yes |
|
||
| `ihdgd` | same | same | same | yes | MSI-X | yes | yes | yes |
|
||
| `virtio-gpud` | same | same | same | yes | n/a | yes | yes | yes |
|
||
| `xhcid` | same | same | same | yes | MSI-X | yes | yes | yes |
|
||
| `ihdad` | same | same | same | yes | MSI | yes | yes | yes |
|
||
| `ac97d` | same | same | same | yes | INTx | yes | yes | yes |
|
||
| `vboxd` | same | same | same | yes | n/a | yes | yes | yes |
|
||
| `amd-mp2-i2cd` | same | same | same | yes | MSI | yes | yes | yes |
|
||
| `intel-thc-hidd` | same | same | same | yes | MSI | yes | yes | yes |
|
||
|
||
**Crucial invariant:** all 17 drivers already fulfil C3–C8, C12, C16, C17
|
||
through `pcid_interface::PciFunctionHandle::connect_default()` followed by
|
||
`PciClient::*` calls. driver-manager's role is to deliver a working channel
|
||
FD into the child's env. No driver rewrite required at any phase.
|
||
|
||
### 9.4 TOML schema (canonical end-state at C3)
|
||
|
||
**Match table (`/lib/drivers.d/*.toml`):**
|
||
```toml
|
||
# matches are AND-ed within an entry, OR-ed across entries
|
||
[[driver]]
|
||
name = "e1000d"
|
||
description = "Intel e1000 Gigabit Ethernet"
|
||
priority = 50
|
||
|
||
[driver.command]
|
||
argv = ["e1000d"] # or absolute path
|
||
|
||
[driver.depends_on]
|
||
schemes = ["pci", "firmware"]
|
||
|
||
[[driver.match]]
|
||
vendor = 0x8086
|
||
device = 0x100E
|
||
class = 0x02 # network controller
|
||
subclass = 0x00 # ethernet
|
||
|
||
[[driver.match]]
|
||
vendor = 0x8086
|
||
device = 0x10D3
|
||
# wildcard rest
|
||
|
||
[driver.params]
|
||
debug = { type = "bool", default = false, writable = true }
|
||
priority_arg = { type = "int", default = 0, writable = true }
|
||
exclusive_with = { type = "string", default = "", writable = false }
|
||
```
|
||
|
||
**Policy layer (`/etc/driver-manager.d/*.toml`):**
|
||
```toml
|
||
# Blacklist
|
||
[[blacklist]]
|
||
module = "iTCO_wdt"
|
||
reason = "CachyOS precedent; conflicts with iTCO hardware"
|
||
|
||
# Forced module-options
|
||
[amdgpu.params]
|
||
si_support = true
|
||
cik_support = true
|
||
radeon_overlap = "exclusive" # CachyOS mutual exclusion pattern
|
||
|
||
# Autoload (cold-boot pre-driver)
|
||
[[autoload]]
|
||
module = "ntsync"
|
||
```
|
||
|
||
**Initfs manifest (`/etc/driver-manager.d/initfs.manifest`):**
|
||
```toml
|
||
# ordered (CachyOS-style hook ordering)
|
||
[ramdisk]
|
||
microcode = ["amd-ucode", "intel-ucode"]
|
||
policy = "00-driver-conf"
|
||
kms_drivers = ["amdgpu", "i915"]
|
||
block_drivers = ["ahci", "nvme", "virtio_blk"]
|
||
fs_drivers = ["redoxfs", "ext4"]
|
||
```
|
||
|
||
### 9.5 Migration effort & ownership
|
||
|
||
| Phase | Effort estimate | Owner role |
|
||
|---|---|---|
|
||
| D-Phase | Effort estimate | Owner role |
|
||
|---|---|---|
|
||
| D1 — Linux capability bridge | 6–10 weeks | driver-runtime engineer |
|
||
| D2 — Modern technology surface | 8–12 weeks (largest phase; SMP + S/P + PM + IOMMU + AER + MSI-X + NUMA) | driver-runtime + kernel-interface engineer + ACPI engineer |
|
||
| D3 — Hotplug event-driven | 4–6 weeks | driver-runtime engineer |
|
||
| D4 — Quirk integration + audit | 6–8 weeks (includes the § 0.5 no-stubs audit) | driver-runtime + SRE |
|
||
| D5 — Feature-complete gate | 1–2 weeks | driver-runtime engineer + operator ratification |
|
||
| **D-phase total** | **25–38 weeks (~6–9 months)** | |
|
||
|
||
| C-Phase | Effort estimate | Owner role |
|
||
|---|---|---|
|
||
| C0 — Service wiring (dormant) | 1 week | driver-runtime engineer |
|
||
| C1 — Dual-mode observation | 2–4 weeks (must run alongside pcid-spawner in production) | driver-runtime engineer + build-system engineer |
|
||
| C2 — Initfs switchover | 2–3 weeks | driver-runtime + boot-system engineer |
|
||
| C3 — Rootfs switchover | 2–4 weeks | driver-runtime engineer |
|
||
| C4 — Operator-ratified production cutover | 1–2 weeks + 2-week soak + 3 hardware reboots | operator + driver-runtime engineer |
|
||
| **C-phase total** | **8–14 weeks + soak (~2–4 months)** | |
|
||
|
||
**Grand total: 33–52 weeks (~8–13 months)** for full D+C trajectory.
|
||
|
||
**Operator ratification required at the following phase boundaries:**
|
||
|
||
- **D5 → C0** — feature-complete gate (the § 0.5 audit clean + hardware matrix passes)
|
||
- **C1 → C2** — rootfs observation confirmed dual-mode parity
|
||
- **C2 → C3** — initfs switchover ratified
|
||
- **C3 → C4** — rootfs switchover ratified
|
||
- **C4 transition** — production cutover ratified
|
||
|
||
Phase boundaries without explicit operator ratification are not allowed to advance.
|
||
|
||
### 9.6 References
|
||
|
||
**Internal (Red Bear OS):**
|
||
|
||
- `local/AGENTS.md` — policy authority
|
||
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` — supersedes for desktop path
|
||
- `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` — GPU-specific decisions
|
||
- `local/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md` — PCI/IRQ quality
|
||
- `local/docs/USB-IMPLEMENTATION-PLAN.md` — USB bus (out of scope here)
|
||
- `local/docs/WIFI-IMPLEMENTATION-PLAN.md` — Wi-Fi bus (out of scope here)
|
||
- `local/docs/QUIRKS-SYSTEM.md` — `redox-driver-sys` quirks surface
|
||
- `local/docs/QUIRKS-IMPROVEMENT-PLAN.md` — Task 2.1 driver-manager bridge
|
||
- `local/docs/HARDWARE-VALIDATION-MATRIX.md` — status of driver runs
|
||
- `local/docs/UPSTREAM-SYNC-PROCEDURE.md` — historical status note to update
|
||
- `local/docs/PATCH-GOVERNANCE.md` — patch carrier rules
|
||
- `local/docs/RELEASE-BUMP-WORKFLOW.md` — version sync
|
||
- `local/scripts/TOOLS.md` — tool inventory
|
||
|
||
**External cross-reference (not authoritative here, cited for design intent):**
|
||
|
||
- Linux 7.1 reference tree at `local/reference/linux-7.1/` (commit `ab9de95c9`):
|
||
- `drivers/pci/pci-driver.c:1021-1742` — pci_driver, pci_bus_type
|
||
- `drivers/pci/pci.c:2120, 3916, 4172` — `pci_enable_device`, `pci_request_regions`, `pci_set_master`
|
||
- `drivers/pci/msi/api.c:205-264` — `pci_alloc_irq_vectors_affinity`
|
||
- `drivers/pci/hotplug/pciehp_core.c:185-372` — native hotplug
|
||
- `drivers/pci/pcie/aer.c:1203-1280` — AER recovery
|
||
- `drivers/base/bus.c:732, 818, 612, 869` — driver-core binding
|
||
- CachyOS-Settings (`master`, v1.3.5): https://github.com/CachyOS/CachyOS-Settings
|
||
- `usr/lib/udev/rules.d/60-ioschedulers.rules` — kernel-event → sysfs-write policy
|
||
- `usr/lib/udev/rules.d/71-nvidia.rules` — bind/unbind lifecycle symmetry
|
||
- `usr/lib/udev/rules.d/20-audio-pm.rules` — cross-subsystem reaction
|
||
- `usr/lib/udev/rules.d/85-iw-regulatory.rules` + `cachyos-iw-set-regdomain.{path,service}` — udev→systemd delegation
|
||
- `usr/lib/modprobe.d/{amdgpu,blacklist,nvidia}.conf` — driver-exclusion pattern
|
||
- CachyOS/linux-cachyos: scheduler variants, `mkinitcpio` preset ordering.
|
||
|
||
---
|
||
|
||
## 10. Position statement
|
||
|
||
This plan supersedes the inline deferred notes that accompany the existing
|
||
`driver-manager` recipe:
|
||
|
||
- `config/redbear-mini.toml:31` ("driver-manager requires driver config migration and is not yet ready")
|
||
- `config/redbear-device-services.toml:9-13` ("driver-manager intentionally not included … its service launched pcid-spawner instead of driver-manager").
|
||
|
||
These notes remain accurate at the moment of writing (2026-07-20). They will
|
||
be amended at the relevant phase boundaries as the migration advances. At
|
||
**no point** in the migration is `pcid-spawner` removed from the tree, the
|
||
recipe, or the live image. The boot path is never single-point-of-failure.
|
||
|
||
**v1.1 additions (this revision):** § 0 Strategic Context is added with
|
||
rationale, success criteria, upstream risk, modern-technology surface,
|
||
comprehensive-implementation principle, and the parallel-development
|
||
constraint. § 5 is restructured into D-Phase (parallel development) and
|
||
C-Phase (cutover & validation). All cross-references in §§ 1, 2, 4, 5, 6,
|
||
7, 8, 9 are updated to the new phase nomenclature. The § 0.5 comprehensive
|
||
principle is the binding code-quality bar; the § 0.6 parallel-development
|
||
constraint is the binding development model.
|
||
|
||
**Binding constraints derived from § 0:**
|
||
|
||
- **Comprehensive implementation** — every public trait method on `Bus`,
|
||
`Driver`, and `Manager` is fully implemented. No `unimplemented!()`, no
|
||
`todo!()`, no empty match arms returning trivial defaults, no
|
||
`#[cfg(...)]`-gated no-ops. Honoring `local/AGENTS.md` § STUB AND
|
||
WORKAROUND POLICY — ZERO TOLERANCE.
|
||
- **Modern technology surface** — SMP-aware concurrent probe, C/P-state
|
||
coordination, runtime PM, IOMMU group management, AER error recovery,
|
||
MSI-X vector allocation, NUMA-aware DMA. None of these are stubs.
|
||
- **Parallel development model** — driver-manager is being built in
|
||
parallel with the live pcid-spawner system. It is **NOT** shipped, NOT
|
||
enabled, NOT included in any boot path until the D5 feature-complete
|
||
gate ratifies. No exceptions.
|
||
- **Upstream-first response** — if Redox upstream ships an equivalent
|
||
manager within 6 months of D5, evaluate and consider migrating per
|
||
Local Fork Supremacy Policy. The migration plan is robust to upstream
|
||
divergence; it does NOT block on upstream decisions.
|
||
|
||
**Status of § 0.6 (parallel development) at the moment of writing:**
|
||
driver-manager is being built. It is NOT shipped. The boot path is
|
||
pcid-spawner. The migration plan enters C-phase only after D5 ratifies.
|
||
|
||
The migration's authority chain is:
|
||
**this document → `local/AGENTS.md` → `AGENTS.md`**. Every implementation
|
||
step must be defensible against this chain, the § 0.5 comprehensive
|
||
principle, and the § 0.6 parallel-development constraint.
|
||
|
||
**Last reviewed:** 2026-07-20 (v1.1: strategic-context + D/C phase restructure)
|
||
**Next review:** at **D5** exit gate, after `local/scripts/driver-manager-audit-no-stubs.py`
|
||
reports zero violations AND `local/docs/HARDWARE-VALIDATION-MATRIX.md`
|
||
shows driver-manager validated on at least one AMD and one Intel profile
|
||
across storage, network, and GPU categories.
|