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>
This commit is contained in:
parent
fed6cefe3b
commit
23a0d4e8fa
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user