Module Name: src
Committed By: riastradh
Date: Mon Jun 29 23:54:06 UTC 2020
Modified Files:
src/sys/arch/arm/arm32: cpu.c
src/sys/arch/arm/include: cpu.h
src/sys/arch/arm/vfp: vfp_init.c
Log Message:
Implement fpu_kern_enter/leave for arm32.
To generate a diff of this commit:
cvs rdiff -u -r1.145 -r1.146 src/sys/arch/arm/arm32/cpu.c
cvs rdiff -u -r1.110 -r1.111 src/sys/arch/arm/include/cpu.h
cvs rdiff -u -r1.64 -r1.65 src/sys/arch/arm/vfp/vfp_init.c
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/arm/arm32/cpu.c
diff -u src/sys/arch/arm/arm32/cpu.c:1.145 src/sys/arch/arm/arm32/cpu.c:1.146
--- src/sys/arch/arm/arm32/cpu.c:1.145 Sat Jun 20 07:10:36 2020
+++ src/sys/arch/arm/arm32/cpu.c Mon Jun 29 23:54:05 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.145 2020/06/20 07:10:36 skrll Exp $ */
+/* $NetBSD: cpu.c,v 1.146 2020/06/29 23:54:05 riastradh Exp $ */
/*
* Copyright (c) 1995 Mark Brinicombe.
@@ -46,7 +46,7 @@
#include "opt_multiprocessor.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.145 2020/06/20 07:10:36 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.146 2020/06/29 23:54:05 riastradh Exp $");
#include <sys/param.h>
@@ -229,6 +229,8 @@ cpu_attach(device_t dv, cpuid_t id)
#endif
vfp_attach(ci); /* XXX SMP */
+
+ ci->ci_kfpu_spl = -1;
}
enum cpu_class {
Index: src/sys/arch/arm/include/cpu.h
diff -u src/sys/arch/arm/include/cpu.h:1.110 src/sys/arch/arm/include/cpu.h:1.111
--- src/sys/arch/arm/include/cpu.h:1.110 Sun Mar 29 09:06:38 2020
+++ src/sys/arch/arm/include/cpu.h Mon Jun 29 23:54:06 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.110 2020/03/29 09:06:38 skrll Exp $ */
+/* $NetBSD: cpu.h,v 1.111 2020/06/29 23:54:06 riastradh Exp $ */
/*
* Copyright (c) 1994-1996 Mark Brinicombe.
@@ -168,6 +168,8 @@ struct cpu_info {
int ci_want_resched;/* resched() was called */
int ci_intr_depth; /* */
+ int ci_kfpu_spl;
+
struct cpu_softc *
ci_softc; /* platform softc */
Index: src/sys/arch/arm/vfp/vfp_init.c
diff -u src/sys/arch/arm/vfp/vfp_init.c:1.64 src/sys/arch/arm/vfp/vfp_init.c:1.65
--- src/sys/arch/arm/vfp/vfp_init.c:1.64 Tue Oct 29 16:18:23 2019
+++ src/sys/arch/arm/vfp/vfp_init.c Mon Jun 29 23:54:06 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: vfp_init.c,v 1.64 2019/10/29 16:18:23 joerg Exp $ */
+/* $NetBSD: vfp_init.c,v 1.65 2020/06/29 23:54:06 riastradh Exp $ */
/*
* Copyright (c) 2008 ARM Ltd
@@ -32,7 +32,7 @@
#include "opt_cputypes.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.64 2019/10/29 16:18:23 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.65 2020/06/29 23:54:06 riastradh Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -46,6 +46,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v
#include <arm/undefined.h>
#include <arm/vfpreg.h>
#include <arm/mcontext.h>
+#include <arm/fpu.h>
#include <uvm/uvm_extern.h> /* for pmap.h */
@@ -658,4 +659,72 @@ vfp_setcontext(struct lwp *l, const mcon
sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx));
}
+void
+fpu_kern_enter(void)
+{
+ struct lwp *l = curlwp;
+ struct cpu_info *ci;
+ uint32_t fpexc;
+ int s;
+
+ /*
+ * Block all interrupts. We must block preemption since -- if
+ * this is a user thread -- there is nowhere to save the kernel
+ * fpu state, and if we want this to be usable in interrupts,
+ * we can't let interrupts interfere with the fpu state in use
+ * since there's nowhere for them to save it.
+ */
+ s = splhigh();
+ ci = curcpu();
+ KASSERT(ci->ci_kfpu_spl == -1);
+ ci->ci_kfpu_spl = s;
+
+ /*
+ * If we are in a softint and have a pinned lwp, the fpu state
+ * is that of the pinned lwp, so save it there.
+ */
+ if ((l->l_pflag & LP_INTR) && (l->l_switchto != NULL))
+ l = l->l_switchto;
+ if (vfp_used_p(l))
+ vfp_savecontext(l);
+
+ /* Enable the fpu. */
+ fpexc = armreg_fpexc_read();
+ fpexc |= VFP_FPEXC_EN;
+ fpexc &= ~VFP_FPEXC_EX;
+ armreg_fpexc_write(fpexc);
+}
+
+void
+fpu_kern_leave(void)
+{
+ static const struct vfpreg zero_vfpreg;
+ struct cpu_info *ci = curcpu();
+ int s;
+ uint32_t fpexc;
+
+ KASSERT(ci->ci_cpl == IPL_HIGH);
+ KASSERT(ci->ci_kfpu_spl != -1);
+
+ /*
+ * Zero the fpu registers; otherwise we might leak secrets
+ * through Spectre-class attacks to userland, even if there are
+ * no bugs in fpu state management.
+ */
+ load_vfpregs(&zero_vfpreg);
+
+ /*
+ * Disable the fpu so that the kernel can't accidentally use
+ * it again.
+ */
+ fpexc = armreg_fpexc_read();
+ fpexc &= ~VFP_FPEXC_EN;
+ armreg_fpexc_write(fpexc);
+
+ /* Restore interrupts. */
+ s = ci->ci_kfpu_spl;
+ ci->ci_kfpu_spl = -1;
+ splx(s);
+}
+
#endif /* FPU_VFP */