Commit 78510792 authored by Josh Triplett's avatar Josh Triplett Committed by H. Peter Anvin

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: default avatarJosh Triplett <josh@joshtriplett.org>
Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.orgSigned-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 984ff8a4
...@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void) ...@@ -419,10 +419,21 @@ void __init efi_reserve_boot_services(void)
} }
} }
static void __init efi_free_boot_services(void) static void __init efi_unmap_memmap(void)
{
if (memmap.map) {
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL;
}
}
void __init efi_free_boot_services(void)
{ {
void *p; void *p;
if (!efi_native)
return;
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
efi_memory_desc_t *md = p; efi_memory_desc_t *md = p;
unsigned long long start = md->phys_addr; unsigned long long start = md->phys_addr;
...@@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void) ...@@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void)
free_bootmem_late(start, size); free_bootmem_late(start, size);
} }
efi_unmap_memmap();
} }
static int __init efi_systab_init(void *phys) static int __init efi_systab_init(void *phys)
...@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void) ...@@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
* non-native EFI * non-native EFI
*/ */
if (!efi_native) if (!efi_native) {
goto out; efi_unmap_memmap();
return;
}
/* Merge contiguous regions of the same type and attribute */ /* Merge contiguous regions of the same type and attribute */
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
...@@ -877,13 +892,6 @@ void __init efi_enter_virtual_mode(void) ...@@ -877,13 +892,6 @@ void __init efi_enter_virtual_mode(void)
panic("EFI call to SetVirtualAddressMap() failed!"); panic("EFI call to SetVirtualAddressMap() failed!");
} }
/*
* Thankfully, it does seem that no runtime services other than
* SetVirtualAddressMap() will touch boot services code, so we can
* get rid of it all at this point
*/
efi_free_boot_services();
/* /*
* Now that EFI is in virtual mode, update the function * Now that EFI is in virtual mode, update the function
* pointers in the runtime service table to the new virtual addresses. * pointers in the runtime service table to the new virtual addresses.
...@@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void) ...@@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void)
if (__supported_pte_mask & _PAGE_NX) if (__supported_pte_mask & _PAGE_NX)
runtime_code_page_mkexec(); runtime_code_page_mkexec();
out:
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL;
kfree(new_memmap); kfree(new_memmap);
} }
......
...@@ -496,6 +496,11 @@ extern void efi_map_pal_code (void); ...@@ -496,6 +496,11 @@ extern void efi_map_pal_code (void);
extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg);
extern void efi_gettimeofday (struct timespec *ts); extern void efi_gettimeofday (struct timespec *ts);
extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */
#ifdef CONFIG_X86
extern void efi_free_boot_services(void);
#else
static inline void efi_free_boot_services(void) {}
#endif
extern u64 efi_get_iobase (void); extern u64 efi_get_iobase (void);
extern u32 efi_mem_type (unsigned long phys_addr); extern u32 efi_mem_type (unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr);
......
...@@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void) ...@@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void)
acpi_early_init(); /* before LAPIC and SMP init */ acpi_early_init(); /* before LAPIC and SMP init */
sfi_init_late(); sfi_init_late();
if (efi_enabled)
efi_free_boot_services();
ftrace_init(); ftrace_init();
/* Do the rest non-__init'ed, we're now alive */ /* Do the rest non-__init'ed, we're now alive */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment