|
|
Subscribe / Log in / New account

DMA addresses for UIO

By Jonathan Corbet
April 22, 2025
The Userspace I/O (UIO) subsystem was first added to the kernel by Hans J. Koch for the 2.6.23 release in 2007. Its purpose is to facilitate the writing of drivers (mostly) in user space; to that end, it provides access to a number of resources that user-space code normally cannot touch. One piece that is missing, though, is DMA addresses. A proposal to fill that gap from Bastien Curutchet is running into some opposition, though.

While UIO drivers reside mostly in user space, they still require a small in-kernel component; it is essentially a bit of glue that can probe for a device and handle interrupts, and which informs the kernel of any memory-mapped I/O (MMIO) regions that should be made available to user space. Showing its age, UIO also has a mechanism to make x86 I/O ports available. Once that module is loaded, a user-space driver can open the appropriate /dev/uioX device, map the memory regions into its address space, use that mapping to program the device, and read from the device file descriptor to wait for interrupts. The mapped MMIO areas are usually all that is needed to operate the device.

See this 2007 article for an overview of what the UIO interface looked like then and some of the discussions around its addition to the kernel.

UIO drivers are generally relatively simple; as the complexity of a device increases, so do the advantages of driving it entirely within the kernel. Among other things, UIO drivers are normally limited to simple programmed I/O, where all data transferred goes through the CPU. The performance of programmed I/O transfers is limited, though, so even relatively low-end devices now support DMA transfers instead. Access to the MMIO region is usually sufficient to program a DMA operation into a device, but there is one little detail missing: the address of the I/O buffer to give to the device.

Coming up with DMA addresses is not quite as easy as it sounds. A driver running in user space will see its virtual address space; it can create a buffer there, but the driver's virtual address for that buffer will mean nothing to the device. Even on the simplest of systems, that address will need to be converted to a physical address that the device can access; the user-space pages involved will also need to be locked into memory for the duration of the transfer. On more complex systems, the "physical address" will be in a separate address space for the bus on which the device resides, and may well be translated through an I/O memory-management unit (IOMMU), which must be appropriately programmed. None of this work can be done from user space.

According to Curutchet, there are numerous UIO drivers that include hacks to enable the creation and export of DMA addresses for user-space drivers to use. The posted patch series is an attempt to provide a standard, well-tested mechanism to carry out this task in a relatively safe way. The kernel does have some infrastructure for the management of DMA buffers from user space: the dma-buf layer, which was initially created to enable the sharing of DMA buffers between devices. This layer does almost everything that a UIO driver needs, but it does not make the DMA addresses of its buffers available to user space.

Curutchet's patch set adds a new ioctl() operation to the dma-buf layer that can provide the DMA address for a dma-buf to the caller. The series also adds a new dma-buf heaps module for the creation of simple, cache-coherent DMA buffers. Using this module, user-space drivers can create DMA buffers, but they do not have access to most of the more-complex dma-buf machinery, including all of its synchronization support.

Christian König repeatedly requested an open-source driver that uses this new feature. As Thomas Petazzoni pointed out, though, an open-source user has never been required for any other UIO feature. The presence of an open-source consumer for a new interface can be helpful during the review process, but it does seem a bit late to add that requirement here, when it has never been requested before.

Christoph Hellwig, instead, said that the proper solution to this problem was to use the VFIO and IOMMUFD subsystems. He later added that the proposal is "fundamentally broken and unsafe" and that, if his suggested approach does not work, the only alternative is to write a full in-kernel driver. Petazzoni answered that VFIO and IOMMUFD are not suitable for this use case, and pointed out that making DMA addresses available does not add safety concerns that are not already present:

UIO allows to remap MMIO registers into a user-space application, which can then do whatever it wants with the IP block behind those MMIO registers. If this IP block supports DMA, it already means that _today_ with the current UIO subsystem as it is, the user-space application can program a DMA transfer to read/write to any location in memory.

Creating a clean interface for the management of DMA buffers, he suggested, is likely to make UIO drivers more safe than they are now. Andrew Davis was not convinced, though, characterizing Petazzoni's argument as: "UIO is a broken legacy mess, so let's add more broken things to it as broken + broken => still broken, so no harm done". He later said that improving the UIO interface "gives the impression that is how drivers should still be written" when, he said, the correct solution is to write an in-kernel driver.

As that last quote shows, the real point of contention here is not whether the provision of DMA addresses will somehow make UIO more dangerous; UIO drivers can already corrupt the system. The question is whether UIO should exist at all in 2025. Support for many classes of drivers in the kernel has improved significantly since UIO was merged, and some developers are undoubtedly unhappy with its potential use in developing proprietary drivers. At this point, to some, the value provided by UIO may appear to be negative.

UIO cannot be removed, of course, without breaking an unknown number of existing drivers, but it can be frozen in place with the idea of reducing the number of drivers written to use the UIO interface in the future. The real result of denying new UIO features, though, seems likely to be to just push those features into a set of (probably more dangerous) driver-specific hacks, as is evidently already happening for DMA addresses.

Index entries for this article
KernelDevice drivers/In user space


to post comments

UIO appears to be tasked to address a particularly odd edge case here

Posted Apr 22, 2025 19:14 UTC (Tue) by gutschke (subscriber, #27910) [Link] (3 responses)

From what I got from that conversation on LKML, this is truly a very unusual edge case. It's already a very small group of people who would benefit from UIO in the first place. Two decades ago, it was primarily intended for one-off industrial extension cards that have a very simple MMIO interface. These days, you'd expect that most of these devices would long since have migrated to some other technology (e.g. USB). Apparently, you can even get devices that connect through USB and make an ISA slot available. So, if you are truly stuck having to use ancient hardware, that's yet another viable option.

An even smaller subset of users have devices that are 1) one-off or low-volume, 2) plug into a PCI(e) slot, 3) and require DMA. Most of these users would be well-served with VFIO/IOMMUFD. It's pretty much custom-made for this exact use case, and it offers a much more natural interface. I would expect that anybody who looked at UIO in 2007 and who still today has to deal with interfacing to odd custom hardware would rather invest in VFIO/IOMMUFD-based userspace software.

But in the particular scenario that prompted the current discussion, an additional wrinkle is the lack of an IOMMU in the user's PowerPC device. This is quickly approaching a point where you have to question whether a more pragmatic solution is a hardware upgrade instead of implementing a new user-facing API that will have to be maintained for decades with barely any new users.

And if changing the hardware isn't viable, then writing (and maintaining) a proper kernelspace driver is maybe the best answer anybody can give to this user. At some point, I understand kernel developers being reluctant to add new interfaces, if it is unclear that anybody else really needs them.

Unfortunately, the person who asked for this API was very reluctant to volunteer more information on what their exact use case is and why they are stuck with the particular combination of hardware.

UIO appears to be tasked to address a particularly odd edge case here

Posted Apr 22, 2025 19:36 UTC (Tue) by edeloget (subscriber, #88392) [Link] (2 responses)

Well, there are a lot of tech that could beneficiate from UIO DMA, the main one being the DPDK where all network drivers are implemented in user space. A lot of them already require some form of UIO and they often add other specific requirements such as a vendor provided BSP to support DMA transfers.

UIO appears to be tasked to address a particularly odd edge case here

Posted Apr 22, 2025 19:42 UTC (Tue) by gutschke (subscriber, #27910) [Link]

I don't question the need for doing DMA from userspace. I can certainly see why some use cases call for that. What I am questioning is whether UIO is the best API to shoehorn this feature into, when VFIO is already a perfectly good option for most users and seems to be a lot more maintainable in the long run.

UIO appears to be tasked to address a particularly odd edge case here

Posted Apr 23, 2025 0:55 UTC (Wed) by ahippo (subscriber, #154692) [Link]

If I remember correctly, DPDK supports VFIO very well [1], both with and without IOMMU.

In fact, I remember some NIC crashing a system under heavy load when used with igb_uio, but not with VFIO (thanks to IOMMU supposedly).

[1] https://doc.dpdk.org/guides/linux_gsg/linux_drivers.html#...

USB HID

Posted Apr 22, 2025 23:34 UTC (Tue) by ringerc (subscriber, #3071) [Link] (1 responses)

Lots of weird custom hardware works via the USB HID interface, by exposing an on-board UHCI/XHCI with an integrated HID device.

This became popular because user-space un-signed HID drivers could be written for Windows versions where other drivers require signing, WHQL etc.

USB HID

Posted Apr 23, 2025 1:26 UTC (Wed) by neggles (subscriber, #153254) [Link]

Drivers for custom USB devices are pretty easy these days; libusb on linux and WinUSB on windows are almost entirely API-compatible and WinUSB uses one kernel driver for all devices, so no HID trickery is needed anymore. As a bonus you get support for Windows on ARM (and linux on uncommon architectures) with little to no effort.

Unfortunately, USB and PCI(e) are very different beasts - a USB device has much less control over and access to system memory. USB devices are reliant on their host controller for data movement, and don't have to handle physical memory addresses at all. It's kind of like the difference between read()/write() and mmap(), with PCI being the latter.

The equivalent for PCIe on linux these days would be the vfio-pci kernel driver, which (contrary to popular belief) does not actually require an IOMMU to work. It might be worth updating the documentation to make it clear that using the "unsafe" no-iommu mode is only unsafe in the face of a misbehaving device, and is fine to use on systems without an IOMMU.

That's probably the correct solution here, but i'm not sure how big of a job it would be to convert a driver like the one described here to use vfio-pci; is there a library of handy wrapper/boilerplate code like libusb but for pci?

Simply deprecated interface?

Posted Apr 23, 2025 4:53 UTC (Wed) by marcH (subscriber, #57642) [Link]

> UIO cannot be removed, of course, without breaking an unknown number of existing drivers, but it can be frozen in place with the idea of reducing the number of drivers written to use the UIO interface in the future.

This is the essence of a "deprecated" interface. Was the "deprecated" terminology not used and if not then why not? It would IMHO clarify the situation and save misunderstandings, discussions and time.

Maybe because "deprecated" usually means removal at some unknown point in the future? Removal means "breaking userspace"; the horror! Well, just assume the "unknown point" is "never" and that's it! You've just invented the "forever deprecated" interface which seems to describe UIO perfectly. Problem solved.


Copyright © 2025, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds