vmf_insert_pfn_prot(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… vmf_insert_pfn_prot(9)

Okay so bestie, we're in the Kernel API Manual today and the star of the show is vmf_insert_pfn_prot β€” it lives in section 9, it's iconic, it's giving kernel-internals main character energy. Let's get into it πŸŽ€


✨ NAME ✨

vmf_insert_pfn_prot β€” insert single pfn into user vma with specified pgprot

(Yes that's the whole name. "Insert single pfn into user vma with specified pgprot." Say it with me. Slay.)


🌸 SYNOPSIS 🌸

vm_fault_t vmf_insert_pfn_prot (struct vm_area_struct *vma , unsigned long addr , unsigned long pfn , pgprot_t pgprot );

Four args, one return type, zero chill. Copy it exactly, don't freestyle it πŸ™ˆ


πŸ¦‹ ARGUMENTS πŸ¦‹

  • vma β€” the user vma you're mapping into. That's the destination, bestie.
  • addr β€” the target user address of this page. Where it's going, address-wise.
  • pfn β€” the source kernel pfn. The page you're bringing to the party.
  • pgprot β€” the pgprot flags for the inserted page. The fit, the aesthetic, the whole vibe of the mapping.

πŸ’– DESCRIPTION πŸ’–

So this is exactly like vmf_insert_pfn, except β€” and this is the whole point β€” it lets drivers override pgprot on a per-page basis. Per. Page. Override. Ngl that's kind of a flex πŸ’…

Lowkey important: this only makes sense for IO mappings, and it makes no sense for COW mappings. Fr fr, don't do it.

In general, using multiple vmas is preferable; vmf_insert_pfn_prot should only be used if using multiple VMAs is impractical. Like, it's the emergency backup plan, not the first move ✨

Now, pgprot typically only differs from vma->vm_page_prot when drivers set caching- and encryption bits different than those of vma->vm_page_prot β€” because the caching- or encryption mode may not be known at mmap time. Makes sense, the mmap-time you just didn't know yet πŸ₯²

And this is ok as long as vma->vm_page_prot is not used by the core vm to set caching and encryption bits for those vmas (except for COW pages). This is ensured by the core vm only modifying these page table entries using functions that don't touch caching- or encryption bits, using pte_modify if needed. (See for example mprotect.) πŸ‘‘

Also!! When new page-table entries are created, this is only done using the fault callback, and never using the value of vma->vm_page_prot β€” except for page-table entries that point to anonymous pages as the result of COW. That's the one exception, remember it 🧚


πŸ”₯ CONTEXT πŸ”₯

Process context. May allocate using GFP_KERNEL. So like, you can sleep here, it's fine, that's the vibe check on this one ⭐


🌈 RETURN 🌈

A vm_fault_t value. That's it. That's the return. 🫢


πŸ“ SEE ALSO πŸ“

All of these are from the kernel file ./mm/memory.c β€” go read them, they're the whole friend group:

free_pgd_range(9), free_pgtables(9), __vm_normal_page(9), vm_normal_page(9), vm_normal_folio(9), vm_normal_page_pmd(9), vm_normal_folio_pmd(9), vm_normal_page_pud(9), restore_exclusive_pte(9), cond_install_uffd_wp_ptes(9), zap_vma_for_reaping(9), unmap_vmas(9), zap_vma_range_batched(9), zap_vma_range(9), zap_special_vma_range(9), vm_insert_pages(9), vm_insert_page(9), vm_map_pages(9), vm_map_pages_zero(9), vmf_insert_pfn(9), remap_pfn_range(9), vm_iomap_memory(9), __vmf_anon_prepare(9), finish_mkwrite_fault(9), unmap_mapping_folio(9), unmap_mapping_pages(9), unmap_mapping_range(9), set_pte_range(9), finish_fault(9), mm_account_fault(9), follow_pfnmap_start(9), follow_pfnmap_end(9), generic_access_phys(9), access_remote_vm(9), copy_remote_vm_str(9), folio_zero_user(9)

Periodt. That's the whole list, no cap πŸ”₯


πŸ’œ That's the page, bestie! This one comes from ./mm and it's dated October 2026 β€” write that down, cite it, put it on your fridge πŸŽ€ Bye!! πŸ¦‹

πŸ“¦ where this page comes from