arch/arm64/mm/mmu.c

Source file repositories/reference/linux-study-clean/arch/arm64/mm/mmu.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/mm/mmu.c
Extension
.c
Size
63535 bytes
Lines
2373
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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

core_initcall(map_entry_trampoline);
#endif

/*
 * Declare the VMA areas for the kernel
 */
static void __init declare_kernel_vmas(void)
{
	static struct vm_struct vmlinux_seg[KERNEL_SEGMENT_COUNT];

	declare_vma(&vmlinux_seg[0], _text, _etext, VM_NO_GUARD);
	declare_vma(&vmlinux_seg[1], __start_rodata, __inittext_begin, VM_NO_GUARD);
	declare_vma(&vmlinux_seg[2], __inittext_begin, __inittext_end, VM_NO_GUARD);
	declare_vma(&vmlinux_seg[3], __initdata_begin, __initdata_end, VM_NO_GUARD);
	declare_vma(&vmlinux_seg[4], _data, _end, 0);
}

void __pi_map_range(phys_addr_t *pte, u64 start, u64 end, phys_addr_t pa,
		    pgprot_t prot, int level, pte_t *tbl, bool may_use_cont,
		    u64 va_offset);

static u8 idmap_ptes[IDMAP_LEVELS - 1][PAGE_SIZE] __aligned(PAGE_SIZE) __ro_after_init,
	  kpti_bbml2_ptes[IDMAP_LEVELS - 1][PAGE_SIZE] __aligned(PAGE_SIZE) __ro_after_init;

static void __init create_idmap(void)
{
	phys_addr_t start = __pa_symbol(__idmap_text_start);
	phys_addr_t end   = __pa_symbol(__idmap_text_end);
	phys_addr_t ptep  = __pa_symbol(idmap_ptes);

	__pi_map_range(&ptep, start, end, start, PAGE_KERNEL_ROX,
		       IDMAP_ROOT_LEVEL, (pte_t *)idmap_pg_dir, false,
		       __phys_to_virt(ptep) - ptep);

	if (linear_map_requires_bbml2 ||
	    (IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) && !arm64_use_ng_mappings)) {
		phys_addr_t pa = __pa_symbol(&idmap_kpti_bbml2_flag);

		/*
		 * The KPTI G-to-nG conversion code needs a read-write mapping
		 * of its synchronization flag in the ID map. This is also used
		 * when splitting the linear map to ptes if a secondary CPU
		 * doesn't support bbml2.
		 */
		ptep = __pa_symbol(kpti_bbml2_ptes);
		__pi_map_range(&ptep, pa, pa + sizeof(u32), pa, PAGE_KERNEL,
			       IDMAP_ROOT_LEVEL, (pte_t *)idmap_pg_dir, false,
			       __phys_to_virt(ptep) - ptep);
	}
}

void __init paging_init(void)
{
	map_mem();

	memblock_allow_resize();

	create_idmap();
	declare_kernel_vmas();
}

#ifdef CONFIG_MEMORY_HOTPLUG
static void free_hotplug_page_range(struct page *page, size_t size,
				    struct vmem_altmap *altmap)
{
	if (altmap) {
		vmem_altmap_free(altmap, size >> PAGE_SHIFT);
	} else {
		WARN_ON(PageReserved(page));
		__free_pages(page, get_order(size));
	}
}

static void free_hotplug_pgtable_page(struct page *page)
{
	pagetable_dtor(page_ptdesc(page));
	free_hotplug_page_range(page, PAGE_SIZE, NULL);
}

static bool pgtable_range_aligned(unsigned long start, unsigned long end,
				  unsigned long floor, unsigned long ceiling,
				  unsigned long mask)
{
	start &= mask;
	if (start < floor)
		return false;

	if (ceiling) {
		ceiling &= mask;
		if (!ceiling)

Annotation

Implementation Notes