Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Josh Triplett and committed by
H. Peter Anvin
78510792 984ff8a4

+26 -13
+18 -13
arch/x86/platform/efi/efi.c
··· 419 419 } 420 420 } 421 421 422 - static void __init efi_free_boot_services(void) 422 + static 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 + 430 + void __init efi_free_boot_services(void) 423 431 { 424 432 void *p; 433 + 434 + if (!efi_native) 435 + return; 425 436 426 437 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 427 438 efi_memory_desc_t *md = p; ··· 449 438 450 439 free_bootmem_late(start, size); 451 440 } 441 + 442 + efi_unmap_memmap(); 452 443 } 453 444 454 445 static int __init efi_systab_init(void *phys) ··· 800 787 * non-native EFI 801 788 */ 802 789 803 - if (!efi_native) 804 - goto out; 790 + if (!efi_native) { 791 + efi_unmap_memmap(); 792 + return; 793 + } 805 794 806 795 /* Merge contiguous regions of the same type and attribute */ 807 796 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { ··· 893 878 } 894 879 895 880 /* 896 - * Thankfully, it does seem that no runtime services other than 897 - * SetVirtualAddressMap() will touch boot services code, so we can 898 - * get rid of it all at this point 899 - */ 900 - efi_free_boot_services(); 901 - 902 - /* 903 881 * Now that EFI is in virtual mode, update the function 904 882 * pointers in the runtime service table to the new virtual addresses. 905 883 * ··· 915 907 if (__supported_pte_mask & _PAGE_NX) 916 908 runtime_code_page_mkexec(); 917 909 918 - out: 919 - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); 920 - memmap.map = NULL; 921 910 kfree(new_memmap); 922 911 } 923 912
+5
include/linux/efi.h
··· 496 496 extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); 497 497 extern void efi_gettimeofday (struct timespec *ts); 498 498 extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ 499 + #ifdef CONFIG_X86 500 + extern void efi_free_boot_services(void); 501 + #else 502 + static inline void efi_free_boot_services(void) {} 503 + #endif 499 504 extern u64 efi_get_iobase (void); 500 505 extern u32 efi_mem_type (unsigned long phys_addr); 501 506 extern u64 efi_mem_attributes (unsigned long phys_addr);
+3
init/main.c
··· 631 631 acpi_early_init(); /* before LAPIC and SMP init */ 632 632 sfi_init_late(); 633 633 634 + if (efi_enabled) 635 + efi_free_boot_services(); 636 + 634 637 ftrace_init(); 635 638 636 639 /* Do the rest non-__init'ed, we're now alive */