From 60f107aaa53aa6caa293d6395febcaf801826f79 Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 6 Nov 2022 11:44:30 +0000 Subject: [PATCH] Make EFI runtime calls more robust on arm64 as well. While I have not seen any broken implementations yet, Linux developers claim that arm64 machines intended to run Windows are not much better than x86 machines. And I totally believe that. ok patrick@ --- sys/arch/arm64/arm64/support.S | 5 +++-- sys/arch/arm64/arm64/trap.c | 14 ++++++++++---- sys/arch/arm64/conf/files.arm64 | 4 ++-- sys/arch/arm64/dev/efi_machdep.c | 27 +++++++++++++++++++++++---- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/sys/arch/arm64/arm64/support.S b/sys/arch/arm64/arm64/support.S index a08d11d64c4..5eebc4dbcad 100644 --- a/sys/arch/arm64/arm64/support.S +++ b/sys/arch/arm64/arm64/support.S @@ -1,4 +1,4 @@ -/* $OpenBSD: support.S,v 1.9 2019/03/15 05:42:38 kevlo Exp $ */ +/* $OpenBSD: support.S,v 1.10 2022/11/06 11:44:30 kettenis Exp $ */ /*- * Copyright (c) 2014 Andrew Turner * Copyright (c) 2014-2015 The FreeBSD Foundation @@ -36,8 +36,9 @@ #include #include "assym.h" +#include "efi.h" -#ifdef DDB +#if defined(DDB) || NEFI > 0 ENTRY(setjmp) RETGUARD_SETUP(setjmp, x15) /* Store the stack pointer */ diff --git a/sys/arch/arm64/arm64/trap.c b/sys/arch/arm64/arm64/trap.c index d30e40eb27d..1932e3850d6 100644 --- a/sys/arch/arm64/arm64/trap.c +++ b/sys/arch/arm64/arm64/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.40 2022/08/15 13:33:22 jsg Exp $ */ +/* $OpenBSD: trap.c,v 1.41 2022/11/06 11:44:30 kettenis Exp $ */ /*- * Copyright (c) 2014 Andrew Turner * All rights reserved. @@ -158,11 +158,14 @@ kdata_abort(struct trapframe *frame, uint64_t esr, uint64_t far, int exe) * Only allow user-space access using * unprivileged load/store instructions. */ - if (!is_unpriv_ldst(frame->tf_elr)) { + if (is_unpriv_ldst(frame->tf_elr)) + map = &p->p_vmspace->vm_map; + else if (pcb->pcb_onfault != NULL) + map = kernel_map; + else { panic("attempt to access user address" " 0x%llx from EL1", far); } - map = &p->p_vmspace->vm_map; } /* Handle referenced/modified emulation */ @@ -175,7 +178,7 @@ kdata_abort(struct trapframe *frame, uint64_t esr, uint64_t far, int exe) if (error != 0) { if (curcpu()->ci_idepth == 0 && - pcb->pcb_onfault != 0) { + pcb->pcb_onfault != NULL) { frame->tf_elr = (register_t)pcb->pcb_onfault; return; } @@ -215,6 +218,9 @@ do_el1h_sync(struct trapframe *frame) case EXCP_FP_SIMD: case EXCP_TRAP_FP: panic("FP exception in the kernel"); + case EXCP_INSN_ABORT: + kdata_abort(frame, esr, far, 1); + break; case EXCP_DATA_ABORT: kdata_abort(frame, esr, far, 0); break; diff --git a/sys/arch/arm64/conf/files.arm64 b/sys/arch/arm64/conf/files.arm64 index 2a7bdba0c21..e8087bcadd9 100644 --- a/sys/arch/arm64/conf/files.arm64 +++ b/sys/arch/arm64/conf/files.arm64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.arm64,v 1.61 2022/10/03 19:32:22 kettenis Exp $ +# $OpenBSD: files.arm64,v 1.62 2022/11/06 11:44:30 kettenis Exp $ maxpartitions 16 maxusers 2 8 128 @@ -65,7 +65,7 @@ file arch/arm64/dev/simplebus.c simplebus device efi {} attach efi at fdt -file arch/arm64/dev/efi_machdep.c efi +file arch/arm64/dev/efi_machdep.c efi needs-flag device smbios attach smbios at efi diff --git a/sys/arch/arm64/dev/efi_machdep.c b/sys/arch/arm64/dev/efi_machdep.c index 1dd2c4eb71b..3779f9feba1 100644 --- a/sys/arch/arm64/dev/efi_machdep.c +++ b/sys/arch/arm64/dev/efi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efi_machdep.c,v 1.4 2022/10/29 20:35:50 kettenis Exp $ */ +/* $OpenBSD: efi_machdep.c,v 1.5 2022/11/06 11:44:30 kettenis Exp $ */ /* * Copyright (c) 2017 Mark Kettenis @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,11 @@ void efi_leave(struct efi_softc *); int efi_gettime(struct todr_chip_handle *, struct timeval *); int efi_settime(struct todr_chip_handle *, struct timeval *); +label_t efi_jmpbuf; + +#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \ + (efi_leave(sc), EFAULT) : (efi_enter(sc), 0)) + int efi_match(struct device *parent, void *match, void *aux) { @@ -161,7 +167,8 @@ efi_attach(struct device *parent, struct device *self, void *aux) config_found(self, &fa, NULL); } - efi_enter(sc); + if (efi_enter_check(sc)) + return; status = sc->sc_rs->GetTime(&time, NULL); efi_leave(sc); if (status != EFI_SUCCESS) @@ -252,6 +259,12 @@ efi_map_runtime(struct efi_softc *sc) } } +void +efi_fault(void) +{ + longjmp(&efi_jmpbuf); +} + void efi_enter(struct efi_softc *sc) { @@ -268,6 +281,8 @@ efi_enter(struct efi_softc *sc) cpu_setttb(pm->pm_asid, pm->pm_pt0pa); fpu_kernel_enter(); + + curcpu()->ci_curpcb->pcb_onfault = (void *)efi_fault; } void @@ -276,6 +291,8 @@ efi_leave(struct efi_softc *sc) struct pmap *pm = curcpu()->ci_curpm; uint64_t tcr; + curcpu()->ci_curpcb->pcb_onfault = NULL; + fpu_kernel_exit(); WRITE_SPECIALREG(ttbr0_el1, pmap_kernel()->pm_pt0pa); @@ -296,7 +313,8 @@ efi_gettime(struct todr_chip_handle *handle, struct timeval *tv) EFI_TIME time; EFI_STATUS status; - efi_enter(sc); + if (efi_enter_check(sc)) + return EFAULT; status = sc->sc_rs->GetTime(&time, NULL); efi_leave(sc); if (status != EFI_SUCCESS) @@ -340,7 +358,8 @@ efi_settime(struct todr_chip_handle *handle, struct timeval *tv) time.TimeZone = 0; time.Daylight = 0; - efi_enter(sc); + if (efi_enter_check(sc)) + return EFAULT; status = sc->sc_rs->SetTime(&time); efi_leave(sc); if (status != EFI_SUCCESS) -- 2.20.1