1327 lines · 33.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  Copyright (C) 1995  Linus Torvalds * * This file contains the setup_arch() code, which handles the architecture-dependent * parts of early kernel initialization. */#include <linux/acpi.h>#include <linux/bootconfig.h>#include <linux/console.h>#include <linux/cpu.h>#include <linux/crash_dump.h>#include <linux/dma-map-ops.h>#include <linux/efi.h>#include <linux/hugetlb.h>#include <linux/ima.h>#include <linux/init_ohci1394_dma.h>#include <linux/initrd.h>#include <linux/iscsi_ibft.h>#include <linux/kexec_handover.h>#include <linux/memblock.h>#include <linux/panic_notifier.h>#include <linux/pci.h>#include <linux/random.h>#include <linux/root_dev.h>#include <linux/static_call.h>#include <linux/sysfb.h>#include <linux/swiotlb.h>#include <linux/tboot.h>#include <linux/usb/xhci-dbgp.h>#include <linux/vmalloc.h> #include <uapi/linux/mount.h> #include <xen/xen.h> #include <asm/apic.h>#include <asm/bios_ebda.h>#include <asm/bugs.h>#include <asm/cacheinfo.h>#include <asm/coco.h>#include <asm/cpu.h>#include <asm/efi.h>#include <asm/gart.h>#include <asm/hypervisor.h>#include <asm/io_apic.h>#include <asm/kasan.h>#include <asm/kaslr.h>#include <asm/mce.h>#include <asm/memtype.h>#include <asm/mtrr.h>#include <asm/nmi.h>#include <asm/numa.h>#include <asm/olpc_ofw.h>#include <asm/pci-direct.h>#include <asm/prom.h>#include <asm/proto.h>#include <asm/realmode.h>#include <asm/thermal.h>#include <asm/unwind.h>#include <asm/vsyscall.h> /* * max_low_pfn_mapped: highest directly mapped pfn < 4 GB * max_pfn_mapped:     highest directly mapped pfn > 4 GB * * The direct mapping only covers E820_TYPE_RAM regions, so the ranges and gaps are * represented by pfn_mapped[]. */unsigned long max_low_pfn_mapped;unsigned long max_pfn_mapped; #ifdef CONFIG_DMIRESERVE_BRK(dmi_alloc, 65536);#endif  unsigned long _brk_start = (unsigned long)__brk_base;unsigned long _brk_end   = (unsigned long)__brk_base; struct boot_params boot_params; /* * These are the four main kernel memory regions, we put them into * the resource tree so that kdump tools and other debugging tools * recover it: */ static struct resource rodata_resource = {	.name	= "Kernel rodata",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM}; static struct resource data_resource = {	.name	= "Kernel data",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM}; static struct resource code_resource = {	.name	= "Kernel code",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM}; static struct resource bss_resource = {	.name	= "Kernel bss",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM};  #ifdef CONFIG_X86_32/* CPU data as detected by the assembly code in head_32.S */struct cpuinfo_x86 new_cpu_data; struct apm_info apm_info;EXPORT_SYMBOL(apm_info); #if IS_ENABLED(CONFIG_X86_SPEEDSTEP_SMI)struct ist_info ist_info;EXPORT_SYMBOL(ist_info);#elsestruct ist_info ist_info;#endif #endif struct cpuinfo_x86 boot_cpu_data __read_mostly;EXPORT_SYMBOL(boot_cpu_data);SYM_PIC_ALIAS(boot_cpu_data); #if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)__visible unsigned long mmu_cr4_features __ro_after_init;#else__visible unsigned long mmu_cr4_features __ro_after_init = X86_CR4_PAE;#endif #ifdef CONFIG_IMAstatic phys_addr_t ima_kexec_buffer_phys;static size_t ima_kexec_buffer_size;#endif /* Boot loader ID and version as integers, for the benefit of proc_dointvec */int bootloader_type, bootloader_version; static const struct ctl_table x86_sysctl_table[] = {	{		.procname       = "unknown_nmi_panic",		.data           = &unknown_nmi_panic,		.maxlen         = sizeof(int),		.mode           = 0644,		.proc_handler   = proc_dointvec,	},	{		.procname	= "panic_on_unrecovered_nmi",		.data		= &panic_on_unrecovered_nmi,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= proc_dointvec,	},	{		.procname	= "panic_on_io_nmi",		.data		= &panic_on_io_nmi,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= proc_dointvec,	},	{		.procname	= "bootloader_type",		.data		= &bootloader_type,		.maxlen		= sizeof(int),		.mode		= 0444,		.proc_handler	= proc_dointvec,	},	{		.procname	= "bootloader_version",		.data		= &bootloader_version,		.maxlen		= sizeof(int),		.mode		= 0444,		.proc_handler	= proc_dointvec,	},	{		.procname	= "io_delay_type",		.data		= &io_delay_type,		.maxlen		= sizeof(int),		.mode		= 0644,		.proc_handler	= proc_dointvec,	},#if defined(CONFIG_ACPI_SLEEP)	{		.procname	= "acpi_video_flags",		.data		= &acpi_realmode_flags,		.maxlen		= sizeof(unsigned long),		.mode		= 0644,		.proc_handler	= proc_doulongvec_minmax,	},#endif}; static int __init init_x86_sysctl(void){	register_sysctl_init("kernel", x86_sysctl_table);	return 0;}arch_initcall(init_x86_sysctl); /* * Setup options */ struct sysfb_display_info sysfb_primary_display;EXPORT_SYMBOL(sysfb_primary_display); extern int root_mountflags; unsigned long saved_video_mode; #define RAMDISK_IMAGE_START_MASK	0x07FF#define RAMDISK_PROMPT_FLAG		0x8000#define RAMDISK_LOAD_FLAG		0x4000 static char __initdata command_line[COMMAND_LINE_SIZE];#ifdef CONFIG_CMDLINE_BOOLchar builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;bool builtin_cmdline_added __ro_after_init;#endif #if IS_ENABLED(CONFIG_EDD)struct edd edd;#ifdef CONFIG_EDD_MODULEEXPORT_SYMBOL(edd);#endif/** * copy_edd() - Copy the BIOS EDD information *              from boot_params into a safe place. * */static inline void __init copy_edd(void){     memcpy(edd.mbr_signature, boot_params.edd_mbr_sig_buffer,	    sizeof(edd.mbr_signature));     memcpy(edd.edd_info, boot_params.eddbuf, sizeof(edd.edd_info));     edd.mbr_signature_nr = boot_params.edd_mbr_sig_buf_entries;     edd.edd_info_nr = boot_params.eddbuf_entries;}#elsestatic inline void __init copy_edd(void){}#endif void * __init extend_brk(size_t size, size_t align){	size_t mask = align - 1;	void *ret; 	BUG_ON(_brk_start == 0);	BUG_ON(align & mask); 	_brk_end = (_brk_end + mask) & ~mask;	BUG_ON((char *)(_brk_end + size) > __brk_limit); 	ret = (void *)_brk_end;	_brk_end += size; 	memset(ret, 0, size); 	return ret;} #ifdef CONFIG_X86_32static void __init cleanup_highmap(void){}#endif static void __init reserve_brk(void){	if (_brk_end > _brk_start)		memblock_reserve_kern(__pa_symbol(_brk_start),				      _brk_end - _brk_start); 	/* Mark brk area as locked down and no longer taking any	   new allocations */	_brk_start = 0;} #ifdef CONFIG_BLK_DEV_INITRD static u64 __init get_ramdisk_image(void){	u64 ramdisk_image = boot_params.hdr.ramdisk_image; 	ramdisk_image |= (u64)boot_params.ext_ramdisk_image << 32; 	if (ramdisk_image == 0)		ramdisk_image = phys_initrd_start; 	return ramdisk_image;}static u64 __init get_ramdisk_size(void){	u64 ramdisk_size = boot_params.hdr.ramdisk_size; 	ramdisk_size |= (u64)boot_params.ext_ramdisk_size << 32; 	if (ramdisk_size == 0)		ramdisk_size = phys_initrd_size; 	return ramdisk_size;} static void __init relocate_initrd(void){	/* Assume only end is not page aligned */	u64 ramdisk_image = get_ramdisk_image();	u64 ramdisk_size  = get_ramdisk_size();	u64 area_size     = PAGE_ALIGN(ramdisk_size);	int ret = 0; 	/* We need to move the initrd down into directly mapped mem */	u64 relocated_ramdisk = memblock_phys_alloc_range(area_size, PAGE_SIZE, 0,						      PFN_PHYS(max_pfn_mapped));	if (!relocated_ramdisk)		panic("Cannot find place for new RAMDISK of size %lld\n",		      ramdisk_size); 	initrd_start = relocated_ramdisk + PAGE_OFFSET;	initrd_end   = initrd_start + ramdisk_size;	printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",	       relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1); 	ret = copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);	if (ret)		panic("Copy RAMDISK failed\n"); 	printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"		" [mem %#010llx-%#010llx]\n",		ramdisk_image, ramdisk_image + ramdisk_size - 1,		relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);} static void __init early_reserve_initrd(void){	/* Assume only end is not page aligned */	u64 ramdisk_image = get_ramdisk_image();	u64 ramdisk_size  = get_ramdisk_size();	u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size); 	if (!boot_params.hdr.type_of_loader ||	    !ramdisk_image || !ramdisk_size)		return;		/* No initrd provided by bootloader */ 	memblock_reserve_kern(ramdisk_image, ramdisk_end - ramdisk_image);} static void __init reserve_initrd(void){	/* Assume only end is not page aligned */	u64 ramdisk_image = get_ramdisk_image();	u64 ramdisk_size  = get_ramdisk_size();	u64 ramdisk_end   = PAGE_ALIGN(ramdisk_image + ramdisk_size); 	if (!boot_params.hdr.type_of_loader ||	    !ramdisk_image || !ramdisk_size)		return;		/* No initrd provided by bootloader */ 	initrd_start = 0; 	printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,			ramdisk_end - 1); 	if (pfn_range_is_mapped(PFN_DOWN(ramdisk_image),				PFN_DOWN(ramdisk_end))) {		/* All are mapped, easy case */		initrd_start = ramdisk_image + PAGE_OFFSET;		initrd_end = initrd_start + ramdisk_size;		return;	} 	relocate_initrd(); 	memblock_phys_free(ramdisk_image, ramdisk_end - ramdisk_image);} #elsestatic void __init early_reserve_initrd(void){}static void __init reserve_initrd(void){}#endif /* CONFIG_BLK_DEV_INITRD */ static void __init add_early_ima_buffer(u64 phys_addr){#ifdef CONFIG_IMA	struct ima_setup_data *data; 	data = early_memremap(phys_addr + sizeof(struct setup_data), sizeof(*data));	if (!data) {		pr_warn("setup: failed to memremap ima_setup_data entry\n");		return;	} 	if (data->size) {		memblock_reserve_kern(data->addr, data->size);		ima_kexec_buffer_phys = data->addr;		ima_kexec_buffer_size = data->size;	} 	early_memunmap(data, sizeof(*data));#else	pr_warn("Passed IMA kexec data, but CONFIG_IMA not set. Ignoring.\n");#endif} #if defined(CONFIG_HAVE_IMA_KEXEC) && !defined(CONFIG_OF_FLATTREE)int __init ima_free_kexec_buffer(void){	if (!ima_kexec_buffer_size)		return -ENOENT; 	memblock_phys_free(ima_kexec_buffer_phys,			   ima_kexec_buffer_size); 	ima_kexec_buffer_phys = 0;	ima_kexec_buffer_size = 0; 	return 0;} int __init ima_get_kexec_buffer(void **addr, size_t *size){	int ret; 	if (!ima_kexec_buffer_size)		return -ENOENT; 	ret = ima_validate_range(ima_kexec_buffer_phys, ima_kexec_buffer_size);	if (ret)		return ret; 	*addr = __va(ima_kexec_buffer_phys);	*size = ima_kexec_buffer_size; 	return 0;}#endif static void __init add_kho(u64 phys_addr, u32 data_len){	struct kho_data *kho;	u64 addr = phys_addr + sizeof(struct setup_data);	u64 size = data_len - sizeof(struct setup_data); 	if (!IS_ENABLED(CONFIG_KEXEC_HANDOVER)) {		pr_warn("Passed KHO data, but CONFIG_KEXEC_HANDOVER not set. Ignoring.\n");		return;	} 	kho = early_memremap(addr, size);	if (!kho) {		pr_warn("setup: failed to memremap kho data (0x%llx, 0x%llx)\n",			addr, size);		return;	} 	kho_populate(kho->fdt_addr, kho->fdt_size, kho->scratch_addr, kho->scratch_size); 	early_memunmap(kho, size);} static void __init parse_setup_data(void){	struct setup_data *data;	u64 pa_data, pa_next; 	pa_data = boot_params.hdr.setup_data;	while (pa_data) {		u32 data_len, data_type; 		data = early_memremap(pa_data, sizeof(*data));		data_len = data->len + sizeof(struct setup_data);		data_type = data->type;		pa_next = data->next;		early_memunmap(data, sizeof(*data)); 		switch (data_type) {		case SETUP_E820_EXT:			e820__memory_setup_extended(pa_data, data_len);			break;		case SETUP_DTB:			add_dtb(pa_data);

Lines 1–500 of 1327.