linux kernel - How to 'free' pages manually ref counted by get_page() for mmap? -


i mapping multiple physically non-contiguous memory buffers single linear user space address. use vm_insert_page() , get_page(). need use get_page() on allocated pages because first page of given buffer has ref count > 0 , vm_insert_page() needs ref count > 0. supposedly (according post on net) have 'free' pages increment ref count calling get_page() if no longer needed. however, i'm not quite sure how 'free' pages. need keep track of each page struct returned get_page() , call corresponding api free pages during unmapping? not os me automatically. is, after user process exists, ref counts on pages stay unchanged , incremented again on next mmap user space.

my pseudo code this:

     allocate multiple phys non-contiguous memory buffers using calls pci_alloc_consistent()     4k chunks in buffers allocated above          create page struct using virt_to_page(phys_chunk_addr)          // needed because first page of phys buffer          // have ref count > 0 needed vm_insert_page()!          increment page ref count calling get_page()          place page in vma using vm_insert_page()     
suggestions/pointers. dan.

dma-coherent memory might need architecture-specific caching flags, cannot map userspace.

pci_alloc_consistent deprecated. mapping single contiguous memory block, use dma_alloc_coherent , dma_mmap_coherent.


if aren't concerned portability, can avoid using dma_alloc_coherent altogether , use individual pages instead:

  • allocate bunch of pages alloc_page (for pci, need gfp_dma32);
  • get dma address each page dma_map_page;
  • map them user space vm_insert_page.

please note not coherent dma mapping streaming dma mapping. on x86, not matter, on many other architectures, have call dma_sync_* functions @ appropriate time.

for example of in kernel, see drivers/firewire/core-iso.c, core-cdev.c.


if need have multiple large , physically contiguous buffers mapped 1 virtually contiguous area, cannot use dma_mmap_coherent, have hard way:

  1. call dma_alloc_coherent need it;
  2. in mmap implementation, set vm_area_struct->vm_ops;
  3. in vm_operations_struct.fault, call virt_to_page, call get_page, , set vm_fault->page page.

for example, see sound/core/pcm_native.c.


Comments