u-dma-buf hands a userspace driver a real DMA buffer
User space mappable dma buffer device driver for Linux.
At a glance
- What is it?
- u-dma-buf is a Linux kernel module that allocates contiguous physically addressed memory and maps it into a user space program, which is the missing half of the UIO model on platforms whose DMA is not addressable from userspace.
- Who is it for?
- u-dma-buf suits a developer writing a device driver in user space on a platform where the DMA buffer has to be physically contiguous and cache controllable, and it suits anyone who needs the buffer address in user space rather than only a handle to it. It is the wrong tool if you are on x86 with a modern kernel, because the platform notes are explicit that verification there is not sufficient and that the cache control and the device tree settings do not work.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the module actually does
u-dma-buf is a Linux device driver that allocates contiguous memory blocks in kernel space as DMA buffers and makes them available from user space. The stated intention is that these memory blocks are used as DMA buffers when a user application implements a device driver in user space using UIO, the User space I/O framework. The access path is two ways of the same thing. A DMA buffer can be reached from user space by opening the device file, for example /dev/udmabuf0, and mapping it into the user memory space, or by using the read and write functions. The CPU cache for the allocated buffer can be disabled by setting the O_SYNC flag when opening the device file, and it is also possible to flush or invalidate the CPU cache while keeping the cache enabled. The physical address of the buffer can be obtained by reading a sysfs file, /sys/class/u-dma-buf/udmabuf0/phys_addr. That last point is the one that makes the module useful for a real driver, because a user space driver that programs a device usually needs to hand the device a physical address.
The rename, and why it happened
The readme has a section explaining why the project is called u-dma-buf rather than udmabuf, and the answer is a name collision. The predecessor of u-dma-buf is udmabuf, and the kernel module name has been changed from udmabuf to u-dma-buf, the purpose of which is to avoid duplicate names because another kernel module with the same name as udmabuf has been added since Linux Kernel 5.x. The table of changes is short and complete. The module file became u-dma-buf.ko from udmabuf.ko, the source file became u-dma-buf.c from udmabuf.c, the sys class directory became /sys/class/u-dma-buf/ from /sys/class/udmabuf/, and the device tree compatible property became ikwzm,u-dma-buf from ikwzm,udmabuf-0.10.a. That last row is the one that catches people out, because a device tree that still names the old property will simply fail to probe the driver, and the failure looks like a missing device rather than a renamed binding.
Which platforms are actually verified
The supported platform list is unusually honest, and the honest part is the x86 entry. The operating systems are Linux kernel versions 3.6 to 3.8, then 3.18, 4.4, 4.8, 4.12, 4.14, 4.19, 5.0 to 5.10, 6.1, 6.6, 6.12 and 6.18, and the readme notes which of those the author actually tested on: 3.18, 4.4, 4.8, 4.12, 4.14, 4.19, 5.4, 5.10, 6.1, 6.6, 6.12 and 6.18. The processors listed are ARM Cortex-A9 on the Xilinx ZYNQ and Altera Cyclone V SoC, ARM64 Cortex-A53 on the Xilinx ZYNQ UltraScale+ MPSoC, and RISC-V on the Microchip Polarfire SoC FPGA. And then x86, 64 bit, with a caveat that reads more like an apology: verification is not enough, and the author hopes for results from everyone. Two specific limits are listed for x86. The CPU cache cannot be controlled by the O_SYNC flag, and the CPU cache is always valid. And the various settings cannot be made through the device tree. So on x86 the module is usable but the two features that matter most for a DMA driver are the ones that do not work.
Building it out of tree, or into the kernel source tree
The Makefile is the build interface, and it has a small set of parameters. ARCH is the architecture name and defaults to a shell expression over uname -m that maps arm to arm, aarch64 to arm64 and riscv to riscv. KERNEL_SRC is the kernel source directory and defaults to /lib/modules/$(shell uname -r)/build. The rest are feature toggles for debug reporting, the quirk-mmap behaviour, in-kernel functions, the ioctl interface and the PRIME DMA-BUFS export, all defaulting to y. For a cross-compilation environment the build is one command.
shell$ make ARCH=arm KERNEL_SRC=/home/fpga/src/linux-5.10.120-zynqmp-fpga-generic allOn a target that can compile the module itself, the kernel source has to be present in the build directory.
shell$ make allThere is also a route into the kernel source tree itself, which is the route for a vendor that wants the driver permanently in the image. The steps are to make a directory under drivers/staging, copy the Kconfig, the Makefile and the source file into it, add a source line to the staging Kconfig and an obj line to the staging Makefile, and then set the configuration option.
shell$ cp Kconfig Makefile u-dma-buf.c <linux-source-tree>/drivers/staging/u-dma-buf+obj-$(CONFIG_U_DMA_BUF) += u-dma-buf/In menuconfig the option sits under Device Drivers, then Staging drivers, then u-dma-buf, and in a defconfig it is the single line CONFIG_U_DMA_BUF=m.
Loading it and the eight buffer limit
Loading is done with insmod, and the size of a DMA buffer is provided as an argument. The device driver is created and allocates a DMA buffer with the specified size, and the maximum number of DMA buffers that can be allocated this way is eight, named udmabuf0 through udmabuf7.
zynq$ insmod u-dma-buf.ko udmabuf0=1048576
u-dma-buf udmabuf0: driver version = 5.6.0
u-dma-buf udmabuf0: major number = 248
u-dma-buf udmabuf0: minor number = 0
u-dma-buf udmabuf0: phys address = 0x1e900000
u-dma-buf udmabuf0: buffer size = 1048576
u-dma-buf u-dma-buf.0: driver installed.The output is the interesting part, because it tells you the physical address directly, which is the value a user space driver has to program into the device. The size and the minor number can be specified when the module is loaded, and some platforms allow them to be set in the device tree instead. The device file that appears is readable and writable only by root, and if that needs to change at load time, the readme says to create a udev rule file under /etc/udev/rules.d/.
```rules:99-u-dma-buf.rules SUBSYSTEM=="u-dma-buf", GROUP="root", MODE="0666" ```
Unloading is the mirror image, with rmmod and a message that the driver has been removed. There is also a Debian packaging route, with the details in a separate repository for the kernel module package.
What the module parameters are for
The module exposes its own parameters, listed in a table of name, type, default and description, and the parameter set is where the interesting behaviour lives. The Makefile shows the mechanism clearly, because each of the feature flags is turned into a compiler define for the out-of-tree build and, for the in-tree build, a ccflags entry. The quirk-mmap flag exists because some user space mappings of a DMA buffer behave badly under certain kernels, and the flag makes the driver work around that. The in-kernel functions flag controls whether the driver provides helper functions that other in-tree code can call. The ioctl flag selects the ioctl interface level, and the Makefile shows it being compiled to the value 3 when the flag is on. And the export flag controls the PRIME DMA-BUFS export, which is the mechanism that lets a buffer allocated by this driver be handed to another subsystem. The debug flag turns on the debug reporting that the Makefile describes as a debug report, and the same flag exists in the parameter table as a module parameter, so it can be changed at load time rather than at build time.
Where this is the wrong choice
Three limits are worth naming. The first is the x86 situation, which the readme states in the plainest terms available, and a DMA driver whose cache coherency handling does not work on the platform you are deploying to is not a finished tool. The second is the eight buffer limit and the fixed minor number scheme, which is fine for a single device with a handful of queues and a problem for anything that wants to allocate buffers dynamically as its load changes. The third is the age of the design. The project began as udmabuf in the era when user space DMA on embedded Linux was done with a staging driver, and the in-tree module that later took the udmabuf name is the upstream answer to the same problem. That is not a criticism of the work, which is still maintained and still useful on the platforms it lists, but it does mean a new design should look at what the kernel now provides before starting from here. A final practical note is that the whole model assumes physically contiguous memory that the user space program can also map, which is exactly why the platform list is SoC oriented.
Editorial conclusion
u-dma-buf suits a developer writing a device driver in user space on a platform where the DMA buffer has to be physically contiguous and cache controllable, and it suits anyone who needs the buffer address in user space rather than only a handle to it. It is the wrong tool if you are on x86 with a modern kernel, because the platform notes are explicit that verification there is not sufficient and that the cache control and the device tree settings do not work. It is also the wrong choice if you need a modern replacement, since the name change from udmabuf was made to avoid clashing with a different in-tree module and the current upstream path for such buffers is no longer a staging driver. Before building it, read the supported platform list, since the verified kernel versions are a specific set rather than a range, and note that the maximum number of buffers is eight. The last push was on 2026-10-16 and the repository publishes no releases.
Frequently asked questions
How do I load the u-dma-buf driver?
Use insmod with the size of the buffer as an argument, for example insmod u-dma-buf.ko udmabuf0=1048576. The driver prints the driver version, the major and minor numbers, the physical address and the buffer size, and creates the device file. You can allocate at most eight buffers this way, named udmabuf0 through udmabuf7, and rmmod removes the driver.
How does a user space program access a u-dma-buf buffer?
Either by opening the device file such as /dev/udmabuf0 and mapping it into the user memory space, or by using the read and write functions. The CPU cache can be disabled by setting the O_SYNC flag when opening the file, or the cache can be flushed or invalidated while remaining enabled, and the physical address is published at /sys/class/u-dma-buf/udmabuf0/phys_addr.
Which kernels and processors does u-dma-buf support?
The listed kernels run from 3.6 to 3.8 through 3.18, 4.4, 4.8, 4.12, 4.14 and 4.19, 5.0 to 5.10, and 6.1, 6.6, 6.12 and 6.18, with the author having tested on 3.18, 4.4, 4.8, 4.12, 4.14, 4.19, 5.4, 5.10, 6.1, 6.6, 6.12 and 6.18. The processors are ARM Cortex-A9, ARM64 Cortex-A53 and RISC-V on SoC FPGA platforms, and on x86 the README says verification is not enough and that the O_SYNC cache control and the device tree settings do not work.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ikwzm-udmabuf)Was this useful?