Skip to content

Commit

Permalink
efi: Disable interrupts around EFI calls, not in the epilog/prolog calls
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ingo Molnar authored and Matt Fleming committed Apr 1, 2015
1 parent fed6cef commit 23a0d4e
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 11 deletions.
7 changes: 7 additions & 0 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
11 changes: 3 additions & 8 deletions arch/x86/platform/efi/efi_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand All @@ -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();

Expand 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)
Expand Down
3 changes: 0 additions & 3 deletions arch/x86/platform/efi/efi_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 23a0d4e

Please sign in to comment.