In the module / driver, memory is allocated for DMA transactions through ioctl ():

kbuf = dma_alloc_coherent(NULL, CRU_DMA_BUF0_SIZE, &dma_handle, 0); 

then the physical address is returned to the user space:

 ret = put_user(virt_to_phys(kbuf), (unsigned long __user *)arg/*адрес переменной dma_buf в приложении*/); 

in the application I try to zamapit this area of ​​memory:

 int fd = open("/dev/mem", O_RDWR|O_SYNC); if(mmap_dma = (unsigned long*) mmap(NULL, CRU_DMA_BUF0_SIZE, PROT_READ, MAP_SHARED, fd, dma_buf)) printf("Can't mapping DMA buffer\n"); 

#define CRU_DMA_BUF0_SIZE (0x00800000)

by remote machine I get in dmesg enter image description here

  • They wrote somewhere here that nuclear memory from some version of the kernel was forbidden to just fumble. - dsnk
  • You have something wrong with checking the result of mmap, it always returns non-0. - sercxjo

1 answer 1

Here are a few problems:

  • instead of virt_to_phys() for memory allocated for DMA, it would be better to use dma_to_phys() (which is given a bus address (from dma_handle ) and a pointer to a device) to get the physical address (although it will be the same in most cases)
  • mapping through /dev/mem did not work, since in most of the core kernels protection from access is included anywhere ( CONFIG_STRICT_DEVMEM ) through this file and access is given only to the PICIA and BIOS bus regions

Correctly similar issues are solved by implementing the mmap operation on the character device driver, which will display the same physical addresses in user space somewhere like this:

 typedef struct xxx_struct { struct pci_dev *pcid; dma_addr_t dmaaddr; size_t dmasize; } xxx_t; static int xxx_mmap(struct file *filp, struct vm_area_struct *vma) { xxx_t *p = filp->private_data; vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP | VM_PFNMAP; if (io_remap_pfn_range(vma, vma->vm_start, (unsigned long)dma_to_phys(&p->pcid->dev, p->dmaaddr) >> PAGE_SHIFT + vma->vm_pgoff, MIN(vma->vm_end - vma->vm_start, p->dmasize), vma->vm_page_prot)) return -EAGAIN; return 0; } 

And the user application can only open the file and call mmap() . In English like well described here .