mm/pgtable-generic.c
Source file repositories/reference/linux-study-clean/mm/pgtable-generic.c
File Facts
- System
- Linux kernel
- Corpus path
mm/pgtable-generic.c- Extension
.c- Size
- 13533 bytes
- Lines
- 450
- Domain
- Core OS
- Bucket
- Memory Management
- Inferred role
- Core OS: implementation source
- Status
- source implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/pagemap.hlinux/hugetlb.hlinux/pgtable.hlinux/swap.hlinux/swapops.hlinux/mm_inline.hlinux/iommu.hlinux/pgalloc.hasm/tlb.h
Detected Declarations
function Copyrightfunction p4d_clear_badfunction pud_clear_badfunction pmd_clear_badfunction flagsfunction ptep_clear_flush_youngfunction ptep_clear_flushfunction pmdp_set_access_flagsfunction pmdp_clear_flush_youngfunction pmdp_huge_clear_flushfunction pudp_huge_clear_flushfunction pgtable_trans_huge_depositfunction pgtable_trans_huge_withdrawfunction pmdp_invalidatefunction pmdp_invalidate_adfunction pmdp_collapse_flushfunction pte_free_nowfunction pte_free_deferfunction __pte_offset_mapfunction pmdp_get_lockless_endfunction pmdp_get_lockless_startfunction pmdp_get_lockless_endfunction pte_samefunction kernel_pgtable_work_funcfunction pagetable_free_kernel
Annotated Snippet
static unsigned long pmdp_get_lockless_start(void) { return 0; }
static void pmdp_get_lockless_end(unsigned long irqflags) { }
#endif
pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp)
{
unsigned long irqflags;
pmd_t pmdval;
rcu_read_lock();
irqflags = pmdp_get_lockless_start();
pmdval = pmdp_get_lockless(pmd);
pmdp_get_lockless_end(irqflags);
if (pmdvalp)
*pmdvalp = pmdval;
if (unlikely(pmd_none(pmdval) || !pmd_present(pmdval)))
goto nomap;
if (unlikely(pmd_trans_huge(pmdval)))
goto nomap;
if (unlikely(pmd_bad(pmdval))) {
pmd_clear_bad(pmd);
goto nomap;
}
return __pte_map(&pmdval, addr);
nomap:
rcu_read_unlock();
return NULL;
}
pte_t *pte_offset_map_ro_nolock(struct mm_struct *mm, pmd_t *pmd,
unsigned long addr, spinlock_t **ptlp)
{
pmd_t pmdval;
pte_t *pte;
pte = __pte_offset_map(pmd, addr, &pmdval);
if (likely(pte))
*ptlp = pte_lockptr(mm, &pmdval);
return pte;
}
pte_t *pte_offset_map_rw_nolock(struct mm_struct *mm, pmd_t *pmd,
unsigned long addr, pmd_t *pmdvalp,
spinlock_t **ptlp)
{
pte_t *pte;
VM_WARN_ON_ONCE(!pmdvalp);
pte = __pte_offset_map(pmd, addr, pmdvalp);
if (likely(pte))
*ptlp = pte_lockptr(mm, pmdvalp);
return pte;
}
/*
* pte_offset_map_lock(mm, pmd, addr, ptlp) is usually called with the pmd
* pointer for addr, reached by walking down the mm's pgd, p4d, pud for addr:
* either while holding mmap_lock or vma lock for read or for write; or in
* truncate or rmap context, while holding file's i_mmap_lock or anon_vma lock
* for read (or for write). In a few cases, it may be used with pmd pointing to
* a pmd_t already copied to or constructed on the stack.
*
* When successful, it returns the pte pointer for addr, with its page table
* kmapped if necessary (when CONFIG_HIGHPTE), and locked against concurrent
* modification by software, with a pointer to that spinlock in ptlp (in some
* configs mm->page_table_lock, in SPLIT_PTLOCK configs a spinlock in table's
* struct page). pte_unmap_unlock(pte, ptl) to unlock and unmap afterwards.
*
* But it is unsuccessful, returning NULL with *ptlp unchanged, if there is no
* page table at *pmd: if, for example, the page table has just been removed,
* or replaced by the huge pmd of a THP. (When successful, *pmd is rechecked
* after acquiring the ptlock, and retried internally if it changed: so that a
* page table can be safely removed or replaced by THP while holding its lock.)
*
* pte_offset_map(pmd, addr), and its internal helper __pte_offset_map() above,
* just returns the pte pointer for addr, its page table kmapped if necessary;
* or NULL if there is no page table at *pmd. It does not attempt to lock the
* page table, so cannot normally be used when the page table is to be updated,
* or when entries read must be stable. But it does take rcu_read_lock(): so
* that even when page table is racily removed, it remains a valid though empty
* and disconnected table. Until pte_unmap(pte) unmaps and rcu_read_unlock()s
* afterwards.
*
* pte_offset_map_ro_nolock(mm, pmd, addr, ptlp), above, is like pte_offset_map();
* but when successful, it also outputs a pointer to the spinlock in ptlp - as
* pte_offset_map_lock() does, but in this case without locking it. This helps
* the caller to avoid a later pte_lockptr(mm, *pmd), which might by that time
* act on a changed *pmd: pte_offset_map_ro_nolock() provides the correct spinlock
* pointer for the page table that it returns. Even after grabbing the spinlock,
Annotation
- Immediate include surface: `linux/pagemap.h`, `linux/hugetlb.h`, `linux/pgtable.h`, `linux/swap.h`, `linux/swapops.h`, `linux/mm_inline.h`, `linux/iommu.h`, `linux/pgalloc.h`.
- Detected declarations: `function Copyright`, `function p4d_clear_bad`, `function pud_clear_bad`, `function pmd_clear_bad`, `function flags`, `function ptep_clear_flush_young`, `function ptep_clear_flush`, `function pmdp_set_access_flags`, `function pmdp_clear_flush_young`, `function pmdp_huge_clear_flush`.
- Atlas domain: Core OS / Memory Management.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.