arch/powerpc/mm/book3s64/radix_pgtable.c

Source file repositories/reference/linux-study-clean/arch/powerpc/mm/book3s64/radix_pgtable.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/mm/book3s64/radix_pgtable.c
Extension
.c
Size
42118 bytes
Lines
1698
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 (pud_leaf(*pudp)) {
			ptep = (pte_t *)pudp;
			goto update_the_pte;
		}
		pmdp = pmd_alloc(&init_mm, pudp, idx);
		if (!pmdp)
			continue;
		if (pmd_leaf(*pmdp)) {
			ptep = pmdp_ptep(pmdp);
			goto update_the_pte;
		}
		ptep = pte_alloc_kernel(pmdp, idx);
		if (!ptep)
			continue;
update_the_pte:
		radix__pte_update(&init_mm, idx, ptep, clear, 0, 0);
	}

	radix__flush_tlb_kernel_range(start, end);
}

void radix__mark_rodata_ro(void)
{
	unsigned long start, end;

	start = (unsigned long)_stext;
	end = (unsigned long)__end_rodata;

	radix__change_memory_range(start, end, _PAGE_WRITE);

	for (start = PAGE_OFFSET; start < (unsigned long)_stext; start += PAGE_SIZE) {
		end = start + PAGE_SIZE;
		if (overlaps_interrupt_vector_text(start, end))
			radix__change_memory_range(start, end, _PAGE_WRITE);
		else
			break;
	}
}

void radix__mark_initmem_nx(void)
{
	unsigned long start = (unsigned long)__init_begin;
	unsigned long end = (unsigned long)__init_end;

	radix__change_memory_range(start, end, _PAGE_EXEC);
}
#endif /* CONFIG_STRICT_KERNEL_RWX */

static inline void __meminit
print_mapping(unsigned long start, unsigned long end, unsigned long size, bool exec)
{
	char buf[10];

	if (end <= start)
		return;

	string_get_size(size, 1, STRING_UNITS_2, buf, sizeof(buf));

	pr_info("Mapped 0x%016lx-0x%016lx with %s pages%s\n", start, end, buf,
		exec ? " (exec)" : "");
}

static unsigned long next_boundary(unsigned long addr, unsigned long end)
{
#ifdef CONFIG_STRICT_KERNEL_RWX
	unsigned long stext_phys;

	stext_phys = __pa_symbol(_stext);

	// Relocatable kernel running at non-zero real address
	if (stext_phys != 0) {
		// The end of interrupts code at zero is a rodata boundary
		unsigned long end_intr = __pa_symbol(__end_interrupts) - stext_phys;
		if (addr < end_intr)
			return end_intr;

		// Start of relocated kernel text is a rodata boundary
		if (addr < stext_phys)
			return stext_phys;
	}

	if (addr < __pa_symbol(__srwx_boundary))
		return __pa_symbol(__srwx_boundary);
#endif
	return end;
}

static int __meminit create_physical_mapping(unsigned long start,
					     unsigned long end,
					     int nid, pgprot_t _prot,

Annotation

Implementation Notes