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/63bcc2e03650
branches:  trunk
changeset: 973406:63bcc2e03650
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 4a5f4341c0fd -r 63bcc2e03650 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 4a5f4341c0fd -r 63bcc2e03650 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 4a5f4341c0fd -r 63bcc2e03650 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