aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2012-09-28 20:55:44 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-09-29 15:21:01 -0400
commit785107923a83d8456bbd8564e288a24d84109a46 (patch)
treecda886bdf9d5f33a524b740e7807d17e079cb6b7
parent984ff8a4d2251fbd09b1e8515133bdfe9ef4bcd6 (diff)
efi: Defer freeing boot services memory until after ACPI init
Some new ACPI 5.0 tables reference resources stored in boot services memory, so keep that memory around until we have ACPI and can extract data from it. Signed-off-by: Josh Triplett <josh@joshtriplett.org> Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.org Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--arch/x86/platform/efi/efi.c31
-rw-r--r--include/linux/efi.h5
-rw-r--r--init/main.c3
3 files changed, 26 insertions, 13 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index f55a4ce6dc49..b3dbbdbd2a42 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void)
419 } 419 }
420} 420}
421 421
422static void __init efi_free_boot_services(void) 422static void __init efi_unmap_memmap(void)
423{
424 if (memmap.map) {
425 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
426 memmap.map = NULL;
427 }
428}
429
430void __init efi_free_boot_services(void)
423{ 431{
424 void *p; 432 void *p;
425 433
434 if (!efi_native)
435 return;
436
426 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 437 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
427 efi_memory_desc_t *md = p; 438 efi_memory_desc_t *md = p;
428 unsigned long long start = md->phys_addr; 439 unsigned long long start = md->phys_addr;
@@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void)
438 449
439 free_bootmem_late(start, size); 450 free_bootmem_late(start, size);
440 } 451 }
452
453 efi_unmap_memmap();
441} 454}
442 455
443static int __init efi_systab_init(void *phys) 456static int __init efi_systab_init(void *phys)
@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
787 * non-native EFI 800 * non-native EFI
788 */ 801 */
789 802
790 if (!efi_native) 803 if (!efi_native) {
791 goto out; 804 efi_unmap_memmap();
805 return;
806 }
792 807
793 /* Merge contiguous regions of the same type and attribute */ 808 /* Merge contiguous regions of the same type and attribute */
794 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 809 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -878,13 +893,6 @@ void __init efi_enter_virtual_mode(void)
878 } 893 }
879 894
880 /* 895 /*
881 * Thankfully, it does seem that no runtime services other than
882 * SetVirtualAddressMap() will touch boot services code, so we can
883 * get rid of it all at this point
884 */
885 efi_free_boot_services();
886
887 /*
888 * Now that EFI is in virtual mode, update the function 896 * Now that EFI is in virtual mode, update the function
889 * pointers in the runtime service table to the new virtual addresses. 897 * pointers in the runtime service table to the new virtual addresses.
890 * 898 *
@@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void)
907 if (__supported_pte_mask & _PAGE_NX) 915 if (__supported_pte_mask & _PAGE_NX)
908 runtime_code_page_mkexec(); 916 runtime_code_page_mkexec();
909 917
910out:
911 early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
912 memmap.map = NULL;
913 kfree(new_memmap); 918 kfree(new_memmap);
914} 919}
915 920
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ec45ccd8708a..5782114f4838 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -496,6 +496,11 @@ extern void efi_map_pal_code (void);
496extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); 496extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
497extern void efi_gettimeofday (struct timespec *ts); 497extern void efi_gettimeofday (struct timespec *ts);
498extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ 498extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
499#ifdef CONFIG_X86
500extern void efi_free_boot_services(void);
501#else
502static inline void efi_free_boot_services(void) {}
503#endif
499extern u64 efi_get_iobase (void); 504extern u64 efi_get_iobase (void);
500extern u32 efi_mem_type (unsigned long phys_addr); 505extern u32 efi_mem_type (unsigned long phys_addr);
501extern u64 efi_mem_attributes (unsigned long phys_addr); 506extern u64 efi_mem_attributes (unsigned long phys_addr);
diff --git a/init/main.c b/init/main.c
index b28673087ac0..d61ec542205c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void)
631 acpi_early_init(); /* before LAPIC and SMP init */ 631 acpi_early_init(); /* before LAPIC and SMP init */
632 sfi_init_late(); 632 sfi_init_late();
633 633
634 if (efi_enabled)
635 efi_free_boot_services();
636
634 ftrace_init(); 637 ftrace_init();
635 638
636 /* Do the rest non-__init'ed, we're now alive */ 639 /* Do the rest non-__init'ed, we're now alive */