Loose ends: repin illumos-ddi, ENOMEM for failed DMA binds, page-size constant in rdrmnull #4

Merged
forge merged 6 commits from loose-ends-20260928 into main 2026-09-29 19:11:14 +00:00
Contributor

Loose ends after the R0, R1 and DMA-drill merges.

1. Pin

illumos-ddi moves from b24c307 to eb0150cadc, the head of illumos-ddi loose-ends-20260928 (illumos/illumos-ddi#3). I chose the branch head so this PR's CI can build now. Once illumos-ddi#3 is merged, move the pin to the merge commit on illumos-ddi main. The branch commits stay reachable from that merge commit, so the pin keeps resolving either way.

API adaptation: illumos-ddi now requires the OwnNode for minor nodes. Device::attach creates card<N> and renderD<128+N> from the node before the GEM state takes it. Opens wait until attach returns, and a later failure (GEM setup, registry) drops the nodes again. No other illumos-ddi API change affects this repository: property updates and LdiIdent::from_dip are not used here.

2. Errno for failed DMA binds

SysMem::bind mapped DDI_DMA_NOMAPPING to EFAULT. That is how every failed root-node bind on the patched kernel reached userland from CREATE_DUMB; EFAULT in a create ioctl reads as a bad user pointer. The handle allocation went through illumos-ddi's generic From<DmaError> for Errno, which also answers EFAULT for NoMapping.

The new drm::dmaerr module maps DMA failures during object creation the way Linux's DRM reports a failed object allocation:

Failure errno
NORESOURCES, TOOBIG, NOMAPPING, PARTIAL_MAP (never requested) ENOMEM
BADATTR, BADLIMITS, TOOSMALL, zero length, out of range EINVAL
DmaError::NotOwnNode (illumos-ddi guard) ENXIO
INUSE, LOCKED, STALE, DDI_FAILURE, unknown codes (not possible for a fresh handle) EIO

The handle allocation, the bind and the drill's raw allocation all use it. The match is exhaustive over DmaError, so a new variant must be decided on. Five host tests cover the table, including NOMAPPING -> ENOMEM.

The errno was also recorded on a kernel. rdrmnull's self drill takes an optional dma-max-transfer property. tools/test/rdrmnull-dma-self-tiny.conf sets it to one page, and tools/test/drm_dma_errno_test.c found:

  • A one-page dumb buffer binds.
  • A four-page one fails with errno 12 (ENOMEM), through rootnex's DDI_DMA_TOOBIG, confirmed by rootnex's "coding error detected" warning.
  • The gem kstat is back at zero afterwards.

DDI_DMA_NOMAPPING itself cannot be produced on a stock kernel with these flags: rootnex returns it only on the IOMMU path, or when trimming with DDI_DMA_PARTIAL, which the core never requests. That mapping is therefore covered by the host test only.

3. Advisory from the R1 review

rdrmnull now uses drm::offsets::PAGE_SIZE instead of the literal 4096 for the drill's cookie limit and for the movable-object reservation.

Verification

Local checks, targeting x86_64-unknown-illumos:

  • check, clippy -D warnings with and without rdrmnull/panic-drill, fmt --check and doc -D warnings pass.
  • cargo test -p drm -p drm-uapi: 47 + 1 passed. The 2 dead-code warnings in the test build are already on main.
  • uapi-check: 0 differences.

Kernel runs used a fresh golden guest on Hephaistos (illumos cda5b9a49f), with rdrmnull built without panic-drill against illumos-ddi 9ebd16add0. The only difference from eb0150cadc is illumos-ddi docs.

Run R0 R1 32-bit probes FAIL
run-r1-test.sh, dma-mode="none" 105 PASS 153 PASS 5 and 4 PASS none
run-r1-test.sh, dma-mode="self" under the root nexus 105 PASS 153 PASS 5 and 4 PASS only the known /etc/path_to_inst residue
drm_dma_errno_test, dma-max-transfer=4096 4 PASS, 0 FAIL

There was no panic in any run, and rem_drv unloaded the module each time.

Loose ends after the R0, R1 and DMA-drill merges. ## 1. Pin illumos-ddi moves from `b24c307` to `eb0150cadc`, the head of illumos-ddi `loose-ends-20260928` (illumos/illumos-ddi#3). I chose the branch head so this PR's CI can build now. **Once illumos-ddi#3 is merged, move the pin to the merge commit on illumos-ddi `main`.** The branch commits stay reachable from that merge commit, so the pin keeps resolving either way. API adaptation: illumos-ddi now requires the `OwnNode` for minor nodes. `Device::attach` creates `card<N>` and `renderD<128+N>` from the node before the GEM state takes it. Opens wait until attach returns, and a later failure (GEM setup, registry) drops the nodes again. No other illumos-ddi API change affects this repository: property updates and `LdiIdent::from_dip` are not used here. ## 2. Errno for failed DMA binds `SysMem::bind` mapped `DDI_DMA_NOMAPPING` to `EFAULT`. That is how every failed root-node bind on the patched kernel reached userland from `CREATE_DUMB`; `EFAULT` in a create ioctl reads as a bad user pointer. The handle allocation went through illumos-ddi's generic `From<DmaError> for Errno`, which also answers `EFAULT` for `NoMapping`. The new `drm::dmaerr` module maps DMA failures during object creation the way Linux's DRM reports a failed object allocation: | Failure | errno | | --- | --- | | `NORESOURCES`, `TOOBIG`, `NOMAPPING`, `PARTIAL_MAP` (never requested) | `ENOMEM` | | `BADATTR`, `BADLIMITS`, `TOOSMALL`, zero length, out of range | `EINVAL` | | `DmaError::NotOwnNode` (illumos-ddi guard) | `ENXIO` | | `INUSE`, `LOCKED`, `STALE`, `DDI_FAILURE`, unknown codes (not possible for a fresh handle) | `EIO` | The handle allocation, the bind and the drill's raw allocation all use it. The match is exhaustive over `DmaError`, so a new variant must be decided on. Five host tests cover the table, including NOMAPPING -> ENOMEM. The errno was also recorded on a kernel. `rdrmnull`'s self drill takes an optional `dma-max-transfer` property. `tools/test/rdrmnull-dma-self-tiny.conf` sets it to one page, and `tools/test/drm_dma_errno_test.c` found: - A one-page dumb buffer binds. - A four-page one fails with errno 12 (`ENOMEM`), through rootnex's `DDI_DMA_TOOBIG`, confirmed by rootnex's "coding error detected" warning. - The `gem` kstat is back at zero afterwards. `DDI_DMA_NOMAPPING` itself cannot be produced on a stock kernel with these flags: rootnex returns it only on the IOMMU path, or when trimming with `DDI_DMA_PARTIAL`, which the core never requests. That mapping is therefore covered by the host test only. ## 3. Advisory from the R1 review `rdrmnull` now uses `drm::offsets::PAGE_SIZE` instead of the literal `4096` for the drill's cookie limit and for the movable-object reservation. ## Verification Local checks, targeting `x86_64-unknown-illumos`: - `check`, `clippy -D warnings` with and without `rdrmnull/panic-drill`, `fmt --check` and `doc -D warnings` pass. - `cargo test -p drm -p drm-uapi`: 47 + 1 passed. The 2 dead-code warnings in the test build are already on `main`. - `uapi-check`: 0 differences. Kernel runs used a fresh golden guest on Hephaistos (illumos `cda5b9a49f`), with `rdrmnull` built without `panic-drill` against illumos-ddi `9ebd16add0`. The only difference from `eb0150cadc` is illumos-ddi docs. | Run | R0 | R1 | 32-bit probes | FAIL | | --- | --- | --- | --- | --- | | `run-r1-test.sh`, `dma-mode="none"` | 105 PASS | 153 PASS | 5 and 4 PASS | none | | `run-r1-test.sh`, `dma-mode="self"` under the root nexus | 105 PASS | 153 PASS | 5 and 4 PASS | only the known `/etc/path_to_inst` residue | | `drm_dma_errno_test`, `dma-max-transfer=4096` | | | | 4 PASS, 0 FAIL | There was no panic in any run, and `rem_drv` unloaded the module each time.
illumos-ddi now takes the driver's OwnNode for minor nodes, property
updates and LDI identifiers. Device::attach creates the card and render
nodes from the node before the GEM state takes it; opens wait until
attach returns, and a later failure drops the nodes again.

The pin is the head of illumos-ddi's loose-ends-20260928 branch
(eb0150cadc); move it to the merge commit on illumos-ddi main once that
branch is merged.
On a patched kernel the root-node drill saw every failed bind reach
userland as EFAULT from CREATE_DUMB: SysMem::bind mapped
DDI_DMA_NOMAPPING to EFAULT, which in a create ioctl reads as a bad user
pointer. drm::dmaerr now maps DMA failures during object creation the
way Linux's DRM reports a failed object allocation: ENOMEM for a
shortage or no mapping (NORESOURCES, TOOBIG, NOMAPPING, PARTIAL_MAP),
EINVAL for attributes that can never be satisfied, ENXIO for the
own-node guard, EIO for faults a fresh handle cannot produce. The handle
allocation, the bind and the drill's raw allocation all use it; host
tests cover the table.

rdrmnull's self drill takes an optional dma-max-transfer property;
tools/test/rdrmnull-dma-self-tiny.conf sets it to one page and
drm_dma_errno_test.c checks that a four-page dumb buffer then fails with
ENOMEM.
Use the core's page size instead of a literal 4096 in rdrmnull
All checks were successful
ci / check-hosted (pull_request) Successful in 4m36s
ci / kmod-illumos (pull_request) Successful in 5m51s
bef21aa92e
The drill's cookie limit and the movable objects' reservation now use
drm::offsets::PAGE_SIZE, as the R1 review advised.
The local decoder knew six of the ten failure codes, so a raw BADLIMITS or
TOOSMALL became EIO although the module documentation promises EINVAL.
illumos-ddi now exports its complete decoder; use it through code_errno and
test all ten codes against the documented errno.
The property is read, applied and logged only for dma-mode="self", and a
bad value reports the actual lookup error. The errno test now checks that a
failed creation leaves the gem kstat unchanged, and the tiny conf names the
rootnex warning that the refusal logs.
Pin illumos-ddi at 449bfe73e9, which exports DmaError::check
Some checks failed
ci / check-hosted (pull_request) Failing after 0s
ci / kmod-illumos (pull_request) Failing after 0s
450b7850b9
Author
Contributor

CI note: the kmod-illumos job at 450b785 never ran. Solstice runs 11 and 12 failed in "Set up job" with solstice-ci: failed to enqueue job(s) to message broker (a broker outage; the hosted job passed on this head in run 11). Equivalent check done by hand: cargo +nightly-2026-04-16 build --locked -p rdrmnull --release for the kmod target, then on oibldofgate (illumos-cda5b9a49f) ld -ztype=kmod -z allextract succeeded and elfdump -d shows SUNW_KMOD; archive sha256 0776c4b6… identical on both sides.

CI note: the kmod-illumos job at `450b785` never ran. Solstice runs 11 and 12 failed in "Set up job" with `solstice-ci: failed to enqueue job(s) to message broker` (a broker outage; the hosted job passed on this head in run 11). Equivalent check done by hand: `cargo +nightly-2026-04-16 build --locked -p rdrmnull --release` for the kmod target, then on oibldofgate (illumos-cda5b9a49f) `ld -ztype=kmod -z allextract` succeeded and `elfdump -d` shows `SUNW_KMOD`; archive sha256 `0776c4b6…` identical on both sides.
forge merged commit 931c290942 into main 2026-09-29 19:11:14 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
illumos/illumos-drm!4
No description provided.