make_device_exclusive(9)
π make_device_exclusive(9) β from the Kernel API Manual, bestie
okay so you opened make_device_exclusive(9) and you're like "what is this even doing" β don't panic, I got you. This is the one that marks a page for exclusive use by a device. very demure, very kernel. π
β¨ NAME β¨
make_device_exclusive β mark a page for exclusive use by a device
π¦ SYNOPSIS π¦
struct page * make_device_exclusive (struct mm_struct *mm , unsigned
long addr , void *owner , struct folio **foliop );
πΈ ARGUMENTS πΈ
mmβ themm_structof the target process, aka whose address space we're messing withaddrβ the virtual address you want to mark for exclusive device accessownerβ this gets passed along to theMMU_NOTIFY_EXCLUSIVErange notifier so it can do its filtering thingfoliopβ the folio pointer lands in here on success. that's the whole point, bestie π«Ά
π DESCRIPTION π
so here's the plot: this function looks up the page mapped at the address you gave it, grabs a folio reference, locks that folio, and then replaces the PTE with a special device-exclusive PFN swap entry β which is the fancy way of saying access through the process page tables is now blocked. π₯ and it returns with the folio locked and referenced, so you better treat it right.
on fault, those device-exclusive entries get swapped back to the original PTE under folio lock, and this happens after calling MMU notifiers. the way that works is honestly iconic.
now, important stuff, don't skip:
- only anonymous non-hugetlb folios are supported π€
- the VMA must have write permissions, so we can fault in the anonymous page writable in order to mark it exclusive
- the caller must hold the
mmap_lockin read mode
a driver using this to program access from a device has to use an mmu notifier critical section to hold a device specific lock during programming. once programming is complete it should drop the folio lock and reference, and after that point CPU access to the page will revoke the exclusive access. periodt. π
π NOTES π
- this function always operates on individual PTEs mapping individual pages. PMD-sized THPs are first remapped to be mapped by PTEs before the conversion happens on a single PTE corresponding to
addr. so like, no skipping steps π - while concurrent access through the process page tables is prevented, concurrent access through other page references (e.g., earlier GUP invocation) is not handled and not supported. ngl, read that one twice π
- device-exclusive entries are considered "clean" and "old" by core-mm. device drivers must update the folio state when informed by MMU notifiers. no cap, that's on you π§
β RETURN β
pointer to the mapped page on success, otherwise a negative error. simple as that π
π SEE ALSO π
kernel file ./mm/rmap.c and honestly a whole friend group: __anon_vma_prepare(9), anon_vma_clone(9), unlink_anon_vmas(9), page_address_in_vma(9), folio_referenced(9), mapping_wrprotect_range(9), pfn_mkclean_range(9), folio_move_anon_rmap(9), __folio_set_anon(9), __page_check_anon_rmap(9), folio_add_anon_rmap_ptes(9), folio_add_anon_rmap_pmd(9), folio_add_new_anon_rmap(9), folio_add_file_rmap_ptes(9), folio_add_file_rmap_pmd(9), folio_add_file_rmap_pud(9), folio_remove_rmap_ptes(9), folio_remove_rmap_pmd(9), folio_remove_rmap_pud(9), try_to_unmap(9), try_to_migrate(9), __rmap_walk_file(9)
and that's the whole page, bestie π this lil' entry lives in ./mm and it's dated October 2026 β the footer even insists on repeating make_device_exclusive(9) at you, which is so extra of it. slay. β¨π¦π
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms