mmap kernel device driver side

Linux kernel Device Driver MMap implementation Notes

(linux kernel mmap internals)  

While every one knows there are two kinds of drivers char and block drivers,

less known/acknowledged is that fact that there are two kinds of drivers :-)

  1.  memcpy

  2. mmap


memcpy drivers copy each user request data into kernel via copy_from_user which affects performance.

mmap drivers don't do it and hence improve performance.

Here is a very high level explanation of how the stuff works.

The discussion is valid for both LOAD and STORE instructions though only LOAD is referred to.

GOAL (refer legend at the bottom of the page for abbreviations)

A Load instruction in user space LD uvaddr

and

A Load instruction in kernel space LD kvaddr 

should result in the same paddr being put on the Memory BUS


For this to happen

process's user space VMA  and kernel space driver memory 

(from kmalloc or get_free_pages)

should share the same physical pages in main memory.

Typicall the following steps are done.

1.  kernel does kmalloc or get_free_pages to reserve memory (Note that this is not swappable)

     km = kmalloc(size,GFP_ATOMIC);    

2.  Then the PFN (Page Frame Number) of km is found using simple arithmetic by kernel functions

     pfn = virt_to_page(km)
 

3. As the page is accessible form user space also, it may be swapped out. So as to stop it

    SetPageReserved(pfn) 

This should be done for all pfn's which are mmap'ed.

PTE (page table entries) do not have information whether the pfn belongs to user or kernel.

It just has an entry  saying if it  is accessible from  user space.

(So swapper doesn't care if it is the result of kmalloc in kernel. It just sees accessible from user space bit. swapper's are note mmap() aware) 

As this pfn is accessible from user space ,the swapper may think that it can be swapped out.

Hence it is mandatory to lock these pages to stop swapper from swapping them out.


 4. Now in the driver we actually need to set traslation of user space VMA to these kmalloc PFNs as follows

remap_pfn_range( 

 vma,   vma->vm_start,  pfn,  PAGE_SIZE,  ,vma->vm_page_prot);

5. Note that it is important to do SetPageUnReserved() during cleanup or munmap.

 

6. Informally speaking 

mmap() is equivalent to malloc()

munmap() is equivalent to free()

Summary

============


MMU(TLB(uvaddr)) == MMU(TLB(kvaddr) == paddr

Note that In MIPS64 there is no MMU unlike x86 but TLB.

(In x86 TLB is a cache unlike MIPS)

 LEGEND

uvaddr = User Virtual Address (Address used in "LOAD/STORE" instruction)

kvaddr = Kernel Virtual Address (Address used in  "LOAD/STORE" instruction)

paddr = Physical Address put on the Memory Bus (i.e, sent to DRAM controller)

VMA = Virtual Memory Areas  (Virtual Memory Segments like in the 4GB address space for 32b processor)

PFN = Page Frame Number (RAM is divided into Frames of usually 4KB each)


Keywords

mmap, kernel mmap, linux kernel mmap, linux device driver mmap, mmap fundamentals

 

OLD KEYWORDS

mmap (for linux kernel/device driver enthusiasts)