Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Update to support EFI runtime outside the kernel virtual...
details: https://anonhg.NetBSD.org/src/rev/367ef4e99fdc
branches: trunk
changeset: 364639:367ef4e99fdc
user: skrll <skrll%NetBSD.org@localhost>
date: Sat Apr 02 11:16:06 2022 +0000
description:
Update to support EFI runtime outside the kernel virtual address space
by creating an EFI RT pmap that can be activated / deactivated when
required.
Adds support for EFI RT to ARM_MMU_EXTENDED (ASID) 32-bit Arm machines.
On Arm64 the usage of pmapboot_enter is reduced and the mappings are
created much later in the boot process -- now in cpu_startup_hook.
Backward compatiblity for KVA mapped RT from old bootaa64.efi is
maintained.
Adding support to other platforms should be easier as a result.
diffstat:
sys/arch/aarch64/aarch64/efi_machdep.c | 69 ++++++++++++--
sys/arch/aarch64/aarch64/pmap.c | 125 ++++++++++++++++++++++++++-
sys/arch/aarch64/include/pmap.h | 7 +-
sys/arch/aarch64/include/vmparam.h | 16 ++-
sys/arch/arm/arm/efi_machdep.c | 123 ++++++++++++++++++++++++++++
sys/arch/arm/arm/efi_runtime.c | 21 +++-
sys/arch/arm/arm/trap.c | 61 +++++++++++++
sys/arch/arm/arm32/arm32_kvminit.c | 26 +++++-
sys/arch/arm/arm32/locore.S | 16 +++-
sys/arch/arm/arm32/pmap.c | 144 ++++++++++++++++++++++++++++++++-
sys/arch/arm/conf/files.arm | 7 +-
sys/arch/arm/include/arm32/machdep.h | 27 +++++-
sys/arch/arm/include/arm32/pmap.h | 12 ++-
sys/arch/arm/include/asan.h | 4 +-
sys/arch/arm/include/frame.h | 18 +++-
sys/arch/evbarm/conf/GENERIC | 6 +-
sys/arch/evbarm/fdt/fdt_machdep.c | 15 +-
sys/stand/efiboot/bootaa64/Makefile | 6 +-
sys/stand/efiboot/bootarm/Makefile | 5 +-
sys/stand/efiboot/version | 3 +-
20 files changed, 650 insertions(+), 61 deletions(-)
diffs (truncated from 1294 to 300 lines):
diff -r 7d33c18e0a01 -r 367ef4e99fdc sys/arch/aarch64/aarch64/efi_machdep.c
--- a/sys/arch/aarch64/aarch64/efi_machdep.c Sat Apr 02 09:53:20 2022 +0000
+++ b/sys/arch/aarch64/aarch64/efi_machdep.c Sat Apr 02 11:16:06 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: efi_machdep.c,v 1.10 2021/03/21 07:09:54 skrll Exp $ */
+/* $NetBSD: efi_machdep.c,v 1.11 2022/04/02 11:16:06 skrll Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.10 2021/03/21 07:09:54 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.11 2022/04/02 11:16:06 skrll Exp $");
#include <sys/param.h>
#include <uvm/uvm_extern.h>
@@ -46,35 +46,68 @@
bool fpu_used;
} arm_efirt_state;
+static bool efi_userva = true;
+
void
-arm_efirt_md_map_range(vaddr_t va, paddr_t pa, size_t sz, enum arm_efirt_mem_type type)
+arm_efirt_md_map_range(vaddr_t va, paddr_t pa, size_t sz,
+ enum arm_efirt_mem_type type)
{
- pt_entry_t attr;
+ int flags = 0;
+ int prot = 0;
switch (type) {
case ARM_EFIRT_MEM_CODE:
- attr = LX_BLKPAG_AF | LX_BLKPAG_AP_RW | LX_BLKPAG_UXN |
- LX_BLKPAG_ATTR_NORMAL_WB;
+ /* need write permission because fw devs */
+ prot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
break;
case ARM_EFIRT_MEM_DATA:
- attr = LX_BLKPAG_AF | LX_BLKPAG_AP_RW | LX_BLKPAG_UXN | LX_BLKPAG_PXN |
- LX_BLKPAG_ATTR_NORMAL_WB;
+ prot = VM_PROT_READ | VM_PROT_WRITE;
break;
case ARM_EFIRT_MEM_MMIO:
- attr = LX_BLKPAG_AF | LX_BLKPAG_AP_RW | LX_BLKPAG_UXN | LX_BLKPAG_PXN |
- LX_BLKPAG_ATTR_DEVICE_MEM;
+ prot = VM_PROT_READ | VM_PROT_WRITE;
+ flags = PMAP_DEV;
break;
default:
- panic("arm_efirt_md_map_range: unsupported type %d", type);
+ panic("%s: unsupported type %d", __func__, type);
}
- pmapboot_enter(va, pa, sz, L3_SIZE, attr, NULL);
+ /* even if TBI is disabled, AARCH64_ADDRTOP_TAG means KVA */
+ bool kva = (va & AARCH64_ADDRTOP_TAG) != 0;
+ if (kva) {
+ if (va < EFI_RUNTIME_VA ||
+ va >= EFI_RUNTIME_VA + EFI_RUNTIME_SIZE) {
+ printf("Incorrect EFI mapping address %" PRIxVADDR "\n", va);
+ return;
+ }
+ efi_userva = false;
+ } else {
+ if (!efi_userva) {
+ printf("Can't mix EFI RT address spaces\n");
+ return;
+ }
+ }
+
+ while (sz != 0) {
+ if (kva) {
+ pmap_kenter_pa(va, pa, prot, flags);
+ } else {
+ pmap_enter(pmap_efirt(), va, pa, prot, flags | PMAP_WIRED);
+ }
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ sz -= PAGE_SIZE;
+ }
+ if (kva)
+ pmap_update(pmap_kernel());
+ else
+ pmap_update(pmap_efirt());
}
int
arm_efirt_md_enter(void)
{
struct lwp *l = curlwp;
+ int err;
/* Save FPU state */
arm_efirt_state.fpu_used = fpu_used_p(l) != 0;
@@ -89,7 +122,14 @@
* Install custom fault handler. EFI lock is held across calls so
* shared faultbuf is safe here.
*/
- return cpu_set_onfault(&arm_efirt_state.faultbuf);
+ err = cpu_set_onfault(&arm_efirt_state.faultbuf);
+ if (err)
+ return err;
+
+ if (efi_userva)
+ pmap_activate_efirt();
+
+ return 0;
}
void
@@ -97,6 +137,9 @@
{
struct lwp *l = curlwp;
+ if (efi_userva)
+ pmap_deactivate_efirt();
+
/* Disable FP access */
reg_cpacr_el1_write(CPACR_FPEN_NONE);
isb();
diff -r 7d33c18e0a01 -r 367ef4e99fdc sys/arch/aarch64/aarch64/pmap.c
--- a/sys/arch/aarch64/aarch64/pmap.c Sat Apr 02 09:53:20 2022 +0000
+++ b/sys/arch/aarch64/aarch64/pmap.c Sat Apr 02 11:16:06 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.131 2022/03/19 09:53:18 skrll Exp $ */
+/* $NetBSD: pmap.c,v 1.132 2022/04/02 11:16:06 skrll Exp $ */
/*
* Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,11 +27,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.131 2022/03/19 09:53:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.132 2022/04/02 11:16:06 skrll Exp $");
#include "opt_arm_debug.h"
#include "opt_cpuoptions.h"
#include "opt_ddb.h"
+#include "opt_efi.h"
#include "opt_modular.h"
#include "opt_multiprocessor.h"
#include "opt_pmap.h"
@@ -198,8 +199,16 @@
struct vm_page **);
static struct pmap kernel_pmap __cacheline_aligned;
+static struct pmap efirt_pmap __cacheline_aligned;
struct pmap * const kernel_pmap_ptr = &kernel_pmap;
+
+pmap_t
+pmap_efirt(void)
+{
+ return &efirt_pmap;
+}
+
static vaddr_t pmap_maxkvaddr;
vaddr_t virtual_avail, virtual_end;
@@ -281,6 +290,9 @@
#define IN_DIRECTMAP_ADDR(va) \
IN_RANGE((va), AARCH64_DIRECTMAP_START, AARCH64_DIRECTMAP_END)
+#define PMAP_EFIVA_P(va) \
+ IN_RANGE((va), EFI_RUNTIME_VA, EFI_RUNTIME_VA + EFI_RUNTIME_SIZE)
+
#ifdef MODULAR
#define IN_MODULE_VA(va) IN_RANGE((va), module_start, module_end)
#else
@@ -290,7 +302,8 @@
#ifdef DIAGNOSTIC
#define KERNEL_ADDR_P(va) \
- IN_RANGE((va), VM_MIN_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS)
+ (IN_RANGE((va), VM_MIN_KERNEL_ADDRESS, VM_MAX_KERNEL_ADDRESS) || \
+ PMAP_EFIVA_P(va))
#define KASSERT_PM_ADDR(pm, va) \
do { \
@@ -492,6 +505,28 @@
CTASSERT(sizeof(kpm->pm_stats.wired_count) == sizeof(long));
CTASSERT(sizeof(kpm->pm_stats.resident_count) == sizeof(long));
+
+#if defined(EFI_RUNTIME)
+ memset(&efirt_pmap, 0, sizeof(efirt_pmap));
+ struct pmap * const efipm = &efirt_pmap;
+ struct pmap_asid_info * const efipai = PMAP_PAI(efipm, cpu_tlb_info(ci));
+
+ efipai->pai_asid = KERNEL_PID;
+ efipm->pm_refcnt = 1;
+
+ vaddr_t efi_l0va = uvm_pageboot_alloc(Ln_TABLE_SIZE);
+ KASSERT((efi_l0va & PAGE_MASK) == 0);
+
+ efipm->pm_l0table = (pd_entry_t *)efi_l0va;
+ memset(efipm->pm_l0table, 0, Ln_TABLE_SIZE);
+
+ efipm->pm_l0table_pa = AARCH64_KVA_TO_PA(efi_l0va);
+
+ efipm->pm_activated = false;
+ LIST_INIT(&efipm->pm_vmlist);
+ LIST_INIT(&efipm->pm_pvlist); /* not used for efi pmap */
+ mutex_init(&efipm->pm_lock, MUTEX_DEFAULT, IPL_NONE);
+#endif
}
#ifdef MULTIPROCESSOR
@@ -1456,6 +1491,33 @@
pm_unlock(pm);
}
+#if defined(EFI_RUNTIME)
+void
+pmap_activate_efirt(void)
+{
+ kpreempt_disable();
+
+ struct cpu_info *ci = curcpu();
+ struct pmap *pm = &efirt_pmap;
+ struct pmap_asid_info * const pai = PMAP_PAI(pm, cpu_tlb_info(ci));
+
+ UVMHIST_FUNC(__func__);
+ UVMHIST_CALLARGS(pmaphist, " (pm=%#jx)", (uintptr_t)pm, 0, 0, 0);
+
+ ci->ci_pmap_asid_cur = pai->pai_asid;
+ UVMHIST_LOG(pmaphist, "setting asid to %#jx", pai->pai_asid,
+ 0, 0, 0);
+ tlb_set_asid(pai->pai_asid, pm);
+
+ /* Re-enable translation table walks using TTBR0 */
+ uint64_t tcr = reg_tcr_el1_read();
+ reg_tcr_el1_write(tcr & ~TCR_EPD0);
+ isb();
+ pm->pm_activated = true;
+
+ PMAP_COUNT(activate);
+}
+#endif
void
pmap_activate(struct lwp *l)
@@ -1492,6 +1554,32 @@
PMAP_COUNT(activate);
}
+#if defined(EFI_RUNTIME)
+void
+pmap_deactivate_efirt(void)
+{
+ struct cpu_info * const ci = curcpu();
+ struct pmap * const pm = &efirt_pmap;
+
+ UVMHIST_FUNC(__func__); UVMHIST_CALLED(pmaphist);
+
+ /* Disable translation table walks using TTBR0 */
+ uint64_t tcr = reg_tcr_el1_read();
+ reg_tcr_el1_write(tcr | TCR_EPD0);
+ isb();
+
+ UVMHIST_LOG(pmaphist, "setting asid to %#jx", KERNEL_PID,
+ 0, 0, 0);
+
+ ci->ci_pmap_asid_cur = KERNEL_PID;
+ tlb_set_asid(KERNEL_PID, pmap_kernel());
+
+ pm->pm_activated = false;
+
+ PMAP_COUNT(deactivate);
+}
+#endif
+
void
pmap_deactivate(struct lwp *l)
{
@@ -1607,6 +1695,12 @@
if (pm == pmap_kernel())
return;
+#if defined(EFI_RUNTIME)
+ /* EFI runtme L0-L3 pages will never be freed */
+ if (pm == pmap_efirt())
+ return;
+#endif
+
KASSERT(mutex_owned(&pm->pm_lock));
/* no need for L0 page */
@@ -1641,6 +1735,12 @@
if (pm == pmap_kernel())
return false;
+#if defined(EFI_RUNTIME)
+ /* EFI runtme L0-L3 pages will never be freed */
+ if (pm == pmap_efirt())
+ return false;
Home |
Main Index |
Thread Index |
Old Index