mm/huge_memory.c

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

File Facts

System
Linux kernel
Corpus path
mm/huge_memory.c
Extension
.c
Size
138782 bytes
Lines
5019
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations split_huge_pages_fops = {
	.owner	 = THIS_MODULE,
	.write	 = split_huge_pages_write,
};

static int __init split_huge_pages_debugfs(void)
{
	debugfs_create_file("split_huge_pages", 0200, NULL, NULL,
			    &split_huge_pages_fops);
	return 0;
}
late_initcall(split_huge_pages_debugfs);
#endif

#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
int set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
		struct page *page)
{
	struct folio *folio = page_folio(page);
	struct vm_area_struct *vma = pvmw->vma;
	struct mm_struct *mm = vma->vm_mm;
	unsigned long address = pvmw->address;
	bool anon_exclusive, present, writable, softdirty, uffd_wp;
	pmd_t pmdval;
	swp_entry_t entry;
	pmd_t pmdswp;

	if (!(pvmw->pmd && !pvmw->pte))
		return 0;

	present = pmd_present(*pvmw->pmd);
	if (likely(present)) {
		flush_cache_range(vma, address, address + HPAGE_PMD_SIZE);

		pmdval = pmdp_invalidate(vma, address, pvmw->pmd);

		writable = pmd_write(pmdval);
		softdirty = pmd_soft_dirty(pmdval);
		uffd_wp = pmd_uffd_wp(pmdval);
	} else {
		softleaf_t old_entry;

		pmdval = pmdp_huge_get_and_clear(vma->vm_mm, address, pvmw->pmd);
		old_entry = softleaf_from_pmd(pmdval);

		writable = softleaf_is_device_private_write(old_entry);
		softdirty = pmd_swp_soft_dirty(pmdval);
		uffd_wp = pmd_swp_uffd_wp(pmdval);
	}

	/* See folio_try_share_anon_rmap_pmd(): invalidate PMD first. */
	anon_exclusive = folio_test_anon(folio) && PageAnonExclusive(page);
	if (anon_exclusive && folio_try_share_anon_rmap_pmd(folio, page)) {
		set_pmd_at(mm, address, pvmw->pmd, pmdval);
		return -EBUSY;
	}

	/* Determine type of migration entry. */
	if (writable)
		entry = make_writable_migration_entry(page_to_pfn(page));
	else if (anon_exclusive)
		entry = make_readable_exclusive_migration_entry(page_to_pfn(page));
	else
		entry = make_readable_migration_entry(page_to_pfn(page));

	/* Set A/D bits as necessary. */
	if (present && pmd_young(pmdval))
		entry = make_migration_entry_young(entry);
	if (present && pmd_dirty(pmdval)) {
		folio_mark_dirty(folio);
		entry = make_migration_entry_dirty(entry);
	}

	/* Set PMD. */
	pmdswp = swp_entry_to_pmd(entry);
	if (softdirty)
		pmdswp = pmd_swp_mksoft_dirty(pmdswp);
	if (uffd_wp)
		pmdswp = pmd_swp_mkuffd_wp(pmdswp);
	set_pmd_at(mm, address, pvmw->pmd, pmdswp);

	/* Migration entry installed: cleanup rmap, folio. */
	folio_remove_rmap_pmd(folio, page, vma);
	folio_put(folio);
	trace_set_migration_pmd(address, pmd_val(pmdswp));

	return 0;
}

void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)

Annotation

Implementation Notes