arch/x86/boot/compressed/kaslr.c

Source file repositories/reference/linux-study-clean/arch/x86/boot/compressed/kaslr.c

File Facts

System
Linux kernel
Corpus path
arch/x86/boot/compressed/kaslr.c
Extension
.c
Size
24859 bytes
Lines
910
Domain
Architecture Layer
Bucket
arch/x86
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 slot_area {
	u64 addr;
	unsigned long num;
};

#define MAX_SLOT_AREA 100

static struct slot_area slot_areas[MAX_SLOT_AREA];
static unsigned int slot_area_index;
static unsigned long slot_max;

static void store_slot_info(struct mem_vector *region, unsigned long image_size)
{
	struct slot_area slot_area;

	if (slot_area_index == MAX_SLOT_AREA)
		return;

	slot_area.addr = region->start;
	slot_area.num = 1 + (region->size - image_size) / CONFIG_PHYSICAL_ALIGN;

	slot_areas[slot_area_index++] = slot_area;
	slot_max += slot_area.num;
}

/*
 * Skip as many 1GB huge pages as possible in the passed region
 * according to the number which users specified:
 */
static void
process_gb_huge_pages(struct mem_vector *region, unsigned long image_size)
{
	u64 pud_start, pud_end;
	unsigned long gb_huge_pages;
	struct mem_vector tmp;

	if (!IS_ENABLED(CONFIG_X86_64) || !max_gb_huge_pages) {
		store_slot_info(region, image_size);
		return;
	}

	/* Are there any 1GB pages in the region? */
	pud_start = ALIGN(region->start, PUD_SIZE);
	pud_end = ALIGN_DOWN(region->start + region->size, PUD_SIZE);

	/* No good 1GB huge pages found: */
	if (pud_start >= pud_end) {
		store_slot_info(region, image_size);
		return;
	}

	/* Check if the head part of the region is usable. */
	if (pud_start >= region->start + image_size) {
		tmp.start = region->start;
		tmp.size = pud_start - region->start;
		store_slot_info(&tmp, image_size);
	}

	/* Skip the good 1GB pages. */
	gb_huge_pages = (pud_end - pud_start) >> PUD_SHIFT;
	if (gb_huge_pages > max_gb_huge_pages) {
		pud_end = pud_start + (max_gb_huge_pages << PUD_SHIFT);
		max_gb_huge_pages = 0;
	} else {
		max_gb_huge_pages -= gb_huge_pages;
	}

	/* Check if the tail part of the region is usable. */
	if (region->start + region->size >= pud_end + image_size) {
		tmp.start = pud_end;
		tmp.size = region->start + region->size - pud_end;
		store_slot_info(&tmp, image_size);
	}
}

static u64 slots_fetch_random(void)
{
	unsigned long slot;
	unsigned int i;

	/* Handle case of no slots stored. */
	if (slot_max == 0)
		return 0;

	slot = kaslr_get_random_long("Physical") % slot_max;

	for (i = 0; i < slot_area_index; i++) {
		if (slot >= slot_areas[i].num) {
			slot -= slot_areas[i].num;
			continue;

Annotation

Implementation Notes