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