DriverKit

RSS for tag

Develop device drivers that run in user space using DriverKit.

Posts under DriverKit tag

200 Posts

Post

Replies

Boosts

Views

Activity

[DEXT Migration Issue] IOUserSCSIParallelInterfaceController fails to handle low-level I/O from `diskutil`
Hello everyone, We are migrating our KEXT for a Thunderbolt storage device to a DEXT based on IOUserSCSIParallelInterfaceController. We've run into a fundamental issue where the driver's behavior splits based on the I/O source: high-level I/O from the file system (e.g., Finder, cp) is mostly functional (with a minor ls -al sorting issue for Traditional Chinese filenames), while low-level I/O directly to the block device (e.g., diskutil) fails or acts unreliably. Basic read/write with dd appears to be mostly functional. We suspect that our DEXT is failing to correctly register its full device "personality" with the I/O Kit framework, unlike its KEXT counterpart. As a result, low-level I/O requests with special attributes (like cache synchronization) sent by diskutil are not being handled correctly by the IOUserSCSIParallelInterfaceController framework of our DEXT. Actions Performed & Relevant Logs 1. Discrepancy: diskutil info Shows Different Device Identities for DEXT vs. KEXT For the exact same hardware, the KEXT and DEXT are identified by the system as two different protocols. KEXT Environment: Device Identifier: disk5 Protocol: Fibre Channel Interface ... Disk Size: 66.0 TB Device Block Size: 512 Bytes DEXT Environment: Device Identifier: disk5 Protocol: SCSI SCSI Domain ID: 2 SCSI Target ID: 0 ... Disk Size: 66.0 TB Device Block Size: 512 Bytes 2. Divergent I/O Behavior: Partial Success with Finder/cp vs. Failure with diskutil High-Level I/O (Partially Successful): In the DEXT environment, if we operate on an existing volume (e.g., /Volumes/MyVolume), file copy operations using Finder or cp succeed. Furthermore, the logs we've placed in our single I/O entry point, UserProcessParallelTask_Impl, are triggered. Side Effect: However, running ls -al on such a volume shows an incorrect sorting order for files with Traditional Chinese names (they appear before . and ..). Low-Level I/O (Contradictory Behavior): In the DEXT environment, when we operate directly on the raw block device (/dev/disk5): diskutil partitionDisk ... -> Fails 100% of the time with the error: Error: -69825: Wiping volume data to prevent future accidental probing failed. dd command -> Basic read/write operations appear to work correctly (a write can be immediately followed by a read within the same DEXT session, and the data is correct). 3. Evidence of Cache Synchronization Failure (Non-deterministic Behavior) The success of the dd command is not deterministic. Cross-environment tests prove that its write operations are unreliable: First Test: In the DEXT environment, write a file with random data to /dev/disk5 using dd. Reboot into the KEXT environment. Read the data back from /dev/disk5 using dd. The result is a file filled with all zeros. Conclusion: The write operation only went to the hardware cache, and the data was lost upon reboot. Second Test: In the DEXT environment, write the same random file to /dev/disk5 using dd. Key Variable: Immediately after, still within the DEXT environment, read the data back once for verification. The content is correct! Reboot into the KEXT environment. Read the data back from /dev/disk5. This time, the content is correct! Conclusion: The additional read operation in the second test unintentionally triggered a hardware cache flush. This proves that the dd (in our DEXT) write operation by itself does not guarantee synchronization, making its behavior unreliable. Our Problem Based on the observations above, we have the conclusion: High-Level Path (triggered by Finder/cp): When an I/O request originates from the high-level file system, the framework seems to enter a fully-featured mode. In this mode, all SCSI commands, including READ/WRITE, INQUIRY, and SYNCHRONIZE CACHE, are correctly packaged and dispatched to our UserProcessParallelTask_Impl entry point. Therefore, Finder operations are mostly functional. Low-Level Path (triggered by dd/diskutil): When an I/O request originates from the low-level raw block device layer: The most basic READ/WRITE commands can be dispatched (which is why dd appears to work). However, critical management commands, such as INQUIRY and SYNCHRONIZE CACHE, are not being correctly dispatched or handled. This leads to the incorrect device identification in diskutil info and the failure of diskutil partitionDisk due to its inability to confirm cache synchronization. We would greatly appreciate any guidance, suggestions, or insights on how to resolve this discrepancy. Specifically, what is the recommended approach within DriverKit to ensure that a DEXT based on IOUserSCSIParallelInterfaceController can properly declare its capabilities and handle both high-level and low-level I/O requests uniformly? Thank you. Charles
12
0
2.0k
Jul ’26
Automate system extensions installation
Hello, We are running some tests with our driver with SIP on. We have all the entitlements and everything works smoothly. Thing is, when we run our xxxx.app from Applications, it pops up a GUI with install and uninstall button that we created. When we do install, it prompts us to enable system extension in System settings. I am wondering if there is a way to automate this. I understand I can automate running the xxxx.app from command line but can we automate having to go to System settings->login items & Extensions and enabling our system extension from command line too. Does Apple force an user to go to settings and do it once for security? From my research, I did not find any reliable answer to this. Thank you for your help!
1
0
1.1k
Jul ’26
DriverKit VLAN offload: IOUserNetworkPacket::getVlanTag() always returns false, kFeatureHardwareVlan undocumented
I've built an open-source DriverKit + NetworkingDriverKit (IOUserNetworkEthernet/Skywalk) driver for a USB 5GbE adapter (AQTION AQC111U chipset). As far as I can tell this is the first public one for real third-party hardware: github.com/jquirke/AQC111Driver It's a fully functional driver at this point: RX/TX hardware checksum offload, jumbo frame/MTU control up to 16KB, runtime-controllable diagnostics via a custom IOUserClient, and most recently working 802.1Q VLAN support via macOS's vlan(4) software path. While attempting to implement hardware offload VLAN support, I ran into what looks like a gap between documentation and the public SDK, and I'd appreciate expert opinion either way before filing Feedback. The issue: IOUserNetworkPacket::getVlanTag()/setVlanTag() (DriverKit 24.0+) have a doc comment stating: "Get the Vlan Tag from the packet, where the driver has enabled the kFeatureHardwareVlan capability; for the case that feature is not enabled, this method will return false." kFeatureHardwareVlan does not appear anywhere in the public NetworkingDriverKit.framework/Headers/ tree confirmed via exhaustive grep, including the full hwAssist/feature-flag enum in IOUserNetworkTypes.h. I tested every plausible related mechanism exhaustively, with a real device reattach for each combination, to rule out attach-time-only behaviour: +------------------------+--------------------------+--------------+-----------+ | HWAssist bit declared? | SetSoftwareVlanSupport()| getVlanTag() | vlan0 MTU | +------------------------+--------------------------+--------------+-----------+ | Yes | true | always false | 1500 | | Yes | false | always false | 1500 | | No | not called | always false | 1496 | | No | false | always false | 1496 | +------------------------+--------------------------+--------------+-----------+ none of these combinations gates real 802.1q tag-delivery/demux behavior at all; it seems Vlan support is completely implemented in software on the MacOS side and I have to explicitly program my hardware registers to disable VLAN tagging. Question: is hardware VLAN tag insert/strip (via getVlanTag()/setVlanTag()) currently reachable from a third-party DriverKit USB Ethernet driver at all? If kFeatureHardwareVlan is real but intentionally withheld from public headers, is there a documented path (entitlement, different NDK version, etc.) to enable it or is this confirmed unreachable without Apple's direct involvement (Feedback/DTS)? Can share full test logs/methodology if useful.
2
2
1.3k
Jul ’26
Entitlements received only for vendor ID. Is this normal?
Hi, I recently requested for some entitlements from Apple. In the form that I filled, there was only placeholder for Vendor ID so I put my vendor ID (in decimals). There was no placeholder to specify Device ID. However, in the Description placeholder at the end of the form, I did put the device ID (in decimals). After I got the entitlements, I tried loading my driver to match the device. It does match with only vendor ID but does not match with Vendor and Device ID together. So, now matching has widened little bit more than what we wanted. I was wondering if this is normal or if I did something wrong due to which entitlements was only granted for vendor ID but not for vendor + device Id. Thank you for your time!
1
0
1.2k
Jul ’26
Master Abort on a link side of the Root Complex
I'm encountering a bug developing a (Thunderbolt) PCIDriverKit dext. The system runs well for a while, and then the hardware instance is shut down by the OS (Sonoma 14.7.6) for some unknown reason, but the dext is not, so hardware reads return 0xFFFFFFFF (device disconnected). There is no crash report, or diagnostic report. I don't see anything related in a sysdiagnose capture. The only hint I can find is the kernel logs indicate: 2026-07-01 16:18:15.929 Df kernel[0:139] (AppleT8122PCIeC) apciec[pcic1-bridge]::handleCompletionTimeoutInterrupt Completion timeout detected at address 0xe00510020 2026-07-01 16:18:15.929 Df kernel[0:139] (AppleT8122PCIeC) apciec[pcic1-bridge]::handleCompleterAbortInterrupt Completer Abort received (pri_status = 0x00100407, sec_status = 0x200000f0): 2026-07-01 16:18:15.929 Df kernel[0:139] (AppleT8122PCIeC) apciec[pcic1-bridge]::handleCompleterAbortInterrupt * Received Master Abort on a link side of the Root Complex That address (0xe00510020) looks like it's our PCI device (at a BAR0, offset 0x0020) read. What does this error explicitly mean? Did the device take too long to respond to the read request? After the event, every device on that Thunderbolt bus is disconnected, and a reboot seems to be required. Hardware is a 14" 2023 MacBook Pro M3.
1
0
1k
Jul ’26
Reboot-free upgrade of an always-matched DriverKit dext
I have a DriverKit dext that implements a virtual SCSI HBA (no physical hardware). Because a bare IOUserSCSIParallelInterfaceController has no provider to match, the bundle ships two IOKitPersonalities: Bootstrap — IOClass IOUserService, IOProviderClass IOUserResources, IOResourceMatch IOKit. In Start() it does SetProperties({NvmeOfSCSIHBA: true}) + RegisterService(), publishing itself as a nub. Controller — IOClass IOUserSCSIParallelInterfaceController, IOProviderClass IOUserService, IOPropertyMatch {NvmeOfSCSIHBA: true} — it matches the bootstrap nub. This loads and runs correctly. The problem is upgrades. Activating a higher CFBundleVersion via OSSystemExtensionRequest.activationRequest (in-place replace) always defers the old version's termination to reboot. The new version reaches [activated enabled] but never starts; the old process keeps running until reboot. From sysextd/kernelmanagerd: kernelmanagerd Dext … v15 … is being replaced and cannot be terminated right away sysextd delegate returns Error Domain=OSSystemExtensionErrorDomain Code=101 "…is being replaced", assumes responsibility for old version …, keeping old version 15 sysextd turning the responsibility for termination of …, version 15 over to delegate (with uninstallation at the next reboot) sysextd a category delegate declined to terminate extension with identifier: … sysextd v15 terminating_for_uninstall → terminating_for_upgrade_via_delegate Key observation: this defers even on a fresh boot where the dext was never opened — no app/daemon ever opened the IOUserClient, no I/O, nothing attached beyond the controller↔nub match. So it does not appear to be a "client still holds it open" / busy-state situation; the driver_extension category delegate declines the moment it's a replacement. What I've tried: In-place activationRequest (replace): always defers to reboot (above). deactivationRequest (standalone): the request hangs — no delegate callback at all (waited ~13 min), even with no client open. Disconnecting all clients first (graceful Stop() that cancels its dispatch queues and completes async) does not change the replace deferral. My understanding from the docs/forums is that the normal reboot-free replace relies on the backing device being disconnected/reconnected to quiesce the old dext (thread 677040). My controller matches a persistent IOUserResources-backed nub that never detaches, so there's no equivalent quiesce point. Questions: For a dext whose only provider is a self-published IOUserResources nub (no detachable hardware), is reboot-free replacement structurally impossible — i.e. is the Code=101 "is being replaced" defer inherent to this matching pattern? Is the supported way to live-upgrade such a dext to deactivationRequest → (on .completed) → activationRequest rather than an in-place replace? If so, what makes a deactivationRequest complete in-session vs. defer to reboot for an IOUserResources-matched dext — and what would cause it to hang with no delegate callback? (Daemon's IOUserClient is closed; the controller's Stop() cancels its queues and completes.) Should the dext itself proactively tear down the published nub (e.g. terminate the bootstrap IOService) before/at upgrade so the controller detaches — or does that just re-match the still-staged old personalities and relaunch the old version? Is there a recommended pattern for a virtual (hardwareless) DriverKit HBA that needs in-field, reboot-free version updates, or is reboot genuinely required for this class of dext? Environment: macOS 27 (Tahoe)
1
0
1k
Jul ’26
Reboot-free upgrade of an always-matched DriverKit dext
I have a DriverKit dext that implements a virtual SCSI HBA (no physical hardware). Because a bare IOUserSCSIParallelInterfaceController has no provider to match, the bundle ships two IOKitPersonalities: Bootstrap — IOClass IOUserService, IOProviderClass IOUserResources, IOResourceMatch IOKit. In Start() it does SetProperties({NvmeOfSCSIHBA: true}) + RegisterService(), publishing itself as a nub. Controller — IOClass IOUserSCSIParallelInterfaceController, IOProviderClass IOUserService, IOPropertyMatch {NvmeOfSCSIHBA: true} — it matches the bootstrap nub. This loads and runs correctly. The problem is upgrades. Activating a higher CFBundleVersion via OSSystemExtensionRequest.activationRequest (in-place replace) always defers the old version's termination to reboot. The new version reaches [activated enabled] but never starts; the old process keeps running until reboot. From sysextd/kernelmanagerd: kernelmanagerd Dext … v15 … is being replaced and cannot be terminated right away sysextd delegate returns Error Domain=OSSystemExtensionErrorDomain Code=101 "…is being replaced", assumes responsibility for old version …, keeping old version 15 sysextd turning the responsibility for termination of …, version 15 over to delegate (with uninstallation at the next reboot) sysextd a category delegate declined to terminate extension with identifier: … sysextd v15 terminating_for_uninstall → terminating_for_upgrade_via_delegate Key observation: this defers even on a fresh boot where the dext was never opened — no app/daemon ever opened the IOUserClient, no I/O, nothing attached beyond the controller↔nub match. So it does not appear to be a "client still holds it open" / busy-state situation; the driver_extension category delegate declines the moment it's a replacement. What I've tried: In-place activationRequest (replace): always defers to reboot (above). deactivationRequest (standalone): the request hangs — no delegate callback at all (waited ~13 min), even with no client open. Disconnecting all clients first (graceful Stop() that cancels its dispatch queues and completes async) does not change the replace deferral. My understanding from the docs/forums is that the normal reboot-free replace relies on the backing device being disconnected/reconnected to quiesce the old dext (thread 677040). My controller matches a persistent IOUserResources-backed nub that never detaches, so there's no equivalent quiesce point. Questions: For a dext whose only provider is a self-published IOUserResources nub (no detachable hardware), is reboot-free replacement structurally impossible — i.e. is the Code=101 "is being replaced" defer inherent to this matching pattern? Is the supported way to live-upgrade such a dext to deactivationRequest → (on .completed) → activationRequest rather than an in-place replace? If so, what makes a deactivationRequest complete in-session vs. defer to reboot for an IOUserResources-matched dext — and what would cause it to hang with no delegate callback? (Daemon's IOUserClient is closed; the controller's Stop() cancels its queues and completes.) Should the dext itself proactively tear down the published nub (e.g. terminate the bootstrap IOService) before/at upgrade so the controller detaches — or does that just re-match the still-staged old personalities and relaunch the old version? Is there a recommended pattern for a virtual (hardwareless) DriverKit HBA that needs in-field, reboot-free version updates, or is reboot genuinely required for this class of dext? Environment: macOS 27 (Tahoe)
0
0
880
Jun ’26
Supported way to expose an iPhone+controller as a macOS gamepad without restricted entitlements?
I’m prototyping a personal-use system that lets an iPhone with a physically attached controller act as an input device for a Mac. End goal: Use the iPhone as the transport and sensor host Use the attached physical controller for buttons/sticks Map the iPhone gyroscope to the controller’s right stick to get gyro aim in Mac games / cloud-streamed games such as GeForce NOW that don't support the gyro. What I’m trying to understand is whether Apple supports any path for this on macOS that does NOT require restricted entitlements or paid-program-only capabilities. What I’ve already found: CoreHID virtual HID device creation appears to require com.apple.developer.hid.virtual.device HIDDriverKit / system extensions appear to require Apple-granted entitlements as well GCVirtualController does not seem to solve the problem because I need a controller-visible device that other apps can see, not just controls inside my own app So my concrete question is: Is there any supported, entitlement-free way for a personal macOS app to expose a game-controller-like input device that other apps can consume system-wide? If not, is the official answer that this class of solution necessarily requires one of: CoreHID with restricted entitlement HIDDriverKit/system extension entitlement some other Apple-approved framework or program I’m missing I’m not asking about App Store distribution. This is primarily for local/personal use during development. I’m trying to understand the supported platform boundary before investing further. Any guidance on the recommended architecture for this use case would be appreciated.
4
1
1.8k
Jun ’26
Custom ethernet interface with userspace transport via DriverKit
We're developing a custom Thunderbolt device and want to expose it to macOS as an ethernet interface, while owning the full network stack implementation up to and including IP, TCP and UDP — bypassing the macOS network stack for those layers. Is IOEthernetController the right DriverKit approach for this, and does it allow intercepting traffic before it reaches the macOS IP stack?
4
0
914
Jun ’26
System Panic with IOUserSCSIParallelInterfaceController during Dispatch Queue Configuration
Hello everyone, We are in the process of migrating a high-performance storage KEXT to DriverKit. During our initial validation phase, we noticed a performance gap between the DEXT and the KEXT, which prompted us to try and optimize our I/O handling process. Background and Motivation: Our test hardware is a RAID 0 array of two HDDs. According to AJA System Test, our legacy KEXT achieves a write speed of about 645 MB/s on this hardware, whereas the new DEXT reaches about 565 MB/s. We suspect the primary reason for this performance gap might be that the DEXT, by default, uses a serial work-loop to submit I/O commands, which fails to fully leverage the parallelism of the hardware array. Therefore, to eliminate this bottleneck and improve performance, we configured a dedicated parallel dispatch queue (MyParallelIOQueue) for the UserProcessParallelTask method. However, during our implementation attempt, we encountered a critical issue that caused a system-wide crash. The Operation Causing the Panic: We configured MyParallelIOQueue using the following combination of methods: In the .iig file: We appended the QUEUENAME(MyParallelIOQueue) macro after the override keyword of the UserProcessParallelTask method declaration. In the .cpp file: We manually created a queue with the same name by calling the IODispatchQueue::Create() function within our UserInitializeController method. The Result: This results in a macOS kernel panic during the DEXT loading process, forcing the user to perform a hard reboot. After the reboot, checking with the systemextensionsctl list command reveals the DEXT's status as [activated waiting for user], which indicates that it encountered an unrecoverable, fatal error during its initialization. Key Code Snippets to Reproduce the Panic: In .iig file - this was our exact implementation: class DRV_MAIN_CLASS_NAME: public IOUserSCSIParallelInterfaceController { public: virtual kern_return_t UserProcessParallelTask(...) override QUEUENAME(MyParallelIOQueue); }; In .h file: struct DRV_MAIN_CLASS_NAME_IVars { // ... IODispatchQueue* MyParallelIOQueue; }; In UserInitializeController implementation: kern_return_t IMPL(DRV_MAIN_CLASS_NAME, UserInitializeController) { // ... // We also included code to manually create the queue. kern_return_t ret = IODispatchQueue::Create("MyParallelIOQueue", kIODispatchQueueReentrant, 0, &ivars->MyParallelIOQueue); if (ret != kIOReturnSuccess) { // ... error handling ... } // ... return kIOReturnSuccess; } Our Question: What is the officially recommended and most stable method for configuring UserProcessParallelTask_Impl() to use a parallel I/O queue? Clarifying this is crucial for all developers pursuing high-performance storage solutions with DriverKit. Any explanation or guidance would be greatly appreciated. Best Regards, Charles
28
0
4.4k
Jun ’26
Dext Auto Registration vs. Manual Registration
I need a bit more support. Per Apple’s guidance, our dext’s hosting app checks to see if the dext is installed, and if it is not installed, it will register the dext. I am going to refer to this as “auto registration.” I have also added a menu option to register the dext, which I am going to call “manual registration.” The manual registration works. The user is prompted to “Allow” the dext to be loaded, and things proceed normally. The auto-registration does not work. It produces an error response that is not helpful: Request did fail with Error 1 (The operation couldn’t be completed. (OSSystemExtensionErrorDomain error 1.)) Registration failed, unknown error. They execute the exact same code path – the auto registration calls the menu option’s function that executes from user selection. When comparing the sysextd logs, they differ starting at “Advancing from validating to validating_by_category.” The manual registration has a trace that reads: got reply from com.apple.system_extension.driver_extension... The auto registration does not get this reply. Attached are the two logs. This is Sonoma 14.7.6, the earliest OS we must support. Any suggestions on what is happening or how to fix it so that auto registration can work? Validate_by_category failure trace Validate_by_category success trace
3
0
1.1k
Jun ’26
Optimizing SCSI HBA Constraints and Alignment for DriverKit on Apple Silicon
Hi Kevin, I'm starting this new thread to focus on alignment optimization and recalibrating our HBA constraints. Following up on your suggestion about UserReportHBAConstraints and alignment optimization, here are our current DEXT settings: Via UserReportHBAConstraints(): kIOMaximumSegmentCountRead/WriteKey: 129 kIOMaximumSegmentByteCountRead/WriteKey: 65,536 (64 KB) kIOMinimumSegmentAlignmentByteCountKey: 4 bytes kIOMaximumSegmentAddressableBitCountKey: 32 kIOMinimumHBADataAlignmentMaskKey: 0 Via SetProperties() (additional injection): kIOMaximumByteCountRead/WriteKey: 524,288 (512 KB) kIOMaximumBlockCountRead/WriteKey: 1,024 We inherited the segment count (129) and max I/O length (512 KB) from our legacy KEXT, which were originally calculated based on a 4 KB segment size (Max I/O 512 KB / 4 KB + 1 = 129). The current alignment value of 4 was essentially a placeholder, as the legacy hardware didn't enforce strict page-level alignment. Given that our testing is on Apple Silicon, we are considering increasing kIOMinimumSegmentAlignmentByteCountKey to 16,384 (16 KB) to match the native page size. However, I have two specific questions regarding this: Stripe Size vs. Page Size: Our RAID stripe size is typically larger than 16 KB (e.g., 64 KB or 128 KB). Should we be aligning the system to the RAID stripe size for hardware efficiency, or is it more critical to stick to the 16 KB page size to optimize the IOMMU/DART mapping overhead in DriverKit? Recalibration: If we increase the alignment to 16 KB, should we also adjust the kIOMaximumSegmentByteCount to match (i.e., 16 KB), or is it better to keep it at 64 KB to allow fewer, larger segments per I/O? We suspect that the 38% gain we saw in 4 KB Random Reads might improve even further if we fix this alignment bottleneck. Looking forward to your thoughts. Best regards, Charles
4
0
1.4k
Jun ’26
One Driver talking to another Driver.
One of the possible solutions to a problem that I'm working on is to have two Drivers loading in one DriverKit dext, an IOUserHIDEventService and an IOUserHIDDevice. For this to work, however, I need to have the event service send a message to the Device. IOKit has the service and connection objects that I can use just like an app would (just like the app the driver communication example). But DriverKit complains whenever I try to add the IOKit framework, saying that it is not supported. Is there another way that I can send a message directly from one driver to another?
2
0
1.9k
Jun ’26
DriverKit issue with TestFlight
Hi, We’re developing a DriverKit extension for iPadOS. In local Debug and Release builds, everything works as expected, but the same build uploaded to TestFlight fails at IOServiceOpen with the following errors: -536870212 (0xE00002EC) kIOReturnUnsupported -536870201 (0xE00002F7) kIOReturnNotPermitted What we’ve verified so far App entitlements We checked our main app entitlements file, and it has the correct capabilities for the driverkit communication <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.driverkit.userclient-access</key> <array> <string>abc.def.ABCDriver</string> </array> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.device.usb</key> <true/> <key>com.apple.security.files.user-selected.read-write</key> <true/> </dict> </plist> we also checked the Provisioning profile (as shown on the portal) and the “Enabled Capabilities” seems to have the correct DriverKit Capabilities enabled. Enabled Capabilities Access Wi-Fi Information, DriverKit, DriverKit (development), DriverKit Communicates with Drivers, DriverKit USB Transport (development), DriverKit USB Transport - VendorID, DriverKit UserClient Access, iCloud, In-App Purchase, Sign In with Apple, System Extension When we download and inspect the provisioning profile as plain text, we notice that some expected DriverKit entitlements appear to be missing from the section. <key>Entitlements</key> <dict> <key>beta-reports-active</key> <true/> <key>com.apple.developer.networking.wifi-info</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>application-identifier</key> <string>ABC123456.abc.def</string> <key>keychain-access-groups</key> <array> <string>ABC123456.*</string> <string>com.apple.token</string> </array> <key>get-task-allow</key> <false/> <key>com.apple.developer.team-identifier</key> <string>ABC123456</string> <key>com.apple.developer.ubiquity-kvstore-identifier</key> <string>ABC123456.*</string> <key>com.apple.developer.icloud-services</key> <string>*</string> <key>com.apple.developer.icloud-container-identifiers</key> <array></array> <key>com.apple.developer.icloud-container-development-container-identifiers</key> <array></array> <key>com.apple.developer.ubiquity-container-identifiers</key> <array></array> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <key>com.apple.developer.applesignin</key> <array> <string>Default</string> </array> </dict> We have a couple of questions: Could the missing com.apple.developer.driverkit.userclient-access entitlement in the provisioning profile alone explain the kIOReturnUnsupported / kIOReturnNotPermitted failures from IOServiceOpen? Why do some DriverKit capabilities appear in the Apple Developer portal UI but vanish from the actual profile we download? Is there an extra step we’re overlooking when regenerating profiles after toggling those capabilities? Thanks
10
0
1.8k
Jun ’26
[iPadOS / USBDriverKit] Communicating with RP2040: Avoiding OS preemption of standard CDC-ACM?
Hello everyone, I am currently working on an iPadOS application that requires communicating with a custom hardware board based on the Raspberry Pi RP2040 microcontroller via USB. My initial thought was to use the standard CDC-ACM (virtual serial port) profile on the RP2040. However, my understanding is that iPadOS's built-in system drivers will automatically claim any standard CDC-ACM interfaces, preempting my custom USBDriverKit driver from matching and taking control of the device. Is my assumption correct that iPadOS will strictly preempt a standard CDC-ACM device, making a custom DriverKit implementation impossible for that specific class?
1
0
1.2k
May ’26
Xcode Signing Fails: Provisioning Profile "doesn't match" com.apple.developer.driverkit.userclient-access entitlement
Hello everyone, I am migrating a legacy KEXT to a DriverKit (DEXT) architecture. While the DEXT itself is working correctly, I am completely blocked by a code signing issue when trying to establish the UserClient connection from our SwiftUI management app. Project Goal & Status: Our DEXT (com.accusys.Acxxx.driver) activates successfully (systemextensionsctl list confirms [activated enabled]). The core functionality is working (diskutil list shows the corresponding disk device node). The Core Problem: The userclient-access Signing Error To allow the app to connect to the DEXT, the com.apple.developer.driverkit.userclient-access entitlement is required in the app's .entitlements file. However, as soon as this entitlement is added, the build fails. Both automatic and manual signing fail with the same error: `Provisioning profile ... doesn't match the entitlements file's value for the ... userclient-access entitlement.` This build failure prevents the generation of an .app bundle, making it impossible to inspect the final entitlements with codesign. What We've Confirmed: The necessary capabilities (like DriverKit Communicates with Drivers) are visible and enabled for our App ID on the developer portal. The issue persists on a clean system state and on the latest macOS Sequoia 15.7.1. Our Research and Hypothesis: We have reviewed the official documentation "Diagnosing issues with entitlements" (TN3125). According to the documentation, a "doesn't match" error implies a discrepancy between the entitlements file and the provisioning profile. Given that we have tried both automatic and manual profiles (after enabling the capability online), our hypothesis is that the provisioning profile generation process on Apple's backend is not correctly including the approved userclient-access entitlement into the profile file itself. The build fails because Xcode correctly detects this discrepancy. Our Questions: Did we misunderstand a step in the process, or is the issue not with the entitlement request at all? Alternatively, are there any other modifications we can make to successfully connect our App to the DEXT and trigger NewUserClient? Thank you for any guidance.
11
0
1.8k
May ’26
sysextd silently fails to realize a signed DriverKit extension after "attempting to realize" — which log surfaces the rejection reason?
A signed DriverKit extension fails OSSystemExtensionRequest activation on macOS 26.4.1. The user-facing error is OSSystemExtensionErrorDomain code 4 ("Extension not found in App bundle") — but the dext is in the bundle, the identifier matches, and sysextd confirms it received the request: sysextd: [com.apple.sx:XPC] client activation request for com.arqitekta.bluefield.rshim.driver sysextd: attempting to realize extension with identifier com.arqitekta.bluefield.rshim.driver …and then nothing further. systemextensionsctl list reports 0 extensions. Question: Which log subsystem/category surfaces the kernel-side reason that sysextd aborts after "attempting to realize"? com.apple.sx only shows the request was accepted; whatever vetoes the realize step isn't in that subsystem (or isn't at info/debug level). Is there a separate predicate for the kernelmanagerd / dext-loading path I should be capturing? Environment: macOS 26.4.1 (25E253), Apple Silicon Mac Studio Xcode 26.2 (17C52), DriverKit SDK 25.2 SIP disabled, systemextensionsctl developer on Apple Developer Program, signed "Apple Development: …" DriverKit entitlement request 264CFJJU36 approved; profile includes com.apple.developer.driverkit, allow-any-userclient-access, transport.pci Already verified: Dext at Contents/Library/SystemExtensions/RshimDriver.dext CFBundleIdentifier matches the request, CFBundlePackageType=DEXT codesign --verify --deep --strict passes on app + dext embedded.provisionprofile parses, contains the expected entitlements Three IOKitPersonalities (BF2 / BF2-alt / BF3) using Apple's placeholder IOPCIPrimaryMatch Installer app entitled with com.apple.developer.system-extension.install only spctl -a -vv on the dext reports "rejected" — expected for development signing, should be bypassed under developer mode Minimal repro: https://github.com/jfabienke/bluefield-macos-toolkit/tree/dev-stub-entitlements/rshim-dext — build.sh produces the failing app dext. Captured artefacts (build output, embedded profile dump, signing report, repro shell script) under rshim-dext/dts-artifacts/. Looking for either (a) the right log show predicate to find the actual refusal reason, or (b) an environmental requirement on macOS 26 I'm missing.
1
0
1.8k
Apr ’26
[DEXT Migration Issue] IOUserSCSIParallelInterfaceController fails to handle low-level I/O from `diskutil`
Hello everyone, We are migrating our KEXT for a Thunderbolt storage device to a DEXT based on IOUserSCSIParallelInterfaceController. We've run into a fundamental issue where the driver's behavior splits based on the I/O source: high-level I/O from the file system (e.g., Finder, cp) is mostly functional (with a minor ls -al sorting issue for Traditional Chinese filenames), while low-level I/O directly to the block device (e.g., diskutil) fails or acts unreliably. Basic read/write with dd appears to be mostly functional. We suspect that our DEXT is failing to correctly register its full device "personality" with the I/O Kit framework, unlike its KEXT counterpart. As a result, low-level I/O requests with special attributes (like cache synchronization) sent by diskutil are not being handled correctly by the IOUserSCSIParallelInterfaceController framework of our DEXT. Actions Performed & Relevant Logs 1. Discrepancy: diskutil info Shows Different Device Identities for DEXT vs. KEXT For the exact same hardware, the KEXT and DEXT are identified by the system as two different protocols. KEXT Environment: Device Identifier: disk5 Protocol: Fibre Channel Interface ... Disk Size: 66.0 TB Device Block Size: 512 Bytes DEXT Environment: Device Identifier: disk5 Protocol: SCSI SCSI Domain ID: 2 SCSI Target ID: 0 ... Disk Size: 66.0 TB Device Block Size: 512 Bytes 2. Divergent I/O Behavior: Partial Success with Finder/cp vs. Failure with diskutil High-Level I/O (Partially Successful): In the DEXT environment, if we operate on an existing volume (e.g., /Volumes/MyVolume), file copy operations using Finder or cp succeed. Furthermore, the logs we've placed in our single I/O entry point, UserProcessParallelTask_Impl, are triggered. Side Effect: However, running ls -al on such a volume shows an incorrect sorting order for files with Traditional Chinese names (they appear before . and ..). Low-Level I/O (Contradictory Behavior): In the DEXT environment, when we operate directly on the raw block device (/dev/disk5): diskutil partitionDisk ... -> Fails 100% of the time with the error: Error: -69825: Wiping volume data to prevent future accidental probing failed. dd command -> Basic read/write operations appear to work correctly (a write can be immediately followed by a read within the same DEXT session, and the data is correct). 3. Evidence of Cache Synchronization Failure (Non-deterministic Behavior) The success of the dd command is not deterministic. Cross-environment tests prove that its write operations are unreliable: First Test: In the DEXT environment, write a file with random data to /dev/disk5 using dd. Reboot into the KEXT environment. Read the data back from /dev/disk5 using dd. The result is a file filled with all zeros. Conclusion: The write operation only went to the hardware cache, and the data was lost upon reboot. Second Test: In the DEXT environment, write the same random file to /dev/disk5 using dd. Key Variable: Immediately after, still within the DEXT environment, read the data back once for verification. The content is correct! Reboot into the KEXT environment. Read the data back from /dev/disk5. This time, the content is correct! Conclusion: The additional read operation in the second test unintentionally triggered a hardware cache flush. This proves that the dd (in our DEXT) write operation by itself does not guarantee synchronization, making its behavior unreliable. Our Problem Based on the observations above, we have the conclusion: High-Level Path (triggered by Finder/cp): When an I/O request originates from the high-level file system, the framework seems to enter a fully-featured mode. In this mode, all SCSI commands, including READ/WRITE, INQUIRY, and SYNCHRONIZE CACHE, are correctly packaged and dispatched to our UserProcessParallelTask_Impl entry point. Therefore, Finder operations are mostly functional. Low-Level Path (triggered by dd/diskutil): When an I/O request originates from the low-level raw block device layer: The most basic READ/WRITE commands can be dispatched (which is why dd appears to work). However, critical management commands, such as INQUIRY and SYNCHRONIZE CACHE, are not being correctly dispatched or handled. This leads to the incorrect device identification in diskutil info and the failure of diskutil partitionDisk due to its inability to confirm cache synchronization. We would greatly appreciate any guidance, suggestions, or insights on how to resolve this discrepancy. Specifically, what is the recommended approach within DriverKit to ensure that a DEXT based on IOUserSCSIParallelInterfaceController can properly declare its capabilities and handle both high-level and low-level I/O requests uniformly? Thank you. Charles
Replies
12
Boosts
0
Views
2.0k
Activity
Jul ’26
Automate system extensions installation
Hello, We are running some tests with our driver with SIP on. We have all the entitlements and everything works smoothly. Thing is, when we run our xxxx.app from Applications, it pops up a GUI with install and uninstall button that we created. When we do install, it prompts us to enable system extension in System settings. I am wondering if there is a way to automate this. I understand I can automate running the xxxx.app from command line but can we automate having to go to System settings->login items & Extensions and enabling our system extension from command line too. Does Apple force an user to go to settings and do it once for security? From my research, I did not find any reliable answer to this. Thank you for your help!
Replies
1
Boosts
0
Views
1.1k
Activity
Jul ’26
DriverKit VLAN offload: IOUserNetworkPacket::getVlanTag() always returns false, kFeatureHardwareVlan undocumented
I've built an open-source DriverKit + NetworkingDriverKit (IOUserNetworkEthernet/Skywalk) driver for a USB 5GbE adapter (AQTION AQC111U chipset). As far as I can tell this is the first public one for real third-party hardware: github.com/jquirke/AQC111Driver It's a fully functional driver at this point: RX/TX hardware checksum offload, jumbo frame/MTU control up to 16KB, runtime-controllable diagnostics via a custom IOUserClient, and most recently working 802.1Q VLAN support via macOS's vlan(4) software path. While attempting to implement hardware offload VLAN support, I ran into what looks like a gap between documentation and the public SDK, and I'd appreciate expert opinion either way before filing Feedback. The issue: IOUserNetworkPacket::getVlanTag()/setVlanTag() (DriverKit 24.0+) have a doc comment stating: "Get the Vlan Tag from the packet, where the driver has enabled the kFeatureHardwareVlan capability; for the case that feature is not enabled, this method will return false." kFeatureHardwareVlan does not appear anywhere in the public NetworkingDriverKit.framework/Headers/ tree confirmed via exhaustive grep, including the full hwAssist/feature-flag enum in IOUserNetworkTypes.h. I tested every plausible related mechanism exhaustively, with a real device reattach for each combination, to rule out attach-time-only behaviour: +------------------------+--------------------------+--------------+-----------+ | HWAssist bit declared? | SetSoftwareVlanSupport()| getVlanTag() | vlan0 MTU | +------------------------+--------------------------+--------------+-----------+ | Yes | true | always false | 1500 | | Yes | false | always false | 1500 | | No | not called | always false | 1496 | | No | false | always false | 1496 | +------------------------+--------------------------+--------------+-----------+ none of these combinations gates real 802.1q tag-delivery/demux behavior at all; it seems Vlan support is completely implemented in software on the MacOS side and I have to explicitly program my hardware registers to disable VLAN tagging. Question: is hardware VLAN tag insert/strip (via getVlanTag()/setVlanTag()) currently reachable from a third-party DriverKit USB Ethernet driver at all? If kFeatureHardwareVlan is real but intentionally withheld from public headers, is there a documented path (entitlement, different NDK version, etc.) to enable it or is this confirmed unreachable without Apple's direct involvement (Feedback/DTS)? Can share full test logs/methodology if useful.
Replies
2
Boosts
2
Views
1.3k
Activity
Jul ’26
Entitlements received only for vendor ID. Is this normal?
Hi, I recently requested for some entitlements from Apple. In the form that I filled, there was only placeholder for Vendor ID so I put my vendor ID (in decimals). There was no placeholder to specify Device ID. However, in the Description placeholder at the end of the form, I did put the device ID (in decimals). After I got the entitlements, I tried loading my driver to match the device. It does match with only vendor ID but does not match with Vendor and Device ID together. So, now matching has widened little bit more than what we wanted. I was wondering if this is normal or if I did something wrong due to which entitlements was only granted for vendor ID but not for vendor + device Id. Thank you for your time!
Replies
1
Boosts
0
Views
1.2k
Activity
Jul ’26
Master Abort on a link side of the Root Complex
I'm encountering a bug developing a (Thunderbolt) PCIDriverKit dext. The system runs well for a while, and then the hardware instance is shut down by the OS (Sonoma 14.7.6) for some unknown reason, but the dext is not, so hardware reads return 0xFFFFFFFF (device disconnected). There is no crash report, or diagnostic report. I don't see anything related in a sysdiagnose capture. The only hint I can find is the kernel logs indicate: 2026-07-01 16:18:15.929 Df kernel[0:139] (AppleT8122PCIeC) apciec[pcic1-bridge]::handleCompletionTimeoutInterrupt Completion timeout detected at address 0xe00510020 2026-07-01 16:18:15.929 Df kernel[0:139] (AppleT8122PCIeC) apciec[pcic1-bridge]::handleCompleterAbortInterrupt Completer Abort received (pri_status = 0x00100407, sec_status = 0x200000f0): 2026-07-01 16:18:15.929 Df kernel[0:139] (AppleT8122PCIeC) apciec[pcic1-bridge]::handleCompleterAbortInterrupt * Received Master Abort on a link side of the Root Complex That address (0xe00510020) looks like it's our PCI device (at a BAR0, offset 0x0020) read. What does this error explicitly mean? Did the device take too long to respond to the read request? After the event, every device on that Thunderbolt bus is disconnected, and a reboot seems to be required. Hardware is a 14" 2023 MacBook Pro M3.
Replies
1
Boosts
0
Views
1k
Activity
Jul ’26
Reboot-free upgrade of an always-matched DriverKit dext
I have a DriverKit dext that implements a virtual SCSI HBA (no physical hardware). Because a bare IOUserSCSIParallelInterfaceController has no provider to match, the bundle ships two IOKitPersonalities: Bootstrap — IOClass IOUserService, IOProviderClass IOUserResources, IOResourceMatch IOKit. In Start() it does SetProperties({NvmeOfSCSIHBA: true}) + RegisterService(), publishing itself as a nub. Controller — IOClass IOUserSCSIParallelInterfaceController, IOProviderClass IOUserService, IOPropertyMatch {NvmeOfSCSIHBA: true} — it matches the bootstrap nub. This loads and runs correctly. The problem is upgrades. Activating a higher CFBundleVersion via OSSystemExtensionRequest.activationRequest (in-place replace) always defers the old version's termination to reboot. The new version reaches [activated enabled] but never starts; the old process keeps running until reboot. From sysextd/kernelmanagerd: kernelmanagerd Dext … v15 … is being replaced and cannot be terminated right away sysextd delegate returns Error Domain=OSSystemExtensionErrorDomain Code=101 "…is being replaced", assumes responsibility for old version …, keeping old version 15 sysextd turning the responsibility for termination of …, version 15 over to delegate (with uninstallation at the next reboot) sysextd a category delegate declined to terminate extension with identifier: … sysextd v15 terminating_for_uninstall → terminating_for_upgrade_via_delegate Key observation: this defers even on a fresh boot where the dext was never opened — no app/daemon ever opened the IOUserClient, no I/O, nothing attached beyond the controller↔nub match. So it does not appear to be a "client still holds it open" / busy-state situation; the driver_extension category delegate declines the moment it's a replacement. What I've tried: In-place activationRequest (replace): always defers to reboot (above). deactivationRequest (standalone): the request hangs — no delegate callback at all (waited ~13 min), even with no client open. Disconnecting all clients first (graceful Stop() that cancels its dispatch queues and completes async) does not change the replace deferral. My understanding from the docs/forums is that the normal reboot-free replace relies on the backing device being disconnected/reconnected to quiesce the old dext (thread 677040). My controller matches a persistent IOUserResources-backed nub that never detaches, so there's no equivalent quiesce point. Questions: For a dext whose only provider is a self-published IOUserResources nub (no detachable hardware), is reboot-free replacement structurally impossible — i.e. is the Code=101 "is being replaced" defer inherent to this matching pattern? Is the supported way to live-upgrade such a dext to deactivationRequest → (on .completed) → activationRequest rather than an in-place replace? If so, what makes a deactivationRequest complete in-session vs. defer to reboot for an IOUserResources-matched dext — and what would cause it to hang with no delegate callback? (Daemon's IOUserClient is closed; the controller's Stop() cancels its queues and completes.) Should the dext itself proactively tear down the published nub (e.g. terminate the bootstrap IOService) before/at upgrade so the controller detaches — or does that just re-match the still-staged old personalities and relaunch the old version? Is there a recommended pattern for a virtual (hardwareless) DriverKit HBA that needs in-field, reboot-free version updates, or is reboot genuinely required for this class of dext? Environment: macOS 27 (Tahoe)
Replies
1
Boosts
0
Views
1k
Activity
Jul ’26
Reboot-free upgrade of an always-matched DriverKit dext
I have a DriverKit dext that implements a virtual SCSI HBA (no physical hardware). Because a bare IOUserSCSIParallelInterfaceController has no provider to match, the bundle ships two IOKitPersonalities: Bootstrap — IOClass IOUserService, IOProviderClass IOUserResources, IOResourceMatch IOKit. In Start() it does SetProperties({NvmeOfSCSIHBA: true}) + RegisterService(), publishing itself as a nub. Controller — IOClass IOUserSCSIParallelInterfaceController, IOProviderClass IOUserService, IOPropertyMatch {NvmeOfSCSIHBA: true} — it matches the bootstrap nub. This loads and runs correctly. The problem is upgrades. Activating a higher CFBundleVersion via OSSystemExtensionRequest.activationRequest (in-place replace) always defers the old version's termination to reboot. The new version reaches [activated enabled] but never starts; the old process keeps running until reboot. From sysextd/kernelmanagerd: kernelmanagerd Dext … v15 … is being replaced and cannot be terminated right away sysextd delegate returns Error Domain=OSSystemExtensionErrorDomain Code=101 "…is being replaced", assumes responsibility for old version …, keeping old version 15 sysextd turning the responsibility for termination of …, version 15 over to delegate (with uninstallation at the next reboot) sysextd a category delegate declined to terminate extension with identifier: … sysextd v15 terminating_for_uninstall → terminating_for_upgrade_via_delegate Key observation: this defers even on a fresh boot where the dext was never opened — no app/daemon ever opened the IOUserClient, no I/O, nothing attached beyond the controller↔nub match. So it does not appear to be a "client still holds it open" / busy-state situation; the driver_extension category delegate declines the moment it's a replacement. What I've tried: In-place activationRequest (replace): always defers to reboot (above). deactivationRequest (standalone): the request hangs — no delegate callback at all (waited ~13 min), even with no client open. Disconnecting all clients first (graceful Stop() that cancels its dispatch queues and completes async) does not change the replace deferral. My understanding from the docs/forums is that the normal reboot-free replace relies on the backing device being disconnected/reconnected to quiesce the old dext (thread 677040). My controller matches a persistent IOUserResources-backed nub that never detaches, so there's no equivalent quiesce point. Questions: For a dext whose only provider is a self-published IOUserResources nub (no detachable hardware), is reboot-free replacement structurally impossible — i.e. is the Code=101 "is being replaced" defer inherent to this matching pattern? Is the supported way to live-upgrade such a dext to deactivationRequest → (on .completed) → activationRequest rather than an in-place replace? If so, what makes a deactivationRequest complete in-session vs. defer to reboot for an IOUserResources-matched dext — and what would cause it to hang with no delegate callback? (Daemon's IOUserClient is closed; the controller's Stop() cancels its queues and completes.) Should the dext itself proactively tear down the published nub (e.g. terminate the bootstrap IOService) before/at upgrade so the controller detaches — or does that just re-match the still-staged old personalities and relaunch the old version? Is there a recommended pattern for a virtual (hardwareless) DriverKit HBA that needs in-field, reboot-free version updates, or is reboot genuinely required for this class of dext? Environment: macOS 27 (Tahoe)
Replies
0
Boosts
0
Views
880
Activity
Jun ’26
Supported way to expose an iPhone+controller as a macOS gamepad without restricted entitlements?
I’m prototyping a personal-use system that lets an iPhone with a physically attached controller act as an input device for a Mac. End goal: Use the iPhone as the transport and sensor host Use the attached physical controller for buttons/sticks Map the iPhone gyroscope to the controller’s right stick to get gyro aim in Mac games / cloud-streamed games such as GeForce NOW that don't support the gyro. What I’m trying to understand is whether Apple supports any path for this on macOS that does NOT require restricted entitlements or paid-program-only capabilities. What I’ve already found: CoreHID virtual HID device creation appears to require com.apple.developer.hid.virtual.device HIDDriverKit / system extensions appear to require Apple-granted entitlements as well GCVirtualController does not seem to solve the problem because I need a controller-visible device that other apps can see, not just controls inside my own app So my concrete question is: Is there any supported, entitlement-free way for a personal macOS app to expose a game-controller-like input device that other apps can consume system-wide? If not, is the official answer that this class of solution necessarily requires one of: CoreHID with restricted entitlement HIDDriverKit/system extension entitlement some other Apple-approved framework or program I’m missing I’m not asking about App Store distribution. This is primarily for local/personal use during development. I’m trying to understand the supported platform boundary before investing further. Any guidance on the recommended architecture for this use case would be appreciated.
Replies
4
Boosts
1
Views
1.8k
Activity
Jun ’26
Custom ethernet interface with userspace transport via DriverKit
We're developing a custom Thunderbolt device and want to expose it to macOS as an ethernet interface, while owning the full network stack implementation up to and including IP, TCP and UDP — bypassing the macOS network stack for those layers. Is IOEthernetController the right DriverKit approach for this, and does it allow intercepting traffic before it reaches the macOS IP stack?
Replies
4
Boosts
0
Views
914
Activity
Jun ’26
System Panic with IOUserSCSIParallelInterfaceController during Dispatch Queue Configuration
Hello everyone, We are in the process of migrating a high-performance storage KEXT to DriverKit. During our initial validation phase, we noticed a performance gap between the DEXT and the KEXT, which prompted us to try and optimize our I/O handling process. Background and Motivation: Our test hardware is a RAID 0 array of two HDDs. According to AJA System Test, our legacy KEXT achieves a write speed of about 645 MB/s on this hardware, whereas the new DEXT reaches about 565 MB/s. We suspect the primary reason for this performance gap might be that the DEXT, by default, uses a serial work-loop to submit I/O commands, which fails to fully leverage the parallelism of the hardware array. Therefore, to eliminate this bottleneck and improve performance, we configured a dedicated parallel dispatch queue (MyParallelIOQueue) for the UserProcessParallelTask method. However, during our implementation attempt, we encountered a critical issue that caused a system-wide crash. The Operation Causing the Panic: We configured MyParallelIOQueue using the following combination of methods: In the .iig file: We appended the QUEUENAME(MyParallelIOQueue) macro after the override keyword of the UserProcessParallelTask method declaration. In the .cpp file: We manually created a queue with the same name by calling the IODispatchQueue::Create() function within our UserInitializeController method. The Result: This results in a macOS kernel panic during the DEXT loading process, forcing the user to perform a hard reboot. After the reboot, checking with the systemextensionsctl list command reveals the DEXT's status as [activated waiting for user], which indicates that it encountered an unrecoverable, fatal error during its initialization. Key Code Snippets to Reproduce the Panic: In .iig file - this was our exact implementation: class DRV_MAIN_CLASS_NAME: public IOUserSCSIParallelInterfaceController { public: virtual kern_return_t UserProcessParallelTask(...) override QUEUENAME(MyParallelIOQueue); }; In .h file: struct DRV_MAIN_CLASS_NAME_IVars { // ... IODispatchQueue* MyParallelIOQueue; }; In UserInitializeController implementation: kern_return_t IMPL(DRV_MAIN_CLASS_NAME, UserInitializeController) { // ... // We also included code to manually create the queue. kern_return_t ret = IODispatchQueue::Create("MyParallelIOQueue", kIODispatchQueueReentrant, 0, &ivars->MyParallelIOQueue); if (ret != kIOReturnSuccess) { // ... error handling ... } // ... return kIOReturnSuccess; } Our Question: What is the officially recommended and most stable method for configuring UserProcessParallelTask_Impl() to use a parallel I/O queue? Clarifying this is crucial for all developers pursuing high-performance storage solutions with DriverKit. Any explanation or guidance would be greatly appreciated. Best Regards, Charles
Replies
28
Boosts
0
Views
4.4k
Activity
Jun ’26
PCIe/Thunderbolt device delegation to Linux guest VM on Apple Silicon
Does Virtualization.framework support delegating a Thunderbolt/PCIe device to a Linux guest VM running on Apple Silicon? We're developing a custom PCIe device and would like to iterate on the driver in a Linux VM environment on the same host.
Replies
2
Boosts
0
Views
1.2k
Activity
Jun ’26
Can a Thunderbolt device expose new child devices dynamically after enumeration?
Can a Thunderbolt device dynamically expose logical child devices to macOS and control their connection and disconnection lifecycle, independently of the physical device connection?
Replies
2
Boosts
0
Views
1.2k
Activity
Jun ’26
Dext Auto Registration vs. Manual Registration
I need a bit more support. Per Apple’s guidance, our dext’s hosting app checks to see if the dext is installed, and if it is not installed, it will register the dext. I am going to refer to this as “auto registration.” I have also added a menu option to register the dext, which I am going to call “manual registration.” The manual registration works. The user is prompted to “Allow” the dext to be loaded, and things proceed normally. The auto-registration does not work. It produces an error response that is not helpful: Request did fail with Error 1 (The operation couldn’t be completed. (OSSystemExtensionErrorDomain error 1.)) Registration failed, unknown error. They execute the exact same code path – the auto registration calls the menu option’s function that executes from user selection. When comparing the sysextd logs, they differ starting at “Advancing from validating to validating_by_category.” The manual registration has a trace that reads: got reply from com.apple.system_extension.driver_extension... The auto registration does not get this reply. Attached are the two logs. This is Sonoma 14.7.6, the earliest OS we must support. Any suggestions on what is happening or how to fix it so that auto registration can work? Validate_by_category failure trace Validate_by_category success trace
Replies
3
Boosts
0
Views
1.1k
Activity
Jun ’26
Optimizing SCSI HBA Constraints and Alignment for DriverKit on Apple Silicon
Hi Kevin, I'm starting this new thread to focus on alignment optimization and recalibrating our HBA constraints. Following up on your suggestion about UserReportHBAConstraints and alignment optimization, here are our current DEXT settings: Via UserReportHBAConstraints(): kIOMaximumSegmentCountRead/WriteKey: 129 kIOMaximumSegmentByteCountRead/WriteKey: 65,536 (64 KB) kIOMinimumSegmentAlignmentByteCountKey: 4 bytes kIOMaximumSegmentAddressableBitCountKey: 32 kIOMinimumHBADataAlignmentMaskKey: 0 Via SetProperties() (additional injection): kIOMaximumByteCountRead/WriteKey: 524,288 (512 KB) kIOMaximumBlockCountRead/WriteKey: 1,024 We inherited the segment count (129) and max I/O length (512 KB) from our legacy KEXT, which were originally calculated based on a 4 KB segment size (Max I/O 512 KB / 4 KB + 1 = 129). The current alignment value of 4 was essentially a placeholder, as the legacy hardware didn't enforce strict page-level alignment. Given that our testing is on Apple Silicon, we are considering increasing kIOMinimumSegmentAlignmentByteCountKey to 16,384 (16 KB) to match the native page size. However, I have two specific questions regarding this: Stripe Size vs. Page Size: Our RAID stripe size is typically larger than 16 KB (e.g., 64 KB or 128 KB). Should we be aligning the system to the RAID stripe size for hardware efficiency, or is it more critical to stick to the 16 KB page size to optimize the IOMMU/DART mapping overhead in DriverKit? Recalibration: If we increase the alignment to 16 KB, should we also adjust the kIOMaximumSegmentByteCount to match (i.e., 16 KB), or is it better to keep it at 64 KB to allow fewer, larger segments per I/O? We suspect that the 38% gain we saw in 4 KB Random Reads might improve even further if we fix this alignment bottleneck. Looking forward to your thoughts. Best regards, Charles
Replies
4
Boosts
0
Views
1.4k
Activity
Jun ’26
Identifiers - what do the icons mean?
On the Certificates, Identifiers and Profiles section of the Account section of developer.apple.com, if you manually configure the Capabilities of an App Identifier, there are icons with no tooltips. Does anyone know what they mean? (I'm particularly interested in the two different icons shown in my screenshot, with the same name)
Replies
1
Boosts
0
Views
1k
Activity
Jun ’26
One Driver talking to another Driver.
One of the possible solutions to a problem that I'm working on is to have two Drivers loading in one DriverKit dext, an IOUserHIDEventService and an IOUserHIDDevice. For this to work, however, I need to have the event service send a message to the Device. IOKit has the service and connection objects that I can use just like an app would (just like the app the driver communication example). But DriverKit complains whenever I try to add the IOKit framework, saying that it is not supported. Is there another way that I can send a message directly from one driver to another?
Replies
2
Boosts
0
Views
1.9k
Activity
Jun ’26
DriverKit issue with TestFlight
Hi, We’re developing a DriverKit extension for iPadOS. In local Debug and Release builds, everything works as expected, but the same build uploaded to TestFlight fails at IOServiceOpen with the following errors: -536870212 (0xE00002EC) kIOReturnUnsupported -536870201 (0xE00002F7) kIOReturnNotPermitted What we’ve verified so far App entitlements We checked our main app entitlements file, and it has the correct capabilities for the driverkit communication <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>com.apple.developer.driverkit.userclient-access</key> <array> <string>abc.def.ABCDriver</string> </array> <key>com.apple.developer.system-extension.install</key> <true/> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.device.usb</key> <true/> <key>com.apple.security.files.user-selected.read-write</key> <true/> </dict> </plist> we also checked the Provisioning profile (as shown on the portal) and the “Enabled Capabilities” seems to have the correct DriverKit Capabilities enabled. Enabled Capabilities Access Wi-Fi Information, DriverKit, DriverKit (development), DriverKit Communicates with Drivers, DriverKit USB Transport (development), DriverKit USB Transport - VendorID, DriverKit UserClient Access, iCloud, In-App Purchase, Sign In with Apple, System Extension When we download and inspect the provisioning profile as plain text, we notice that some expected DriverKit entitlements appear to be missing from the section. <key>Entitlements</key> <dict> <key>beta-reports-active</key> <true/> <key>com.apple.developer.networking.wifi-info</key> <true/> <key>com.apple.developer.driverkit</key> <true/> <key>com.apple.developer.driverkit.communicates-with-drivers</key> <true/> <key>application-identifier</key> <string>ABC123456.abc.def</string> <key>keychain-access-groups</key> <array> <string>ABC123456.*</string> <string>com.apple.token</string> </array> <key>get-task-allow</key> <false/> <key>com.apple.developer.team-identifier</key> <string>ABC123456</string> <key>com.apple.developer.ubiquity-kvstore-identifier</key> <string>ABC123456.*</string> <key>com.apple.developer.icloud-services</key> <string>*</string> <key>com.apple.developer.icloud-container-identifiers</key> <array></array> <key>com.apple.developer.icloud-container-development-container-identifiers</key> <array></array> <key>com.apple.developer.ubiquity-container-identifiers</key> <array></array> <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1234</integer> </dict> </array> <key>com.apple.developer.applesignin</key> <array> <string>Default</string> </array> </dict> We have a couple of questions: Could the missing com.apple.developer.driverkit.userclient-access entitlement in the provisioning profile alone explain the kIOReturnUnsupported / kIOReturnNotPermitted failures from IOServiceOpen? Why do some DriverKit capabilities appear in the Apple Developer portal UI but vanish from the actual profile we download? Is there an extra step we’re overlooking when regenerating profiles after toggling those capabilities? Thanks
Replies
10
Boosts
0
Views
1.8k
Activity
Jun ’26
[iPadOS / USBDriverKit] Communicating with RP2040: Avoiding OS preemption of standard CDC-ACM?
Hello everyone, I am currently working on an iPadOS application that requires communicating with a custom hardware board based on the Raspberry Pi RP2040 microcontroller via USB. My initial thought was to use the standard CDC-ACM (virtual serial port) profile on the RP2040. However, my understanding is that iPadOS's built-in system drivers will automatically claim any standard CDC-ACM interfaces, preempting my custom USBDriverKit driver from matching and taking control of the device. Is my assumption correct that iPadOS will strictly preempt a standard CDC-ACM device, making a custom DriverKit implementation impossible for that specific class?
Replies
1
Boosts
0
Views
1.2k
Activity
May ’26
Xcode Signing Fails: Provisioning Profile "doesn't match" com.apple.developer.driverkit.userclient-access entitlement
Hello everyone, I am migrating a legacy KEXT to a DriverKit (DEXT) architecture. While the DEXT itself is working correctly, I am completely blocked by a code signing issue when trying to establish the UserClient connection from our SwiftUI management app. Project Goal & Status: Our DEXT (com.accusys.Acxxx.driver) activates successfully (systemextensionsctl list confirms [activated enabled]). The core functionality is working (diskutil list shows the corresponding disk device node). The Core Problem: The userclient-access Signing Error To allow the app to connect to the DEXT, the com.apple.developer.driverkit.userclient-access entitlement is required in the app's .entitlements file. However, as soon as this entitlement is added, the build fails. Both automatic and manual signing fail with the same error: `Provisioning profile ... doesn't match the entitlements file's value for the ... userclient-access entitlement.` This build failure prevents the generation of an .app bundle, making it impossible to inspect the final entitlements with codesign. What We've Confirmed: The necessary capabilities (like DriverKit Communicates with Drivers) are visible and enabled for our App ID on the developer portal. The issue persists on a clean system state and on the latest macOS Sequoia 15.7.1. Our Research and Hypothesis: We have reviewed the official documentation "Diagnosing issues with entitlements" (TN3125). According to the documentation, a "doesn't match" error implies a discrepancy between the entitlements file and the provisioning profile. Given that we have tried both automatic and manual profiles (after enabling the capability online), our hypothesis is that the provisioning profile generation process on Apple's backend is not correctly including the approved userclient-access entitlement into the profile file itself. The build fails because Xcode correctly detects this discrepancy. Our Questions: Did we misunderstand a step in the process, or is the issue not with the entitlement request at all? Alternatively, are there any other modifications we can make to successfully connect our App to the DEXT and trigger NewUserClient? Thank you for any guidance.
Replies
11
Boosts
0
Views
1.8k
Activity
May ’26
sysextd silently fails to realize a signed DriverKit extension after "attempting to realize" — which log surfaces the rejection reason?
A signed DriverKit extension fails OSSystemExtensionRequest activation on macOS 26.4.1. The user-facing error is OSSystemExtensionErrorDomain code 4 ("Extension not found in App bundle") — but the dext is in the bundle, the identifier matches, and sysextd confirms it received the request: sysextd: [com.apple.sx:XPC] client activation request for com.arqitekta.bluefield.rshim.driver sysextd: attempting to realize extension with identifier com.arqitekta.bluefield.rshim.driver …and then nothing further. systemextensionsctl list reports 0 extensions. Question: Which log subsystem/category surfaces the kernel-side reason that sysextd aborts after "attempting to realize"? com.apple.sx only shows the request was accepted; whatever vetoes the realize step isn't in that subsystem (or isn't at info/debug level). Is there a separate predicate for the kernelmanagerd / dext-loading path I should be capturing? Environment: macOS 26.4.1 (25E253), Apple Silicon Mac Studio Xcode 26.2 (17C52), DriverKit SDK 25.2 SIP disabled, systemextensionsctl developer on Apple Developer Program, signed "Apple Development: …" DriverKit entitlement request 264CFJJU36 approved; profile includes com.apple.developer.driverkit, allow-any-userclient-access, transport.pci Already verified: Dext at Contents/Library/SystemExtensions/RshimDriver.dext CFBundleIdentifier matches the request, CFBundlePackageType=DEXT codesign --verify --deep --strict passes on app + dext embedded.provisionprofile parses, contains the expected entitlements Three IOKitPersonalities (BF2 / BF2-alt / BF3) using Apple's placeholder IOPCIPrimaryMatch Installer app entitled with com.apple.developer.system-extension.install only spctl -a -vv on the dext reports "rejected" — expected for development signing, should be bypassed under developer mode Minimal repro: https://github.com/jfabienke/bluefield-macos-toolkit/tree/dev-stub-entitlements/rshim-dext — build.sh produces the failing app dext. Captured artefacts (build output, embedded profile dump, signing report, repro shell script) under rshim-dext/dts-artifacts/. Looking for either (a) the right log show predicate to find the actual refusal reason, or (b) an environmental requirement on macOS 26 I'm missing.
Replies
1
Boosts
0
Views
1.8k
Activity
Apr ’26