mm/hugetlb.c

Source file repositories/reference/linux-study-clean/mm/hugetlb.c

File Facts

System
Linux kernel
Corpus path
mm/hugetlb.c
Extension
.c
Size
210300 bytes
Lines
7322
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

* handle_mm_fault() to try to instantiate regular-sized pages in the
 * hugepage VMA.  do_page_fault() is supposed to trap this, so BUG is we get
 * this far.
 */
static vm_fault_t hugetlb_vm_op_fault(struct vm_fault *vmf)
{
	BUG();
	return 0;
}

#ifdef CONFIG_USERFAULTFD
static bool hugetlb_can_userfault(struct vm_area_struct *vma,
				  vm_flags_t vm_flags)
{
	return true;
}

static const struct vm_uffd_ops hugetlb_uffd_ops = {
	.can_userfault = hugetlb_can_userfault,
};
#endif

/*
 * When a new function is introduced to vm_operations_struct and added
 * to hugetlb_vm_ops, please consider adding the function to shm_vm_ops.
 * This is because under System V memory model, mappings created via
 * shmget/shmat with "huge page" specified are backed by hugetlbfs files,
 * their original vm_ops are overwritten with shm_vm_ops.
 */
const struct vm_operations_struct hugetlb_vm_ops = {
	.fault = hugetlb_vm_op_fault,
	.open = hugetlb_vm_op_open,
	.close = hugetlb_vm_op_close,
	.may_split = hugetlb_vm_op_split,
	.pagesize = hugetlb_vm_op_pagesize,
#ifdef CONFIG_USERFAULTFD
	.uffd_ops = &hugetlb_uffd_ops,
#endif
};

static pte_t make_huge_pte(struct vm_area_struct *vma, struct folio *folio,
		bool try_mkwrite)
{
	pte_t entry = folio_mk_pte(folio, vma->vm_page_prot);
	unsigned int shift = huge_page_shift(hstate_vma(vma));

	if (try_mkwrite && (vma->vm_flags & VM_WRITE)) {
		entry = pte_mkwrite_novma(pte_mkdirty(entry));
	} else {
		entry = pte_wrprotect(entry);
	}
	entry = pte_mkyoung(entry);
	entry = arch_make_huge_pte(entry, shift, vma->vm_flags);

	return entry;
}

static void set_huge_ptep_writable(struct vm_area_struct *vma,
				   unsigned long address, pte_t *ptep)
{
	pte_t entry;

	entry = huge_pte_mkwrite(huge_pte_mkdirty(huge_ptep_get(vma->vm_mm, address, ptep)));
	if (huge_ptep_set_access_flags(vma, address, ptep, entry, 1))
		update_mmu_cache(vma, address, ptep);
}

static void set_huge_ptep_maybe_writable(struct vm_area_struct *vma,
					 unsigned long address, pte_t *ptep)
{
	if (vma->vm_flags & VM_WRITE)
		set_huge_ptep_writable(vma, address, ptep);
}

static void
hugetlb_install_folio(struct vm_area_struct *vma, pte_t *ptep, unsigned long addr,
		      struct folio *new_folio, pte_t old, unsigned long sz)
{
	pte_t newpte = make_huge_pte(vma, new_folio, true);

	__folio_mark_uptodate(new_folio);
	hugetlb_add_new_anon_rmap(new_folio, vma, addr);
	if (userfaultfd_wp(vma) && huge_pte_uffd_wp(old))
		newpte = huge_pte_mkuffd_wp(newpte);
	set_huge_pte_at(vma->vm_mm, addr, ptep, newpte, sz);
	hugetlb_count_add(pages_per_huge_page(hstate_vma(vma)), vma->vm_mm);
	folio_set_hugetlb_migratable(new_folio);
}

int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,

Annotation

Implementation Notes