arch/x86/boot/startup/map_kernel.c

Source file repositories/reference/linux-study-clean/arch/x86/boot/startup/map_kernel.c

File Facts

System
Linux kernel
Corpus path
arch/x86/boot/startup/map_kernel.c
Extension
.c
Size
6684 bytes
Lines
218
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

// SPDX-License-Identifier: GPL-2.0

#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pgtable.h>

#include <asm/init.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/sev.h>

extern pmd_t early_dynamic_pgts[EARLY_DYNAMIC_PAGE_TABLES][PTRS_PER_PMD];
extern unsigned int next_early_pgt;

static inline bool check_la57_support(void)
{
	/*
	 * 5-level paging is detected and enabled at kernel decompression
	 * stage. Only check if it has been enabled there.
	 */
	if (!(native_read_cr4() & X86_CR4_LA57))
		return false;

	__pgtable_l5_enabled	= 1;
	pgdir_shift		= 48;
	ptrs_per_p4d		= 512;

	return true;
}

static unsigned long __init sme_postprocess_startup(struct boot_params *bp,
						    pmdval_t *pmd,
						    unsigned long p2v_offset)
{
	unsigned long paddr, paddr_end;
	int i;

	/* Encrypt the kernel and related (if SME is active) */
	sme_encrypt_kernel(bp);

	/*
	 * Clear the memory encryption mask from the .bss..decrypted section.
	 * The bss section will be memset to zero later in the initialization so
	 * there is no need to zero it after changing the memory encryption
	 * attribute.
	 */
	if (sme_get_me_mask()) {
		paddr = (unsigned long)rip_rel_ptr(__start_bss_decrypted);
		paddr_end = (unsigned long)rip_rel_ptr(__end_bss_decrypted);

		for (; paddr < paddr_end; paddr += PMD_SIZE) {
			/*
			 * On SNP, transition the page to shared in the RMP table so that
			 * it is consistent with the page table attribute change.
			 *
			 * __start_bss_decrypted has a virtual address in the high range
			 * mapping (kernel .text). PVALIDATE, by way of
			 * early_snp_set_memory_shared(), requires a valid virtual
			 * address but the kernel is currently running off of the identity
			 * mapping so use the PA to get a *currently* valid virtual address.
			 */
			early_snp_set_memory_shared(paddr, paddr, PTRS_PER_PMD);

			i = pmd_index(paddr - p2v_offset);
			pmd[i] -= sme_get_me_mask();
		}
	}

	/*
	 * Return the SME encryption mask (if SME is active) to be used as a
	 * modifier for the initial pgdir entry programmed into CR3.
	 */
	return sme_get_me_mask();
}

/*
 * This code is compiled using PIC codegen because it will execute from the
 * early 1:1 mapping of memory, which deviates from the mapping expected by the
 * linker. Due to this deviation, taking the address of a global variable will
 * produce an ambiguous result when using the plain & operator.  Instead,
 * rip_rel_ptr() must be used, which will return the RIP-relative address in
 * the 1:1 mapping of memory. Kernel virtual addresses can be determined by
 * subtracting p2v_offset from the RIP-relative address.
 */
unsigned long __init __startup_64(unsigned long p2v_offset,
				  struct boot_params *bp)
{
	pmd_t (*early_pgts)[PTRS_PER_PMD] = rip_rel_ptr(early_dynamic_pgts);

Annotation

Implementation Notes