What is the difference between vm_insert_page() and remap_pfn_range()?
Asked Answered
B

3

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()?

Bedford answered 14/12, 2014 at 9:44 Comment(0)
B
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

Billiebilling answered 14/12, 2014 at 21:29 Comment(3)
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"?Bedford
exactly, you can map only page with vm_insert_pageBilliebilling
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.Bronco
H
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

Hymnal answered 15/12, 2014 at 4:9 Comment(1)
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?Bedford
O
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.

Opalina answered 19/7, 2022 at 7:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.