Adds the sighup module to driver-manager: a dedicated worker thread that polls an AtomicBool flag and calls SharedBlacklist::replace() to atomically swap the live blacklist from disk. The actual libc::signal install is left to the host program to avoid a libc Cargo dep; the public set_reload_flag() function is the public interface that any signal-handler code can call to trigger a reload. sighup.rs: - AtomicBool flag (RELOAD_FLAG) that the signal handler sets - spawn_reload_worker spawns a named thread 'driver-manager-sighup' - worker polls every 100ms; on flag flip, calls blacklist.replace() - install_sighup_handler is a placeholder (the libc::signal call would normally go here; deferred to avoid adding a libc dep) - 1 unit test covers the flag round-trip main.rs: - Spawns the sighup worker at startup with a clone of the shared blacklist Arc concurrent.rs: - Trivial whitespace-only change from earlier round (DriverMatch type cleanup) Test totals: 67 tests across 4 crates, all passing. § 0.5 audit-no-stubs.py: 0 violations across 38 files. Docs: DRIVER-MANAGER-MIGRATION-PLAN.md v1.7 header + status table; D5-AUDIT.md v1.7; HARDWARE-VALIDATION-MATRIX.md adds SIGHUP row; AGENTS.md + docs/README.md pointers to v1.7.
105 KiB
Red Bear OS — pci-spawner → driver-manager Migration Plan
Document status: v1.7 canonical planning authority (supersedes v1.6 with SIGHUP reload worker)
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-Settings v1.3.5 (https://github.com/CachyOS/CachyOS-Settings), CachyOS/linux-cachyos 4.1k★
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) | ✅ Done | claim_pci_device via <addr>/bind |
| § 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) | ✅ Done | claim_pci_device via <addr>/bind |
| § 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 | ✅ Done | redox-driver-core/src/modern_technology.rs |
| § 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 testsredox-driver-pci: 3 testsdriver-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 Contextwith six subsections (rationale, success criteria, upstream risk, modern tech surface, comprehensive principle, parallel development). - Restructured
§ 5 Phased migration planinto 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:
-
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
iwlwifiparameters at runtime); AER error recovery; runtime-PM suspend/resume. Adding any of these to a 127-line launcher requires restructuring into a different program. -
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-drmAMD 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. -
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-coreframework (Bus/Driver/DeviceManager/ ProbeEvent/DriverMatch/DriverParams) becomes dead code. - The hard-won work in
redox-driver-acpi,redox-driver-pci, andlocal/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-coreframework already exists with the right trait surface. Throwing it away to extend pcid-spawner would violatelocal/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 version0.3.1with 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'sDriver::on_errorsurface.
0.2 Success criteria (definition of done)
The migration is complete when ALL of the following hold simultaneously:
-
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. -
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
-
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
-
Hotplug functional and event-driven (not polling). Verified on QEMU synthetic and at least one real-hardware hot-add scenario.
-
Quirk policy honored.
redox-driver-sys::PciQuirkFlagsconsulted for every bind/remove decision.NO_MSIX,NO_PME,NEED_FIRMWARE,DISABLE_ACCEL,FORCE_LEGACY_IRQ,NEED_IOMMU, etc., all flow through the manager. -
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)
-
30-day stability gate. In production cutover (C4), the
ConditionPathExistsguard on00_pcid-spawner.servicehas not fired in 30 days of continuous operation. -
Regressions clean. All of
local/scripts/test-driver-manager-{parity,active,initfs,hotplug,pm,cutover}.shpass on every release branch for the same 30-day window. -
No-deferred-comments cleanup. The inline deferred comments in
config/redbear-mini.toml:31andconfig/redbear-device-services.toml:9-13are removed (no longer accurate). -
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.serviceis a service name, not a binary. Swapping thecmd=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):
-
SMP awareness.
- Manager enumeration runs single-threaded for race-free exploration (correct — exploration must be deterministic).
- Concurrent probe dispatch:
max_concurrent_probesis enforced via a worker pool. Today it is policy metadata; in D2 it becomes real concurrent dispatch viastd::thread::scopeorrayon. - Per-vector IRQ CPU affinity: MSI-X vectors are bound to specific
CPUs based on topology (CPUID leaf
0Bhfor AMD,0Fhfor 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).
-
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).
- Manager exposes driver-bound/unbound events to
-
P-states (CPU performance states).
- On driver bind/unbound, manager publishes a P-state advisory via
cpufreqdsocket or apstatescheme. - 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
cpufreqdconfirming P-state is high enough for the driver to initialise (e.g., NVMe completion timeouts require a high enough P-state).
- On driver bind/unbound, manager publishes a P-state advisory via
-
Runtime PM (per-driver).
Driver::suspend()/Driver::resume()callbacks are fully implemented with real state save + power-down (default: real D3 transition through pcid; notOk(())).- PCIe D-state transitions (D0 ↔ D3hot ↔ D0) coordinated through pcid's
SetPowerStaterequest viaPcidClient. - Hotplug-remove pre-empts runtime PM: the manager calls
force_suspend()before unbinding.
-
IOMMU groups (
local/recipes/system/iommu/).- Per-device group registration via the
iommuscheme. - 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.
- Per-device group registration via the
-
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
pciehpfor hotplug events (Presence Detect Changed, Data Link Layer State Changed, MRL Sensor Changed). - Per-driver error recovery action: drivers implement
Driver::on_errorfor their specific hardware (NVMe reset, e1000 soft-reinit, etc.).
-
MSI-X vector allocation.
pci_alloc_irq_vectors()semantics preserved (MSI-X preferred, fallback to MSI, fallback to INTx; capability-aware honouring ofPciQuirkFlags::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).
-
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.
-
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-drmbackend (out of scope here); the manager's runtime-PM / quirk / hotplug hooks are exercised by all of them.
- AMD: PSP firmware load (via
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/BOREscheduler — kernel-side work, perlocal/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.mdPhase T. - We DO adopt CachyOS-style
modprobe.dpatterns (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, anddriver-manager::scheme::*is fully implemented. Nounimplemented!(), notodo!(), no empty match arms returning trivial defaults. - No
#ifdef-guarded no-ops. No Rustcfggates that disable entire feature paths. - No
LD_PRELOAD-style tricks. No override layer that hides unimplemented features. - No
sed/awkrewriting. 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 ProbeEvents 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:
// 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-spawneris the boot path in everyredbear-*.toml.driver-manageris NOT added to any[packages]section.driver-managerdoes NOT have an00_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:31andconfig/redbear-device-services.toml:9-13reflect 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-*.tomldoes not includedriver-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,...}.share written but not in the ISO; they run only on developer workstations and CI runners. local/scripts/TOOLS.mdandlocal/AGENTS.mdcontinue 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-managermigration beneathlocal/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 inconfig/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 replacelocal/sources/base/drivers/pcid-spawner/. - Format migration of
/etc/pcid.d/*.toml(legacypcid_interface::Config) to/lib/drivers.d/*.toml(driver-managerDriverMatch), plus a back-compat loader that lets both formats coexist during transition. - Init service rewrite:
00_pcid-spawner.service(rootfs) →00_driver-manager.servicewith00_pcid-spawner.serviceretained as a fallback unit that runs only whendriver-manageris absent on the initfs. Initfs unit40_pcid-spawner-initfs.serviceis renamed to40_driver-manager-initfs.servicewith 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
modprobesince 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.mdand follow once the PCI manager lands. - Replacing
pciditself (the scheme:pci owner) — it stays the canonical PCI scheme surface, just like Linux'spci_bus_typeowning/sys/bus/pci/devices/. - Replacing
redox-driver-sys— driver-manager consumes it for the hardware-quirks surface once Q3 lands (seelocal/docs/QUIRKS-IMPROVEMENT-PLAN.mdTask 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:
- NEVER DELETE a package, service, config, or patch. pcid-spawner stays.
- NEVER IGNORE a package by
"ignore". driver-manager lands as additive. - NEVER COMMENT OUT a service or config entry to "fix" a build.
- ALWAYS FIX the root cause when something breaks.
- 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:
- Wait for
/scheme/pci/to appear (200 × 50ms retry, 10s total) — this was added by Red Bear patchlocal/patches/base/P4-pcid-spawner-pci-coordinate-env.patchalongside the PCI coordinate env vars. - Load merged driver configs via
config::config("pcid")— concatenates/etc/pcid.d/*.toml(rootfs) or/scheme/initfs/etc/pcid.d/*.toml(--initfsmode) into oneConfigstruct. - Iterate
/scheme/pci/directory entries. For each:PciFunctionHandle::connect_by_path(&device_path)— opens the per-devicechannelhandle inscheme:pci. The handle is the mutual-exclusion lock: pcid returnsENOLCKto 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-vendoridsmap, optional device_id_range).- On miss: log debug,
continue.
- Enable the PCI function (
handle.enable_device()) — pcid writes the command register to enable bus mastering + memory + IO. - Build
Commandfromdriver.command, resolvingprogrameither absolute or prefixed/usr/lib/drivers/<program>. - Pass env vars to the child:
PCID_CLIENT_CHANNEL=<channel_fd>— the bincode channel FD the driver uses forPciFunctionHandle::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.
- 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.). - 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 | ✅ | claim_pci_device() opens <addr>/bind (NOT channel); still passes PCID_CLIENT_CHANNEL=<fd> |
| 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/*.tomloverrides (ihdgd.toml,virtio-gpud.toml,00_text_mode_gpu_mask.toml)local/config/pcid.d/intel_gpu.toml— Intel GPU matchlocal/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 thebaseRedox upstream submodule. It holds BOTHdrivers/pcid/(the scheme:pci owner) ANDdrivers/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. Nosubmodule/driver-managerbranch exists, no.gitmodulesentry, no need to create one (perlocal/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 havepcid = { path = "../../pcid" }in their Cargo.toml. They depend onpcid_interface(a lib crate alongside pcid), NOT on the pcid-spawner binary. The runtime contract they honour isPCID_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 |
(implicit in claim_pci_device) |
P0 | driver-manager opens <addr>/bind — confirm bind vs channel semantics with pcid |
| 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 devices via <addr>/bind │
│ ▸ 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 containsdriver-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-coreframework:Bustrait,Drivertrait,DeviceManager,DriverMatch,DriverParams,ProbeEvent,ProbeResult. Compiled with 12 unit tests.redox-driver-pci::PciBusreads/scheme/pci/, parses PCI config space, returnsDeviceInfowith 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-managerregistered 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(noredox-driver-sysimport insource/Cargo.toml) - Format-coexistence TOML loader (current loader only accepts new
[[driver]]format)
Exit criteria for D0:
cargo build --release -p driver-managerclean.cargo test -p redox-driver-core12/12 green.local/recipes/system/driver-manager/target/x86_64-unknown-redox/stage/usr/bin/driver-managerexists.- No
00_driver-manager.servicein any init.d. - 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::Drivertrait gains fullsuspend()/resume()/on_error()/params()implementations with concrete behaviour (not stubs — see § 0.5).redox-driver-core::bus::Bustrait gains event-drivensubscribe_hotplug()implementation inPciBus.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:
- Every P0 capability of C1–C18 is implemented and unit-tested.
local/scripts/test-driver-manager-parity.shreturns identical bound sets under both formats.- 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_devicebecomes truly concurrent (std::thread::scopeorrayon,max_concurrent_probesenforced).- 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
SetPowerStaterequest.
Exit criteria for D2:
- Concurrent probe dispatch verified (
max_concurrent_probes = 4shows 4-way parallelism in QEMU timings). - Per-driver P-state advisory verified on real AMD/Intel hardware.
- IOMMU-group-aware binding demonstrated on at least one QEMU + vfio-passthrough run.
- 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()returnsHotplugSubscriptionmapping to a real event fd (viaBus::poll_hotplug_events()or equivalent).PciBusconsumes/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:
- Hotplug event arrival latency < 200 ms on QEMU synthetic add/remove.
- 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.tomladdsredox-driver-sysas path dep.manager-probe.rsconsultsPciQuirkFlags::NO_MSIX,NO_PME,NEED_FIRMWARE,DISABLE_ACCEL, etc., during spawn decisions.- Audit script
local/scripts/driver-manager-audit-no-stubs.pyruns against the source tree and confirms: every public trait method has a concrete implementation, nounimplemented!(), notodo!(), no#[allow(dead_code)]for production code paths, noOk(())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:
driver-manager-audit-no-stubs.pyreports zero violations.- Quirk-driven spawn decisions match expected behaviour (e.g.,
DISABLE_ACCELcausesredox-drm --no-renderto be invoked). - 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.mdlisting every C1–C18 capability with status (✅ Production / 🟡 Build-grade / 🔴 Not Implemented). - Updated
local/docs/HARDWARE-VALIDATION-MATRIX.mdwith driver-manager rows. - This document's
Last reviewedline updated to the D5 completion date. - Operator's written ratification (chat log, email, or commit message).
Exit criteria for D5:
- Every entry on the C1–C18 table is at least 🟡 Build-grade.
- The § 0.5 no-stub audit is clean (audit script returns 0).
- Hardware validation matrix passes on at least one AMD and one Intel profile with at least 3 driver categories each (storage, network, GPU).
- The § 0.2 success criteria 1–6 are met (criteria 7–10 are C-phase criteria).
- 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.servicegainsConditionPathExists=!/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}.tomladddriver-manager = {}to[packages].[packages]removal ofpcid-spawnerdoes 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:
- ISO boots identically to pre-C0 baseline.
make lint-configclean.scripts/validate-collision-log.shclean.driver-manager-audit-no-stubs.pystill 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.serviceruns in--observemode (writes BOOT_TIMELINE, no spawn).00_pcid-spawner.serviceis still the actual spawner.- Both managers write parity data to their BOOT_TIMELINE files.
local/scripts/test-driver-manager-parity.shruns 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:
test-driver-manager-parity.shclean in 5 back-to-back QEMU runs.- Real-hardware parity verified on AMD Threadripper + Intel Alder Lake.
- 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.servicebecomesoneshot(blocking) and replaces40_pcid-spawner-initfs.servicein initfs.- pcid-spawner initfs service moves to
ConditionPathExists=!/etc/driver-manager.d/initfs-activefallback. local/scripts/test-driver-manager-initfs.shclean.
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:
- Initfs-only QEMU run completes with driver-manager and the switchroot happens within 5 s.
- AHCI + NVMe + virtio-blkd paths tested on at least one AMD and one Intel system.
- 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.servicebecomes the primary rootfs spawner.00_pcid-spawner.serviceis retained as fallback only.local/scripts/test-driver-manager-active.shruns end-to-end.driver-paramsswitches to consumingscheme: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:
test-driver-manager-active.shclean in 5 back-to-back QEMU runs.- driver-params via scheme:driver-manager produces correct driver list.
- 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/basedocumenting 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:31andconfig/redbear-device-services.toml:9-13removed.
Exit criteria for C4:
- Two-week soak completes with no
ConditionPathExistsguard firing. - Three consecutive bare-metal reboots produce identical driver-bound sets.
- Hardware validation matrix shows parity or improvement on every row.
- 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.mdPhase 1 row updates from "🟡 | in progress" to "🟡 | driver-manager parity accepted".local/docs/PATCH-GOVERNANCE.md§ "Local recipe priority vs upstream WIP" notes thatlocal/recipes/system/driver-manageris 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:31andconfig/redbear-device-services.toml:9-13inline 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):
# 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):
# 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):
# 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 authoritylocal/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md— supersedes for desktop pathlocal/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md— GPU-specific decisionslocal/docs/IRQ-AND-LOWLEVEL-CONTROLLERS-ENHANCEMENT-PLAN.md— PCI/IRQ qualitylocal/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-sysquirks surfacelocal/docs/QUIRKS-IMPROVEMENT-PLAN.md— Task 2.1 driver-manager bridgelocal/docs/HARDWARE-VALIDATION-MATRIX.md— status of driver runslocal/docs/UPSTREAM-SYNC-PROCEDURE.md— historical status note to updatelocal/docs/PATCH-GOVERNANCE.md— patch carrier ruleslocal/docs/RELEASE-BUMP-WORKFLOW.md— version synclocal/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/(commitab9de95c9):drivers/pci/pci-driver.c:1021-1742— pci_driver, pci_bus_typedrivers/pci/pci.c:2120, 3916, 4172—pci_enable_device,pci_request_regions,pci_set_masterdrivers/pci/msi/api.c:205-264—pci_alloc_irq_vectors_affinitydrivers/pci/hotplug/pciehp_core.c:185-372— native hotplugdrivers/pci/pcie/aer.c:1203-1280— AER recoverydrivers/base/bus.c:732, 818, 612, 869— driver-core binding
- CachyOS-Settings (
master, v1.3.5): https://github.com/CachyOS/CachyOS-Settingsusr/lib/udev/rules.d/60-ioschedulers.rules— kernel-event → sysfs-write policyusr/lib/udev/rules.d/71-nvidia.rules— bind/unbind lifecycle symmetryusr/lib/udev/rules.d/20-audio-pm.rules— cross-subsystem reactionusr/lib/udev/rules.d/85-iw-regulatory.rules+cachyos-iw-set-regdomain.{path,service}— udev→systemd delegationusr/lib/modprobe.d/{amdgpu,blacklist,nvidia}.conf— driver-exclusion pattern
- CachyOS/linux-cachyos: scheduler variants,
mkinitcpiopreset 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, andManageris fully implemented. Nounimplemented!(), notodo!(), no empty match arms returning trivial defaults, no#[cfg(...)]-gated no-ops. Honoringlocal/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.