arch/riscv/mm/hugetlbpage.c

Source file repositories/reference/linux-study-clean/arch/riscv/mm/hugetlbpage.c

File Facts

System
Linux kernel
Corpus path
arch/riscv/mm/hugetlbpage.c
Extension
.c
Size
9650 bytes
Lines
458
Domain
Architecture Layer
Bucket
arch/riscv
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (napot_cont_size(order) == sz) {
			pte = pte_alloc_huge(mm, pmd, addr & napot_cont_mask(order));
			break;
		}
	}

out:
	if (pte) {
		pte_t pteval = ptep_get_lockless(pte);

		WARN_ON_ONCE(pte_present(pteval) && !pte_huge(pteval));
	}
	return pte;
}

pte_t *huge_pte_offset(struct mm_struct *mm,
		       unsigned long addr,
		       unsigned long sz)
{
	unsigned long order;
	pte_t *pte = NULL;
	pgd_t *pgd;
	p4d_t *p4d;
	pud_t *pud;
	pmd_t *pmd;

	pgd = pgd_offset(mm, addr);
	if (!pgd_present(pgdp_get(pgd)))
		return NULL;

	p4d = p4d_offset(pgd, addr);
	if (!p4d_present(p4dp_get(p4d)))
		return NULL;

	pud = pud_offset(p4d, addr);
	if (sz == PUD_SIZE)
		/* must be pud huge, non-present or none */
		return (pte_t *)pud;

	if (!pud_present(pudp_get(pud)))
		return NULL;

	pmd = pmd_offset(pud, addr);
	if (sz == PMD_SIZE)
		/* must be pmd huge, non-present or none */
		return (pte_t *)pmd;

	if (!pmd_present(pmdp_get(pmd)))
		return NULL;

	for_each_napot_order(order) {
		if (napot_cont_size(order) == sz) {
			pte = pte_offset_huge(pmd, addr & napot_cont_mask(order));
			break;
		}
	}
	return pte;
}

unsigned long hugetlb_mask_last_page(struct hstate *h)
{
	unsigned long hp_size = huge_page_size(h);

	switch (hp_size) {
#ifndef __PAGETABLE_PMD_FOLDED
	case PUD_SIZE:
		return P4D_SIZE - PUD_SIZE;
#endif
	case PMD_SIZE:
		return PUD_SIZE - PMD_SIZE;
	case napot_cont_size(NAPOT_CONT64KB_ORDER):
		return PMD_SIZE - napot_cont_size(NAPOT_CONT64KB_ORDER);
	default:
		break;
	}

	return 0UL;
}

static pte_t get_clear_contig(struct mm_struct *mm,
			      unsigned long addr,
			      pte_t *ptep,
			      unsigned long ncontig)
{
	pte_t pte, tmp_pte;
	bool present;

	pte = ptep_get_and_clear(mm, addr, ptep);
	present = pte_present(pte);
	while (--ncontig) {

Annotation

Implementation Notes