Module Name:    src
Committed By:   skrll
Date:           Sat Apr  2 11:16:08 UTC 2022

Modified Files:
        src/sys/arch/aarch64/aarch64: efi_machdep.c pmap.c
        src/sys/arch/aarch64/include: pmap.h vmparam.h
        src/sys/arch/arm/arm: efi_runtime.c
        src/sys/arch/arm/arm32: arm32_kvminit.c locore.S pmap.c
        src/sys/arch/arm/conf: files.arm
        src/sys/arch/arm/include: asan.h frame.h
        src/sys/arch/arm/include/arm32: machdep.h pmap.h
        src/sys/arch/evbarm/conf: GENERIC
        src/sys/arch/evbarm/fdt: fdt_machdep.c
        src/sys/stand/efiboot: version
        src/sys/stand/efiboot/bootaa64: Makefile
        src/sys/stand/efiboot/bootarm: Makefile
Added Files:
        src/sys/arch/arm/arm: efi_machdep.c trap.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/aarch64/aarch64/efi_machdep.c
cvs rdiff -u -r1.131 -r1.132 src/sys/arch/aarch64/aarch64/pmap.c
cvs rdiff -u -r1.51 -r1.52 src/sys/arch/aarch64/include/pmap.h
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/aarch64/include/vmparam.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/arm/efi_machdep.c \
    src/sys/arch/arm/arm/trap.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/arm/efi_runtime.c
cvs rdiff -u -r1.68 -r1.69 src/sys/arch/arm/arm32/arm32_kvminit.c
cvs rdiff -u -r1.43 -r1.44 src/sys/arch/arm/arm32/locore.S
cvs rdiff -u -r1.434 -r1.435 src/sys/arch/arm/arm32/pmap.c
cvs rdiff -u -r1.165 -r1.166 src/sys/arch/arm/conf/files.arm
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/include/asan.h
cvs rdiff -u -r1.22 -r1.23 src/sys/arch/arm/include/frame.h
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/arm/include/arm32/machdep.h
cvs rdiff -u -r1.172 -r1.173 src/sys/arch/arm/include/arm32/pmap.h
cvs rdiff -u -r1.106 -r1.107 src/sys/arch/evbarm/conf/GENERIC
cvs rdiff -u -r1.90 -r1.91 src/sys/arch/evbarm/fdt/fdt_machdep.c
cvs rdiff -u -r1.30 -r1.31 src/sys/stand/efiboot/version
cvs rdiff -u -r1.11 -r1.12 src/sys/stand/efiboot/bootaa64/Makefile
cvs rdiff -u -r1.8 -r1.9 src/sys/stand/efiboot/bootarm/Makefile

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/aarch64/aarch64/efi_machdep.c
diff -u src/sys/arch/aarch64/aarch64/efi_machdep.c:1.10 src/sys/arch/aarch64/aarch64/efi_machdep.c:1.11
--- src/sys/arch/aarch64/aarch64/efi_machdep.c:1.10	Sun Mar 21 07:09:54 2021
+++ src/sys/arch/aarch64/aarch64/efi_machdep.c	Sat Apr  2 11:16:06 2022
@@ -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 @@ static struct {
 	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);
+	}
+
+	/* 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;
+		}
 	}
 
-	pmapboot_enter(va, pa, sz, L3_SIZE, attr, NULL);
+	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 @@ arm_efirt_md_enter(void)
 	 * 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 @@ arm_efirt_md_exit(void)
 {
 	struct lwp *l = curlwp;
 
+	if (efi_userva)
+		pmap_deactivate_efirt();
+
 	/* Disable FP access */
 	reg_cpacr_el1_write(CPACR_FPEN_NONE);
 	isb();

Index: src/sys/arch/aarch64/aarch64/pmap.c
diff -u src/sys/arch/aarch64/aarch64/pmap.c:1.131 src/sys/arch/aarch64/aarch64/pmap.c:1.132
--- src/sys/arch/aarch64/aarch64/pmap.c:1.131	Sat Mar 19 09:53:18 2022
+++ src/sys/arch/aarch64/aarch64/pmap.c	Sat Apr  2 11:16:06 2022
@@ -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 <r...@nerv.org>
@@ -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 @@ static int _pmap_get_pdp(struct pmap *, 
     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 @@ phys_to_pp(paddr_t pa)
 #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 @@ phys_to_pp(paddr_t pa)
 #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 @@ pmap_bootstrap(vaddr_t vstart, vaddr_t v
 
 	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 @@ pmap_protect(struct pmap *pm, vaddr_t sv
 	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_activate(struct lwp *l)
 	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 @@ _pmap_pdp_addref(struct pmap *pm, paddr_
 	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 @@ _pmap_pdp_delref(struct pmap *pm, paddr_
 	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;
+#endif
+
 	KASSERT(mutex_owned(&pm->pm_lock));
 
 	/* no need for L0 page */
@@ -1722,7 +1822,8 @@ _pmap_get_pdp(struct pmap *pm, vaddr_t v
 	idx = l0pde_index(va);
 	pde = l0[idx];
 	if (!l0pde_valid(pde)) {
-		KASSERT(!kenter || IN_MODULE_VA(va));
+		KASSERTMSG(!kenter || IN_MODULE_VA(va) || PMAP_EFIVA_P(va),
+		    "%s va %" PRIxVADDR, kenter ? "kernel" : "user", va);
 		/* no need to increment L0 occupancy. L0 page never freed */
 		pdppa = pmap_alloc_pdp(pm, &pdppg, flags, false);  /* L1 pdp */
 		if (pdppa == POOL_PADDR_INVALID) {
@@ -1739,7 +1840,8 @@ _pmap_get_pdp(struct pmap *pm, vaddr_t v
 	idx = l1pde_index(va);
 	pde = l1[idx];
 	if (!l1pde_valid(pde)) {
-		KASSERT(!kenter || IN_MODULE_VA(va));
+		KASSERTMSG(!kenter || IN_MODULE_VA(va) || PMAP_EFIVA_P(va),
+		    "%s va %" PRIxVADDR, kenter ? "kernel" : "user", va);
 		pdppa0 = pdppa;
 		pdppg0 = pdppg;
 		pdppa = pmap_alloc_pdp(pm, &pdppg, flags, false);  /* L2 pdp */
@@ -1758,7 +1860,8 @@ _pmap_get_pdp(struct pmap *pm, vaddr_t v
 	idx = l2pde_index(va);
 	pde = l2[idx];
 	if (!l2pde_valid(pde)) {
-		KASSERT(!kenter || IN_MODULE_VA(va));
+		KASSERTMSG(!kenter || IN_MODULE_VA(va) || PMAP_EFIVA_P(va),
+		    "%s va %" PRIxVADDR, kenter ? "kernel" : "user", va);
 		pdppa0 = pdppa;
 		pdppg0 = pdppg;
 		pdppa = pmap_alloc_pdp(pm, &pdppg, flags, false);  /* L3 pdp */
@@ -1790,7 +1893,13 @@ _pmap_enter(struct pmap *pm, vaddr_t va,
 	uint32_t mdattr;
 	unsigned int idx;
 	int error = 0;
-	const bool user = (pm != pmap_kernel());
+#if defined(EFI_RUNTIME)
+	const bool efirt_p = pm == pmap_efirt();
+#else
+	const bool efirt_p = false;
+#endif
+	const bool kernel_p = pm == pmap_kernel();
+	const bool user = !kernel_p && !efirt_p;
 	bool need_sync_icache, need_enter_pv;
 
 	UVMHIST_FUNC(__func__);
@@ -2005,7 +2114,7 @@ _pmap_enter(struct pmap *pm, vaddr_t va,
 	attr = L3_PAGE | (kenter ? 0 : LX_BLKPAG_NG);
 	attr = _pmap_pte_adjust_prot(attr, prot, mdattr, user);
 	attr = _pmap_pte_adjust_cacheflags(attr, flags);
-	if (VM_MAXUSER_ADDRESS > va)
+	if (VM_MAXUSER_ADDRESS > va && !efirt_p)
 		attr |= LX_BLKPAG_APUSER;
 	if (flags & PMAP_WIRED)
 		attr |= LX_BLKPAG_OS_WIRED;

Index: src/sys/arch/aarch64/include/pmap.h
diff -u src/sys/arch/aarch64/include/pmap.h:1.51 src/sys/arch/aarch64/include/pmap.h:1.52
--- src/sys/arch/aarch64/include/pmap.h:1.51	Sat Jan 15 08:14:37 2022
+++ src/sys/arch/aarch64/include/pmap.h	Sat Apr  2 11:16:06 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.51 2022/01/15 08:14:37 skrll Exp $ */
+/* $NetBSD: pmap.h,v 1.52 2022/04/02 11:16:06 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -388,6 +388,11 @@ aarch64_mmap_flags(paddr_t mdpgno)
 #define pmap_wired_count(pmap)		((pmap)->pm_stats.wired_count)
 #define pmap_resident_count(pmap)	((pmap)->pm_stats.resident_count)
 
+struct pmap *
+	pmap_efirt(void);
+void	pmap_activate_efirt(void);
+void	pmap_deactivate_efirt(void);
+
 void	pmap_procwr(struct proc *, vaddr_t, int);
 bool	pmap_extract_coherency(pmap_t, vaddr_t, paddr_t *, bool *);
 void	pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t);

Index: src/sys/arch/aarch64/include/vmparam.h
diff -u src/sys/arch/aarch64/include/vmparam.h:1.18 src/sys/arch/aarch64/include/vmparam.h:1.19
--- src/sys/arch/aarch64/include/vmparam.h:1.18	Sun Mar 21 07:32:44 2021
+++ src/sys/arch/aarch64/include/vmparam.h	Sat Apr  2 11:16:06 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: vmparam.h,v 1.18 2021/03/21 07:32:44 skrll Exp $ */
+/* $NetBSD: vmparam.h,v 1.19 2022/04/02 11:16:06 skrll Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -130,7 +130,7 @@
  *   0xffff_0000_0000_0000  -   64T  direct mapping
  *   0xffff_4000_0000_0000  -   32T  (KASAN SHADOW MAP)
  *   0xffff_6000_0000_0000  -   32T  (not used)
- *   0xffff_8000_0000_0000  -    1G  EFI_RUNTIME
+ *   0xffff_8000_0000_0000  -    1G  (EFI_RUNTIME - legacy)
  *   0xffff_8000_4000_0000  -   64T  (not used)
  *   0xffff_c000_0000_0000  -   64T  KERNEL VM Space (including text/data/bss)
  *  (0xffff_c000_4000_0000     -1GB) KERNEL VM start of KVM
@@ -141,6 +141,13 @@
 #define VM_MAX_KERNEL_ADDRESS	((vaddr_t) 0xffffffffffe00000L)
 
 /*
+ * Reserved space for EFI runtime services (legacy)
+ */
+#define	EFI_RUNTIME_VA		0xffff800000000000L
+#define	EFI_RUNTIME_SIZE	0x0000000040000000L
+
+
+/*
  * last 254MB of kernel vm area (0xfffffffff0000000-0xffffffffffe00000)
  * may be used for devmap.  see aarch64/pmap.c:pmap_devmap_*
  */
@@ -149,11 +156,6 @@
 
 #define VM_KERNEL_VM_BASE	(0xffffc00040000000L)
 #define VM_KERNEL_VM_SIZE	(VM_KERNEL_IO_ADDRESS - VM_KERNEL_VM_BASE)
-/*
- * Reserved space for EFI runtime services
- */
-#define	EFI_RUNTIME_VA		0xffff800000000000L
-#define	EFI_RUNTIME_SIZE	0x0000000040000000L
 
 /* virtual sizes (bytes) for various kernel submaps */
 #define USRIOSIZE		(PAGE_SIZE / 8)

Index: src/sys/arch/arm/arm/efi_runtime.c
diff -u src/sys/arch/arm/arm/efi_runtime.c:1.6 src/sys/arch/arm/arm/efi_runtime.c:1.7
--- src/sys/arch/arm/arm/efi_runtime.c:1.6	Sun Oct 10 13:03:09 2021
+++ src/sys/arch/arm/arm/efi_runtime.c	Sat Apr  2 11:16:06 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: efi_runtime.c,v 1.6 2021/10/10 13:03:09 jmcneill Exp $ */
+/* $NetBSD: efi_runtime.c,v 1.7 2022/04/02 11:16:06 skrll Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #include "efi.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efi_runtime.c,v 1.6 2021/10/10 13:03:09 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efi_runtime.c,v 1.7 2022/04/02 11:16:06 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/mutex.h>
@@ -54,11 +54,11 @@ __KERNEL_RCSID(0, "$NetBSD: efi_runtime.
 #define	EFI_DEVICE_ERROR	EFIERR(7)
 
 static kmutex_t efi_lock;
-
-static struct efi_rt *RT = NULL;
+static struct efi_rt *RT;
+static struct efi_rt efi_rtcopy;
 
 #if NEFI > 0 && BYTE_ORDER == LITTLE_ENDIAN
-static const struct efi_ops arm_efi_ops = {
+static struct efi_ops arm_efi_ops = {
 	.efi_gettime	= arm_efirt_gettime,
 	.efi_settime	= arm_efirt_settime,
 	.efi_getvar	= arm_efirt_getvar,
@@ -95,10 +95,19 @@ arm_efirt_init(paddr_t efi_system_table)
 		return EINVAL;
 	}
 
-	RT = ST->st_rt;
+	struct efi_rt *rt = ST->st_rt;
 	mutex_init(&efi_lock, MUTEX_DEFAULT, IPL_HIGH);
 
+	pmap_activate_efirt();
+
+	memcpy(&efi_rtcopy, rt, sizeof(efi_rtcopy));
+	RT = &efi_rtcopy;
+
+	pmap_deactivate_efirt();
+
+#if NEFI > 0
 	efi_register_ops(&arm_efi_ops);
+#endif
 
 	return 0;
 #else

Index: src/sys/arch/arm/arm32/arm32_kvminit.c
diff -u src/sys/arch/arm/arm32/arm32_kvminit.c:1.68 src/sys/arch/arm/arm32/arm32_kvminit.c:1.69
--- src/sys/arch/arm/arm32/arm32_kvminit.c:1.68	Sun Mar 21 09:00:55 2021
+++ src/sys/arch/arm/arm32/arm32_kvminit.c	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: arm32_kvminit.c,v 1.68 2021/03/21 09:00:55 skrll Exp $	*/
+/*	$NetBSD: arm32_kvminit.c,v 1.69 2022/04/02 11:16:07 skrll Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003, 2005  Genetec Corporation.  All rights reserved.
@@ -123,11 +123,12 @@
 
 #include "opt_arm_debug.h"
 #include "opt_arm_start.h"
+#include "opt_efi.h"
 #include "opt_fdt.h"
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: arm32_kvminit.c,v 1.68 2021/03/21 09:00:55 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: arm32_kvminit.c,v 1.69 2022/04/02 11:16:07 skrll Exp $");
 
 #include <sys/param.h>
 
@@ -171,6 +172,12 @@ __KERNEL_RCSID(0, "$NetBSD: arm32_kvmini
 #endif
 #endif
 
+#if defined(EFI_RUNTIME)
+#if !defined(ARM_MMU_EXTENDED)
+#error EFI_RUNTIME is only supported with ARM_MMU_EXTENDED
+#endif
+#endif
+
 struct bootmem_info bootmem_info;
 
 extern void *msgbufaddr;
@@ -389,6 +396,11 @@ valloc_pages(struct bootmem_info *bmi, p
 		valloc_pages(bmi, &kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE,
 		    VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE, true);
 		add_pages(bmi, &kernel_l1pt);
+#if defined(EFI_RUNTIME)
+		valloc_pages(bmi, &efirt_l1pt, L1_TABLE_SIZE / PAGE_SIZE,
+		    VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE, true);
+		add_pages(bmi, &efirt_l1pt);
+#endif
 	}
 
 	while (nbytes > free_pv->pv_size) {
@@ -544,6 +556,10 @@ arm32_kernel_vm_init(vaddr_t kernel_vm_b
 	kernel_l1pt.pv_pa = 0;
 	kernel_l1pt.pv_va = 0;
 
+#if defined(EFI_RUNTIME)
+	efirt_l1pt.pv_pa = 0;
+	efirt_l1pt.pv_va = 0;
+#endif
 	/*
 	 * Allocate the L2 pages, but if we get to a page that is aligned for
 	 * an L1 page table, we will allocate the pages for it first and then
@@ -972,6 +988,12 @@ arm32_kernel_vm_init(vaddr_t kernel_vm_b
 	    kernel_l1pt.pv_pa, kernel_l1pt.pv_pa + L1_TABLE_SIZE - 1,
 	    kernel_l1pt.pv_va, kernel_l1pt.pv_va + L1_TABLE_SIZE - 1,
 	    L1_TABLE_SIZE / PAGE_SIZE);
+#if defined(EFI_RUNTIME)
+	VPRINTF(mem_fmt, "EFI L1 page directory",
+	    efirt_l1pt.pv_pa, efirt_l1pt.pv_pa + L1_TABLE_SIZE - 1,
+	    efirt_l1pt.pv_va, efirt_l1pt.pv_va + L1_TABLE_SIZE - 1,
+	    L1_TABLE_SIZE / PAGE_SIZE);
+#endif
 	VPRINTF(mem_fmt, "ABT stack (CPU 0)",
 	    abtstack.pv_pa, abtstack.pv_pa + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
 	    abtstack.pv_va, abtstack.pv_va + (ABT_STACK_SIZE * PAGE_SIZE) - 1,

Index: src/sys/arch/arm/arm32/locore.S
diff -u src/sys/arch/arm/arm32/locore.S:1.43 src/sys/arch/arm/arm32/locore.S:1.44
--- src/sys/arch/arm/arm32/locore.S:1.43	Fri Aug 28 13:36:52 2020
+++ src/sys/arch/arm/arm32/locore.S	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.43 2020/08/28 13:36:52 skrll Exp $	*/
+/*	$NetBSD: locore.S,v 1.44 2022/04/02 11:16:07 skrll Exp $	*/
 
 /*
  * Copyright (C) 1994-1997 Mark Brinicombe
@@ -40,7 +40,7 @@
 #include <arm/asm.h>
 #include <arm/locore.h>
 
-	RCSID("$NetBSD: locore.S,v 1.43 2020/08/28 13:36:52 skrll Exp $")
+	RCSID("$NetBSD: locore.S,v 1.44 2022/04/02 11:16:07 skrll Exp $")
 
 /*
  * This is for kvm_mkdb, and should be the address of the beginning
@@ -201,6 +201,18 @@ ENTRY_NP(cpu_reset)
 END(cpu_reset)
 #endif	/* OFW */
 
+
+/*
+ * int cpu_set_onfault(struct faultbuf *fb)
+ */
+ENTRY_NP(cpu_set_onfault)
+	GET_CURPCB(r1)
+	str	r0, [r1, #PCB_ONFAULT]
+	stmia	r0, {r4-r14}
+	mov	r0, #0
+	RET
+END(cpu_set_onfault)
+
 /*
  * setjump + longjmp
  */

Index: src/sys/arch/arm/arm32/pmap.c
diff -u src/sys/arch/arm/arm32/pmap.c:1.434 src/sys/arch/arm/arm32/pmap.c:1.435
--- src/sys/arch/arm/arm32/pmap.c:1.434	Sat Mar 19 09:54:25 2022
+++ src/sys/arch/arm/arm32/pmap.c	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.c,v 1.434 2022/03/19 09:54:25 skrll Exp $	*/
+/*	$NetBSD: pmap.c,v 1.435 2022/04/02 11:16:07 skrll Exp $	*/
 
 /*
  * Copyright 2003 Wasabi Systems, Inc.
@@ -184,6 +184,7 @@
 #include "opt_arm_debug.h"
 #include "opt_cpuoptions.h"
 #include "opt_ddb.h"
+#include "opt_efi.h"
 #include "opt_lockdebug.h"
 #include "opt_multiprocessor.h"
 
@@ -192,7 +193,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.434 2022/03/19 09:54:25 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.435 2022/04/02 11:16:07 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -225,6 +226,12 @@ __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.4
 #define VPRINTF(...)	__nothing
 #endif
 
+#if defined(EFI_RUNTIME)
+#if !defined(ARM_MMU_EXTENDED)
+#error EFI_RUNTIME is only supported with ARM_MMU_EXTENDED
+#endif
+#endif
+
 /*
  * pmap_kernel() points here
  */
@@ -238,6 +245,17 @@ static struct pmap	kernel_pmap_store = {
 struct pmap * const	kernel_pmap_ptr = &kernel_pmap_store;
 #undef pmap_kernel
 #define pmap_kernel()	(&kernel_pmap_store)
+
+#if defined(EFI_RUNTIME)
+static struct pmap	efirt_pmap;
+
+struct pmap *
+pmap_efirt(void)
+{
+	return &efirt_pmap;
+}
+#endif
+
 #ifdef PMAP_NEED_ALLOC_POOLPAGE
 int			arm_poolpage_vmfreelist = VM_FREELIST_DEFAULT;
 #endif
@@ -760,6 +778,9 @@ pv_addrqh_t pmap_boot_freeq = SLIST_HEAD
 pv_addr_t kernelpages;
 pv_addr_t kernel_l1pt;
 pv_addr_t systempage;
+#if defined(EFI_RUNTIME)
+pv_addr_t efirt_l1pt;
+#endif
 
 #ifdef PMAP_CACHE_VIPT
 #define PMAP_VALIDATE_MD_PAGE(md)	\
@@ -3075,7 +3096,12 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 	struct vm_page *pg, *opg;
 	u_int nflags;
 	u_int oflags;
-	const bool kpm_p = (pm == pmap_kernel());
+	const bool kpm_p = pm == pmap_kernel();
+#if defined(EFI_RUNTIME)
+	const bool efirt_p = pm == pmap_efirt();
+#else
+	const bool efirt_p = false;
+#endif
 #ifdef ARM_HAS_VBAR
 	const bool vector_page_p = false;
 #else
@@ -3298,6 +3324,12 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 		if (prot & VM_PROT_WRITE)
 			npte = l2pte_set_writable(npte);
 
+		if (efirt_p) {
+			if (prot & VM_PROT_EXECUTE) {
+				npte &= ~L2_XS_XN;	/* and executable */
+			}
+		}
+
 		/*
 		 * Make sure the vector table is mapped cacheable
 		 */
@@ -3357,6 +3389,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_
 	 * If exec protection was requested but the page hasn't been synced,
 	 * sync it now and allow execution from it.
 	 */
+
 	if ((nflags & PVF_EXEC) && (npte & L2_XS_XN)) {
 		struct vm_page_md *md = VM_PAGE_TO_MD(pg);
 		npte &= ~L2_XS_XN;
@@ -4948,6 +4981,53 @@ pmap_md_pdetab_deactivate(pmap_t pm)
 }
 #endif
 
+
+#if defined(EFI_RUNTIME)
+void
+pmap_activate_efirt(void)
+{
+	kpreempt_disable();
+
+	struct cpu_info * const ci = curcpu();
+	struct pmap * const pm = &efirt_pmap;
+	struct pmap_asid_info * const pai = PMAP_PAI(pm, cpu_tlb_info(ci));
+
+	UVMHIST_FUNC(__func__);
+	UVMHIST_CALLARGS(maphist, " (pm=%#jx)", (uintptr_t)pm, 0, 0, 0);
+
+	PMAPCOUNT(activations);
+
+	/*
+	 * Assume that TTBR1 has only global mappings and TTBR0 only
+	 * has non-global mappings.  To prevent speculation from doing
+	 * evil things we disable translation table walks using TTBR0
+	 * before setting the CONTEXTIDR (ASID) or new TTBR0 value.
+	 * Once both are set, table walks are reenabled.
+	 */
+	const uint32_t old_ttbcr = armreg_ttbcr_read();
+	armreg_ttbcr_write(old_ttbcr | TTBCR_S_PD0);
+	isb();
+
+	armreg_contextidr_write(pai->pai_asid);
+	armreg_ttbr_write(pm->pm_l1_pa |
+	    (ci->ci_mpidr ? TTBR_MPATTR : TTBR_UPATTR));
+	/*
+	 * Now we can reenable tablewalks since the CONTEXTIDR and TTRB0
+	 * have been updated.
+	 */
+	isb();
+
+	armreg_ttbcr_write(old_ttbcr & ~TTBCR_S_PD0);
+
+	ci->ci_pmap_asid_cur = pai->pai_asid;
+	ci->ci_pmap_cur = pm;
+
+	UVMHIST_LOG(maphist, " <-- done", 0, 0, 0, 0);
+}
+
+#endif
+
+
 void
 pmap_activate(struct lwp *l)
 {
@@ -5106,6 +5186,7 @@ pmap_activate(struct lwp *l)
 	UVMHIST_LOG(maphist, " <-- done", 0, 0, 0, 0);
 }
 
+
 void
 pmap_deactivate(struct lwp *l)
 {
@@ -5131,6 +5212,35 @@ pmap_deactivate(struct lwp *l)
 	UVMHIST_LOG(maphist, "  <-- done", 0, 0, 0, 0);
 }
 
+
+#if defined(EFI_RUNTIME)
+void
+pmap_deactivate_efirt(void)
+{
+	UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist);
+
+	struct cpu_info * const ci = curcpu();
+
+	/*
+	 * Disable translation table walks from TTBR0 while no pmap has been
+	 * activated.
+	 */
+	const uint32_t old_ttbcr = armreg_ttbcr_read();
+	armreg_ttbcr_write(old_ttbcr | TTBCR_S_PD0);
+	isb();
+
+	armreg_contextidr_write(KERNEL_PID);
+	isb();
+
+	KASSERTMSG(ci->ci_pmap_asid_cur == KERNEL_PID, "ci_pmap_asid_cur %u",
+	    ci->ci_pmap_asid_cur);
+	kpreempt_enable();
+
+	UVMHIST_LOG(maphist, " <-- done", 0, 0, 0, 0);
+}
+#endif
+
+
 void
 pmap_update(pmap_t pm)
 {
@@ -6245,6 +6355,27 @@ pmap_bootstrap(vaddr_t vstart, vaddr_t v
 #endif
 	mutex_init(&pm->pm_lock, MUTEX_DEFAULT, IPL_VM);
 
+
+#if defined(EFI_RUNTIME)
+	VPRINTF("efirt ");
+	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(curcpu()));
+
+	efipai->pai_asid = KERNEL_PID;
+	efipm->pm_refs = 1;
+	efipm->pm_stats.wired_count = 0;
+	efipm->pm_stats.resident_count = 1;
+	efipm->pm_l1 = (pd_entry_t *)efirt_l1pt.pv_va;
+	efipm->pm_l1_pa = efirt_l1pt.pv_pa;
+	// Needed?
+#ifdef MULTIPROCESSOR
+	kcpuset_create(&efipm->pm_active, true);
+	kcpuset_create(&efipm->pm_onproc, true);
+#endif
+	mutex_init(&efipm->pm_lock, MUTEX_DEFAULT, IPL_VM);
+#endif
+
 	VPRINTF("locks ");
 	/*
 	 * pmap_kenter_pa() and pmap_kremove() may be called from interrupt
@@ -6338,6 +6469,13 @@ pmap_bootstrap(vaddr_t vstart, vaddr_t v
 		printf("pmap_bootstrap: WARNING! wrong cache mode for "
 		    "primary L1 @ 0x%lx\n", kernel_l1pt.pv_va);
 	}
+#if defined(EFI_RUNTIME)
+	if (pmap_set_pt_cache_mode(l1pt, efirt_l1pt.pv_va,
+		    L1_TABLE_SIZE / L2_S_SIZE)) {
+		printf("pmap_bootstrap: WARNING! wrong cache mode for "
+		    "EFI RT L1 @ 0x%lx\n", efirt_l1pt.pv_va);
+	}
+#endif
 
 #ifdef PMAP_CACHE_VIVT
 	cpu_dcache_wbinv_all();

Index: src/sys/arch/arm/conf/files.arm
diff -u src/sys/arch/arm/conf/files.arm:1.165 src/sys/arch/arm/conf/files.arm:1.166
--- src/sys/arch/arm/conf/files.arm:1.165	Fri Aug  6 19:38:53 2021
+++ src/sys/arch/arm/conf/files.arm	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-#	$NetBSD: files.arm,v 1.165 2021/08/06 19:38:53 jmcneill Exp $
+#	$NetBSD: files.arm,v 1.166 2022/04/02 11:16:07 skrll Exp $
 
 # temporary define to allow easy moving to ../arch/arm/arm32
 defflag				ARM32
@@ -208,9 +208,14 @@ file	arch/arm/arm/procfs_machdep.c		proc
 file	arch/arm/arm/sig_machdep.c
 file	arch/arm/arm/sigcode.S
 file	arch/arm/arm/syscall.c
+file	arch/arm/arm/trap.c
 file	arch/arm/arm/undefined.c
 file	arch/arm/arm/vectors.S			arm32
 
+# EFI runtime (machdep)
+file	arch/arm/arm/efi_machdep.c		efi_runtime
+
+
 # files common to arm32 implementations
 file	arch/arm/arm32/arm32_machdep.c		arm32
 file	arch/arm/arm32/bus_dma.c		arm32

Index: src/sys/arch/arm/include/asan.h
diff -u src/sys/arch/arm/include/asan.h:1.7 src/sys/arch/arm/include/asan.h:1.8
--- src/sys/arch/arm/include/asan.h:1.7	Wed Jan 27 08:40:32 2021
+++ src/sys/arch/arm/include/asan.h	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: asan.h,v 1.7 2021/01/27 08:40:32 skrll Exp $	*/
+/*	$NetBSD: asan.h,v 1.8 2022/04/02 11:16:07 skrll Exp $	*/
 
 /*
  * Copyright (c) 2020 The NetBSD Foundation, Inc.
@@ -29,6 +29,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "opt_efi.h"
+
 #include <sys/atomic.h>
 #include <sys/ksyms.h>
 

Index: src/sys/arch/arm/include/frame.h
diff -u src/sys/arch/arm/include/frame.h:1.22 src/sys/arch/arm/include/frame.h:1.23
--- src/sys/arch/arm/include/frame.h:1.22	Wed Oct  6 05:29:32 2021
+++ src/sys/arch/arm/include/frame.h	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: frame.h,v 1.22 2021/10/06 05:29:32 skrll Exp $	*/
+/*	$NetBSD: frame.h,v 1.23 2022/04/02 11:16:07 skrll Exp $	*/
 
 /*
  * Copyright (c) 1994-1997 Mark Brinicombe.
@@ -81,6 +81,22 @@ typedef struct trapframe {
 
 #define TRAP_USERMODE(tf)	(((tf)->tf_spsr & PSR_MODE) == PSR_USR32_MODE)
 
+#define FB_R4	0
+#define FB_R5	1
+#define FB_R6	2
+#define FB_R7	3
+#define FB_R8	4
+#define FB_R9	5
+#define FB_R10	6
+#define FB_R11	7
+#define FB_R12	8
+#define FB_R13	9
+#define FB_R14	10
+#define FB_MAX	11
+struct faultbuf {
+	register_t fb_reg[FB_MAX];
+};
+
 /*
  * Signal frame.  Pushed onto user stack before calling sigcode.
  */

Index: src/sys/arch/arm/include/arm32/machdep.h
diff -u src/sys/arch/arm/include/arm32/machdep.h:1.35 src/sys/arch/arm/include/arm32/machdep.h:1.36
--- src/sys/arch/arm/include/arm32/machdep.h:1.35	Fri Aug 28 13:36:52 2020
+++ src/sys/arch/arm/include/arm32/machdep.h	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.h,v 1.35 2020/08/28 13:36:52 skrll Exp $ */
+/* $NetBSD: machdep.h,v 1.36 2022/04/02 11:16:07 skrll Exp $ */
 
 #ifndef _ARM32_MACHDEP_H_
 #define _ARM32_MACHDEP_H_
@@ -110,6 +110,31 @@ void set_spl_masks(void);
 void dump_spl_masks(void);
 #endif
 
+/* cpu_onfault */
+int cpu_set_onfault(struct faultbuf *) __returns_twice;
+void cpu_jump_onfault(struct trapframe *, const struct faultbuf *, int);
+
+static inline void
+cpu_unset_onfault(void)
+{
+	curpcb->pcb_onfault = NULL;
+}
+
+static inline void
+cpu_enable_onfault(struct faultbuf *fb)
+{
+	curpcb->pcb_onfault = fb;
+}
+
+static inline struct faultbuf *
+cpu_disable_onfault(void)
+{
+	struct faultbuf * const fb = curpcb->pcb_onfault;
+	if (fb != NULL)
+		curpcb->pcb_onfault = NULL;
+	return fb;
+}
+
 #endif	/* _KERNEL */
 
 #endif	/* _ARM32_MACHDEP_H_ */

Index: src/sys/arch/arm/include/arm32/pmap.h
diff -u src/sys/arch/arm/include/arm32/pmap.h:1.172 src/sys/arch/arm/include/arm32/pmap.h:1.173
--- src/sys/arch/arm/include/arm32/pmap.h:1.172	Sat Jan 15 08:14:37 2022
+++ src/sys/arch/arm/include/arm32/pmap.h	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: pmap.h,v 1.172 2022/01/15 08:14:37 skrll Exp $	*/
+/*	$NetBSD: pmap.h,v 1.173 2022/04/02 11:16:07 skrll Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003 Wasabi Systems, Inc.
@@ -286,6 +286,9 @@ extern pv_addr_t undstack;
 extern pv_addr_t idlestack;
 extern pv_addr_t systempage;
 extern pv_addr_t kernel_l1pt;
+#if defined(EFI_RUNTIME)
+extern pv_addr_t efirt_l1pt;
+#endif
 
 #ifdef ARM_MMU_EXTENDED
 extern bool arm_has_tlbiasid_p;	/* also in <arm/locore.h> */
@@ -386,6 +389,8 @@ void	pmap_prefer(vaddr_t, vaddr_t *, int
 
 #ifdef ARM_MMU_EXTENDED
 int	pmap_maxproc_set(int);
+struct pmap *
+	pmap_efirt(void);
 #endif
 
 void	pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t);
@@ -398,6 +403,11 @@ vaddr_t	pmap_steal_memory(vsize_t, vaddr
 #endif
 void	pmap_bootstrap(vaddr_t, vaddr_t);
 
+struct pmap *
+	pmap_efirt(void);
+void	pmap_activate_efirt(void);
+void	pmap_deactivate_efirt(void);
+
 void	pmap_do_remove(pmap_t, vaddr_t, vaddr_t, int);
 int	pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t, int);
 int	pmap_prefetchabt_fixup(void *);

Index: src/sys/arch/evbarm/conf/GENERIC
diff -u src/sys/arch/evbarm/conf/GENERIC:1.106 src/sys/arch/evbarm/conf/GENERIC:1.107
--- src/sys/arch/evbarm/conf/GENERIC:1.106	Mon Mar 21 09:20:04 2022
+++ src/sys/arch/evbarm/conf/GENERIC	Sat Apr  2 11:16:07 2022
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: GENERIC,v 1.106 2022/03/21 09:20:04 jmcneill Exp $
+#	$NetBSD: GENERIC,v 1.107 2022/04/02 11:16:07 skrll Exp $
 #
 #	GENERIC ARM (aarch32) kernel
 #
@@ -109,6 +109,10 @@ makeoptions 	COPY_SYMTAB=1
 
 config		netbsd		root on ? type ?
 
+# EFI runtime support
+options 	EFI_RUNTIME
+#pseudo-device	efi		# /dev/efi
+
 # Device tree support
 armfdt0		at root
 simplebus*	at fdt? pass 0

Index: src/sys/arch/evbarm/fdt/fdt_machdep.c
diff -u src/sys/arch/evbarm/fdt/fdt_machdep.c:1.90 src/sys/arch/evbarm/fdt/fdt_machdep.c:1.91
--- src/sys/arch/evbarm/fdt/fdt_machdep.c:1.90	Sat Mar 19 13:51:35 2022
+++ src/sys/arch/evbarm/fdt/fdt_machdep.c	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_machdep.c,v 1.90 2022/03/19 13:51:35 hannken Exp $ */
+/* $NetBSD: fdt_machdep.c,v 1.91 2022/04/02 11:16:07 skrll Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.90 2022/03/19 13:51:35 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_machdep.c,v 1.91 2022/04/02 11:16:07 skrll Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_bootconfig.h"
@@ -613,12 +613,6 @@ initarm(void *arg)
 	VPRINTF("%s: fdt_build_bootconfig\n", __func__);
 	fdt_build_bootconfig(memory_start, memory_end);
 
-#ifdef EFI_RUNTIME
-	fdt_map_efi_runtime("netbsd,uefi-runtime-code", ARM_EFIRT_MEM_CODE);
-	fdt_map_efi_runtime("netbsd,uefi-runtime-data", ARM_EFIRT_MEM_DATA);
-	fdt_map_efi_runtime("netbsd,uefi-runtime-mmio", ARM_EFIRT_MEM_MMIO);
-#endif
-
 	/* Perform PT build and VM init */
 	cpu_kernel_vm_init(memory_start, memory_size);
 
@@ -722,6 +716,11 @@ consinit(void)
 void
 cpu_startup_hook(void)
 {
+#ifdef EFI_RUNTIME
+	fdt_map_efi_runtime("netbsd,uefi-runtime-code", ARM_EFIRT_MEM_CODE);
+	fdt_map_efi_runtime("netbsd,uefi-runtime-data", ARM_EFIRT_MEM_DATA);
+	fdt_map_efi_runtime("netbsd,uefi-runtime-mmio", ARM_EFIRT_MEM_MMIO);
+#endif
 
 	fdtbus_intr_init();
 

Index: src/sys/stand/efiboot/version
diff -u src/sys/stand/efiboot/version:1.30 src/sys/stand/efiboot/version:1.31
--- src/sys/stand/efiboot/version:1.30	Fri Mar 25 21:23:00 2022
+++ src/sys/stand/efiboot/version	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-$NetBSD: version,v 1.30 2022/03/25 21:23:00 jmcneill Exp $
+$NetBSD: version,v 1.31 2022/04/02 11:16:07 skrll Exp $
 
 NOTE ANY CHANGES YOU MAKE TO THE EFI BOOTLOADER HERE.  The format of this
 file is important - make sure the entries are appended on end, last item
@@ -33,3 +33,4 @@ is taken as the current.
 2.10:	Use disk I/O protocol for block devices.
 2.11:	Add support for changing the video mode.
 2.12:	Add userconf support.
+2.13:	Add Arm RT support and change Arm64 (aarch64) RT VAs.

Index: src/sys/stand/efiboot/bootaa64/Makefile
diff -u src/sys/stand/efiboot/bootaa64/Makefile:1.11 src/sys/stand/efiboot/bootaa64/Makefile:1.12
--- src/sys/stand/efiboot/bootaa64/Makefile:1.11	Wed Oct  6 10:13:19 2021
+++ src/sys/stand/efiboot/bootaa64/Makefile	Sat Apr  2 11:16:07 2022
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.11 2021/10/06 10:13:19 jmcneill Exp $
+# $NetBSD: Makefile,v 1.12 2022/04/02 11:16:07 skrll Exp $
 
 PROG=		bootaa64.efi
 OBJFMT=		binary
@@ -16,8 +16,8 @@ EXTRA_SOURCES+=	cache.S
 COPTS+=		-mgeneral-regs-only -mlittle-endian -fno-jump-tables
 AFLAGS+=	-mlittle-endian
 CFLAGS+=	-DEFIBOOT_ALIGN=0x200000
-CFLAGS+=	-DEFIBOOT_RUNTIME_ADDRESS=0xffff800000000000L
-CFLAGS+=	-DEFIBOOT_RUNTIME_SIZE=0x40000000UL
+CFLAGS+=	-DEFIBOOT_RUNTIME_ADDRESS=0x0000000200200000UL
+CFLAGS+=	-DEFIBOOT_RUNTIME_SIZE=0xfe00000UL
 CFLAGS+=	-DEFIBOOT_MODULE_MACHINE=\"evbarm\"
 LDFLAGS+=	-EL
 

Index: src/sys/stand/efiboot/bootarm/Makefile
diff -u src/sys/stand/efiboot/bootarm/Makefile:1.8 src/sys/stand/efiboot/bootarm/Makefile:1.9
--- src/sys/stand/efiboot/bootarm/Makefile:1.8	Wed Oct  6 10:15:20 2021
+++ src/sys/stand/efiboot/bootarm/Makefile	Sat Apr  2 11:16:08 2022
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.8 2021/10/06 10:15:20 jmcneill Exp $
+# $NetBSD: Makefile,v 1.9 2022/04/02 11:16:08 skrll Exp $
 
 PROG=		bootarm.efi
 OBJFMT=		binary
@@ -16,7 +16,10 @@ COPTS+=		-mfloat-abi=soft -mno-unaligned
 COPTS+=		-ffreestanding -fno-unwind-tables
 AFLAGS+=	-mlittle-endian
 CFLAGS+=	-DEFIBOOT_ALIGN=0x1000000
+CFLAGS+=	-DEFIBOOT_RUNTIME_ADDRESS=0x00010000U
+CFLAGS+=	-DEFIBOOT_RUNTIME_SIZE=0x7ff0000U
 CFLAGS+=	-DEFIBOOT_MODULE_MACHINE=\"evbarm\"
+#CPPFLAGS.efifdt.c+=   -Wconversion
 LDFLAGS+=	-N -EL
 
 .include "${.CURDIR}/../Makefile.efiboot"

Added files:

Index: src/sys/arch/arm/arm/efi_machdep.c
diff -u /dev/null src/sys/arch/arm/arm/efi_machdep.c:1.1
--- /dev/null	Sat Apr  2 11:16:08 2022
+++ src/sys/arch/arm/arm/efi_machdep.c	Sat Apr  2 11:16:06 2022
@@ -0,0 +1,123 @@
+/* $NetBSD: efi_machdep.c,v 1.1 2022/04/02 11:16:06 skrll Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jared McNeill <jmcne...@invisible.ca> and Nick Hudson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.1 2022/04/02 11:16:06 skrll Exp $");
+
+#include <sys/param.h>
+#include <uvm/uvm_extern.h>
+
+#include <arm/vfpreg.h>
+
+#include <arm/arm/efi_runtime.h>
+
+#include <arm/arm32/machdep.h>
+
+static struct {
+	struct faultbuf	aert_faultbuf;
+	uint32_t	aert_tpidrprw;
+	uint32_t	aert_fpexc;
+} arm_efirt_state;
+
+int
+arm_efirt_md_enter(void)
+{
+	arm_efirt_state.aert_tpidrprw = armreg_tpidrprw_read();
+
+	/* Disable the VFP.  */
+	arm_efirt_state.aert_fpexc = armreg_fpexc_read();
+	armreg_fpexc_write(arm_efirt_state.aert_fpexc & ~VFP_FPEXC_EN);
+	isb();
+
+	/*
+	 * Install custom fault handler. EFI lock is held across calls so
+	 * shared faultbuf is safe here.
+	 */
+	int err = cpu_set_onfault(&arm_efirt_state.aert_faultbuf);
+	if (err)
+		return err;
+
+	pmap_activate_efirt();
+
+	return 0;
+}
+
+void
+arm_efirt_md_exit(void)
+{
+	pmap_deactivate_efirt();
+
+	armreg_tpidrprw_write(arm_efirt_state.aert_tpidrprw);
+
+	/* Restore FP access (if it existed) */
+	armreg_fpexc_write(arm_efirt_state.aert_fpexc);
+	isb();
+
+	/* Remove custom fault handler */
+	cpu_unset_onfault();
+}
+
+
+void
+arm_efirt_md_map_range(vaddr_t va, paddr_t pa, size_t sz,
+    enum arm_efirt_mem_type type)
+{
+	int flags = 0;
+	int prot = 0;
+
+	switch (type) {
+	case ARM_EFIRT_MEM_CODE:
+		/* need write permission because fw devs */
+		prot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
+		break;
+	case ARM_EFIRT_MEM_DATA:
+		prot = VM_PROT_READ | VM_PROT_WRITE;
+		break;
+	case ARM_EFIRT_MEM_MMIO:
+		prot = VM_PROT_READ | VM_PROT_WRITE;
+		flags = PMAP_DEV;
+		break;
+	default:
+		panic("%s: unsupported type %d", __func__, type);
+	}
+	if (va >= VM_MAXUSER_ADDRESS || va >= VM_MAXUSER_ADDRESS - sz) {
+		printf("Incorrect EFI mapping range %" PRIxVADDR
+		    "- %" PRIxVADDR "\n", va, va + sz);
+	}
+
+	while (sz != 0) {
+		pmap_enter(pmap_efirt(), va, pa, prot, flags | PMAP_WIRED);
+		va += PAGE_SIZE;
+		pa += PAGE_SIZE;
+		sz -= PAGE_SIZE;
+	}
+	pmap_update(pmap_efirt());
+}
Index: src/sys/arch/arm/arm/trap.c
diff -u /dev/null src/sys/arch/arm/arm/trap.c:1.1
--- /dev/null	Sat Apr  2 11:16:08 2022
+++ src/sys/arch/arm/arm/trap.c	Sat Apr  2 11:16:06 2022
@@ -0,0 +1,61 @@
+/*	$NetBSD: trap.c,v 1.1 2022/04/02 11:16:06 skrll Exp $	*/
+
+/*-
+ * Copyright (c) 2022 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Nick Hudson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.1 2022/04/02 11:16:06 skrll Exp $");
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <arm/frame.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <arm/arm32/pmap.h>
+#include <arm/arm32/machdep.h>
+
+void
+cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int val)
+{
+	tf->tf_r4 = fb->fb_reg[FB_R4];
+	tf->tf_r5 = fb->fb_reg[FB_R5];
+	tf->tf_r6 = fb->fb_reg[FB_R6];
+	tf->tf_r7 = fb->fb_reg[FB_R7];
+	tf->tf_r8 = fb->fb_reg[FB_R8];
+	tf->tf_r9 = fb->fb_reg[FB_R9];
+	tf->tf_r10 = fb->fb_reg[FB_R10];
+	tf->tf_r11 = fb->fb_reg[FB_R11];
+	tf->tf_r12 = fb->fb_reg[FB_R12];
+	tf->tf_svc_sp = fb->fb_reg[FB_R13];
+	tf->tf_pc = fb->fb_reg[FB_R14];
+	tf->tf_r0 = val;
+}
+

Reply via email to