ikwzm / udmabuf

User space mappable dma buffer device driver for Linux.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Using "u-dma-buf" on x86 with IOMMU enabled

JMStranz opened this issue · comments

Hi!

First of all, I would like to thank you for your work.

However, I have a problem using "u-dma-buf" on an x86 system with IOMMU enabled.

If the option "VT-d" is activated in the BIOS, then the command "echo "create udmabuf1 0x9000" > /dev/u-dma-buf-mgr" always returns an error.
The reason is that the function "dma_alloc_coherent()" (used in "udmabuf_device_setup()") returns with the value "0".

If IOMMU is disabled in the Linux command line with "intel_iommu=off", then the buffer can be successfully created with the command "echo "create udmabuf1 0x9000" > /dev/u-dma-buf-mgr".

May the driver "u-dma-buf" only be used with deactivated IOMMU?

I would be very grateful for any advice!

Best regards
Jan-Marc.

For completion:
The following kernel configurations are set:

CONFIG_CMA=y
CONFIG_DMA_CMA=y

CONFIG_CMA_DEBUGFS=y
CONFIG_CMA_AREAS=7
CONFIG_CMA_SIZE_MBYTES=8
CONFIG_CMA_SIZE_SEL_MBYTES=y
CONFIG_CMA_ALIGMENT=8

After trying "echo "create udmabuf1 0x9000" > /dev/u-dma-buf-mgr" "dmesg" shows

[ 126.157968] u-dma-buf-mgr : create udmabuf1 36864
[ 126.163010] dma_alloc_coherent(size=36864) failed. return(0)
[ 126.163128] u-dma-buf u-dma-buf.0.auto: driver setup failed. return=-12
[ 126.163779] u-dma-buf u-dma-buf.0.auto: driver installed.
[ 126.164097] u-dma-buf: probe of u-dma-buf.0.auto failed with error -12

Best regards
Jan-Marc.

Thank you for the issue.

May the driver "u-dma-buf" only be used with deactivated IOMMU?

Yes. Unfortunately, u-dma-buf does not support IOMMU.
Because u-dma-buf aims to secure a physically contiguous memory space.
IOMMU was unexpected.

I believe this is further complicated by the IOMMU presenting different address spaces to different devices, meaning the address for DMA needs to be translated to one that the specific device can use.

summary from chatGPT

void *cpu_addr;                  // for kernel access
dma_addr_t dma_addr;      // for device access
unsigned long phys_addr; // for mmap to user-space

/* Allocate DMA-coherent memory */
cpu_addr = dma_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL);
if (!cpu_addr) {
    /* Error handling */
}

/* convert to phys addr */
phys_addr = virt_to_phys(cpu_addr);

then, user-space can mmap phys_addr to access dma buffer