aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/setup.c7
-rw-r--r--arch/x86/platform/efi/efi.c45
-rw-r--r--arch/x86/platform/efi/efi_64.c5
-rw-r--r--include/linux/efi.h1
4 files changed, 55 insertions, 3 deletions
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 605e5ae19c7f..b9ca498f5602 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -910,6 +910,13 @@ void __init setup_arch(char **cmdline_p)
910 memblock.current_limit = get_max_mapped(); 910 memblock.current_limit = get_max_mapped();
911 memblock_x86_fill(); 911 memblock_x86_fill();
912 912
913 /*
914 * The EFI specification says that boot service code won't be called
915 * after ExitBootServices(). This is, in fact, a lie.
916 */
917 if (efi_enabled)
918 efi_reserve_boot_services();
919
913 /* preallocate 4k for mptable mpc */ 920 /* preallocate 4k for mptable mpc */
914 early_reserve_e820_mpc_new(); 921 early_reserve_e820_mpc_new();
915 922
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index b30aa26a8df2..0d3a4fa34560 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -304,6 +304,40 @@ static void __init print_efi_memmap(void)
304} 304}
305#endif /* EFI_DEBUG */ 305#endif /* EFI_DEBUG */
306 306
307void __init efi_reserve_boot_services(void)
308{
309 void *p;
310
311 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
312 efi_memory_desc_t *md = p;
313 unsigned long long start = md->phys_addr;
314 unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
315
316 if (md->type != EFI_BOOT_SERVICES_CODE &&
317 md->type != EFI_BOOT_SERVICES_DATA)
318 continue;
319
320 memblock_x86_reserve_range(start, start + size, "EFI Boot");
321 }
322}
323
324static void __init efi_free_boot_services(void)
325{
326 void *p;
327
328 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
329 efi_memory_desc_t *md = p;
330 unsigned long long start = md->phys_addr;
331 unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
332
333 if (md->type != EFI_BOOT_SERVICES_CODE &&
334 md->type != EFI_BOOT_SERVICES_DATA)
335 continue;
336
337 free_bootmem_late(start, size);
338 }
339}
340
307void __init efi_init(void) 341void __init efi_init(void)
308{ 342{
309 efi_config_table_t *config_tables; 343 efi_config_table_t *config_tables;
@@ -536,7 +570,9 @@ void __init efi_enter_virtual_mode(void)
536 570
537 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 571 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
538 md = p; 572 md = p;
539 if (!(md->attribute & EFI_MEMORY_RUNTIME)) 573 if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
574 md->type != EFI_BOOT_SERVICES_CODE &&
575 md->type != EFI_BOOT_SERVICES_DATA)
540 continue; 576 continue;
541 577
542 size = md->num_pages << EFI_PAGE_SHIFT; 578 size = md->num_pages << EFI_PAGE_SHIFT;
@@ -593,6 +629,13 @@ void __init efi_enter_virtual_mode(void)
593 } 629 }
594 630
595 /* 631 /*
632 * Thankfully, it does seem that no runtime services other than
633 * SetVirtualAddressMap() will touch boot services code, so we can
634 * get rid of it all at this point
635 */
636 efi_free_boot_services();
637
638 /*
596 * Now that EFI is in virtual mode, update the function 639 * Now that EFI is in virtual mode, update the function
597 * pointers in the runtime service table to the new virtual addresses. 640 * pointers in the runtime service table to the new virtual addresses.
598 * 641 *
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 2649426a7905..ac3aa54e2654 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -49,10 +49,11 @@ static void __init early_code_mapping_set_exec(int executable)
49 if (!(__supported_pte_mask & _PAGE_NX)) 49 if (!(__supported_pte_mask & _PAGE_NX))
50 return; 50 return;
51 51
52 /* Make EFI runtime service code area executable */ 52 /* Make EFI service code area executable */
53 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { 53 for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
54 md = p; 54 md = p;
55 if (md->type == EFI_RUNTIME_SERVICES_CODE) 55 if (md->type == EFI_RUNTIME_SERVICES_CODE ||
56 md->type == EFI_BOOT_SERVICES_CODE)
56 efi_set_executable(md, executable); 57 efi_set_executable(md, executable);
57 } 58 }
58} 59}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 33fa1203024e..e376270cd26e 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -299,6 +299,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,
299 struct resource *data_resource, struct resource *bss_resource); 299 struct resource *data_resource, struct resource *bss_resource);
300extern unsigned long efi_get_time(void); 300extern unsigned long efi_get_time(void);
301extern int efi_set_rtc_mmss(unsigned long nowtime); 301extern int efi_set_rtc_mmss(unsigned long nowtime);
302extern void efi_reserve_boot_services(void);
302extern struct efi_memory_map memmap; 303extern struct efi_memory_map memmap;
303 304
304/** 305/**