Commit 4692cf46 authored by Ingo Molnar's avatar Ingo Molnar Committed by Luis Henriques

efi: Disable interrupts around EFI calls, not in the epilog/prolog calls

commit 23a0d4e8 upstream.

Tapasweni Pathak reported that we do a kmalloc() in efi_call_phys_prolog()
on x86-64 while having interrupts disabled, which is a big no-no, as
kmalloc() can sleep.

Solve this by removing the irq disabling from the prolog/epilog calls
around EFI calls: it's unnecessary, as in this stage we are single
threaded in the boot thread, and we don't ever execute this from
interrupt contexts.
Reported-by: default avatarTapasweni Pathak <tapaswenipathak@gmail.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarMatt Fleming <matt.fleming@intel.com>
[ luis: backported to 3.16: adjusted context ]
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent 9d1d87b2
...@@ -236,12 +236,19 @@ static efi_status_t __init phys_efi_set_virtual_address_map( ...@@ -236,12 +236,19 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
efi_memory_desc_t *virtual_map) efi_memory_desc_t *virtual_map)
{ {
efi_status_t status; efi_status_t status;
unsigned long flags;
efi_call_phys_prelog(); efi_call_phys_prelog();
/* Disable interrupts around EFI calls: */
local_irq_save(flags);
status = efi_call_phys(efi_phys.set_virtual_address_map, status = efi_call_phys(efi_phys.set_virtual_address_map,
memory_map_size, descriptor_size, memory_map_size, descriptor_size,
descriptor_version, virtual_map); descriptor_version, virtual_map);
local_irq_restore(flags);
efi_call_phys_epilog(); efi_call_phys_epilog();
return status; return status;
} }
......
...@@ -33,11 +33,10 @@ ...@@ -33,11 +33,10 @@
/* /*
* To make EFI call EFI runtime service in physical addressing mode we need * To make EFI call EFI runtime service in physical addressing mode we need
* prelog/epilog before/after the invocation to disable interrupt, to * prolog/epilog before/after the invocation to claim the EFI runtime service
* claim EFI runtime service handler exclusively and to duplicate a memory in * handler exclusively and to duplicate a memory mapping in low memory space,
* low memory space say 0 - 3G. * say 0 - 3G.
*/ */
static unsigned long efi_rt_eflags;
void efi_sync_low_kernel_mappings(void) {} void efi_sync_low_kernel_mappings(void) {}
void __init efi_dump_pagetable(void) {} void __init efi_dump_pagetable(void) {}
...@@ -59,8 +58,6 @@ void efi_call_phys_prelog(void) ...@@ -59,8 +58,6 @@ void efi_call_phys_prelog(void)
{ {
struct desc_ptr gdt_descr; struct desc_ptr gdt_descr;
local_irq_save(efi_rt_eflags);
load_cr3(initial_page_table); load_cr3(initial_page_table);
__flush_tlb_all(); __flush_tlb_all();
...@@ -79,8 +76,6 @@ void efi_call_phys_epilog(void) ...@@ -79,8 +76,6 @@ void efi_call_phys_epilog(void)
load_cr3(swapper_pg_dir); load_cr3(swapper_pg_dir);
__flush_tlb_all(); __flush_tlb_all();
local_irq_restore(efi_rt_eflags);
} }
void __init efi_runtime_mkexec(void) void __init efi_runtime_mkexec(void)
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <asm/time.h> #include <asm/time.h>
static pgd_t *save_pgd __initdata; static pgd_t *save_pgd __initdata;
static unsigned long efi_flags __initdata;
/* /*
* We allocate runtime services regions bottom-up, starting from -4G, i.e. * We allocate runtime services regions bottom-up, starting from -4G, i.e.
...@@ -89,7 +88,6 @@ void __init efi_call_phys_prelog(void) ...@@ -89,7 +88,6 @@ void __init efi_call_phys_prelog(void)
return; return;
early_code_mapping_set_exec(1); early_code_mapping_set_exec(1);
local_irq_save(efi_flags);
n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
...@@ -117,7 +115,6 @@ void __init efi_call_phys_epilog(void) ...@@ -117,7 +115,6 @@ void __init efi_call_phys_epilog(void)
set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);
kfree(save_pgd); kfree(save_pgd);
__flush_tlb_all(); __flush_tlb_all();
local_irq_restore(efi_flags);
early_code_mapping_set_exec(0); early_code_mapping_set_exec(0);
} }
......
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