Skip to content

Commit

Permalink
efi/x86: Split SetVirtualAddresMap() wrappers into 32 and 64 bit vers…
Browse files Browse the repository at this point in the history
…ions

Split the phys_efi_set_virtual_address_map() routine into 32 and 64 bit
versions, so we can simplify them individually in subsequent patches.

There is very little overlap between the logic anyway, and this has
already been factored out in prolog/epilog routines which are completely
different between 32 bit and 64 bit. So let's take it one step further,
and get rid of the overlap completely.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Arvind Sankar <nivedita@alum.mit.edu>
Cc: Matthew Garrett <mjg59@google.com>
Cc: linux-efi@vger.kernel.org
Link: https://lkml.kernel.org/r/20200103113953.9571-8-ardb@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ard Biesheuvel authored and Ingo Molnar committed Jan 10, 2020
1 parent 98dd0e3 commit 6982947
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 57 deletions.
8 changes: 4 additions & 4 deletions arch/x86/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ extern asmlinkage unsigned long efi_call_phys(void *, ...);

extern asmlinkage u64 efi_call(void *fp, ...);

#define efi_call_phys(f, args...) efi_call((f), args)

/*
* struct efi_scratch - Scratch space used while switching to/from efi_mm
* @phys_stack: stack used during EFI Mixed Mode
Expand Down Expand Up @@ -115,8 +113,6 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
extern struct efi_scratch efi_scratch;
extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable);
extern int __init efi_memblock_x86_reserve_range(void);
extern pgd_t * __init efi_call_phys_prolog(void);
extern void __init efi_call_phys_epilog(pgd_t *save_pgd);
extern void __init efi_print_memmap(void);
extern void __init efi_memory_uc(u64 addr, unsigned long size);
extern void __init efi_map_region(efi_memory_desc_t *md);
Expand Down Expand Up @@ -177,6 +173,10 @@ extern efi_status_t efi_thunk_set_virtual_address_map(
unsigned long descriptor_size,
u32 descriptor_version,
efi_memory_desc_t *virtual_map);
efi_status_t efi_set_virtual_address_map(unsigned long memory_map_size,
unsigned long descriptor_size,
u32 descriptor_version,
efi_memory_desc_t *virtual_map);

/* arch specific definitions used by the stub code */

Expand Down
30 changes: 2 additions & 28 deletions arch/x86/platform/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
#include <asm/x86_init.h>
#include <asm/uv/uv.h>

static struct efi efi_phys __initdata;
struct efi efi_phys __initdata;
static efi_system_table_t efi_systab __initdata;

static efi_config_table_type_t arch_tables[] __initdata = {
Expand Down Expand Up @@ -97,32 +97,6 @@ static int __init setup_add_efi_memmap(char *arg)
}
early_param("add_efi_memmap", setup_add_efi_memmap);

static efi_status_t __init phys_efi_set_virtual_address_map(
unsigned long memory_map_size,
unsigned long descriptor_size,
u32 descriptor_version,
efi_memory_desc_t *virtual_map)
{
efi_status_t status;
unsigned long flags;
pgd_t *save_pgd;

save_pgd = efi_call_phys_prolog();
if (!save_pgd)
return EFI_ABORTED;

/* 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(save_pgd);

return status;
}

void __init efi_find_mirror(void)
{
efi_memory_desc_t *md;
Expand Down Expand Up @@ -1042,7 +1016,7 @@ static void __init __efi_enter_virtual_mode(void)
efi_sync_low_kernel_mappings();

if (!efi_is_mixed()) {
status = phys_efi_set_virtual_address_map(
status = efi_set_virtual_address_map(
efi.memmap.desc_size * count,
efi.memmap.desc_size,
efi.memmap.desc_version,
Expand Down
21 changes: 16 additions & 5 deletions arch/x86/platform/efi/efi_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,16 @@ void __init efi_map_region(efi_memory_desc_t *md)
void __init efi_map_region_fixed(efi_memory_desc_t *md) {}
void __init parse_efi_setup(u64 phys_addr, u32 data_len) {}

pgd_t * __init efi_call_phys_prolog(void)
extern struct efi efi_phys;

efi_status_t __init efi_set_virtual_address_map(unsigned long memory_map_size,
unsigned long descriptor_size,
u32 descriptor_version,
efi_memory_desc_t *virtual_map)
{
struct desc_ptr gdt_descr;
efi_status_t status;
unsigned long flags;
pgd_t *save_pgd;

/* Current pgd is swapper_pg_dir, we'll restore it later: */
Expand All @@ -80,14 +87,18 @@ pgd_t * __init efi_call_phys_prolog(void)
gdt_descr.size = GDT_SIZE - 1;
load_gdt(&gdt_descr);

return save_pgd;
}
/* 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);

void __init efi_call_phys_epilog(pgd_t *save_pgd)
{
load_fixmap_gdt(0);
load_cr3(save_pgd);
__flush_tlb_all();

return status;
}

void __init efi_runtime_update_mappings(void)
Expand Down
56 changes: 36 additions & 20 deletions arch/x86/platform/efi/efi_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ static void __init early_code_mapping_set_exec(int executable)
}
}

void __init efi_old_memmap_phys_epilog(pgd_t *save_pgd);
static void __init efi_old_memmap_phys_epilog(pgd_t *save_pgd);

pgd_t * __init efi_old_memmap_phys_prolog(void)
static pgd_t * __init efi_old_memmap_phys_prolog(void)
{
unsigned long vaddr, addr_pgd, addr_p4d, addr_pud;
pgd_t *save_pgd, *pgd_k, *pgd_efi;
Expand Down Expand Up @@ -144,7 +144,7 @@ pgd_t * __init efi_old_memmap_phys_prolog(void)
return NULL;
}

void __init efi_old_memmap_phys_epilog(pgd_t *save_pgd)
static void __init efi_old_memmap_phys_epilog(pgd_t *save_pgd)
{
/*
* After the lock is released, the original page table is restored.
Expand Down Expand Up @@ -185,23 +185,6 @@ void __init efi_old_memmap_phys_epilog(pgd_t *save_pgd)
early_code_mapping_set_exec(0);
}

pgd_t * __init efi_call_phys_prolog(void)
{
if (efi_enabled(EFI_OLD_MEMMAP))
return efi_old_memmap_phys_prolog();

efi_switch_mm(&efi_mm);
return efi_mm.pgd;
}

void __init efi_call_phys_epilog(pgd_t *save_pgd)
{
if (efi_enabled(EFI_OLD_MEMMAP))
efi_old_memmap_phys_epilog(save_pgd);
else
efi_switch_mm(efi_scratch.prev_mm);
}

EXPORT_SYMBOL_GPL(efi_mm);

/*
Expand Down Expand Up @@ -1018,3 +1001,36 @@ void efi_thunk_runtime_setup(void)
efi.query_capsule_caps = efi_thunk_query_capsule_caps;
}
#endif /* CONFIG_EFI_MIXED */

efi_status_t __init efi_set_virtual_address_map(unsigned long memory_map_size,
unsigned long descriptor_size,
u32 descriptor_version,
efi_memory_desc_t *virtual_map)
{
efi_status_t status;
unsigned long flags;
pgd_t *save_pgd = NULL;

if (efi_enabled(EFI_OLD_MEMMAP)) {
save_pgd = efi_old_memmap_phys_prolog();
if (!save_pgd)
return EFI_ABORTED;
} else {
efi_switch_mm(&efi_mm);
}

/* Disable interrupts around EFI calls: */
local_irq_save(flags);
status = efi_call(efi.systab->runtime->set_virtual_address_map,
memory_map_size, descriptor_size,
descriptor_version, virtual_map);
local_irq_restore(flags);


if (save_pgd)
efi_old_memmap_phys_epilog(save_pgd);
else
efi_switch_mm(efi_scratch.prev_mm);

return status;
}

0 comments on commit 6982947

Please sign in to comment.