arch/powerpc/mm/nohash/8xx.c

Source file repositories/reference/linux-study-clean/arch/powerpc/mm/nohash/8xx.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/mm/nohash/8xx.c
Extension
.c
Size
5704 bytes
Lines
223
Domain
Architecture Layer
Bucket
arch/powerpc
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 (psize == MMU_PAGE_8M) {
			if (WARN_ON(!pmd_none(*pmdp) || !pmd_none(*(pmdp + 1))))
				return -EINVAL;

			ptep = early_alloc_pgtable(PTE_FRAG_SIZE);
			pmd_populate_kernel(&init_mm, pmdp, ptep);

			ptep = early_alloc_pgtable(PTE_FRAG_SIZE);
			pmd_populate_kernel(&init_mm, pmdp + 1, ptep);

			ptep = (pte_t *)pmdp;
		} else {
			ptep = early_pte_alloc_kernel(pmdp, va);
			/* The PTE should never be already present */
			if (WARN_ON(pte_present(*ptep) && pgprot_val(prot)))
				return -EINVAL;
		}
	} else {
		if (psize == MMU_PAGE_8M)
			ptep = (pte_t *)pmdp;
		else
			ptep = pte_offset_kernel(pmdp, va);
	}

	if (WARN_ON(!ptep))
		return -ENOMEM;

	set_huge_pte_at(&init_mm, va, ptep,
			arch_make_huge_pte(pfn_pte(pa >> PAGE_SHIFT, prot), shift, 0),
			1UL << shift);

	return 0;
}

/*
 * MMU_init_hw does the chip-specific initialization of the MMU hardware.
 */
void __init MMU_init_hw(void)
{
}

static bool immr_is_mapped __initdata;

void __init mmu_mapin_immr(void)
{
	if (immr_is_mapped)
		return;

	immr_is_mapped = true;

	__early_map_kernel_hugepage(VIRT_IMMR_BASE, PHYS_IMMR_BASE,
				    PAGE_KERNEL_NCG, MMU_PAGE_512K, true);
}

static int mmu_mapin_ram_chunk(unsigned long offset, unsigned long top,
			       pgprot_t prot, bool new)
{
	unsigned long v = PAGE_OFFSET + offset;
	unsigned long p = offset;
	int err = 0;

	WARN_ON(!IS_ALIGNED(offset, SZ_16K) || !IS_ALIGNED(top, SZ_16K));

	for (; p < ALIGN(p, SZ_512K) && p < top && !err; p += SZ_16K, v += SZ_16K)
		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_16K, new);
	for (; p < ALIGN(p, SZ_8M) && p < top && !err; p += SZ_512K, v += SZ_512K)
		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
	for (; p < ALIGN_DOWN(top, SZ_8M) && p < top && !err; p += SZ_8M, v += SZ_8M)
		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_8M, new);
	for (; p < ALIGN_DOWN(top, SZ_512K) && p < top && !err; p += SZ_512K, v += SZ_512K)
		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
	for (; p < ALIGN_DOWN(top, SZ_16K) && p < top && !err; p += SZ_16K, v += SZ_16K)
		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_16K, new);

	if (!new)
		flush_tlb_kernel_range(PAGE_OFFSET + v, PAGE_OFFSET + top);

	return err;
}

unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
	unsigned long etext8 = ALIGN(__pa(_etext), SZ_8M);
	unsigned long sinittext = __pa(_sinittext);
	bool strict_boundary = strict_kernel_rwx_enabled() || debug_pagealloc_enabled_or_kfence();
	unsigned long boundary = strict_boundary ? sinittext : etext8;
	unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M);

	WARN_ON(top < einittext8);

Annotation

Implementation Notes