The kext is the only component allowed to own hardware resources. Userspace never receives a physical address, arbitrary register offset, or generic MMIO write operation. All future buffer objects, virtual-address mappings, command buffers, and fences are referenced by per-client opaque 64-bit handles.
Opening the IOUserClient requires kIOClientPrivilegeAdministrator. This is a
necessary first gate, not a substitute for kernel validation. Every request
also has an exact fixed size and ABI version.
detached
│ probe: read PCI config identity and BAR descriptors only
▼
probed
│ gsp: firmware validation, bootstrap, RPC transport
▼
firmware-ready
│ compute: DMA-safe VRAM/BO and virtual-memory setup
▼
memory-ready
│ compute: channel, pushbuffer, interrupt, fence
▼
channel-ready
│ first verified NAK vector-add
▼
running ──────────────────────────────────────┐
│ │ timeout/Xid/invariant failure
└─────────────────────────────────────────▼
faulted
Transitions only move one step forward. Every non-detached state can become
faulted; faulted is terminal until reboot. Version 0.x must not attempt a
full automatic PCI reset.
Each boot mode is a compile-time capability boundary, not merely a logging
level. The bootstrap release contains probe operations only. Although it
recognizes the strings gsp, compute, fb, and metal, it rejects them and
does not attach.
The canonical declarations are in include/rtxdarwin/abi.h. All structures:
- use
uint8_t,uint16_t,uint32_t, oruint64_tfields; - start with
{ uint32_t size; uint32_t version; }; - have compile-time size assertions;
- reserve fields for compatible growth;
- are little-endian because the only target is x86_64;
- never expose kernel pointers or physical addresses.
| Selector | Bootstrap behavior | Intended first owner |
|---|---|---|
GET_DEVICE_INFO |
Implemented | probe |
ALLOC_BO, FREE_BO, MAP_BO |
Envelope validated, unsupported | memory |
VM_INIT, VM_BIND |
Envelope validated, unsupported | memory |
CHANNEL_CREATE, SUBMIT, WAIT_FENCE |
Envelope validated, unsupported | channel/compute |
GET_FAULT |
Implemented | all stages |
MAP_BO will eventually return a mapping token consumed by a controlled
clientMemoryForType implementation. It is not a physical address and cannot
select arbitrary memory.
The probe release performs these device accesses:
- read configuration dword 0x00 for vendor/device;
- read configuration dword 0x08 for revision/class;
- read configuration dword 0x2c for subsystem vendor/device;
- retain the existing
IODeviceMemoryregistry array and read each matchingIOMemoryDescriptor's length/tag (the tag's low byte is the BAR register); - read each present memory BAR's low flag nibble, or the low two bits for I/O.
The PCI getDeviceMemoryWithRegister/getDeviceMemoryWithIndex accessors are
not used: Apple's IOPCIDevice implementation
may change tunnel link-power policy in those accessors. Descriptor types are
checked as IOMemoryDescriptor, consistent with the objects created by
IOPCIBridge::constructRange.
Missing descriptors report length/flags zero, not a measured zero-size BAR.
Linux resource flags are IORESOURCE_*, not the Darwin raw BAR flag bits, and
must not be compared directly. A 64-bit BAR's upper register is not another BAR.
Module metadata follows the Swift Build/Xcode generator:
kmod_info.start/stop point to libkmod's _start/_stop wrappers; the optional
custom callbacks remain null. tools/inspect_kext.py checks these pointers in
the linked Mach-O, as well as the plist and configured identity. This is not a
kernel dependency-resolution, signing, loadability, or hardware test.
RTXDarwinMMIOWrites=0 is a declaration of this code's policy, not an
instrumented hardware counter or independent evidence of bus traffic.
It deliberately does not call PCI config-write methods, map methods, memory or
bus-master enable methods, I/O port writes, DMA APIs, interrupts, or reset.
tools/check_driver_policy.py enforces the source-level boundary in CI.
Binding requires all of the following:
- compile-time
RTXD_HARDWARE_CONFIGURED=1; - NVIDIA vendor
0x10de; - one OpenRM 570.144 RTX 3060 device ID accepted by the generator;
- Gigabyte subsystem vendor
0x1458; - the measured subsystem device ID;
- PCI function zero;
- Darwin build
25G83; - platform model
MacPro7,1; - boot argument exactly
rtxd=probein the bootstrap.
The generated Info.plist provides exact PCI matching, and the driver repeats
the check at runtime. Defense in depth is intentional.
Future code is split so an earlier mode cannot link a later capability:
driver/probe/ PCI identity, no MMIO mappings
driver/gsp/ bounded BAR access, firmware loader, RPC, interrupts
driver/memory/ DMA, VRAM, BO handles, VM bindings
driver/channel/ channels, command validation, fences, timeout-to-fault
nvkmd/darwin/ Mesa-side BO/VM/EXEC/sync adapter
framebuffer/ GOP preservation, then explicit modesetting
metal/ accelerator and userspace companion experiment
These future directories are architectural assignments, not current code.
The first Metal proof is deliberately small: a public-API application must see
the RTX in MTLCopyAllDevices, create a device/queue/buffers/pipeline, and run
vector-add without private calls or CPU fallback. A private companion may be
needed internally, but the acceptance application remains ordinary public
Metal.
If Tahoe rejects third-party GPU companions even after an in-memory Lilu lookup patch, the project stops at the documented boundary. It will not modify the sealed system volume or Apple binaries and will not claim Metal support.