Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm Implement fpu_kern_enter/leave for arm32.
details: https://anonhg.NetBSD.org/src/rev/272a7d9e92f5
branches: trunk
changeset: 935319:272a7d9e92f5
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Jun 29 23:54:05 2020 +0000
description:
Implement fpu_kern_enter/leave for arm32.
diffstat:
sys/arch/arm/arm32/cpu.c | 6 ++-
sys/arch/arm/include/cpu.h | 4 +-
sys/arch/arm/vfp/vfp_init.c | 73 +++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 78 insertions(+), 5 deletions(-)
diffs (144 lines):
diff -r 66f9e42c39c6 -r 272a7d9e92f5 sys/arch/arm/arm32/cpu.c
--- a/sys/arch/arm/arm32/cpu.c Mon Jun 29 23:53:12 2020 +0000
+++ b/sys/arch/arm/arm32/cpu.c Mon Jun 29 23:54:05 2020 +0000
@@ -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 @@
#endif
vfp_attach(ci); /* XXX SMP */
+
+ ci->ci_kfpu_spl = -1;
}
enum cpu_class {
diff -r 66f9e42c39c6 -r 272a7d9e92f5 sys/arch/arm/include/cpu.h
--- a/sys/arch/arm/include/cpu.h Mon Jun 29 23:53:12 2020 +0000
+++ b/sys/arch/arm/include/cpu.h Mon Jun 29 23:54:05 2020 +0000
@@ -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 @@
int ci_want_resched;/* resched() was called */
int ci_intr_depth; /* */
+ int ci_kfpu_spl;
+
struct cpu_softc *
ci_softc; /* platform softc */
diff -r 66f9e42c39c6 -r 272a7d9e92f5 sys/arch/arm/vfp/vfp_init.c
--- a/sys/arch/arm/vfp/vfp_init.c Mon Jun 29 23:53:12 2020 +0000
+++ b/sys/arch/arm/vfp/vfp_init.c Mon Jun 29 23:54:05 2020 +0000
@@ -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 @@
#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 @@
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 */
Home |
Main Index |
Thread Index |
Old Index