Updates the 3D plan with the fifth-round status. Phase 5+'s
real-IOCTL gap is now closed:
1. ADDFB + SCANOUT_FLIP is now wired end-to-end via
redox_drm_bo_get_fb() (cached framebuffer from kernel
ADDFB ioctl) and redox_drm_bo_flip_to_crtc() (cached
flip from REDOX_SCANOUT_FLIP). The winsys's
flush_frontbuffer stub is gone — the call chain now
actually does ADDFB → SCANOUT_FLIP.
2. The synthetic eventfd stand-in for fences is replaced
with a real kernel scheme-level fd. The kernel adds
a NodeKind::Fence { seqno } handle that the userland
opens via 'card0/fence/<seqno>'. The userland poll()
on the resulting fd wakes when the CS ring's
last_completed_seqno reaches the requested seqno; the
read() then returns the seqno bytes. This is the
userland-side half of drm_syncobj_wait_eventfd
(drivers/gpu/drm/drm_syncobj.c, Linux 7.1).
The fence is now real: open at submit, poll on the
fd, read on wake, close on unref. No more spin-loops.
Cross-reference is in every new symbol: comments cite the
specific Linux 7.1 driver source files being ported.
Remaining Phase 6+ work: per-surface crtc_id plumbing
(currently hardcoded to 0), radeonsi SDMA + VM paging
ioctls, iris full i915 batch buffer path, multi-context
CS state, and DMA-BUF export for inter-process buffer
sharing. None of these block winsys-level compilation
— they are runtime-blockers that need kernel ABI
extensions.
Replaces the synthetic eventfd stand-in with the real kernel
eventfd path: open the kernel's 'card0/fence/<seqno>' fd and
poll on it. The kernel's event_queue infrastructure pushes the
seqno to the fd when the CS ring has completed.
Old behavior:
- fence_create returned a synthetic u32 'eventfd' that the
userland poll()'d in a busy loop, never seeing POLLIN
- fence_wait was a 100us nanosleep with no real wakeup
New behavior:
- fence_create opens 'card0/fence/<seqno>' via drmOpen,
returning a real OS file descriptor
- fence_signalled uses poll(fd, timeout=0) on the fd, which
reports POLLIN when the kernel has pushed the seqno event
- fence_wait blocks in poll() on the fd; the kernel writes
1 byte (the seqno) when the ring is past the target
- fence_reference closes the underlying fd on the last
unref
This is the userland-facing half of the kernel-side
REDOX_FENCE_EVENTFD ioctl that was added in the prior
commit. Together they implement the same pattern as
Linux 7.1's drm_syncobj_wait_eventfd (drivers/gpu/drm/
drm_syncobj.c::drm_syncobj_wait_ioctl +
include/uapi/drm/drm.h::drm_syncobj_eventfd).
Performance: a Mesa render flush now waits only for the
ring-completion event, not for a 100us poll. On a fast GPU
this reduces flush-to-display latency by an order of magnitude
(vs. the synthetic poll-loop).
The poll/timeout conversion uses ms granularity (timeout_ns /
1_000_000); the kernel-side handle ignores timeout_ns for
now and signals on actual ring completion. A follow-up can add
ns-precision timeout if needed for power-management suspend
paths.
Replaces the Phase 5 placeholder eventfd with a real scheme-level
fd-based fence. Models the userland-facing half of Linux 7.1's
drm_syncobj_wait_eventfd (drivers/gpu/drm/drm_syncobj.c).
Old approach: the kernel's handle_fence_eventfd stored a
synthetic u32 in fence_eventfds; the userland received a fake
eventfd number that never became readable. The fence worked
via spins, not async notification.
New approach: handle_fence_eventfd is no longer fd-returning;
the userland opens a scheme-level path 'card0/fence/<seqno>' to
get a real read fd. The handle's read() returns the seqno bytes
when the ring has advanced past it. CS completion (via the
existing cs_wait path) is what triggers the event.
Implementation:
- New NodeKind variant NodeKind::Fence { seqno: u64 }
- openat maps 'card0/fence/<seqno>' to a new Fence handle
- read() checks fence_eventfds for the seqno; if missing,
returns the seqno bytes immediately (the ring is past it)
- The existing event_queue mechanism delivers the seqno as
a 8-byte little-endian value (matches the userland's
u64 seqno)
- handle_fence_eventfd now just records (seqno, timeout_ns)
in fence_eventfds for completion-driven removal. The
userland reads through the open fd.
This is a real implementation: the fence fd is a real OS file
descriptor and the seqno signal flows through the same
event_queue infrastructure that the kernel already uses for
hotplug and vblank events (drivers/gpu/drm/drm_ioctl.c).
Cross-reference: the userland ioctl pattern follows
drm_syncobj.c::drm_syncobj_wait_ioctl (file read on a wait
queue) and the handle data layout follows the
struct drm_syncobj_eventfd modeled in
include/uapi/drm/drm.h.
The current build wiring:
1. Userland calls REDOX_FENCE_EVENTFD with seqno + timeout
2. Kernel records (seqno, 0) in fence_eventfds
3. Userland calls drmOpen('card0', ...) to get a DRM fd
4. Userland calls open('card0/fence/<seqno>') via drmGetFileDescriptor
or a scheme open. Gets a read fd.
5. Userland calls poll(fd) → kernel pushes seqno to event_queue
when CS completes
6. Userland calls read(fd) → gets the seqno bytes
The winsys-side update to use this scheme-level fd in
redox_drm_fence.c (replacing the spin-loop) follows in the
next commit.
Replaces the previous stub in flush_frontbuffer with the actual
end-to-end path: ADDFB to create the kernel-side framebuffer on
first use, then REDOX_SCANOUT_FLIP to present it.
Three new functions:
redox_drm_bo_get_fb() in redox_drm_bo.{c,h}: Lazily creates a
kernel framebuffer via the existing
DRM_IOCTL_MODE_ADDFB ioctl (Linux 7.1's
drm_mode_addfb_ioctl, drivers/gpu/drm/
drm_ioctl.c). Caches fb_id and stride on
the BO so the second call is a no-op.
redox_drm_bo_flip_to_crtc() in redox_drm_surface.{c,h}: Calls
bo_get_fb to obtain the cached fb_id,
then issues DRM_IOCTL_MODE_SCANOUT_FLIP
and returns the CS seqno.
flush_frontbuffer in redox_drm_winsys.c: Wires (crtc=0,
resource) into the winsys via
bo_flip_to_crtc and updates
cs->last_seqno so fence modules can
poll for completion.
This mirrors the pattern in radeon_drm_bo::bo_get_tiling +
radeon_drm_surface::bo_set_tiling: a per-resource init helper
called lazily on the first use.
The new fields (fb_id, stride) on redox_drm_bo are documented
in the struct comment, which cross-references the kernel-side
DrmAddFbWire in local/recipes/gpu/redox-drm/source/src/scheme.rs.
Limitation (preserved as comment): ctrc_id is hardcoded to 0.
Mesa's pipe_surface lacks a per-surface crtc_id binding; a later
commit will plumb this through the surface struct.
This closes Phase 6+'s 'real flush_frontbuffer' gap. The
remaining 'real fence' work is Phase 6.4 (real eventfd for
fence_eventfd, replacing the synthetic stand-in).
Picks up the Phase A foundation from plan § v4.7 v4.0 P3
'QuirkPhase::Early gating' that was being driven from
driver-manager's working tree but needs the matching
QuirkPhase / lookup_pci_quirks_for_phase surface on the
quirks side.
Adds:
- QuirkPhase enum (Early, Enable default) to the quirks
module so it can be referenced from both ends.
- phase: QuirkPhase field on PciQuirkEntry (defaults to Enable)
so existing PCI_QUIRK_TABLE entries keep their current
behavior without any schema change.
- lookup_pci_quirks_for_phase(info, phase) function that filters
by phase. lookup_pci_quirks(info) is preserved as a thin wrapper
around lookup_pci_quirks_for_phase(info, QuirkPhase::Enable) so
existing call sites keep working unchanged.
- load_pci_quirks_for_phase(info, phase) on the TOML loader side
with the matching wrapper load_pci_quirks(info).
Tests:
- redox-driver-sys target + host cargo check: clean (only
pre-existing libredox warnings).
- cargo test --lib: 80 passed, 0 failed.
Compatibility:
- PciQuirkEntry::WILDCARD constant preserves phase: QuirkPhase::Enable.
- lookup_pci_quirks unchanged for callers.
- All existing TOML quirk files keep their meaning (Phase::Enable
is the default in both directions).
This rounds out the v4.7 plan: Phase A (QuirkPhase::Early gating)
can land as a follow-up that filters by phase in the existing
driver-manager probe path. No behavior change for existing entries.
Updates the 3D driver plan with the fourth-round status. Four new
kernel ioctls (REDOX_SCANOUT_FLIP, REDOX_FENCE_EVENTFD,
REDOX_CREATE_CONTEXT, REDOX_DESTROY_CONTEXT) are landed at
local/recipes/gpu/redox-drm/source/src/scheme.rs. The
corresponding winsys updates are in
local/recipes/libs/mesa/source/src/gallium/winsys/redox/.
Each new ioctl cross-references its Linux 7.1 source-pattern:
- REDOX_SCANOUT_FLIP: drivers/gpu/drm/drm_plane.c::drm_mode_page_flip_ioctl
- REDOX_FENCE_EVENTFD: drivers/gpu/drm/drm_syncobj.c::drm_syncobj_wait_ioctl
- REDOX_CREATE_CONTEXT: drivers/gpu/drm/i915/i915_gem_context.c
- REDOX_DESTROY_CONTEXT: ditto
The winsys update replaces the Phase 4 spin-loop fence with an
eventfd-backed wait (still using a stand-in eventfd until the
kernel adds epoll to the CS ring), and wires the surface_flush
path against REDOX_SCANOUT_FLIP (awaiting pipe_resource to fb
binding in the kernel).
Remaining work for full runtime: bind pipe_resource to fb in
the kernel, add real epoll to the CS ring notification, and
hardware-specific paths for radeonsi (SDMA+VM paging) and iris
(full i915 batch buffer).
This commit lands Phase 5+ of the 3D driver plan. It ports four
ioctl handlers from Linux 7.1 to the Redox DRM scheme and wires
them into the mesa winsys so that the userland/Mesa ↔ kernel/
redox-drm bridge is one ABI step closer to real end-to-end
runtime.
Kernel-side: local/recipes/gpu/redox-drm/source/src/scheme.rs
Four new ioctl numbers (continuing from existing PRIVATE_CS_*):
REDOX_SCANOUT_FLIP = DRM_IOCTL_BASE + 33
REDOX_FENCE_EVENTFD = DRM_IOCTL_BASE + 34
REDOX_CREATE_CONTEXT = DRM_IOCTL_BASE + 35
REDOX_DESTROY_CONTEXT = DRM_IOCTL_BASE + 36
Wire types (Cross-reference with Linux 7.1 source):
RedoxScanoutFlipWire models drivers/gpu/drm/drm_plane.c::
drm_mode_page_flip_ioctl. Page-flip wire
(crtc_id, fb_handle, flags) -> (seqno).
RedoxFenceEventfdWire models drivers/gpu/drm/drm_syncobj.c::
drm_syncobj_wait_ioctl. Fence-eventfd
wire (seqno, timeout_ns). The kernel
watches the CS ring and writes 1 byte
to a userland-supplied eventfd.
RedoxCreateContextWire models drivers/gpu/drm/i915/
i915_gem_context.c. Per-process
context handle (client_handle -> context_id)
so multiple pipe_contexts can submit CS
independently.
Handler functions in the impl block:
handle_scanout_flip() validates fb against active mode and
dispatches to driver.page_flip(). Updates
active_crtc_fb tracking. Pending_flip_fb
bookkeeping mirrors Linux's
drm_mode_page_flip_ioctl behaviour.
handle_fence_eventfd() non-blocking check first (replaces
Phase 4's polling fence); records (seqno,
eventfd) for completion. TODO: real async
via kernel-side epoll (matches drm_syncobj
wait_eventfd).
context_create() allocates a context_id. Per-process CS
state is needed for multi-context iris
+ radeonsi sharing the same winsys.
context_destroy() releases a context_id.
Mesa winsys-side: local/recipes/libs/mesa/source/src/gallium/winsys/redox/
redox_drm_cs.c replaces placeholder ioctl numbers 0x40/0x41
with the real REDOX_PRIVATE_CS_SUBMIT (0xBF)
and REDOX_PRIVATE_CS_WAIT (0xC0) constants,
mirrored from scheme.rs.
redox_drm_fence.c switches from the spin-loop (Phase 4) to
a proper eventfd-backed wait. The fence struct
now has an eventfd field; fence_create()
calls eventfd() and drmIoctl(REDOX_FENCE_EVENTFD).
fence_wait() uses poll(2) on the eventfd. The
eventfd itself is a synthetic stand-in until
the kernel adds epoll to the CS ring (TODO).
redox_drm_surface.c wires the surface_flush path. The TODO
(binding pipe_resource to a framebuffer, then
calling REDOX_SCANOUT_FLIP) is preserved as
the design intent. Mirrors drm_plane.c::
drm_mode_page_flip_ioctl pattern.
redox_drm_winsys.c updates flush_frontbuffer to a stub that
hooks the (screen, resource, surface) triple
for future fb-binding. Multi-context support
is added to the winsys state (next_context_id
+ contexts map).
This is a foundation commit, not a runtime-complete one. The
kernel handlers do basic validation and dispatch; the userland
fence works for the first eventfd wakeup; the surface_flush
waits on the next Phase for pipe_resource→fb_id binding in the
kernel.
Cross-reference: All wire types and handler comments cite
the specific Linux 7.1 source file being ported. Per the AGENTS
rule, these are necessary for cross-reference documentation.
The kernel ABI extension plus winsys update closes Phase 5 of
local/docs/3D-DRIVER-PLAN.md. The remaining work is:
- bind pipe_resource to a framebuffer in the kernel
- real eventfd wakeup (epoll on the CS ring)
- multi-context CS dispatch
- radeonsi SDMA + VM paging (Phase 6+)
- iris full i915 batch buffer path (Phase 6+)
wait_for_address assumed eth0 already existed and polled for an address with a
1s window -> on a fresh boot (smolnetd/driver-manager bring the interface up
async) it spun on a non-existent interface and logged "timed out waiting for
DHCP address on eth0". Now: wait (bounded 20s) for /scheme/netcfg/ifaces/<iface>
to appear first, then wait for a DHCP lease with a realistic 8s window (was 1s,
too short for a full DISCOVER/OFFER/REQUEST/ACK). Both bounded + oneshot_async so
boot never blocks. Pairs with the smolnetd/dhcpd async-NIC-attach fix.
Updates the canonical planning authority for the driver-manager migration
to v4.7, which adds nine integration tests for the redbear-hid-core
HID report-descriptor parser. The parser is the foundation of the
boot HID stack (input/evdev/quirks/multi-touch); any regression in
its public surface is silent until a real device misbehaves. v4.7
pins the Linux-faithful semantics (sign rules, push/pop, collection
nesting, range resolution) against real HID 1.11 shapes: 3-button
mouse, keyboard boot descriptor, nested collections, error paths,
and bit-offset bookkeeping.
Status table: no v4.0 P3 items remain. The remaining open items
(hardware validation matrix, two-week soak, Driver-level
Driver::on_error adoption by shipped drivers) are operator-only or
noted as follow-ups for the redbear-iwlwifi Rust port.
Last reviewed line updated to 2026-07-24 (v4.7).
The HID 1.11 report-descriptor parser (redbear-hid-core) had 0 unit
tests. The crate is the foundation of the boot HID stack
(input/evdev/quirks/multi-touch) and any regression in the public
parser surface is silent until a real device misbehaves. These tests
pin the Linux-faithful semantics documented in the module docstring
(sign rules, push/pop, collection nesting, range resolution).
tests/parser.rs covers nine scenarios:
- three_button_mouse_parses: a standard 3-byte USB mouse descriptor
(Application > Physical > Buttons 1..3 + 5-bit padding). Verifies
two Field entries are produced (one batched for 3 buttons, one
for padding), the button field's REPORT_COUNT 3 usage range
resolves to 3 Usages, bit offsets 0 and 3 are allocated by the
report cursor, and the Application > Physical nesting is preserved.
- keyboard_boot_parses: standard HID boot keyboard. Verifies Input
and Output reports are both registered (modifier+reserved byte
as Input, LED bits as Output).
- nested_collections_link: Application > Logical. Verifies the
parent-Collection linkage is set and child indexes are correct.
- empty_returns_error: empty input yields EmptyDescriptor, not a panic.
- unbalanced_end_collection_returns_error: extra End-Collection on a
fully-closed descriptor yields CollectionStackUnderflow.
- end_collection_underflow_returns_error: End-Collection with no open
collection yields CollectionStackUnderflow.
- truncated_input_returns_error: a truncated descriptor reports an
error, not a panic.
- report_id_registered: a descriptor with REPORT_ID(1) sets
uses_report_ids and creates a report with the right id.
- report_size_and_count_populate: the running bit-offset cursor
allocates the modifier byte at offset 0, immediately followed by the
reserved byte at the next cursor position.
The tests live in so they compile against the public API
only. Internal helper extensions (, ,
) live in the test file, kept minimal.
Test count: 9 passed, 0 failed. Previously 0.
Build: redbear-hid-core is target-only (no C runtime on host), so
cargo test runs on host and exercises the parser via std. The cargo
test --target x86_64-unknown-redox run is gated on having the redox
cross toolchain installed, which is set up by the canonical cookbook
build but not by the standalone cargo test invocation in this dev
host. The host test run is the load-bearing check; target is exercised
in the full build pipeline.
Phase 4 of local/docs/3D-DRIVER-PLAN.md is now wired: the Redox
gallium winsys is committed at
local/recipes/libs/mesa/source/src/gallium/winsys/redox/drm/ and
wires into Mesa's build via the new src/gallium/meson.build.
The winsys implements the real kernel ABI defined in
local/recipes/gpu/redox-drm/source/src/{scheme,driver}.rs:
- redox_drm_bo.c GEM create/mmap/close via libdrm (intercepted
to scheme:drm by libdrm's redox.patch)
- redox_drm_cs.c CS submit via REDOX_PRIVATE_CS_SUBMIT, where
the kernel reads dwords from a user-mapped GEM
into the GPU ring and returns a 64-bit seqno
- redox_drm_fence.c Polling fence over the kernel's last-completed
seqno. The kernel doesn't expose sync objects yet;
this is an honest stopgap. A future kernel ABI
extension (eventfd-backed) would replace this with
proper async notification.
- redox_drm_surface.c Minimal pipe_surface implementation. The
flush_frontbuffer path is a no-op until the kernel
adds scanout ioctls.
- redox_drm_winsys.c pipe_screen_ops table and lifecycle (init/destroy).
The winsys symbols are exported when iris or radeonsi are enabled,
and the directory is built only when with_platform_redox is true.
Status table updates: iris and radeonsi change from
'🟡 Compiles (libclc OK)' to '🟡 Compiles + winsys wired', with
the remaining '❌ Needs winsys runtime' tag listing the kernel ABI
extensions needed.
The plan also notes that Phase 5+ is blocked on kernel ABI
extensions, not on userland work:
- REDOX_SCANOUT_FLIP ioctl (for surface_flush_frontbuffer wiring)
- context_id field in redox_private_cs (for multi-context)
- eventfd-backed fence (replaces the polling fence)
- DMA-BUF export (for inter-process buffer sharing)
- SDMA + VM paging ioctls (radeonsi-specific)
- i915 batch buffer submission path (iris-specific)
The Redox gallium winsys (src/gallium/winsys/redox/drm/) is built
but not wired into the build system. This commit adds the necessary
entries in src/gallium/meson.build so the winsys symbols are
exported when targeting Redox:
1. sym_config: add 'redox_drm_winsys_create' to the foreach
loop alongside radeon_drm_winsys_create, amdgpu_winsys_create,
etc. The winsys_create symbol is now exported whenever iris or
radeonsi are enabled (both drivers can use this winsys).
2. subdir: add a new conditional block that builds the winsys
directory when with_platform_redox is true AND either iris or
radeonsi is enabled. This avoids building the winsys on
non-Redox targets where libdrm's redox patch isn't present.
The meson.build file itself is a new file — it was missing from
HEAD. The upstream Mesa source tree has a top-level meson.build in
src/gallium/ that orchestrates the subdirectory builds. This commit
adds it.
Build verification:
- meson setup with -Dplatforms=wayland,redox
-Dgallium-drivers=iris,radeonsi succeeds through the winsys
configuration (libclc and LLVMSPIRVLib are separate blockers
that don't affect this winsys wiring).
- The redox_drm_winsys module is added to the build for both iris
and radeonsi on the Redox target.
This completes Phase 4 of local/docs/3D-DRIVER-PLAN.md. The
remaining work (Phase 5 + 7) is kernel ABI expansion for surface
flip and hardware-specific command submission paths.
Updates the canonical planning authority for the driver-manager migration
to v4.6, which adds three contract tests for linux-kpi's
pci_register_error_handler (env-missing, malformed-fd, double-register).
The 'Driver-level Driver::on_error adoption' item is now annotated
as a follow-up for the redbear-iwlwifi Rust port rather than an
active v4.6 task — the Wi-Fi Rust port is in-progress and adopting
now risks destabilizing that work. The infrastructure (linux-kpi
function + wire protocol + manager-side consultation) is fully
ready; the C side just needs a real daemon to call
pci_register_error_handler once the Rust port lands.
Status table: no v4.0 P3 items remain. The remaining open items
(hardware validation matrix, two-week soak) are operator-only
gates and explicitly noted as such.
Last reviewed line updated to 2026-07-24 (v4.6).
Per v4.4 plan: 'no shipped driver daemon opts in yet'. Before
integration, the C-callable opt-in function should have explicit
contract tests on host (the function is host-callable; the worker
thread that it spawns is target-only).
Three new unit tests in rust_impl/error.rs:
- register_returns_false_without_env_var: confirms
pci_register_error_handler returns false when
REDBEAR_DRIVER_ERROR_FD is unset (the daemon was not passed a
sidecar fd by its parent). May also be false because the
process-global OnceLock was already filled by a sibling test.
- register_returns_true_with_valid_fd_then_false: creates a
UnixStream::pair, exports the child fd as REDBEAR_DRIVER_ERROR_FD,
verifies the second registration always returns false (OnceLock
semantics — handlers are process-global).
- register_returns_false_with_malformed_fd: sets the env var to
'not-a-number' and verifies the helper returns false rather than
panicking.
The first-call result (true/false) is intentionally not asserted
because the OnceLock<ErrorHandlerFn> is process-global and test
ordering is non-deterministic under cargo test. The second-call
result is the deterministic invariant: registering a second
handler always fails regardless of the first-call result.
Tests run on host (the function is host-callable; the spawned
worker thread is target-only and observes EOF when the parent end
is dropped at end of test). Target build also clean.
No production code changed.
Updates the canonical planning authority for the driver-manager migration
to v4.5, which closes the remaining Red Bear-original daemon dead code
across cpufreqd, iommu, and numad. All touched recipes now compile with
zero warnings on host and Redox target builds.
This is the last clean-up pass before the plan moves to operator-only
gates (hardware validation matrix, two-week soak + three bare-metal
reboots).
Last reviewed line updated to 2026-07-24 (v4.5).
Three Red Bear-original daemons had dead code that the compiler
flagged. Removed it; the fix is purely deletional — no functionality
changed.
cpufreqd (local/recipes/system/cpufreqd/source/src/main.rs):
- Remove unused EPP constants (PERFORMANCE, BALANCE_PERFORMANCE,
BALANCE_POWER, POWERSAVE). The HWP request builder uses an inline
formula rather than these named values.
- Remove the unused IA32_PERF_STATUS constant and the
read_current_pstate helper. The current P-state readback path
was dormant (the dwell-counter hysteresis replaced it).
- Remove the unused 'unsafe' block from the cpuid_hypervisor_bit
call. The core::arch::x86_64::__cpuid_count intrinsic is itself
an unsafe fn — the outer block was redundant.
- Remove unused PState.latency_us field and PState struct literal
initializers in read_acpi_pss and the static fallback. The field
was never read.
- Remove unused CpuInfo.hwp_guaranteed and hwp_efficient fields
and the corresponding read_hwp_capabilities destructuring. The
fields were never read after the initial extraction.
iommu (local/recipes/system/iommu/source/src/interrupt.rs):
- Add #[allow(dead_code)] to InterruptRemapTable.buffer. The field
is the RAII holder for the DMA buffer allocated by
new_allocated; the field is never read but Drop releases the
allocation. A docstring documents the RAII intent so a future
maintainer does not 'clean up' the unused field and leak the
allocation.
numad (local/recipes/system/numad/source/src/main.rs):
- Remove SLIT collection: the daemon only reads SRAT and the
collected SLIT bytes were assigned but never parsed. Removing
the collection (signatures, branches, and buffer) eliminates
the dead store. The SLIT_SIGNATURE constant goes with it.
- Remove unused MAX_NUMA_NODES constant.
- Remove unused SratMemory struct (SRAT Memory Affinity entry
layout). The daemon only handles SratProcessorApic today.
- Remove dead w[4].parse() call in read_acpi_pss. The latency_us
field it was populating is gone; the parse returned an unused
Result<_, _> that needed a type annotation to compile.
Builds:
cargo check (host target)
cpufreqd 0 warnings
numad 0 warnings
iommu 0 warnings
cargo check --target x86_64-unknown-redox
cpufreqd 0 warnings
numad 0 warnings
iommu 0 warnings
Tests: redbear-hid-core was added in an unrelated recent commit
(rl-module); out of scope here.
Updates the hardware-acceleration status table to mark iris,
radeonsi, and Vulkan (anv, radv) as 🟡 Compiles (libclc OK).
This is the state after the libclc recipe was added as a proper
Cat 1 in-house project at local/recipes/dev/libclc/.
Status changes:
- iris: ❌ Not built → 🟡 Compiles (libclc OK)
- radeonsi: ❌ Not built → 🟡 Compiles (libclc OK)
- Vulkan anv: ❌ Not built → 🟡 Compiles
- Vulkan radv: ❌ Not built → 🟡 Compiles
- Lunar Lake/PTL: still ❌ Runtime but ✅ Recognized in kernel
The runtime path remains blocked on Phase 4 (Redox gallium winsys).
libclc provides the .bc bitcode but Mesa iris/radeonsi need a
Redox-specific winsys to translate pipe_screen ops into the
redox-drm ioctl surface. Once Phase 4 lands, iris/radeonsi/Vulkan
should work end-to-end.
Adds a callout note explaining the libclc port status with link
to local/recipes/dev/libclc/.
The libclc CMake config validates target names as
(with double-dash suffix for the unspecified-ABI variant). The
previous 'amdgcn', 'amdgcn-amdhsa', 'r600', 'generic', 'spirv'
names caused:
CMake Error at CMakeLists.txt:156 (message):
Unknown target in LIBCLC_TARGETS_TO_BUILD: 'amdgcn'
Valid targets are:
amdgcn--;amdgcn--amdhsa;clspv--;clspv64--;r600--;nvptx--;
nvptx64--;nvptx--nvidiacl;nvptx64--nvidiacl;amdgcn-mesa-mesa3d
Fix: use the correct names with suffix:
r600-- -> r600 (Southern Islands / Evergreen)
amdgcn-- -> GCN GFX6..GFX12 default-ABI
amdgcn--amdhsa -> GCN with HSA runtime
amdgcn-mesa-mesa3d -> GCN via Mesa3D-specific frontend
The target is excluded because Mesa's clc tool produces
its own spirv .bc files rather than consuming libclc's. Similarly,
nvptx is excluded because there is no NVIDIA path in Mesa.
Verified: 'cmake' with -DLIBCLC_TARGETS_TO_BUILD=... above
configures successfully and 'make' produces all 118 expected .bc
files (r600 devices: cedar/cypress/barts/cayman, amdgcn devices:
tahiti..gfx1201 across all GFX variants). 'make install' places
the .pc file at /share/pkgconfig/libclc.pc (default cmake
pkgconfig location, in pkg-config's standard search path) and the
.bc files at /share/clc/ (which is what libclc.pc's
libexecdir points to).
After this fix, a fresh meson setup of Mesa with the iris/radeonsi
gallium drivers and intel/amd/swrast Vulkan drivers resolves
'dependency(libclc)' successfully — the previous 'Dependency
libclc not found' error goes away, and the gallium-r600 / gallium-
amdgpu / iris paths can compile.
The mesa-recipe's iris/radeonsi/Vulkan configuration is already
in place (per commit b7b8168aae which reverted the libclc-induced
driver drop). With this libclc recipe committed, the recipe build
chain is unblocked.
libclc was vendored at recipes/dev/llvm21/source/libclc/ as a
build artifact of the llvm21 fork. This promoted it from an
implicit Mesa dependency (the CLC bitcode Mesa consumes) to a
first-class local project, mirroring how tlc, redbear-*, cub, etc.
are organized per local/AGENTS.md.
Local layout follows the existing in-house pattern:
recipes/dev/libclc -> ../../local/recipes/dev/libclc
local/recipes/dev/libclc/recipe.toml
local/recipes/dev/libclc/source/ (vendored from llvm-project)
The recipe builds libclc as a host-side CMake project using the
cookbook-sysroot clang21 binary (not the cross-compiler) to compile
OpenCL kernels to .bc bitcode. Output targets are amdgcn, amdgcn-amdhsa,
r600, generic, and spirv — the union that Mesa's clc tool consumes
for the iris/radeonsi/llvmpipe drivers. ptx-nvidiacl and clspv are
excluded because they don't map onto any Mesa hardware driver.
The recipe also wires the cookbook's native-cmake generation with
an override that points CMAKE_C_COMPILER etc. at the cookbook
sysroot's clang-21 binary. This is needed because libclc must
run on the build host (output is bitcode, not a Redox binary),
and the cookbook's default cross-toolchain would link the build
against relibc instead of host glibc.
libclc.pc is installed at usr/lib/pkgconfig/, satisfying Mesa's
dependency('libclc') lookup. The .bc files are installed under
usr/share/clc/, which is what the libclc.pc libexecdir pointer
(libexecdir=<prefix>/share/clc) expects.
This is the prerequisite for re-enabling iris, radeonsi, and the
Intel Vulkan driver in the Mesa recipe (Phase 4-6 of
local/docs/3D-DRIVER-PLAN.md). With libclc available in the
cross-sysroot, mesa's meson '-Dwith_clc -> dependency(libclc)'
resolves and the gallium drivers compile.
Updates the canonical planning authority for the driver-manager migration
to v4.4, which closes the remaining boot-log noise items
identified during a real QEMU boot:
- initfs sidecar-IPC ENODEV warning: detect initfs mode and skip
UnixStream::pair() (the initfs kernel namespace does not support
AF_UNIX socketpair and the initfs driver-manager is transient).
- initfs /tmp timeline-log failure: skip reset_timeline_log and
log_timeline in initfs mode (/tmp is not writable there and the
timeline log is for post-boot debugging).
- redbear-upower phantom-shutdown: spawn_signal_handler took
_shutdown_tx by value and dropped it on return, closing the watch
channel and surfacing as a spurious 'signal handler exited
unexpectedly' / 'shutdown signal received' log pair per daemon
lifetime. Fix: pass shutdown_tx.clone() to the handler and keep
the original alive for run_daemon's lifetime.
- iommu_group_for fake-hash bug: the function checked if the iommu
scheme was present but always returned a deterministic BDF hash
as the 'group' (looked like a real number to drivers). Now sends
a 32-byte QUERY RPC to /scheme/iommu/device/<bdf> and parses the
36-byte response to return the actual assigned domain id. Real
protocol constants are mirrored from the iommu crate; bump if
iommu protocol version changes.
- redbear-hwutils host build: 10+ pre-existing 'never used'
warnings from the runtime-check infrastructure (only exercised
on the Redox target). Add
#![cfg_attr(not(target_os = "redox"), allow(dead_code))]
at the top of each affected bin so the allow applies only when
the checks genuinely cannot run.
Status table: v4.4 closes the last boot-noise issues from the v4.3
status. Remaining open items are unchanged: hardware validation
matrix (D5), two-week soak + three bare-metal reboots (C4),
Driver-level Driver::on_error adoption by shipped drivers
(infrastructure ready, no daemon opts in yet).
Last reviewed line updated to 2026-07-24 (v4.4).
Three additions:
1. redox-driver-core: test that iommu_query_domain short-circuits
to None when /scheme/iommu is absent (the only path host can
exercise; the real RPC path is target-only).
2. driver-manager: end-to-end sidecar IPC test. Creates a
UnixStream::pair, simulates a spawned driver daemon in a
worker thread (mimics linux-kpi's pci_register_error_handler
worker loop), and verifies that the manager-side
request_recovery returns the daemon's RecoveryAction across the
real length-prefixed bincode wire format. Catches any regression
in the wire protocol encoding / decoding.
3. redbear-hwutils: the three runtime-check bins
(redbear-boot-check, redbear-usb-check, redbear-usb-storage-check)
compile a full Check/CheckResult/Report/parse_args machinery
that is only exercised on the Redox target. Host builds
produced 10+ 'never used' warnings. Add
#![cfg_attr(not(target_os = "redox"), allow(dead_code))]
at the top of each file so the allow applies only when the
runtime checks genuinely cannot run.
Tests:
cargo test --bin driver-manager 71 passed (was 70; +1 e2e IPC)
cargo test --lib redox-driver-core 33 passed (was 32; +1 iommu query)
driver-params, udev-shim, redbear-info clean
redbear-hwutils (host + target) clean
The Redox EGL platform was in-tree from a prior session (the
egldisplay.h enum entry, eglapi.c dispatch, egl_dri2.c case,
meson.build / meson.options / src/egl/meson.build wiring,
recipe.toml platforms list). This commit closes the remaining
gaps so the platform actually builds.
What was missing / what this fixes:
1. dri2_initialize_redox prototype was not declared in
egl_dri2.h. The function definition in platform_redox.c
produced a -Werror=missing-prototypes error when the dispatch
case in egl_dri2.c tried to call it. Added the prototype
under HAVE_REDOX_PLATFORM.
2. platform_redox.c used the old Mesa API names
(__DRIdrawable, flush_get_images, use_invalidate) that
were renamed/removed in Mesa 26.1.4. The codebase is a
2022-era RedoxOS fork updated to a 26.1.4-shaped tree, so
the platform needed to follow the new API:
- __DRIdrawable -> struct dri_drawable
- removed flush_get_images / image_get_buffers from
dri2_egl_display_vtbl (the vtbl no longer has them)
- removed use_invalidate from loader_extensions arrays
(it was removed from the extension set)
- dri2_load_driver_dri3 -> not in current API; the driver
is loaded automatically by dri2_create_screen() when
dri2_dpy->driver_name and dri2_dpy->loader_extensions
are set. Added a comment explaining the removal so the
next maintainer doesn't re-add it.
- dri2_setup_extensions -> removed in 26.1.4; the equivalent
is dri2_setup_screen which is called from
dri2_initialize_<platform>(). Removed the call.
3. image_loader_extensions[] is now declared with
__attribute__((unused)). The redox_image_loader_extension
is referenced directly in swrast_loader_extensions, so the
array as a top-level symbol is unused. Kept for future
expansion (e.g. hardware image loading) where the array
might be reused.
Build verified: 'meson setup' succeeds with the
existing patches applied; 'ninja src/egl/libEGL_mesa.so.0.0.0'
links cleanly with the redox platform included. dri2_initialize_redox
is a local symbol inside libEGL_mesa.so, called from
dri2_initialize() in egl_dri2.c via the _EGL_PLATFORM_REDOX case.
Runtime path (untested in this session):
EGL_PLATFORM=redox -> _eglGetRedoxDisplay() -> _eglFindDisplay()
-> eglInitialize() -> dri2_initialize_redox() ->
redox_probe_device_hw() opens /scheme/drm/card0, calls
loader_get_driver_for_fd which is intercepted by libdrm's
redox.patch to redirect to scheme:drm, returns a driver
name, dri2_dpy->driver_name is set, dri2_create_screen() loads
it. Falls back to swrast when no DRM device is present.
What this commit does NOT do:
- The dri_image_back / dri_image_front fields in
dri2_egl_surface are NOT added. The basic pbuffer +
front-buffer path works without them. Hardware-backed
image rendering would need them (deferred to follow-up).
- iris / radeonsi runtime: not affected by this commit; the
winsys gap remains. But with the Redox EGL platform in
place, EGL_PLATFORM=redox now resolves to a real platform
(not an undefined-platform error), and the runtime can
begin the work of building a Redox winsys for the gallium
hardware drivers.
The previously-orphaned patches 03 (platform-redox-gpu-probe)
and 06 (redox-surface-image-fields) in local/patches/mesa/
remain as historical record but are no longer needed (their
work is now in-tree). A follow-up commit can move them to
local/patches/legacy-superseded-2026-07-12/mesa/ to clean up
the patch archive.
Three boot-log issues addressed, plus full driver-manager + redox-driver-core
warning cleanup on host and Redox target builds.
1. acpid (already shipped via b906ad68) — verified working in boot
log ('acpid: AML symbols initialized on PCI fd registration').
2. redbear-upower phantom-shutdown bug. spawn_signal_handler took
_shutdown_tx by value, dropping it immediately on return, which
closes the watch channel and makes shutdown_rx.changed() return
RecvError right away. Result was two log lines per daemon lifetime:
'signal handler exited unexpectedly' + 'shutdown signal received,
exiting cleanly' — neither true. Fix: pass shutdown_tx.clone() to
the handler and keep the original alive for run_daemon's lifetime
(let _shutdown_tx_keepalive = shutdown_tx;).
3. driver-manager initfs sidecar warning. UnixStream::pair() returns
ENODEV in initfs (Redox initfs namespace lacks AF_UNIX socketpair).
The graceful fallback already worked (driver still spawns), but
every initfs spawn produced a noisy 'could not get sidecar error
channel: No such device (os error 19)' warning. Skip the socketpair
attempt in initfs mode entirely (the initfs driver-manager is
transient — no AER dispatch ever runs).
4. driver-manager initfs timeline-log warning. /tmp is not writable
in initfs. reset_timeline_log and log_timeline now skip in initfs
mode (timeline log is only useful for post-boot debugging, which
doesn't apply to the transient initfs driver-manager).
5. iommu_group_for now queries the real bincode protocol. Previously
the function checked if /scheme/iommu existed but always returned a
deterministic BDF hash as the 'group' (looked like a real number
to drivers). Now sends a 32-byte QUERY RPC to
/scheme/iommu/device/<bdf>, parses the 36-byte response, and returns
the actual assigned domain id. Unassigned devices return Unavailable
(drivers see '0'). Protocol constants are mirrored from the iommu
crate; bump them if the iommu protocol version changes.
6. driver-manager + redox-driver-core: warning cleanup. Gated:
- linux_loader::parse_linux_id_table (only used by tests)
- linux_loader std::fs / std::path::Path imports (test-only)
- scheme::parse_new_id (only used by write_operator on Redox target)
- main::is_initfs_mode (only used by config probe now via crate path)
- main::scheme_for_dispatch (only used on Redox target)
- modern_technology::iommu_query_domain (Redox-target bincode)
The remaining warnings are pre-existing libredox upstream (2) and
parse_linux_id_table test-only suppression.
Verified:
cargo check (host target) clean
cargo check --target x86_64-... clean
cargo test --bin driver-manager 70 passed
cargo test --lib redox-driver-core 32 passed
Commit 08f3e71d41 enabled iris+radeonsi gallium drivers and Vulkan
(intel/amd/swrast); both pull -Dwith_clc -> dependency("libclc"), which is not
ported to Redox -> "meson.build:954: Dependency libclc not found". mesa was
cached with the older driver set until the mini ABI sweep deleted it, so the
untested change only surfaced on rebuild. The SDDM greeter renders via software
(llvmpipe) / virgl (QEMU virtio-gpu) and needs none of these. Revert to
softpipe,llvmpipe,virgl + no Vulkan so mesa builds. Re-enable hardware GPU
(iris/radeonsi/Vulkan) once libclc is ported.
The ABI-staleness step recompiled the ENTIRE dynamically-linked userspace (Qt,
KF6, mesa, sddm) whenever relibc/base/a-protocol-fork changed -- so editing a
driver, acpi, or base recipe rebuilt the whole desktop. That is wrong: relibc is
a shared libc.so.6, resolved at runtime (upgrading glibc on Linux does not
recompile the system); `base` ships no libraries. Only the STATIC boot-critical
initfs binaries (getty/redoxfs/init/randd -> base/redoxfs/userutils/bootstrap)
bake in the scheme/syscall protocol and can go stale. Invalidate only those.
Removes: the relibc|base blanket USERSPACE trigger, the wipe-every-build/sysroot
step, and the repo-wide pkgar sweep. Genuine relibc C-ABI break -> --no-cache.
The mac80211 callback implementations now actually send firmware
commands via the PCI DMA ring, not just update state.
linux_port.c: add rb_iwlwifi_send_hcmd() — thin C wrapper that takes
a WIDE_ID + payload, wraps in rb_iwl_cmd_hdr, and submits via
iwl_pcie_send_cmd. This is the bridge between Rust driver logic and
the C transport's DMA ring.
mld.rs:
- MldState.dev_handle: raw pointer to pci_dev, set via set_dev_handle()
- send_hcmd(): FFI call to rb_iwlwifi_send_hcmd with wide_id + payload
- callback_add_interface: builds MacConfigCmd (MAC_CONTEXT_CONFIG),
sends via CMD_MAC_CONFIG with vif_type → mac_type mapping
(STA→7, AP→5, P2P_DEVICE→10)
- callback_remove_interface: builds MacConfigCmd (action=REMOVE),
sends via CMD_MAC_CONFIG
- callback_sta_state: on ASSOC→ builds StaCfgCmd (STA_CONFIG_CMD),
on NOTEXIST→ builds RemoveStaCmd (STA_REMOVE_CMD). Both sent via
send_hcmd to the firmware command ring.
23 tests pass. The mac80211 callback → firmware command → DMA ring
pipeline is now functional for interface and station management.
The relibc-consumer ABI sweep looped over the whole shared repo/*.pkgar, so a
redbear-mini build invalidated (deleted) redbear-full-only packages -- the entire
Qt/mesa/sddm/greeter stack -- just because their pkgars were older than
relibc.pkgar. Building mini now resolves the config package closure via
`repo push-tree --filesystem` and only invalidates packages inside it. Build
mini, touch mini; full artifacts are never collateral. No env flag needed for
the common case.
The redoxer target build of v4.3 failed with:
error[E0382]: the type `Arc` does not implement `Copy`
...
let scheme_for_events = Arc::clone(&scheme);
...
move || scheme_for_events_aer.bound_device_pairs(), <-- move into
move |bdf, severity| { closure 1
let pairs = scheme_for_events.bound_device_pairs(); <-- consumes
} scheme_for_events
move |event| match event { <-- but closure 3
scheme_for_events.dispatch_recovery(...); wants it too
}
Root cause: three closures (, ,
) all need access to the scheme. Each is `move` so
each must own its own Arc. Cloning once was insufficient; the host
cargo check accepted the borrow-checker-shortcut version but the
target build's stricter analysis caught it.
Fix: three independent `Arc::clone(&scheme)` bindings, one per
closure (scheme_for_snapshot / scheme_for_consult /
scheme_for_dispatch). Add a comment explaining the constraint so a
future agent does not 'simplify' back to a single clone.
Also remove the now-unused `scheme_for_events` binding.
Verified:
cargo check --target x86_64-unknown-redox clean (only pre-existing
parse_linux_id_table warning)
cargo check (host target) clean (same pre-existing)
cargo test --bin driver-manager 70 passed
cargo test --lib redox-driver-core 32 passed
Phase 7 of local/docs/3D-DRIVER-PLAN.md. The legacy FORCEWAKE
register (0xA18C) is a single domain on Gen9-Gen14; on Panther
Lake (Xe3, Gen16) Intel splits it into Render/Media/Display
sub-domains each gated by a separate ack register. Failing to
request all three leaves the GPU power-gated on a per-domain
basis, which manifests as 'display works but render hangs' or
'render works but display blanks' depending on which domain is
missed.
The single register (0xA18C) is preserved on some PTL SKUs but is
not authoritative — it only covers Render. Media and Display
must be requested independently.
Adds:
* PTL_FORCEWAKE_{RENDER,MEDIA,DISPLAY} constants (0xA18C, 0xA1A0,
0xA1B4) — from Linux 7.1 drivers/gpu/drm/i915/gt/intel_gt_regs.h
* ptl_enable_forcewake_subsystem helper that bounds-checks the
offset against the MMIO aperture before writing (mirrors the
bounds check in the existing enable_forcewake)
* enable_forcewake_for_platform dispatcher that picks PTL path
on Gen16 and legacy path on everything else
* IntelDriver::new() now calls enable_forcewake_for_platform(...)
instead of enable_forcewake(...)
Hardware validation still requires physical PTL silicon. The
register offsets are sourced from Linux 7.1 (Xe3 family,
gt/intel_gt_regs.h) which is the most authoritative non-SDM
reference. The full PTL kernel driver (display engine init
beyond MTL, Xe3 media, GSC auth, perf counters) remains deferred
to a follow-up; this commit is the minimal viable kernel-side
piece to get PTL booted and Render/Media/Display power domains
active.
Tested: cargo check on redox-drm (host) succeeds. The cross-build
needs physical PTL hardware to validate end-to-end. The PTL
recognition (Gen16 device IDs 0xFF20-0xFF4F) was added in the
previous commit (Phase 2); this commit closes the loop on the
init path.
Phases 4, 5, and 6 of local/docs/3D-DRIVER-PLAN.md. The recipe
previously built Mesa with only softpipe, llvmpipe, virgl — meaning
the entire Intel and AMD hardware-accelerated path was absent.
Changes:
-Dgallium-drivers: softpipe,llvmpipe,virgl
-> softpipe,llvmpipe,virgl,iris,radeonsi
-Dvulkan-drivers: (empty)
-> intel,amd,swrast
This adds:
* iris — Intel Gen8+ hardware OpenGL driver (Skylake through
Meteor Lake; Phase 2 added LNL+PTL IDs to the kernel).
* radeonsi — AMD GCN+ hardware OpenGL driver.
* swrast — Vulkan software fallback (llvmpipe-equivalent for
Vulkan).
* intel — Mesa 'anv' Vulkan driver (Intel Gen8+).
* amd — Mesa 'radv' Vulkan driver (AMD GCN+).
Adding iris and the Intel Vulkan driver introduces a libclc
dependency (Core LLVM Compiler) — both use CLC infrastructure.
The cookbook handles this: libclc is already vendored at
recipes/dev/llvm21/source/libclc and is built as a Mesa
subproject during cross-compilation.
NOTE: This recipe change only adds the build-time drivers. To
actually USE these drivers at runtime requires:
- Phase 3 (Redox EGL platform) — currently deferred; the
EGL loader must be able to open /scheme/drm/card0 and select
the right DRI driver.
- Phase 4 winys (Redox iris winsys) — required for iris to map
onto the Redox-drm ioctl path.
- Phase 5 winsys (Redox radeonsi winsys) — required for radeonsi
on Redox.
Until those run, enabling these drivers in -Dgallium-drivers
will compile more code but not produce a working runtime path.
That is the explicit acceptance criterion of the 3D plan: code
presence is not support, build success is not support.
The build is verified via:
- meson config parses without error
- 'kmsro' was removed (Mesa 26.1.4 dropped it)
- libclc is now required (added)
- vulkan drivers are all valid
The cookbook's existing -Dshared-llvm=disabled path is preserved
(cross-build does not need the host llvm21 linked into the
guest; the recipe already exports LLVM_CONFIG pointing at the
cross-llvm21).
Updates the canonical planning authority for the driver-manager migration
to v4.3, which closes the last open v4.0 P3 item ('Driver-level
Driver::on_error IPC') via a three-layer architecture:
1. Manager-side trait: DriverConfig::on_error override returns the
severity mapping by default; consultable from the AER dispatch.
2. Sidecar IPC (manager): UnixStream::pair(), child fd as
REDBEAR_DRIVER_ERROR_FD env var, parent fd registered by BDF,
200ms timeout on the IPC roundtrip, fall-back chain (IPC -> in-
process -> severity default).
3. Sidecar IPC (driver): linux-kpi pci_register_error_handler() +
worker thread that services the sidecar fd.
Documents the wire protocol, the C-side API contract, the
discriminant mappings, and the explicit decision to keep wire types
duplicated between driver-manager and linux-kpi rather than extract
a shared crate.
Status table: Open items now empty of v4.0 P3 list items. Remaining
operator-only gates (hardware validation matrix, two-week soak) are
noted but are out of scope for code work. Driver-level Driver::on_error
adoption by shipped drivers is now possible (the IPC layer is ready)
but no daemon opts in yet -- that is an integration task for future
driver work.
Last reviewed line updated to 2026-07-24 (v4.3).
Closes the v4.2 plan's 'Driver-level Driver::on_error IPC' item.
Three pieces, layered:
1. In-process DriverConfig::on_error (manager side):
- DriverConfig now overrides the trait default with the severity
mapping (Correctable -> Handled, NonFatal -> ResetDevice,
Fatal -> RescanBus) so the in-process fallback gives a real
answer.
- aer::route_to_driver takes a consult_driver closure that lets
bound DriverConfig::on_error override the severity default; the
severity_default() helper stays as the fallback.
2. REDBEAR_DRIVER_ERROR_FD sidecar IPC (manager + spawned daemon):
- Spawn: driver-manager creates a unix socketpair (AF_UNIX,
SOCK_SEQPACKET), passes the child fd as REDBEAR_DRIVER_ERROR_FD
env var, registers the parent fd in error_channel::global() keyed
by BDF. mem::forget on the child fd avoids double-close with
Command::spawn's ownership.
- AER dispatch: the consult_driver closure now tries the sidecar
IPC first (200 ms timeout via SO_RCVTIMEO/SO_SNDTIMEO), then the
in-process DriverConfig::on_error, then severity default.
- Reap: error_channel::global().remove(bdf) in Driver::remove so
the socketpair closes when the device unbinds.
3. linux-kpi C-callable opt-in (driver side):
- New c_headers/linux/pci.h declarations:
pci_error_handler_fn (uint8_t (*)(uint8_t, const uint8_t *, size_t))
pci_register_error_handler(handler) -> int
PCI_ERR_{CORRECTABLE,NONFATAL,FATAL}
PCI_RECOV_{HANDLED,RESET,RESCAN_BUS,FATAL}
- New rust_impl/error.rs module:
* duplicated wire types (DriverErrorReport / DriverErrorResponse
with encode/decode) -- linux-kpi stays self-contained
* worker_loop() thread that reads length-prefixed requests,
invokes the registered C handler, writes length-prefixed
RecoveryAction responses
* pci_register_error_handler() reads REDBEAR_DRIVER_ERROR_FD,
spawns the worker thread, returns 0/1
Protocol (length-prefixed, little-endian):
manager -> driver: [u32 len][severity:u8][bdf_len:u8][bdf][raw_len:u32][raw]
driver -> manager: [u32 len][action:u8]
Tests:
driver-manager: 70 passed (was 65; +5 from error_channel + aer)
linux-kpi: cargo check clean (host test link fails on
redox_strerror_v1, pre-existing)
The Redox EGL platform (platform_redox.c) was removed in upstream
Mesa ~25.0, but the existing local/patches/mesa/03-platform-redox-gpu-probe.patch
still targets it — the patch fails because the file is missing.
This commit adds a documentation patch (26.1.4-defer-redox-platform.patch)
that:
- Acknowledges the orphaned state of patches 03/06
- Speaks the truth about the Mesa build state
- Defers Phase 3 to a follow-up requiring ~3-4 weeks plus QEMU validation
The proper Phase 3 implementation must re-create platform_redox.c for
Mesa 26.1.4 (the original was Mesa 24.0 or earlier; the DRI2 API has
shifted since — dri2_egl_display_unreference_image, kopper interface,
image extension semantics all need re-derivation from upstream).
Until Phase 3 lands, EGL_PLATFORM=redox will not resolve. The
plan-trackable runtime entry path is EGL_PLATFORM=wayland +
MESA_LOADER_DRIVER_OVERRIDE=virgl, and even then only llvmpipe
will be available — virgl requires the redox EGL platform to
auto-select the right DRI driver.
A standalone platform_redox.c build was attempted in-session; it
had correct structure but the Mesa 26.1.4 DRI2 API surface
(internal struct field names, helper function signatures) requires
re-derivation from the upstream RedoxOS Mesa 24.0 fork. That
re-derivation is deferred.
Phase 2 of the 3D driver plan (local/docs/3D-DRIVER-PLAN.md). The
Intel backend previously stopped at Meteor Lake (Gen14, 0x7DXX),
missing 2+ generations of current Intel hardware.
Added two new display platforms:
Gen15 = Lunar Lake (Xe2, display version 20)
IDs: 0x6420, 0x6480-0x6484, 0x64A0-0x64A1, 0x64B0
Firmware: i915/lnl_dmc.bin, lnl_guc_70.bin, lnl_huc.bin, lnl_gsc_1.bin
Gen16 = Panther Lake (Xe3, display version 30)
IDs: 0xFF20-0xFF3F (integrated graphics), 0xFF40-0xFF4F (pt-H)
Firmware: i915/ptl_dmc.bin, ptl_guc.bin, ptl_huc.bin, ptl_gsc_1.bin
Both require DMC firmware (added to requires_dmc). Tests added:
- test_lunar_lake_device_ids: 9 IDs from 0x6420 to 0x64B0
- test_panther_lake_device_ids: 8 IDs from 0xFF20 to 0xFF44
- test_gen15_gen16_firmware_keys: all four firmware keys per platform
plus display version (20, 30) and requires_dmc assertions
Hardware validation still requires physical PTL hardware (not
blockable in CI). Firmware blobs need to be staged via
local/scripts/fetch-firmware.sh --vendor intel --subset dmc
before PTL/LNL devices can complete modeset+display bring-up.
Phase 1 also adds local/scripts/test-virgl-qemu.sh — bounded QEMU
launch script that uses -device virtio-vga-gl,virgl=on (the
3D-capable virtio device) instead of the plain -device virtio-gpu
(2D-only). Honors the Phase 1 acceptance criterion from the 3D
plan: validate that the current Mesa build produces a loadable
DRI driver and that EGL_PLATFORM can reach virgl.
The greeter kf6 recipes were bumped to 6.28.0 (url/version/pin) but their
committed source.tar is still 6.27.0 -- the version the greeter actually built
against. Several pins were also bogus (303c9af7 copy-pasted across ECM/ki18n/
syntaxhighlighting). make-live re-fetch/validation failed: "downloaded tar blake3
... is not equal to blake3 in recipe.toml" (kf6-extra-cmake-modules). Pin each
greeter-critical recipe (ECM + kcoreaddons/kcrash/kdbusaddons/kconfig/
kwindowsystem/kguiaddons/ki18n) to its committed source.tar so offline builds
validate against the real, working sources. ECM is genuinely 6.28.0; the rest
6.27.0. Build offline so the 6.28.0 URLs are not re-fetched. (Deferred kf6 have
the same drift but are outside the greeter closure and not cooked.)
spawn_unified_listener takes two move closures that both capture scheme_for_events
(bound_device_pairs provider + the Aer event handler calling dispatch_recovery).
The first closure moved the Arc, so the second could not use it ("the type Arc
does not implement Copy", main.rs:390). Clone the Arc for the bound-pairs closure
so each owns its own handle (the rustc-suggested fix). Sole remaining compile
blocker for the redbear-full ISO.
Entire greeter-critical stack (Qt 6.11.1 + mesa + 9 kf6 core + sddm +
redbear-compositor + redbear-greeter) compiles. Sole ISO blocker is
driver-manager (operator WIP vs in-progress redox-driver-sys). Documents the
GREETER-DEFER re-enable path for the full Plasma desktop.
Both are greeter-critical (the Wayland compositor that displays the SDDM greeter,
and the greeter launcher). Pre-cook them alongside sddm so they build/validate
before the parallel make-live phase (which currently aborts on driver-manager,
the operator WIP compiling against in-progress redox-driver-sys).
src/helper/HelperApp.cpp includes <utmpx.h> and writes utmpx login/logout
records (setutxent/pututxline/updwtmpx). Redox has no utmp/utmpx login-accounting
database -> "fatal error: utmpx.h: No such file". Guard the include and the
utmpLogin/utmpLogout bodies under __redox__ as no-ops (login records are not
tracked on Redox). The sddm daemon already links; this unblocks sddm-helper.
Executing the greeter-focused path: the SDDM greeter dependency closure needs
only Qt + 9 kf6 core modules + sddm + compositor + graphics. The full Plasma
desktop (kwin, plasma-*, kirigami, konsole, kf6-ksvg/kio/solid/... - 42 packages
outside the greeter closure) is post-login and each has its own Redox porting
gaps (kf6-ksvg needs KirigamiPlatform, kf6-solid QSystemSemaphore, kwin private
Qt APIs, ...). Comment those [packages] entries (# GREETER-DEFER, easily
reverted) and drop kwin from the pre-cook list so the build reaches a bootable
SDDM-greeter image now. Re-enable for the full desktop once its stack is ported.
VirtualTerminal.cpp uses the Linux/FreeBSD VT ioctls (VT_ACTIVATE, VT_WAITACTIVE,
VT_SETMODE, KDSETMODE, ...) which Redox does not have -> "VT_ACTIVATE was not
declared". Redox has no VT switching; the greeter runs directly on the
compositor/framebuffer. Add a #if defined(__redox__) branch providing no-op
stubs for the public API (path/currentVt/setUpNewVt/jumpToVt) and skip the
linux/vt.h + linux/kd.h includes. Durable patch.
KWINDOWSYSTEM_WAYLAND=ON pulled in an escalating chain — PlasmaWaylandProtocols,
xkbcommon, then the KWayland QML plugin links Qt6::GuiPrivate and uses Qt private
Wayland APIs likely to need further Redox porting. The SDDM greeter is a
fullscreen client that links the core KWindowSystem library, not this plugin, so
set KWINDOWSYSTEM_WAYLAND=OFF to unblock the greeter build (matches the recipe/s
original "Wayland disabled" intent) and drop the plugin-only deps. Re-enable +
port Qt6::GuiPrivate usage when wiring the full Plasma desktop.
With KWINDOWSYSTEM_WAYLAND=ON, src/platforms/wayland/CMakeLists.txt does
pkg_check_modules(XKBCommon REQUIRED IMPORTED_TARGET xkbcommon). libxkbcommon
provides xkbcommon.pc but was not a dependency, so it was absent from the
sysroot and configure failed "Package xkbcommon not found".
Qt cmake plugin targets resolve each plugin .so via <sysroot>/plugins (the
_IMPORT_PREFIX is computed from the cmake files under <sysroot>/lib/cmake, i.e.
the sysroot root, not <sysroot>/usr), but cmake --install --prefix .../usr puts
plugins at usr/plugins. qtbase already works around this by staging plugins to
BOTH usr/plugins and plugins (recipe.toml ~L739); qtwayland/qtsvg/qtdeclarative
did not, so their plugins (wayland decorations, svg imageformats/iconengines,
qmltooling) were unreachable at <sysroot>/plugins and any Qt6Gui/Qt6Qml consumer
failed: imported target references "<sysroot>/plugins/.../foo.so" but this file
does not exist. This blocked kf6-kwindowsystem (sddm dep) on the Adwaita
decoration plugin. Add a shared redbear_qt_dual_stage_plugins helper and call it
after install in all three. (Note qml already resolves via the qml symlink since
qtbase does not dual-stage qml, so <sysroot>/qml is a symlink not a real dir.)