arch/x86/boot/compressed/pgtable_64.c

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

File Facts

System
Linux kernel
Corpus path
arch/x86/boot/compressed/pgtable_64.c
Extension
.c
Size
5874 bytes
Lines
202
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

strncmp(signature, EFI64_LOADER_SIGNATURE, 4)) {
		ebda_start = *(unsigned short *)0x40e << 4;
		bios_start = *(unsigned short *)0x413 << 10;
	}

	if (bios_start < BIOS_START_MIN || bios_start > BIOS_START_MAX)
		bios_start = BIOS_START_MAX;

	if (ebda_start > BIOS_START_MIN && ebda_start < bios_start)
		bios_start = ebda_start;

	bios_start = round_down(bios_start, PAGE_SIZE);

	/* Find the first usable memory region under bios_start. */
	for (i = boot_params_ptr->e820_entries - 1; i >= 0; i--) {
		unsigned long new = bios_start;

		entry = &boot_params_ptr->e820_table[i];

		/* Skip all entries above bios_start. */
		if (bios_start <= entry->addr)
			continue;

		/* Skip non-RAM entries. */
		if (entry->type != E820_TYPE_RAM)
			continue;

		/* Adjust bios_start to the end of the entry if needed. */
		if (bios_start > entry->addr + entry->size)
			new = entry->addr + entry->size;

		/* Keep bios_start page-aligned. */
		new = round_down(new, PAGE_SIZE);

		/* Skip the entry if it's too small. */
		if (new - TRAMPOLINE_32BIT_SIZE < entry->addr)
			continue;

		/* Protect against underflow. */
		if (new - TRAMPOLINE_32BIT_SIZE > bios_start)
			break;

		bios_start = new;
		break;
	}

	/* Place the trampoline just below the end of low memory */
	return bios_start - TRAMPOLINE_32BIT_SIZE;
}

asmlinkage void configure_5level_paging(struct boot_params *bp, void *pgtable)
{
	void (*toggle_la57)(void *cr3);
	bool l5_required = false;

	/* Initialize boot_params. Required for cmdline_find_option_bool(). */
	sanitize_boot_params(bp);
	boot_params_ptr = bp;

	/*
	 * Check if LA57 is desired and supported.
	 *
	 * There are several parts to the check:
	 *   - if user asked to disable 5-level paging: no5lvl in cmdline
	 *   - if the machine supports 5-level paging:
	 *     + CPUID leaf 7 is supported
	 *     + the leaf has the feature bit set
	 */
	if (!cmdline_find_option_bool("no5lvl") &&
	    native_cpuid_eax(0) >= 7 && (native_cpuid_ecx(7) & BIT(16))) {
		l5_required = true;

		/* Initialize variables for 5-level paging */
		__pgtable_l5_enabled = 1;
		pgdir_shift = 48;
		ptrs_per_p4d = 512;
	}

	/*
	 * The trampoline will not be used if the paging mode is already set to
	 * the desired one.
	 */
	if (l5_required == !!(native_read_cr4() & X86_CR4_LA57))
		return;

	trampoline_32bit = (unsigned long *)find_trampoline_placement();

	/* Preserve trampoline memory */
	memcpy(trampoline_save, trampoline_32bit, TRAMPOLINE_32BIT_SIZE);

Annotation

Implementation Notes