arch/powerpc/mm/nohash/kaslr_booke.c

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

File Facts

System
Linux kernel
Corpus path
arch/powerpc/mm/nohash/kaslr_booke.c
Extension
.c
Size
9779 bytes
Lines
396
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

struct regions {
	unsigned long pa_start;
	unsigned long pa_end;
	unsigned long kernel_size;
	unsigned long dtb_start;
	unsigned long dtb_end;
	unsigned long initrd_start;
	unsigned long initrd_end;
	unsigned long crash_start;
	unsigned long crash_end;
	int reserved_mem;
	int reserved_mem_addr_cells;
	int reserved_mem_size_cells;
};

struct regions __initdata regions;

static __init void kaslr_get_cmdline(void *fdt)
{
	early_init_dt_scan_chosen(boot_command_line);
}

static unsigned long __init rotate_xor(unsigned long hash, const void *area,
				       size_t size)
{
	size_t i;
	const unsigned long *ptr = area;

	for (i = 0; i < size / sizeof(hash); i++) {
		/* Rotate by odd number of bits and XOR. */
		hash = (hash << ((sizeof(hash) * 8) - 7)) | (hash >> 7);
		hash ^= ptr[i];
	}

	return hash;
}

/* Attempt to create a simple starting entropy. This can make it defferent for
 * every build but it is still not enough. Stronger entropy should
 * be added to make it change for every boot.
 */
static unsigned long __init get_boot_seed(void *fdt)
{
	unsigned long hash = 0;

	/* build-specific string for starting entropy. */
	hash = rotate_xor(hash, linux_banner, strlen(linux_banner));
	hash = rotate_xor(hash, fdt, fdt_totalsize(fdt));

	return hash;
}

static __init u64 get_kaslr_seed(void *fdt)
{
	int node, len;
	fdt64_t *prop;
	u64 ret;

	node = fdt_path_offset(fdt, "/chosen");
	if (node < 0)
		return 0;

	prop = fdt_getprop_w(fdt, node, "kaslr-seed", &len);
	if (!prop || len != sizeof(u64))
		return 0;

	ret = fdt64_to_cpu(*prop);
	*prop = 0;
	return ret;
}

static __init bool regions_overlap(u32 s1, u32 e1, u32 s2, u32 e2)
{
	return e1 >= s2 && e2 >= s1;
}

static __init bool overlaps_reserved_region(const void *fdt, u32 start,
					    u32 end)
{
	int subnode, len, i;
	u64 base, size;

	/* check for overlap with /memreserve/ entries */
	for (i = 0; i < fdt_num_mem_rsv(fdt); i++) {
		if (fdt_get_mem_rsv(fdt, i, &base, &size) < 0)
			continue;
		if (regions_overlap(start, end, base, base + size))
			return true;
	}

Annotation

Implementation Notes