arch/powerpc/mm/mem.c

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

File Facts

System
Linux kernel
Corpus path
arch/powerpc/mm/mem.c
Extension
.c
Size
11283 bytes
Lines
454
Domain
Architecture Layer
Bucket
arch/powerpc
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

subsys_initcall(add_system_ram_resources);

#ifdef CONFIG_STRICT_DEVMEM
/*
 * devmem_is_allowed(): check to see if /dev/mem access to a certain address
 * is valid. The argument is a physical page number.
 *
 * Access has to be given to non-kernel-ram areas as well, these contain the
 * PCI mmio resources as well as potential bios/acpi data regions.
 */
int devmem_is_allowed(unsigned long pfn)
{
	if (page_is_rtas_user_buf(pfn))
		return 1;
	if (iomem_is_exclusive(PFN_PHYS(pfn)))
		return 0;
	if (!page_is_ram(pfn))
		return 1;
	return 0;
}
#endif /* CONFIG_STRICT_DEVMEM */

/*
 * This is defined in kernel/resource.c but only powerpc needs to export it, for
 * the EHEA driver. Drop this when drivers/net/ethernet/ibm/ehea is removed.
 */
EXPORT_SYMBOL_GPL(walk_system_ram_range);

#ifdef CONFIG_EXECMEM
static struct execmem_info execmem_info __ro_after_init;

#if defined(CONFIG_PPC_8xx) || defined(CONFIG_PPC_BOOK3S_603)
static void prealloc_execmem_pgtable(void)
{
	unsigned long va;

	for (va = ALIGN_DOWN(MODULES_VADDR, PGDIR_SIZE); va < MODULES_END; va += PGDIR_SIZE)
		pte_alloc_kernel(pmd_off_k(va), va);
}
#else
static void prealloc_execmem_pgtable(void) { }
#endif

struct execmem_info __init *execmem_arch_setup(void)
{
	pgprot_t kprobes_prot = strict_module_rwx_enabled() ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC;
	pgprot_t prot = strict_module_rwx_enabled() ? PAGE_KERNEL : PAGE_KERNEL_EXEC;
	unsigned long fallback_start = 0, fallback_end = 0;
	unsigned long start, end;

	/*
	 * BOOK3S_32 and 8xx define MODULES_VADDR for text allocations and
	 * allow allocating data in the entire vmalloc space
	 */
#ifdef MODULES_VADDR
	unsigned long limit = (unsigned long)_etext - SZ_32M;

	/* First try within 32M limit from _etext to avoid branch trampolines */
	if (MODULES_VADDR < PAGE_OFFSET && MODULES_END > limit) {
		start = limit;
		fallback_start = MODULES_VADDR;
		fallback_end = MODULES_END;
	} else {
		start = MODULES_VADDR;
	}

	end = MODULES_END;
#else
	start = VMALLOC_START;
	end = VMALLOC_END;
#endif

	prealloc_execmem_pgtable();

	execmem_info = (struct execmem_info){
		.ranges = {
			[EXECMEM_DEFAULT] = {
				.start	= start,
				.end	= end,
				.pgprot	= prot,
				.alignment = 1,
				.fallback_start	= fallback_start,
				.fallback_end	= fallback_end,
			},
			[EXECMEM_KPROBES] = {
				.start	= VMALLOC_START,
				.end	= VMALLOC_END,
				.pgprot	= kprobes_prot,
				.alignment = 1,
			},

Annotation

Implementation Notes