5

I want to map device memory (NIC) to the kernel space memory region by using ioremap_wc(). And then I want to remap memory region from kernel space to user space, and I can use 2 functions for this: vm_insert_page() and remap_pfn_range()

POSIX mmap(3) usually use the second: remap_pfn_range()

What is the difference between vm_insert_page() and remap_pfn_range(), and when do I need to use vm_insert_page() instead of remap_pfn_range()?

Alex
  • 12,578
  • 15
  • 99
  • 195

3 Answers3

4

As their name suggest vm_insert_page() map a single page, while remap_pfn_range() maps a consecutive block of kernel memory. Check the prototypes and comments vm_insert_page, remap_pfn_range

For example, you can use vm_insert_page to map vmalloc aree

do {
    page = vmalloc_to_page(vaddr);
    vm_insert_page(vma, uaddr, page);
    vaddr += PAGE_SIZE;
} while(/* there is something to map */);

it is not possible using remap_pfn_range because it maps only a consecutive block of kernel memory.

Another difference is that with remap_pfn_range you can map not only RAM buffers, but other ranges. With vm_inser_page you can map only RAM buffers

An explanation from Linus

Federico
  • 3,782
  • 32
  • 46
  • Thanks! Does it mean, that I can't use `vm_inser_page` to remap device memory (NIC) region from kernel space to user space, because *"With vm_inser_page you can map only RAM buffers"*? – Alex Dec 15 '14 at 20:57
  • 1
    exactly, you can map only `page` with `vm_insert_page` – Federico Dec 15 '14 at 21:51
  • I'm trying to remap memory allocated using kzalloc_node() using remap_pfn_range() in driver's mmap() function and free the memory using kfree() in close function in vm_operations_struct. However, my system crashes after some time, with crash trace pointing to kmem_cache_alloc. I'm wondering what might be going wrong and how can I debug this further. Please help. – sham1810 Jul 18 '23 at 05:11
4

vm_insert_page() allows drivers to insert individual pages they've allocated into a user vma. The page has to be allocate within the kernel independently. It requires the page be an order-zero allocation obtained for this purpose. It does not put out warnings, and does not require that PG_reserved be set.

Traditionally, this was done with remap_pfn_range() which took an arbitrary page protection parameter. vm_insert_page() doesn't allow that. Your vma protection will have to be set up correctly, which means that if you want a shared writeable mapping, you'd better ask for a shared writeable mapping!

remap_pfn_range() is used for mapping or remapping a group of pages into the memory.

Refer

askb
  • 6,501
  • 30
  • 43
  • Thanks! I.e. *"which means that if you want a shared writeable mapping, you'd better ask for a shared writeable mapping!"* - Does it mean that I must to use `remap_pfn_range()` in my case, to remap device memory (NIC) region from kernel space to user space? – Alex Dec 15 '14 at 20:55
2

In summary:

Use remap_pfn_range when you don't need struct page for the physical page frames. It will also build page table if given memory is reserved memory. Use vm_insert_page for memory that requires struct page for the physical page frame. (Note that there's also vm_insert_pages, which can insert multiple pages into a VMA.)

For direct I/O from this region, use vm_insert_page/vm_insert_pages as they support get_user_page to obtain struct page, which is necessary for subsequent ext4/scatterlist code.

Chen Li
  • 4,824
  • 3
  • 28
  • 55