From 69c9189320c46b14e5ae3ad4b3a0d35cc63cba20 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Wed, 14 May 2008 08:15:58 -0700 Subject: x86 boot: add code to add BIOS provided EFI memory entries to kernel Add to the kernels boot memory map 'memmap' entries found in the EFI memory descriptors passed in from the BIOS. On EFI systems, up to E820MAX == 128 memory map entries can be passed via the legacy E820 interface (limited by the size of the 'zeropage'). These entries can be duplicated in the EFI descriptors also passed from the BIOS, and possibly more entries passed by the EFI interface, which does not have the E820MAX limit on number of memory map entries. This code doesn't worry about the likely duplicate, overlapping or (unlikely) conflicting entries between the EFI map and the E820 map. It just dumps all the EFI entries into the memmap[] array (which already has the E820 entries) and lets the existing routine sanitize_e820_map() sort the mess out. Signed-off-by: Paul Jackson Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'arch/x86/kernel/efi.c') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 77d424cf68b3..4a1a26d5931f 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -213,6 +213,31 @@ unsigned long efi_get_time(void) eft.minute, eft.second); } +/* + * Tell the kernel about the EFI memory map. This might include + * more than the max 128 entries that can fit in the e820 legacy + * (zeropage) memory map. + */ + +static void __init add_efi_memmap(void) +{ + void *p; + + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { + efi_memory_desc_t *md = p; + unsigned long long start = md->phys_addr; + unsigned long long size = md->num_pages << EFI_PAGE_SHIFT; + int e820_type; + + if (md->attribute & EFI_MEMORY_WB) + e820_type = E820_RAM; + else + e820_type = E820_RESERVED; + add_memory_region(start, size, e820_type); + } + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); +} + #if EFI_DEBUG static void __init print_efi_memmap(void) { @@ -370,6 +395,7 @@ void __init efi_init(void) if (memmap.desc_size != sizeof(efi_memory_desc_t)) printk(KERN_WARNING "Kernel-defined memdesc" "doesn't match the one from EFI!\n"); + add_efi_memmap(); /* Setup for EFI runtime service */ reboot_type = BOOT_EFI; -- cgit v1.2.3 From ecacf09f7d26b2317e8b1d59fa40f62081fad0bb Mon Sep 17 00:00:00 2001 From: "Huang, Ying" Date: Mon, 2 Jun 2008 14:26:21 +0800 Subject: x86: reserve EFI memory map with reserve_early This patch reserves the EFI memory map with reserve_early(). Because EFI memory map is allocated by bootloader, if it is not reserved by reserved_early(), it may be overwritten through address returned by find_e820_area(). Signed-off-by: Huang Ying Cc: andi@firstfloor.org Cc: mingo@redhat.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/efi.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'arch/x86/kernel/efi.c') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 4a1a26d5931f..d5c7fcdd1861 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -238,6 +238,23 @@ static void __init add_efi_memmap(void) sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } +void __init efi_reserve_early(void) +{ + unsigned long pmap; + + pmap = boot_params.efi_info.efi_memmap; +#ifdef CONFIG_X86_64 + pmap += (__u64)boot_params.efi_info.efi_memmap_hi << 32; +#endif + memmap.phys_map = (void *)pmap; + memmap.nr_map = boot_params.efi_info.efi_memmap_size / + boot_params.efi_info.efi_memdesc_size; + memmap.desc_version = boot_params.efi_info.efi_memdesc_version; + memmap.desc_size = boot_params.efi_info.efi_memdesc_size; + reserve_early(pmap, pmap + memmap.nr_map * memmap.desc_size, + "EFI memmap"); +} + #if EFI_DEBUG static void __init print_efi_memmap(void) { @@ -267,21 +284,11 @@ void __init efi_init(void) int i = 0; void *tmp; -#ifdef CONFIG_X86_32 efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; - memmap.phys_map = (void *)boot_params.efi_info.efi_memmap; -#else - efi_phys.systab = (efi_system_table_t *) - (boot_params.efi_info.efi_systab | - ((__u64)boot_params.efi_info.efi_systab_hi<<32)); - memmap.phys_map = (void *) - (boot_params.efi_info.efi_memmap | - ((__u64)boot_params.efi_info.efi_memmap_hi<<32)); +#ifdef CONFIG_X86_64 + efi_phys.systab = (void *)efi_phys.systab + + ((__u64)boot_params.efi_info.efi_systab_hi<<32); #endif - memmap.nr_map = boot_params.efi_info.efi_memmap_size / - boot_params.efi_info.efi_memdesc_size; - memmap.desc_version = boot_params.efi_info.efi_memdesc_version; - memmap.desc_size = boot_params.efi_info.efi_memdesc_size; efi.systab = early_ioremap((unsigned long)efi_phys.systab, sizeof(efi_system_table_t)); -- cgit v1.2.3 From d0be6bdea103b8d04c8a3495538b7c0011ae4129 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Sun, 15 Jun 2008 18:58:51 -0700 Subject: x86: rename two e820 related functions rename update_memory_range to e820_update_range rename add_memory_region to e820_add_region to make it more clear that they are about e820 map operations. Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/kernel/efi.c') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index d5c7fcdd1861..473c89fe5073 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -233,7 +233,7 @@ static void __init add_efi_memmap(void) e820_type = E820_RAM; else e820_type = E820_RESERVED; - add_memory_region(start, size, e820_type); + e820_add_region(start, size, e820_type); } sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } -- cgit v1.2.3 From 05486fa7e631a3be31a0bbc5a575a389a1609e94 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sun, 22 Jun 2008 07:22:02 -0700 Subject: x86 boot: x86_64 efi compiler warning fix Fix a compiler warning. Rather than always casting a u32 to a pointer (which generates a warning on x86_64 systems) instead separate the x86_32 and x86_64 assignments entirely with ifdefs. Until other recent changes to this code, it used to have x86_64 separated like this. Signed-off-by: Paul Jackson Cc: "Yinghai Lu" Cc: "Jack Steiner" Cc: "Mike Travis" Cc: "Huang Cc: Ying" Cc: "Andi Kleen" Cc: "Andrew Morton" Cc: Paul Jackson Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'arch/x86/kernel/efi.c') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 473c89fe5073..a03ca36a302c 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -242,9 +242,11 @@ void __init efi_reserve_early(void) { unsigned long pmap; +#ifdef CONFIG_X86_32 pmap = boot_params.efi_info.efi_memmap; -#ifdef CONFIG_X86_64 - pmap += (__u64)boot_params.efi_info.efi_memmap_hi << 32; +#else + pmap = (boot_params.efi_info.efi_memmap | + ((__u64)boot_params.efi_info.efi_memmap_hi<<32)); #endif memmap.phys_map = (void *)pmap; memmap.nr_map = boot_params.efi_info.efi_memmap_size / @@ -284,10 +286,12 @@ void __init efi_init(void) int i = 0; void *tmp; +#ifdef CONFIG_X86_32 efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; -#ifdef CONFIG_X86_64 - efi_phys.systab = (void *)efi_phys.systab + - ((__u64)boot_params.efi_info.efi_systab_hi<<32); +#else + efi_phys.systab = (efi_system_table_t *) + (boot_params.efi_info.efi_systab | + ((__u64)boot_params.efi_info.efi_systab_hi<<32)); #endif efi.systab = early_ioremap((unsigned long)efi_phys.systab, -- cgit v1.2.3 From 200001eb140ea33477965f2050bea0dac801974b Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Wed, 25 Jun 2008 05:44:46 -0700 Subject: x86 boot: only pick up additional EFI memmap if add_efi_memmap flag Applies on top of the previous patch: x86 boot: add code to add BIOS provided EFI memory entries to kernel Instead of always adding EFI memory map entries (if present) to the memory map after initially finding either E820 BIOS memory map entries and/or kernel command line memmap entries, -instead- only add such additional EFI memory map entries if the kernel boot option: add_efi_memmap is specified. Requiring this 'add_efi_memmap' option is backward compatible with kernels that didn't load such additional EFI memory map entries in the first place, and it doesn't override a configuration that tries to replace all E820 or EFI BIOS memory map entries with ones given entirely on the kernel command line. Signed-off-by: Paul Jackson Cc: "Yinghai Lu" Cc: "Jack Steiner" Cc: "Mike Travis" Cc: "Huang Cc: Ying" Cc: "Andi Kleen" Cc: "Andrew Morton" Cc: Paul Jackson Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'arch/x86/kernel/efi.c') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index a03ca36a302c..94382faeadb6 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -64,6 +64,17 @@ static int __init setup_noefi(char *arg) } early_param("noefi", setup_noefi); +int add_efi_memmap; +EXPORT_SYMBOL(add_efi_memmap); + +static int __init setup_add_efi_memmap(char *arg) +{ + add_efi_memmap = 1; + return 0; +} +early_param("add_efi_memmap", setup_add_efi_memmap); + + static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) { return efi_call_virt2(get_time, tm, tc); @@ -219,7 +230,7 @@ unsigned long efi_get_time(void) * (zeropage) memory map. */ -static void __init add_efi_memmap(void) +static void __init do_add_efi_memmap(void) { void *p; @@ -406,7 +417,8 @@ void __init efi_init(void) if (memmap.desc_size != sizeof(efi_memory_desc_t)) printk(KERN_WARNING "Kernel-defined memdesc" "doesn't match the one from EFI!\n"); - add_efi_memmap(); + if (add_efi_memmap) + do_add_efi_memmap(); /* Setup for EFI runtime service */ reboot_type = BOOT_EFI; -- cgit v1.2.3 From f361a450bf1ad14e2b003217dbf3958638631265 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Thu, 10 Jul 2008 20:38:26 -0700 Subject: x86: introduce max_low_pfn_mapped for 64-bit when more than 4g memory is installed, don't map the big hole below 4g. Signed-off-by: Yinghai Lu Cc: Suresh Siddha Signed-off-by: Ingo Molnar --- arch/x86/kernel/efi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/kernel/efi.c') diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c index 94382faeadb6..06cc8d4254b1 100644 --- a/arch/x86/kernel/efi.c +++ b/arch/x86/kernel/efi.c @@ -473,7 +473,7 @@ void __init efi_enter_virtual_mode(void) size = md->num_pages << EFI_PAGE_SHIFT; end = md->phys_addr + size; - if (PFN_UP(end) <= max_pfn_mapped) + if (PFN_UP(end) <= max_low_pfn_mapped) va = __va(md->phys_addr); else va = efi_ioremap(md->phys_addr, size); -- cgit v1.2.3