diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-03-03 07:34:33 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2015-04-01 12:46:22 +0100 |
commit | 23a0d4e8fa6d3a1d7fb819f79bcc0a3739c30ba9 (patch) | |
tree | a39fccdee6dc1a89756331aac0c4db066060e96c | |
parent | fed6cefe3b6e862dcc74d07324478caa07e84eaf (diff) |
efi: Disable interrupts around EFI calls, not in the epilog/prolog calls
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: Tapasweni Pathak <tapaswenipathak@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r-- | arch/x86/platform/efi/efi.c | 7 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_32.c | 11 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 3 |
3 files changed, 10 insertions, 11 deletions
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index e859d56ce9f8..e7a01e32db95 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -85,12 +85,19 @@ static efi_status_t __init phys_efi_set_virtual_address_map( efi_memory_desc_t *virtual_map) { efi_status_t status; + unsigned long flags; efi_call_phys_prolog(); + + /* Disable interrupts around EFI calls: */ + local_irq_save(flags); status = efi_call_phys(efi_phys.set_virtual_address_map, memory_map_size, descriptor_size, descriptor_version, virtual_map); + local_irq_restore(flags); + efi_call_phys_epilog(); + return status; } diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index 40e7cda52936..abecc6e1dc90 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -33,11 +33,10 @@ /* * To make EFI call EFI runtime service in physical addressing mode we need - * prolog/epilog before/after the invocation to disable interrupt, to - * claim EFI runtime service handler exclusively and to duplicate a memory in - * low memory space say 0 - 3G. + * prolog/epilog before/after the invocation to claim the EFI runtime service + * handler exclusively and to duplicate a memory mapping in low memory space, + * say 0 - 3G. */ -static unsigned long efi_rt_eflags; void efi_sync_low_kernel_mappings(void) {} void __init efi_dump_pagetable(void) {} @@ -61,8 +60,6 @@ void __init efi_call_phys_prolog(void) { struct desc_ptr gdt_descr; - local_irq_save(efi_rt_eflags); - load_cr3(initial_page_table); __flush_tlb_all(); @@ -81,8 +78,6 @@ void __init efi_call_phys_epilog(void) load_cr3(swapper_pg_dir); __flush_tlb_all(); - - local_irq_restore(efi_rt_eflags); } void __init efi_runtime_mkexec(void) diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 17e80d829df0..427eb3540e5f 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -42,7 +42,6 @@ #include <asm/time.h> static pgd_t *save_pgd __initdata; -static unsigned long efi_flags __initdata; /* * We allocate runtime services regions bottom-up, starting from -4G, i.e. @@ -88,7 +87,6 @@ void __init efi_call_phys_prolog(void) return; early_code_mapping_set_exec(1); - local_irq_save(efi_flags); n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); @@ -116,7 +114,6 @@ void __init efi_call_phys_epilog(void) set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); kfree(save_pgd); __flush_tlb_all(); - local_irq_restore(efi_flags); early_code_mapping_set_exec(0); } |