arm64/efi: refactor EFI init and runtime code for reuse by 32-bit ARM
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>
This commit is contained in:
parent
e5bc22a42e
commit
f7d9248942
@ -2,7 +2,9 @@
|
|||||||
#define _ASM_EFI_H
|
#define _ASM_EFI_H
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/mmu_context.h>
|
||||||
#include <asm/neon.h>
|
#include <asm/neon.h>
|
||||||
|
#include <asm/tlbflush.h>
|
||||||
|
|
||||||
#ifdef CONFIG_EFI
|
#ifdef CONFIG_EFI
|
||||||
extern void efi_init(void);
|
extern void efi_init(void);
|
||||||
@ -10,6 +12,8 @@ extern void efi_init(void);
|
|||||||
#define efi_init()
|
#define efi_init()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
|
||||||
|
|
||||||
#define efi_call_virt(f, ...) \
|
#define efi_call_virt(f, ...) \
|
||||||
({ \
|
({ \
|
||||||
efi_##f##_t *__f; \
|
efi_##f##_t *__f; \
|
||||||
@ -63,6 +67,11 @@ extern void efi_init(void);
|
|||||||
* Services are enabled and the EFI_RUNTIME_SERVICES bit set.
|
* 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_load(void);
|
||||||
void efi_virtmap_unload(void);
|
void efi_virtmap_unload(void);
|
||||||
|
|
||||||
|
@ -17,6 +17,29 @@
|
|||||||
|
|
||||||
#include <asm/efi.h>
|
#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)
|
static int __init arm64_dmi_init(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -57,7 +57,7 @@ static int __init uefi_init(void)
|
|||||||
{
|
{
|
||||||
efi_char16_t *c16;
|
efi_char16_t *c16;
|
||||||
void *config_tables;
|
void *config_tables;
|
||||||
u64 table_size;
|
size_t table_size;
|
||||||
char vendor[100] = "unknown";
|
char vendor[100] = "unknown";
|
||||||
int i, retval;
|
int i, retval;
|
||||||
|
|
||||||
@ -69,6 +69,7 @@ static int __init uefi_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_bit(EFI_BOOT, &efi.flags);
|
set_bit(EFI_BOOT, &efi.flags);
|
||||||
|
if (IS_ENABLED(CONFIG_64BIT))
|
||||||
set_bit(EFI_64BIT, &efi.flags);
|
set_bit(EFI_64BIT, &efi.flags);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -107,7 +108,7 @@ static int __init uefi_init(void)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
retval = efi_config_parse_tables(config_tables, efi.systab->nr_tables,
|
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);
|
early_memunmap(config_tables, table_size);
|
||||||
out:
|
out:
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/efi.h>
|
#include <linux/efi.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <linux/memblock.h>
|
#include <linux/memblock.h>
|
||||||
#include <linux/mm_types.h>
|
#include <linux/mm_types.h>
|
||||||
#include <linux/preempt.h>
|
#include <linux/preempt.h>
|
||||||
@ -23,18 +24,14 @@
|
|||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/efi.h>
|
#include <asm/efi.h>
|
||||||
#include <asm/tlbflush.h>
|
|
||||||
#include <asm/mmu_context.h>
|
|
||||||
#include <asm/mmu.h>
|
#include <asm/mmu.h>
|
||||||
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
|
|
||||||
static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss;
|
|
||||||
|
|
||||||
extern u64 efi_system_table;
|
extern u64 efi_system_table;
|
||||||
|
|
||||||
static struct mm_struct efi_mm = {
|
static struct mm_struct efi_mm = {
|
||||||
.mm_rb = RB_ROOT,
|
.mm_rb = RB_ROOT,
|
||||||
.pgd = efi_pgd,
|
|
||||||
.mm_users = ATOMIC_INIT(2),
|
.mm_users = ATOMIC_INIT(2),
|
||||||
.mm_count = ATOMIC_INIT(1),
|
.mm_count = ATOMIC_INIT(1),
|
||||||
.mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
|
.mmap_sem = __RWSEM_INITIALIZER(efi_mm.mmap_sem),
|
||||||
@ -46,35 +43,27 @@ static bool __init efi_virtmap_init(void)
|
|||||||
{
|
{
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
|
|
||||||
|
efi_mm.pgd = pgd_alloc(&efi_mm);
|
||||||
init_new_context(NULL, &efi_mm);
|
init_new_context(NULL, &efi_mm);
|
||||||
|
|
||||||
for_each_efi_memory_desc(&memmap, md) {
|
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))
|
if (!(md->attribute & EFI_MEMORY_RUNTIME))
|
||||||
continue;
|
continue;
|
||||||
if (md->virt_addr == 0)
|
if (md->virt_addr == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pr_info(" EFI remap 0x%016llx => %p\n",
|
ret = efi_create_mapping(&efi_mm, md);
|
||||||
md->phys_addr, (void *)md->virt_addr);
|
if (!ret) {
|
||||||
|
pr_info(" EFI remap %pa => %p\n",
|
||||||
/*
|
&phys, (void *)(unsigned long)md->virt_addr);
|
||||||
* Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
|
} else {
|
||||||
* executable, everything else can be mapped with the XN bits
|
pr_warn(" EFI remap %pa: failed to create mapping (%d)\n",
|
||||||
* set.
|
&phys, ret);
|
||||||
*/
|
return false;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -84,7 +73,7 @@ static bool __init efi_virtmap_init(void)
|
|||||||
* non-early mapping of the UEFI system table and virtual mappings for all
|
* non-early mapping of the UEFI system table and virtual mappings for all
|
||||||
* EFI_MEMORY_RUNTIME regions.
|
* EFI_MEMORY_RUNTIME regions.
|
||||||
*/
|
*/
|
||||||
static int __init arm64_enable_runtime_services(void)
|
static int __init arm_enable_runtime_services(void)
|
||||||
{
|
{
|
||||||
u64 mapsize;
|
u64 mapsize;
|
||||||
|
|
||||||
@ -131,12 +120,7 @@ static int __init arm64_enable_runtime_services(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_initcall(arm64_enable_runtime_services);
|
early_initcall(arm_enable_runtime_services);
|
||||||
|
|
||||||
static void efi_set_pgd(struct mm_struct *mm)
|
|
||||||
{
|
|
||||||
switch_mm(NULL, mm, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void efi_virtmap_load(void)
|
void efi_virtmap_load(void)
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include <asm/efi.h>
|
||||||
|
|
||||||
struct efi __read_mostly efi = {
|
struct efi __read_mostly efi = {
|
||||||
.mps = EFI_INVALID_TABLE_ADDR,
|
.mps = EFI_INVALID_TABLE_ADDR,
|
||||||
.acpi = EFI_INVALID_TABLE_ADDR,
|
.acpi = EFI_INVALID_TABLE_ADDR,
|
||||||
|
Loading…
Reference in New Issue
Block a user