Support clone opens in the CharDevice glue #1

Merged
forge merged 6 commits from drm-r0 into main 2026-09-28 18:10:10 +00:00
Contributor

Needed by the Rust DRM core (illumos-drm, WI-452 R0). A DRM device exposes card0 and renderD128 minors and must hand every open(2) its own minor so per-file state can be tracked, the same clone-open pattern gfx-drm's drm_sunmod.c uses.

  • CharDevice::clone_open: the open(9E) glue lets the driver return a new minor and writes it back through devp. The default keeps existing drivers unchanged.
  • Documents the 32-bit dev_t limit that bounds clone minors.

illumos-drm pins this branch (f36d47958e) until it is on main.

Needed by the Rust DRM core (illumos-drm, WI-452 R0). A DRM device exposes `card0` and `renderD128` minors and must hand every `open(2)` its own minor so per-file state can be tracked, the same clone-open pattern gfx-drm's `drm_sunmod.c` uses. - `CharDevice::clone_open`: the `open(9E)` glue lets the driver return a new minor and writes it back through `devp`. The default keeps existing drivers unchanged. - Documents the 32-bit `dev_t` limit that bounds clone minors. illumos-drm pins this branch (`f36d47958e`) until it is on `main`.
A character device receives one open(9E) per open(2) but only one
close(9E) per device number, so it cannot keep per-file state. The new
CharDevice::clone_open lets a driver return a fresh minor number; the
glue stores makedevice(getmajor(dev), minor) through devp so that the
file gets its own device number and its own close(9E). The default
calls open and keeps the device number, so existing drivers are
unchanged. A returned minor that maps to another instance is closed
again and the open fails with ENXIO.

The DRM core needs this for per-file state (authentication, master,
client capabilities) on card and render nodes.
Document the 32-bit dev_t limit for clone minors
Some checks failed
ci / check-hosted (pull_request) Has been cancelled
ci / kmod-illumos (pull_request) Has been cancelled
f36d47958e
Describe CharDevice::clone_open in the design document
Some checks failed
ci / check-hosted (pull_request) Successful in 3m18s
ci / kmod-illumos (pull_request) Has been cancelled
e019d5bd3c
A driver that lets processes mmap(2) its memory needs the devmap(9E)
entry point, ddi_devmap_segmap(9F) as segmap(9E) and D_DEVMAP in
cb_flag. The new `ops: [char, devmap]` form of module! installs all
three, and CharDevice::devmap receives the minor number, the mapping
handle (DevmapHandle, valid for the call), the user offset, the
remaining length and the caller's data model, and returns the validated
length. The devmap_callback_ctl(9S) callbacks stay with the driver,
which passes them to devmap_umem_setup(9F) or devmap_devmem_setup(9F).

mmap(2) passes the length unrounded, so the glue accepts a validated
length up to the end of the page that holds the last requested byte and
refuses anything longer. A negative offset fails with EINVAL.

The default fails with ENXIO and `ops: [char]` keeps the nodev stubs,
so existing drivers are unchanged. The documentation records two facts
from seg_dev.c: devmap_setup(9F) reports every failure of the entry
point as ENXIO, and a handle can be freed after a successful devmap(9E)
without a devmap_map(9E) or devmap_unmap(9E) call.

The DRM core needs this for GEM object mappings.
Describe CharDevice::devmap in the design document
Some checks failed
ci / check-hosted (pull_request) Has been cancelled
ci / kmod-illumos (pull_request) Has been cancelled
77df4ce177
Refuse a devmap(9E) length of zero or of a partial page
All checks were successful
ci / kmod-illumos (pull_request) Successful in 3m9s
ci / check-hosted (pull_request) Successful in 7m47s
bfc7ff7b2a
devmap_setup(9F) advances its loop by the validated length and rejects
lengths that are not whole pages; a driver that returned 0 would make it
call devmap(9E) for ever, allocating a handle with KM_SLEEP each time.
The glue now fails the mapping with EINVAL for 0 and for lengths that
are not a multiple of the page size.
Author
Contributor

Three commits added for illumos-drm R1 (GEM mmap), same style as clone_open:

  • 94680b671c Support devmap(9E) in the CharDevice glue: CharDevice::devmap(minor, DevmapHandle, off, len, model, ctx) -> Result<usize, Errno> (default ENXIO) and module! { driver: X, ops: [char, devmap] }, which installs the glue as devmap(9E), ddi_devmap_segmap(9F) as segmap(9E) and sets D_DEVMAP. ops: [char] is unchanged. The glue accepts a validated length up to the end of the page holding the last requested byte (mmap(2) passes the length unrounded) and refuses anything longer; a negative offset is EINVAL.
  • bfc7ff7b2a Refuse a devmap(9E) length of zero or of a partial page (devmap_setup(9F) advances only by the validated length, so 0 would loop for ever).
  • 77df4ce177 Describe CharDevice::devmap in the design document (section 5.2), including two facts from seg_dev.c: devmap_setup(9F) reports every driver error as ENXIO, and a handle can be freed after a successful devmap(9E) without any devmap_map/devmap_unmap callback.

illumos-drm pins bfc7ff7b2ae520e0c5592ae4e9780e22564bc070; its R1 pull request (illumos/illumos-drm#2, stacked on illumos/illumos-drm#1) was tested with this revision on oibldofgate: mmap, fork, partial munmap and the refault experiment through these entry points, all passing.

Three commits added for illumos-drm R1 (GEM mmap), same style as `clone_open`: - `94680b671c` Support devmap(9E) in the CharDevice glue: `CharDevice::devmap(minor, DevmapHandle, off, len, model, ctx) -> Result<usize, Errno>` (default `ENXIO`) and `module! { driver: X, ops: [char, devmap] }`, which installs the glue as `devmap(9E)`, `ddi_devmap_segmap(9F)` as `segmap(9E)` and sets `D_DEVMAP`. `ops: [char]` is unchanged. The glue accepts a validated length up to the end of the page holding the last requested byte (`mmap(2)` passes the length unrounded) and refuses anything longer; a negative offset is `EINVAL`. - `bfc7ff7b2a` Refuse a devmap(9E) length of zero or of a partial page (`devmap_setup(9F)` advances only by the validated length, so 0 would loop for ever). - `77df4ce177` Describe CharDevice::devmap in the design document (section 5.2), including two facts from `seg_dev.c`: `devmap_setup(9F)` reports every driver error as `ENXIO`, and a handle can be freed after a successful `devmap(9E)` without any `devmap_map`/`devmap_unmap` callback. illumos-drm pins `bfc7ff7b2ae520e0c5592ae4e9780e22564bc070`; its R1 pull request (illumos/illumos-drm#2, stacked on illumos/illumos-drm#1) was tested with this revision on oibldofgate: mmap, fork, partial munmap and the refault experiment through these entry points, all passing.
forge merged commit 19ada4c467 into main 2026-09-28 18:10:10 +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-ddi!1
No description provided.