What is the difference between dma_mmap_coherent and remap_pfn_range?

I am currently using an example driver , from which I myself based my own custom driver. The mmap code is almost identical, except that I allow the user to control their requested size and base the allocation of memory around this and the fact that I automatically create a char device inside / dev.

To explain the context, for my use case, I would like to narrow down the question I have. dma_mmap_coherent testably works when using kmalloc'd memory, but when I have a reserved area of ​​physical addresses in which I want to use remap_pfn_range, it works fine and dmesg doesn't report any errors, but when I go to read, no matter what I wrote there, it always returns 0xff bytes. This is true if I use iowrite and ioread on the kernel lands after ioremap the memory name or try to write to userland with a little mmland'ing userland test.

I have done as much research on this topic as I can think of. All I can find for the remap_pfn_range documentation is kernel.org page , and some gmain kernel mailing list archives replace remap_page_range with remap_pfn_range. As for dma_mmap_coherent, I was able to find a little more, including a presentation from linux archives .

Ultimately there must be a difference; there seem to be so many different ways to map kernel memory to user land. I have a specific question: what is the difference between dma_mmap_coherent and remap_pfn_range ?

Modifying , it might be nice to give a general overview of how to map kernel memory in the user area as a whole, describing how the various apis will be used in the mmap kernel driver callback.

+5
source share
1 answer

dma_mmap_coherent () is defined in dma-mapping.h as a wrapper around dma_mmap_attrs (). dma_mmap_attrs () tries to find out if the dma_mmap_ops set is installed associated with the device (struct device * dev) you are working with if it does not call dma_common_mmap (), which ultimately leads to calling remap_pfn_range () after setting the page protection as not cached ( see dma_common_mmap () in dma-mapping.c).

As for the general overview of how memory core memory works with user space, the following is my quick and easy way to mmap'ing DMA buffers from user space:

  • Allocate the buffer through IOCTL and assign a buffer identifier for each buffer with some flags:

     /* A copy-from-user call needs to be done before in the IOCTL */ static int my_ioctl_alloc(struct my_struct *info, struct alloc_info *alloc) { ... info->buf->kvaddr = dma_alloc_coherent(dev, alloc->size, info->buf->phyaddr, GFP_KERNEL); info->buf->buf_id = alloc->buf_id; ... } 
  • Define mmap operating files:

     static const struct file_operations my_fops = { .open = my_open, .close = my_close, .mmap = my_mmap, .unlocked_ioctl = my_ioctl, }; 

    Remember to register the my_fops structure somewhere in your driver validation function.

  • Implement mmap operational files:

      static int my_mmap(struct file *fptr, struct vm_area_struct *vma) { ... desc_id = vma->vm_pgoff; buf = find_buf_by_id(alloc, desc_id); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); ret = remap_pfn_range(vma, vma->vm_start, buf->phyaddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); if (ret) { /* Error Handle */ } return 0; } 

At the same time, your kernel driver should have a minimum for placing mmap buffers as well. Buffer release is an exercise for bonus points!

In the application, you open the () file and get a valid fd file descriptor, call the IOCTL allocation, and set the buffer identifier before copying to the kernel. In mmap you must specify the buffer identifier through the offset parameter:

  mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer_id << PAGE_SHIFT); 

PAGE_SHIFT is the architecture-dependent MACRO macro time fixed in the kernel. Hope this helps.

This is not checkpatch.pl compatible code, and it is not the best practice, but I know how to do it. Comments / improvements / suggestions are welcome!

See Linux Device Drivers - Chapter 15: Map and DMA Mapping for sample tutorials and good reference information for interested readers.

0
source

Source: https://habr.com/ru/post/1239441/


All Articles