/* * Copyright (C) 1995 Linus Torvalds * * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 * * Memory region support * David Parsons <orc@pell.chi.il.us>, July-August 1999 * * Added E820 sanitization routine (removes overlapping memory regions); * Brian Moyle <bmoyle@mvista.com>, February 2001 * * Moved CPU detection code to cpu/${cpu}.c * Patrick Mochel <mochel@osdl.org>, March 2002 * * Provisions for empty E820 memory regions (reported by certain BIOSes). * Alex Achenbach <xela@slit.de>, December 2002. * */ /* * This file handles the architecture-dependent parts of initialization */ #include <linux/sched.h>#include <linux/mm.h>#include <linux/mmzone.h>#include <linux/screen_info.h>#include <linux/ioport.h>#include <linux/acpi.h>#include <linux/sfi.h>#include <linux/apm_bios.h>#include <linux/initrd.h>#include <linux/bootmem.h>#include <linux/memblock.h>#include <linux/seq_file.h>#include <linux/console.h>#include <linux/root_dev.h>#include <linux/highmem.h>#include <linux/module.h>#include <linux/efi.h>#include <linux/init.h>#include <linux/edd.h>#include <linux/iscsi_ibft.h>#include <linux/nodemask.h>#include <linux/kexec.h>#include <linux/dmi.h>#include <linux/pfn.h>#include <linux/pci.h>#include <asm/pci-direct.h>#include <linux/init_ohci1394_dma.h>#include <linux/kvm_para.h>#include <linux/dma-contiguous.h> #include <linux/errno.h>#include <linux/kernel.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/user.h>#include <linux/delay.h> #include <linux/kallsyms.h>#include <linux/cpufreq.h>#include <linux/dma-mapping.h>#include <linux/ctype.h>#include <linux/uaccess.h> #include <linux/percpu.h>#include <linux/crash_dump.h>#include <linux/tboot.h>#include <linux/jiffies.h> #include <video/edid.h> #include <asm/mtrr.h>#include <asm/apic.h>#include <asm/realmode.h>#include <asm/e820.h>#include <asm/mpspec.h>#include <asm/setup.h>#include <asm/efi.h>#include <asm/timer.h>#include <asm/i8259.h>#include <asm/sections.h>#include <asm/io_apic.h>#include <asm/ist.h>#include <asm/setup_arch.h>#include <asm/bios_ebda.h>#include <asm/cacheflush.h>#include <asm/processor.h>#include <asm/bugs.h> #include <asm/vsyscall.h>#include <asm/cpu.h>#include <asm/desc.h>#include <asm/dma.h>#include <asm/iommu.h>#include <asm/gart.h>#include <asm/mmu_context.h>#include <asm/proto.h> #include <asm/paravirt.h>#include <asm/hypervisor.h>#include <asm/olpc_ofw.h> #include <asm/percpu.h>#include <asm/topology.h>#include <asm/apicdef.h>#include <asm/amd_nb.h>#include <asm/mce.h>#include <asm/alternative.h>#include <asm/prom.h> /* * max_low_pfn_mapped: highest direct mapped pfn under 4GB * max_pfn_mapped: highest direct mapped pfn over 4GB * * The direct mapping only covers E820_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 static __initdata unsigned long _brk_start = (unsigned long)__brk_base;unsigned long _brk_end = (unsigned long)__brk_base; #ifdef CONFIG_X86_64int default_cpu_present_to_apicid(int mps_cpu){ return __default_cpu_present_to_apicid(mps_cpu);} int default_check_phys_apicid_present(int phys_apicid){ return __default_check_phys_apicid_present(phys_apicid);}#endif struct boot_params boot_params; /* * Machine setup.. */static struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, .flags = IORESOURCE_BUSY | IORESOURCE_MEM}; static struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, .flags = IORESOURCE_BUSY | IORESOURCE_MEM}; static struct resource bss_resource = { .name = "Kernel bss", .start = 0, .end = 0, .flags = IORESOURCE_BUSY | IORESOURCE_MEM}; #ifdef CONFIG_X86_32/* cpu data as detected by the assembly code in head.S */struct cpuinfo_x86 new_cpu_data = { .wp_works_ok = -1,};/* common cpu data for all cpus */struct cpuinfo_x86 boot_cpu_data __read_mostly = { .wp_works_ok = -1,};EXPORT_SYMBOL(boot_cpu_data); unsigned int def_to_bigsmp; /* for MCA, but anyone else can use it if they want */unsigned int machine_id;unsigned int machine_submodel_id;unsigned int BIOS_revision; struct apm_info apm_info;EXPORT_SYMBOL(apm_info); #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \ defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)struct ist_info ist_info;EXPORT_SYMBOL(ist_info);#elsestruct ist_info ist_info;#endif #elsestruct cpuinfo_x86 boot_cpu_data __read_mostly = { .x86_phys_bits = MAX_PHYSMEM_BITS,};EXPORT_SYMBOL(boot_cpu_data);#endif #if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)__visible unsigned long mmu_cr4_features;#else__visible unsigned long mmu_cr4_features = X86_CR4_PAE;#endif /* Boot loader ID and version as integers, for the benefit of proc_dointvec */int bootloader_type, bootloader_version; /* * Setup options */struct screen_info screen_info;EXPORT_SYMBOL(screen_info);struct edid_info edid_info;EXPORT_SYMBOL_GPL(edid_info); 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_BOOLstatic char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;#endif #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)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(__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; 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; return ramdisk_size;} #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)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); u64 ramdisk_here; unsigned long slop, clen, mapaddr; char *p, *q; /* We need to move the initrd down into directly mapped mem */ ramdisk_here = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), area_size, PAGE_SIZE); if (!ramdisk_here) panic("Cannot find place for new RAMDISK of size %lld\n", ramdisk_size); /* Note: this includes all the mem currently occupied by the initrd, we rely on that fact to keep the data intact. */ memblock_reserve(ramdisk_here, area_size); initrd_start = ramdisk_here + PAGE_OFFSET; initrd_end = initrd_start + ramdisk_size; printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_here, ramdisk_here + ramdisk_size - 1); q = (char *)initrd_start; /* Copy the initrd */ while (ramdisk_size) { slop = ramdisk_image & ~PAGE_MASK; clen = ramdisk_size; if (clen > MAX_MAP_CHUNK-slop) clen = MAX_MAP_CHUNK-slop; mapaddr = ramdisk_image & PAGE_MASK; p = early_memremap(mapaddr, clen+slop); memcpy(q, p+slop, clen); early_iounmap(p, clen+slop); q += clen; ramdisk_image += clen; ramdisk_size -= clen; } ramdisk_image = get_ramdisk_image(); ramdisk_size = get_ramdisk_size(); printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to" " [mem %#010llx-%#010llx]\n", ramdisk_image, ramdisk_image + ramdisk_size - 1, ramdisk_here, ramdisk_here + 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(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); u64 mapped_size; if (!boot_params.hdr.type_of_loader || !ramdisk_image || !ramdisk_size) return; /* No initrd provided by bootloader */ initrd_start = 0; mapped_size = memblock_mem_size(max_pfn_mapped); if (ramdisk_size >= (mapped_size>>1)) panic("initrd too large to handle, " "disabling initrd (%lld needed, %lld available)\n", ramdisk_size, mapped_size>>1); 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_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 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, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); data_type = data->type; pa_next = data->next; early_iounmap(data, map_len); switch (data_type) { case SETUP_E820_EXT: parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); break; default: break; } pa_data = pa_next; }} static void __init e820_reserve_setup_data(void){ struct setup_data *data; u64 pa_data; int found = 0; pa_data = boot_params.hdr.setup_data; while (pa_data) { data = early_memremap(pa_data, sizeof(*data)); e820_update_range(pa_data, sizeof(*data)+data->len, E820_RAM, E820_RESERVED_KERN); found = 1; pa_data = data->next; early_iounmap(data, sizeof(*data)); } if (!found) return; sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); memcpy(&e820_saved, &e820, sizeof(struct e820map)); printk(KERN_INFO "extended physical RAM map:\n"); e820_print_map("reserve setup_data");} static void __init memblock_x86_reserve_range_setup_data(void){ struct setup_data *data; u64 pa_data; pa_data = boot_params.hdr.setup_data; while (pa_data) { data = early_memremap(pa_data, sizeof(*data)); memblock_reserve(pa_data, sizeof(*data) + data->len); pa_data = data->next; early_iounmap(data, sizeof(*data)); }} /* * --------- Crashkernel reservation ------------------------------ */ #ifdef CONFIG_KEXEC Lines 1–500 of 1250. Load more
/* * Copyright (C) 1995 Linus Torvalds * * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 * * Memory region support * David Parsons <orc@pell.chi.il.us>, July-August 1999 * * Added E820 sanitization routine (removes overlapping memory regions); * Brian Moyle <bmoyle@mvista.com>, February 2001 * * Moved CPU detection code to cpu/${cpu}.c * Patrick Mochel <mochel@osdl.org>, March 2002 * * Provisions for empty E820 memory regions (reported by certain BIOSes). * Alex Achenbach <xela@slit.de>, December 2002. * */ /* * This file handles the architecture-dependent parts of initialization */ #include <linux/sched.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/screen_info.h> #include <linux/ioport.h> #include <linux/acpi.h> #include <linux/sfi.h> #include <linux/apm_bios.h> #include <linux/initrd.h> #include <linux/bootmem.h> #include <linux/memblock.h> #include <linux/seq_file.h> #include <linux/console.h> #include <linux/root_dev.h> #include <linux/highmem.h> #include <linux/module.h> #include <linux/efi.h> #include <linux/init.h> #include <linux/edd.h> #include <linux/iscsi_ibft.h> #include <linux/nodemask.h> #include <linux/kexec.h> #include <linux/dmi.h> #include <linux/pfn.h> #include <linux/pci.h> #include <asm/pci-direct.h> #include <linux/init_ohci1394_dma.h> #include <linux/kvm_para.h> #include <linux/dma-contiguous.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> #include <linux/user.h> #include <linux/delay.h> #include <linux/kallsyms.h> #include <linux/cpufreq.h> #include <linux/dma-mapping.h> #include <linux/ctype.h> #include <linux/uaccess.h> #include <linux/percpu.h> #include <linux/crash_dump.h> #include <linux/tboot.h> #include <linux/jiffies.h> #include <video/edid.h> #include <asm/mtrr.h> #include <asm/apic.h> #include <asm/realmode.h> #include <asm/e820.h> #include <asm/mpspec.h> #include <asm/setup.h> #include <asm/efi.h> #include <asm/timer.h> #include <asm/i8259.h> #include <asm/sections.h> #include <asm/io_apic.h> #include <asm/ist.h> #include <asm/setup_arch.h> #include <asm/bios_ebda.h> #include <asm/cacheflush.h> #include <asm/processor.h> #include <asm/bugs.h> #include <asm/vsyscall.h> #include <asm/cpu.h> #include <asm/desc.h> #include <asm/dma.h> #include <asm/iommu.h> #include <asm/gart.h> #include <asm/mmu_context.h> #include <asm/proto.h> #include <asm/paravirt.h> #include <asm/hypervisor.h> #include <asm/olpc_ofw.h> #include <asm/percpu.h> #include <asm/topology.h> #include <asm/apicdef.h> #include <asm/amd_nb.h> #include <asm/mce.h> #include <asm/alternative.h> #include <asm/prom.h> /* * max_low_pfn_mapped: highest direct mapped pfn under 4GB * max_pfn_mapped: highest direct mapped pfn over 4GB * * The direct mapping only covers E820_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_DMI RESERVE_BRK(dmi_alloc, 65536); #endif static __initdata unsigned long _brk_start = (unsigned long)__brk_base; unsigned long _brk_end = (unsigned long)__brk_base; #ifdef CONFIG_X86_64 int default_cpu_present_to_apicid(int mps_cpu) { return __default_cpu_present_to_apicid(mps_cpu); } int default_check_phys_apicid_present(int phys_apicid) { return __default_check_phys_apicid_present(phys_apicid); } #endif struct boot_params boot_params; /* * Machine setup.. */ static struct resource data_resource = { .name = "Kernel data", .start = 0, .end = 0, .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; static struct resource code_resource = { .name = "Kernel code", .start = 0, .end = 0, .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; static struct resource bss_resource = { .name = "Kernel bss", .start = 0, .end = 0, .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; #ifdef CONFIG_X86_32 /* cpu data as detected by the assembly code in head.S */ struct cpuinfo_x86 new_cpu_data = { .wp_works_ok = -1, }; /* common cpu data for all cpus */ struct cpuinfo_x86 boot_cpu_data __read_mostly = { .wp_works_ok = -1, }; EXPORT_SYMBOL(boot_cpu_data); unsigned int def_to_bigsmp; /* for MCA, but anyone else can use it if they want */ unsigned int machine_id; unsigned int machine_submodel_id; unsigned int BIOS_revision; struct apm_info apm_info; EXPORT_SYMBOL(apm_info); #if defined(CONFIG_X86_SPEEDSTEP_SMI) || \ defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) struct ist_info ist_info; EXPORT_SYMBOL(ist_info); #else struct ist_info ist_info; #endif #else struct cpuinfo_x86 boot_cpu_data __read_mostly = { .x86_phys_bits = MAX_PHYSMEM_BITS, }; EXPORT_SYMBOL(boot_cpu_data); #endif #if !defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64) __visible unsigned long mmu_cr4_features; #else __visible unsigned long mmu_cr4_features = X86_CR4_PAE; #endif /* Boot loader ID and version as integers, for the benefit of proc_dointvec */ int bootloader_type, bootloader_version; /* * Setup options */ struct screen_info screen_info; EXPORT_SYMBOL(screen_info); struct edid_info edid_info; EXPORT_SYMBOL_GPL(edid_info); 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_BOOL static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE; #endif #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) struct edd edd; #ifdef CONFIG_EDD_MODULE EXPORT_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; } #else static 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_32 static void __init cleanup_highmap(void) { } #endif static void __init reserve_brk(void) { if (_brk_end > _brk_start) memblock_reserve(__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; 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; return ramdisk_size; } #define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT) 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); u64 ramdisk_here; unsigned long slop, clen, mapaddr; char *p, *q; /* We need to move the initrd down into directly mapped mem */ ramdisk_here = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), area_size, PAGE_SIZE); if (!ramdisk_here) panic("Cannot find place for new RAMDISK of size %lld\n", ramdisk_size); /* Note: this includes all the mem currently occupied by the initrd, we rely on that fact to keep the data intact. */ memblock_reserve(ramdisk_here, area_size); initrd_start = ramdisk_here + PAGE_OFFSET; initrd_end = initrd_start + ramdisk_size; printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_here, ramdisk_here + ramdisk_size - 1); q = (char *)initrd_start; /* Copy the initrd */ while (ramdisk_size) { slop = ramdisk_image & ~PAGE_MASK; clen = ramdisk_size; if (clen > MAX_MAP_CHUNK-slop) clen = MAX_MAP_CHUNK-slop; mapaddr = ramdisk_image & PAGE_MASK; p = early_memremap(mapaddr, clen+slop); memcpy(q, p+slop, clen); early_iounmap(p, clen+slop); q += clen; ramdisk_image += clen; ramdisk_size -= clen; } ramdisk_image = get_ramdisk_image(); ramdisk_size = get_ramdisk_size(); printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to" " [mem %#010llx-%#010llx]\n", ramdisk_image, ramdisk_image + ramdisk_size - 1, ramdisk_here, ramdisk_here + 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(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); u64 mapped_size; if (!boot_params.hdr.type_of_loader || !ramdisk_image || !ramdisk_size) return; /* No initrd provided by bootloader */ initrd_start = 0; mapped_size = memblock_mem_size(max_pfn_mapped); if (ramdisk_size >= (mapped_size>>1)) panic("initrd too large to handle, " "disabling initrd (%lld needed, %lld available)\n", ramdisk_size, mapped_size>>1); 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_free(ramdisk_image, ramdisk_end - ramdisk_image); } #else static void __init early_reserve_initrd(void) { } static void __init reserve_initrd(void) { } #endif /* CONFIG_BLK_DEV_INITRD */ 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, map_len, data_type; map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK), (u64)sizeof(struct setup_data)); data = early_memremap(pa_data, map_len); data_len = data->len + sizeof(struct setup_data); data_type = data->type; pa_next = data->next; early_iounmap(data, map_len); switch (data_type) { case SETUP_E820_EXT: parse_e820_ext(pa_data, data_len); break; case SETUP_DTB: add_dtb(pa_data); break; default: break; } pa_data = pa_next; } } static void __init e820_reserve_setup_data(void) { struct setup_data *data; u64 pa_data; int found = 0; pa_data = boot_params.hdr.setup_data; while (pa_data) { data = early_memremap(pa_data, sizeof(*data)); e820_update_range(pa_data, sizeof(*data)+data->len, E820_RAM, E820_RESERVED_KERN); found = 1; pa_data = data->next; early_iounmap(data, sizeof(*data)); } if (!found) return; sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); memcpy(&e820_saved, &e820, sizeof(struct e820map)); printk(KERN_INFO "extended physical RAM map:\n"); e820_print_map("reserve setup_data"); } static void __init memblock_x86_reserve_range_setup_data(void) { struct setup_data *data; u64 pa_data; pa_data = boot_params.hdr.setup_data; while (pa_data) { data = early_memremap(pa_data, sizeof(*data)); memblock_reserve(pa_data, sizeof(*data) + data->len); pa_data = data->next; early_iounmap(data, sizeof(*data)); } } /* * --------- Crashkernel reservation ------------------------------ */ #ifdef CONFIG_KEXEC