Skip to content

Commit

Permalink
arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
Browse files Browse the repository at this point in the history
This refactors the EFI init and runtime code that will be shared
between arm64 and ARM so that it can be built for both archs.

Reviewed-by: Matt Fleming <matt@codeblueprint.co.uk>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
  • Loading branch information
Ard Biesheuvel authored and Will Deacon committed Dec 9, 2015
1 parent e5bc22a commit f7d9248
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 35 deletions.
9 changes: 9 additions & 0 deletions arch/arm64/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
#define _ASM_EFI_H

#include <asm/io.h>
#include <asm/mmu_context.h>
#include <asm/neon.h>
#include <asm/tlbflush.h>

#ifdef CONFIG_EFI
extern void efi_init(void);
#else
#define efi_init()
#endif

int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);

#define efi_call_virt(f, ...) \
({ \
efi_##f##_t *__f; \
Expand Down Expand Up @@ -63,6 +67,11 @@ extern void efi_init(void);
* Services are enabled and the EFI_RUNTIME_SERVICES bit set.
*/

static inline void efi_set_pgd(struct mm_struct *mm)
{
switch_mm(NULL, mm, NULL);
}

void efi_virtmap_load(void);
void efi_virtmap_unload(void);

Expand Down
23 changes: 23 additions & 0 deletions arch/arm64/kernel/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@

#include <asm/efi.h>

int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
{
pteval_t prot_val;

/*
* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
* executable, everything else can be mapped with the XN bits
* set.
*/
if ((md->attribute & EFI_MEMORY_WB) == 0)
prot_val = PROT_DEVICE_nGnRE;
else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
!PAGE_ALIGNED(md->phys_addr))
prot_val = pgprot_val(PAGE_KERNEL_EXEC);
else
prot_val = pgprot_val(PAGE_KERNEL);

create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
md->num_pages << EFI_PAGE_SHIFT,
__pgprot(prot_val | PTE_NG));
return 0;
}

static int __init arm64_dmi_init(void)
{
/*
Expand Down
7 changes: 4 additions & 3 deletions drivers/firmware/efi/arm-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static int __init uefi_init(void)
{
efi_char16_t *c16;
void *config_tables;
u64 table_size;
size_t table_size;
char vendor[100] = "unknown";
int i, retval;

Expand All @@ -69,7 +69,8 @@ static int __init uefi_init(void)
}

set_bit(EFI_BOOT, &efi.flags);
set_bit(EFI_64BIT, &efi.flags);
if (IS_ENABLED(CONFIG_64BIT))
set_bit(EFI_64BIT, &efi.flags);

/*
* Verify the EFI Table
Expand Down Expand Up @@ -107,7 +108,7 @@ static int __init uefi_init(void)
goto out;
}
retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
sizeof(efi_config_table_64_t), NULL);
sizeof(efi_config_table_t), NULL);

early_memunmap(config_tables, table_size);
out:
Expand Down
48 changes: 16 additions & 32 deletions drivers/firmware/efi/arm-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

#include <linux/efi.h>
#include <linux/io.h>
#include <linux/memblock.h>
#include <linux/mm_types.h>
#include <linux/preempt.h>
Expand All @@ -23,18 +24,14 @@

#include <asm/cacheflush.h>
#include <asm/efi.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/mmu.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>

static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;

extern u64 efi_system_table;

static struct mm_struct efi_mm = {
.mm_rb = RB_ROOT,
.pgd = efi_pgd,
.mm_users = ATOMIC_INIT(2),
.mm_count = ATOMIC_INIT(1),
.mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
Expand All @@ -46,35 +43,27 @@ static bool __init efi_virtmap_init(void)
{
efi_memory_desc_t *md;

efi_mm.pgd = pgd_alloc(&efi_mm);
init_new_context(NULL, &efi_mm);

for_each_efi_memory_desc(&memmap, md) {
pgprot_t prot;
phys_addr_t phys = md->phys_addr;
int ret;

if (!(md->attribute & EFI_MEMORY_RUNTIME))
continue;
if (md->virt_addr == 0)
return false;

pr_info(" EFI remap 0x%016llx => %p\n",
md->phys_addr, (void *)md->virt_addr);

/*
* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
* executable, everything else can be mapped with the XN bits
* set.
*/
if ((md->attribute & EFI_MEMORY_WB) == 0)
prot = __pgprot(PROT_DEVICE_nGnRE);
else if (md->type == EFI_RUNTIME_SERVICES_CODE ||
!PAGE_ALIGNED(md->phys_addr))
prot = PAGE_KERNEL_EXEC;
else
prot = PAGE_KERNEL;

create_pgd_mapping(&efi_mm, md->phys_addr, md->virt_addr,
md->num_pages << EFI_PAGE_SHIFT,
__pgprot(pgprot_val(prot) | PTE_NG));
ret = efi_create_mapping(&efi_mm, md);
if (!ret) {
pr_info(" EFI remap %pa => %p\n",
&phys, (void *)(unsigned long)md->virt_addr);
} else {
pr_warn(" EFI remap %pa: failed to create mapping (%d)\n",
&phys, ret);
return false;
}
}
return true;
}
Expand All @@ -84,7 +73,7 @@ static bool __init efi_virtmap_init(void)
* non-early mapping of the UEFI system table and virtual mappings for all
* EFI_MEMORY_RUNTIME regions.
*/
static int __init arm64_enable_runtime_services(void)
static int __init arm_enable_runtime_services(void)
{
u64 mapsize;

Expand Down Expand Up @@ -131,12 +120,7 @@ static int __init arm64_enable_runtime_services(void)

return 0;
}
early_initcall(arm64_enable_runtime_services);

static void efi_set_pgd(struct mm_struct *mm)
{
switch_mm(NULL, mm, NULL);
}
early_initcall(arm_enable_runtime_services);

void efi_virtmap_load(void)
{
Expand Down
2 changes: 2 additions & 0 deletions drivers/firmware/efi/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <linux/io.h>
#include <linux/platform_device.h>

#include <asm/efi.h>

struct efi __read_mostly efi = {
.mps = EFI_INVALID_TABLE_ADDR,
.acpi = EFI_INVALID_TABLE_ADDR,
Expand Down

0 comments on commit f7d9248

Please sign in to comment.