Module Name: src Committed By: jmcneill Date: Mon Dec 16 00:03:51 UTC 2019
Modified Files: src/sys/arch/aarch64/aarch64: efi_machdep.c src/sys/arch/arm/arm: efi_runtime.c efi_runtime.h Log Message: Enable FP access for EFI RT and improve error handling. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/sys/arch/aarch64/aarch64/efi_machdep.c cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/arm/efi_runtime.c \ src/sys/arch/arm/arm/efi_runtime.h 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.4 src/sys/arch/aarch64/aarch64/efi_machdep.c:1.5 --- src/sys/arch/aarch64/aarch64/efi_machdep.c:1.4 Mon Aug 12 15:47:02 2019 +++ src/sys/arch/aarch64/aarch64/efi_machdep.c Mon Dec 16 00:03:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: efi_machdep.c,v 1.4 2019/08/12 15:47:02 skrll Exp $ */ +/* $NetBSD: efi_machdep.c,v 1.5 2019/12/16 00:03:50 jmcneill 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.4 2019/08/12 15:47:02 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: efi_machdep.c,v 1.5 2019/12/16 00:03:50 jmcneill Exp $"); #include <sys/param.h> #include <uvm/uvm_extern.h> @@ -38,6 +38,13 @@ __KERNEL_RCSID(0, "$NetBSD: efi_machdep. #include <arm/arm/efi_runtime.h> +#include <aarch64/machdep.h> + +static struct { + struct faultbuf faultbuf; + bool fpu_used; +} arm_efirt_state; + void arm_efirt_md_map_range(vaddr_t va, paddr_t pa, size_t sz, enum arm_efirt_mem_type type) { @@ -70,3 +77,41 @@ arm_efirt_md_map_range(vaddr_t va, paddr sz -= PAGE_SIZE; } } + +int +arm_efirt_md_enter(void) +{ + struct lwp *l = curlwp; + + /* Save FPU state */ + arm_efirt_state.fpu_used = fpu_used_p(l) != 0; + if (arm_efirt_state.fpu_used) + fpu_save(l); + + /* Enable FP access (AArch64 UEFI calling convention) */ + reg_cpacr_el1_write(CPACR_FPEN_ALL); + __asm __volatile ("isb"); + + /* + * Install custom fault handler. EFI lock is held across calls so + * shared faultbuf is safe here. + */ + return cpu_set_onfault(&arm_efirt_state.faultbuf); +} + +void +arm_efirt_md_exit(void) +{ + struct lwp *l = curlwp; + + /* Disable FP access */ + reg_cpacr_el1_write(CPACR_FPEN_NONE); + __asm __volatile ("isb"); + + /* Restore FPU state */ + if (arm_efirt_state.fpu_used) + fpu_load(l); + + /* Remove custom fault handler */ + cpu_unset_onfault(); +} Index: src/sys/arch/arm/arm/efi_runtime.c diff -u src/sys/arch/arm/arm/efi_runtime.c:1.2 src/sys/arch/arm/arm/efi_runtime.c:1.3 --- src/sys/arch/arm/arm/efi_runtime.c:1.2 Thu Jul 25 02:00:40 2019 +++ src/sys/arch/arm/arm/efi_runtime.c Mon Dec 16 00:03:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: efi_runtime.c,v 1.2 2019/07/25 02:00:40 jmcneill Exp $ */ +/* $NetBSD: efi_runtime.c,v 1.3 2019/12/16 00:03:50 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: efi_runtime.c,v 1.2 2019/07/25 02:00:40 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: efi_runtime.c,v 1.3 2019/12/16 00:03:50 jmcneill Exp $"); #include <sys/param.h> #include <sys/mutex.h> @@ -79,42 +79,46 @@ arm_efirt_init(paddr_t efi_system_table) int arm_efirt_gettime(struct efi_tm *tm) { - efi_status status; + int error; if (RT == NULL || RT->rt_gettime == NULL) return ENXIO; mutex_enter(&efi_lock); - status = RT->rt_gettime(tm, NULL); + if ((error = arm_efirt_md_enter()) == 0) { + if (RT->rt_gettime(tm, NULL) != 0) + error = EIO; + } + arm_efirt_md_exit(); mutex_exit(&efi_lock); - if (status) - return EIO; - return 0; + return error; } int arm_efirt_settime(struct efi_tm *tm) { - efi_status status; + int error; if (RT == NULL || RT->rt_settime == NULL) return ENXIO; mutex_enter(&efi_lock); - status = RT->rt_settime(tm); + if ((error = arm_efirt_md_enter()) == 0) { + if (RT->rt_settime(tm) != 0) + error = EIO; + } + arm_efirt_md_exit(); mutex_exit(&efi_lock); - if (status) - return EIO; - return 0; + return error; } int arm_efirt_reset(enum efi_reset type) { static int reset_called = false; - efi_status status; + int error; if (RT == NULL || RT->rt_reset == NULL) return ENXIO; @@ -122,13 +126,15 @@ arm_efirt_reset(enum efi_reset type) mutex_enter(&efi_lock); if (reset_called == false) { reset_called = true; - status = RT->rt_reset(type, 0, 0, NULL); + if ((error = arm_efirt_md_enter()) == 0) { + if (RT->rt_reset(type, 0, 0, NULL) != 0) + error = EIO; + } + arm_efirt_md_exit(); } else { - status = 1; + error = EPERM; } mutex_exit(&efi_lock); - if (status) - return EIO; - return 0; + return error; } Index: src/sys/arch/arm/arm/efi_runtime.h diff -u src/sys/arch/arm/arm/efi_runtime.h:1.2 src/sys/arch/arm/arm/efi_runtime.h:1.3 --- src/sys/arch/arm/arm/efi_runtime.h:1.2 Wed Oct 31 13:01:48 2018 +++ src/sys/arch/arm/arm/efi_runtime.h Mon Dec 16 00:03:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: efi_runtime.h,v 1.2 2018/10/31 13:01:48 jmcneill Exp $ */ +/* $NetBSD: efi_runtime.h,v 1.3 2019/12/16 00:03:50 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -46,5 +46,7 @@ enum arm_efirt_mem_type { }; void arm_efirt_md_map_range(vaddr_t, paddr_t, size_t, enum arm_efirt_mem_type); +int arm_efirt_md_enter(void); +void arm_efirt_md_exit(void); #endif /* !_ARM_EFI_RUNTIME_H */