Skip to content

Commit

Permalink
efi: Defer freeing boot services memory until after ACPI init
Browse files Browse the repository at this point in the history
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 <[email protected]>
Link: http://lkml.kernel.org/r/baaa6d44bdc4eb0c58e5d1b4ccd2c729f854ac55.1348876882.git.josh@joshtriplett.org
Signed-off-by: H. Peter Anvin <[email protected]>
  • Loading branch information
joshtriplett authored and H. Peter Anvin committed Sep 29, 2012
1 parent 984ff8a commit 7851079
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
31 changes: 18 additions & 13 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

if (!efi_native)
return;

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;
Expand All @@ -438,6 +449,8 @@ static void __init efi_free_boot_services(void)

free_bootmem_late(start, size);
}

efi_unmap_memmap();
}

static int __init efi_systab_init(void *phys)
Expand Down Expand Up @@ -787,8 +800,10 @@ void __init efi_enter_virtual_mode(void)
* non-native EFI
*/

if (!efi_native)
goto out;
if (!efi_native) {
efi_unmap_memmap();
return;
}

/* Merge contiguous regions of the same type and attribute */
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
Expand Down Expand Up @@ -877,13 +892,6 @@ void __init efi_enter_virtual_mode(void)
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
* pointers in the runtime service table to the new virtual addresses.
Expand All @@ -907,9 +915,6 @@ void __init efi_enter_virtual_mode(void)
if (__supported_pte_mask & _PAGE_NX)
runtime_code_page_mkexec();

out:
early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
memmap.map = NULL;
kfree(new_memmap);
}

Expand Down
5 changes: 5 additions & 0 deletions include/linux/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_gettimeofday (struct timespec *ts);
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 u32 efi_mem_type (unsigned long phys_addr);
extern u64 efi_mem_attributes (unsigned long phys_addr);
Expand Down
3 changes: 3 additions & 0 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,9 @@ asmlinkage void __init start_kernel(void)
acpi_early_init(); /* before LAPIC and SMP init */
sfi_init_late();

if (efi_enabled)
efi_free_boot_services();

ftrace_init();

/* Do the rest non-__init'ed, we're now alive */
Expand Down

0 comments on commit 7851079

Please sign in to comment.