Performance issue after migrating from codeless KEXT to DEXT

Hello,


Some of our USB devices present themselves as HID compliant when they are in firmware update mode. This causes problems because we cannot claim the interface with libusb if other programs access it via IOUSBHID. To workaround this we are using a codeless kernel extension that matches the relevant devices to IOUSBInterface.


I am working on migrating our KEXT to DriverKit. So far I have managed to match an empty subclass of IOService to the relevant devices.

Here's an example of the IOKitPersonalities entries I'm using:


<dict>
  <key>CFBundleIdentifier</key>
  <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  <key>CFBundleIdentifierKernel</key>
  <string>com.apple.kpi.iokit</string>
  <key>IOClass</key>
  <string>IOUserService</string>
  <key>IOMatchCategory</key>
  <string>com.apple.null.driver</string>
  <key>IOProviderClass</key>
  <string>IOUSBHostInterface</string>
  <key>IOResourceMatch</key>
  <string>IOKit</string>
  <key>IOUserClass</key>
  <string>DriverKitTestExtension</string>
  <key>IOUserServerName</key>
  <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  <key>bConfigurationValue</key>
  <integer>1</integer>
  <key>bInterfaceNumber</key>
  <integer>0</integer>
  <key>idVendor</key>
  <integer><!-- USB Vendor ID></integer>
  <key>idProduct</key>
  <integer><!-- USB Product ID --></integer>
</dict>


Is it correct to use IOUSBHostInterface as the provider class for this use case?


The new DEXT is working but I am seeing some bad performance regressions in our firmware update code. Calls to libusb are taking tens of seconds. If I use the old KEXT, they return immediately.


Here are some example traces of the problem:


   5 redacted 3168.0  libusb_claim_interface ..../libusb/Sources/libusb/core.c:1310
   4 redacted 3168.0  darwin_claim_interface ..../libusb/Sources/libusb/darwin_usb.c:1089
   3 IOUSBLib 1668.0  IOUSBInterfaceClass::USBInterfaceOpen(bool)
   2 IOKit 1668.0  io_service_wait_quiet
   1 libsystem_kernel.dylib 1668.0  mach_msg
   0 libsystem_kernel.dylib 1668.0  mach_msg_trap


And:


   7 redacted 1859.0  libusb_get_device_list ..../libusb/Sources/libusb/core.c:632
   6 redacted 1859.0  darwin_get_device_list ..../libusb/Sources/libusb/darwin_usb.c:780
   5 redacted 1859.0  process_new_device ..../libusb/Sources/libusb/darwin_usb.c:726
   4 redacted 1766.0  darwin_check_configuration ..../libusb/Sources/libusb/darwin_usb.c:540
   3 IOKit 1766.0  IOIteratorNext
   2 IOKit 1766.0  io_iterator_next
   1 libsystem_kernel.dylib 1766.0  mach_msg
   0 libsystem_kernel.dylib 1766.0  mach_msg_trap
   0 libsystem_kernel.dylib 1766.0  mach_msg_trap


These are recorded in the "Time Profiler" instrument with "Record Waiting Threads" enabled.


Can I do anything in the DEXT to fix this problem? I've tried subclassing IOUSBHostInterface instead of IOService, but that made no difference.


Here's the relevant output from running "ioreg -lirc IOUSBHostInterface":

+-o IOUSBHostInterface@0  <class IORegistryEntry:IOService:IOUSBNub:IOUSBInterface, id 0x10000124e, registered, !matched, active, busy 1 (2304 ms), retain 9>
  | {
  |   "USBSpeed" = 1
  |   "iInterface" = 0
  |   "IOServiceLegacyMatchingRegistryID" = 4294971983
  |   "bInterfaceProtocol" = 0
  |   "bAlternateSetting" = 0
  |   "idProduct" = <!-- USB Product ID -->
  |   "bcdDevice" = 292
  |   "USB Product Name" = <!-- USB Product Name -->
  |   "locationID" = 338690048
  |   "bInterfaceClass" = 3
  |   "bInterfaceSubClass" = 0
  |   "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBHostFamily.kext/Contents/PlugIns/IOUSBLib.bundle"}
  |   "USBPortType" = 0
  |   "bConfigurationValue" = 1
  |   "bInterfaceNumber" = 0
  |   "USB Vendor Name" = <!-- USB Vendor Name -->
  |   "IOServiceDEXTEntitlements" = (("com.apple.developer.driverkit.transport.usb"))
  |   "idVendor" = <!-- USB Vendor ID -->
  |   "bNumEndpoints" = 2
  |   "IOGeneralInterest" = "IOCommand is not serializable"
  |   "IOClassNameOverride" = "IOUSBInterface"
  | }
  | 
  +-o DriverKitTestExtension  <class IORegistryEntry:IOService:IOUserService, id 0x100001253, !registered, !matched, active, busy 0, retain 5>
      {
        "IOClass" = "IOUserService"
        "CFBundleIdentifier" = <!-- DEXT bundle identifier -->
        "IOProviderClass" = "IOUSBHostInterface"
        "IOUserServerCDHash" = "faa70138281d36b53946591685ccdceba4a5d638"
        "idProduct" = <product ID>
        "IOResourceMatch" = "IOKit"
        "bConfigurationValue" = 1
        "IOProbeScore" = 90000
        "IOMatchCategory" = "com.apple.null.driver"
        "IOUserServerName" = <!-- DEXT bundle identifier -->
        "IOMatchedPersonality" = {"IOClass"="IOUserService","CFBundleIdentifier"="<!-- DEXT bundle identifier --> ","IOProviderClass"="IOUSBHostInterface","IOUserServerCDHash"="faa70138281d36b53946591685ccdceba4a5d638","idProduct"=<product ID>,"IOResourceMatch"="IOKit","bConfigurationValue"=1,"IOMatchCategory"="com.apple.null.driver","IOUserServerName"=<DEXT bundle identifier>,"idVendor"=<vendor ID>,"CFBundleIdentifierKernel"="com.apple.kpi.iokit","bInterfaceNumber"=0,"IOUserClass"="DriverKitTestExtension"}
        "idVendor" = <vendor ID>
        "CFBundleIdentifierKernel" = "com.apple.kpi.iokit"
        "bInterfaceNumber" = 0
        "IOUserClass" = "DriverKitTestExtension"
      }

Any input is welcome!

Replies

I found the problem. My DEXT code wasn't being loaded at all. See my answer here: https://stackoverflow.com/a/61818712/7445.