Skip to content

Latest commit

 

History

History
146 lines (116 loc) · 6.46 KB

File metadata and controls

146 lines (116 loc) · 6.46 KB

RTXDarwin architecture and safety invariants

Trust boundary

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.

Capability ladder

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.

ABI v1

The canonical declarations are in include/rtxdarwin/abi.h. All structures:

  • use uint8_t, uint16_t, uint32_t, or uint64_t fields;
  • 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.

Probe implementation

The probe release performs these device accesses:

  1. read configuration dword 0x00 for vendor/device;
  2. read configuration dword 0x08 for revision/class;
  3. read configuration dword 0x2c for subsystem vendor/device;
  4. retain the existing IODeviceMemory registry array and read each matching IOMemoryDescriptor's length/tag (the tag's low byte is the BAR register);
  5. 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.

Exact binding

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=probe in the bootstrap.

The generated Info.plist provides exact PCI matching, and the driver repeats the check at runtime. Defense in depth is intentional.

Planned source boundaries

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.

Metal boundary

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.