Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src-draft/trunk]: src/sys/arch/aarch64 Draft fpu_kthread_enter/leave for aar...



details:   https://anonhg.NetBSD.org/src-all/rev/5f0c9efc2bac
branches:  trunk
changeset: 934741:5f0c9efc2bac
user:      Taylor R Campbell <riastradh%NetBSD.org@localhost>
date:      Wed Jun 17 18:29:42 2020 +0000

description:
Draft fpu_kthread_enter/leave for aarch64.

diffstat:

 sys/arch/aarch64/aarch64/fpu.c  |  63 ++++++++++++++++++++++++++++++++++++++++-
 sys/arch/aarch64/include/fpu.h  |   3 +
 sys/arch/aarch64/include/proc.h |   1 +
 3 files changed, 66 insertions(+), 1 deletions(-)

diffs (114 lines):

diff -r e7941432a3cd -r 5f0c9efc2bac sys/arch/aarch64/aarch64/fpu.c
--- a/sys/arch/aarch64/aarch64/fpu.c    Thu Jun 04 03:23:00 2020 +0000
+++ b/sys/arch/aarch64/aarch64/fpu.c    Wed Jun 17 18:29:42 2020 +0000
@@ -175,6 +175,59 @@
        __asm __volatile ("isb");
 }
 
+static const struct fpreg zero_fpreg;
+
+int
+fpu_kthread_enter(void)
+{
+       struct lwp *l = curlwp;
+       int system_fpu = l->l_md.md_flags & MDL_SYSTEM_FPU;
+
+       KASSERTMSG(l->l_flag & LW_SYSTEM,
+           "fpu_kthread_enter is allowed only in kthreads");
+       KASSERTMSG(curcpu()->ci_kfpu_spl == -1,
+           "fpu_kthread_enter is not allowed between fpu_kern_enter/leave");
+
+       if (!system_fpu) {
+               /*
+                * Notify the FPU fault handler to save the FPU state
+                * for us.
+                */
+               l->l_md.md_flags |= MDL_SYSTEM_FPU;
+
+               /* Enable the FPU.  */
+               fpu_state_load(l, 0);
+       }
+
+       return system_fpu;
+}
+
+void
+fpu_kthread_leave(int system_fpu)
+{
+       struct lwp *l = curlwp;
+
+       KASSERTMSG(l->l_flag & LW_SYSTEM,
+           "fpu_kthread_leave is allowed only in kthreads");
+       KASSERTMSG(l->l_md.md_flags & MDL_SYSTEM_FPU,
+           "fpu_kthread_leave without fpu_kthread_enter");
+
+       if (!system_fpu) {
+               /*
+                * 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_fpregs(&zero_fpreg);
+
+               /* Disable the FPU.  */
+               fpu_state_release(l);
+
+               /* Stop asking to save our FPU state.  */
+               l->l_md.md_flags &= ~MDL_SYSTEM_FPU;
+       }
+}
+
 void
 fpu_kern_enter(void)
 {
@@ -182,6 +235,10 @@
        struct cpu_info *ci;
        int s;
 
+       /* Nothing needed if we're in a kthread with FPU enabled.  */
+       if (l->l_md.md_flags & MDL_SYSTEM_FPU)
+               return;
+
        /*
         * Block all interrupts.  We must block preemption since -- if
         * this is a user thread -- there is nowhere to save the kernel
@@ -214,10 +271,14 @@
 void
 fpu_kern_leave(void)
 {
-       static const struct fpreg zero_fpreg;
+       struct lwp *l = curlwp;
        struct cpu_info *ci = curcpu();
        int s;
 
+       /* Nothing needed if we're in a kthread with FPU enabled.  */
+       if (l->l_md.md_flags & MDL_SYSTEM_FPU)
+               return;
+
        KASSERT(ci->ci_cpl == IPL_HIGH);
        KASSERT(ci->ci_kfpu_spl != -1);
 
diff -r e7941432a3cd -r 5f0c9efc2bac sys/arch/aarch64/include/fpu.h
--- a/sys/arch/aarch64/include/fpu.h    Thu Jun 04 03:23:00 2020 +0000
+++ b/sys/arch/aarch64/include/fpu.h    Wed Jun 17 18:29:42 2020 +0000
@@ -29,6 +29,9 @@
 #ifndef _AARCH64_FPU_H_
 #define _AARCH64_FPU_H_
 
+int fpu_kthread_enter(void);
+void fpu_kthread_leave(int);
+
 void fpu_kern_enter(void);
 void fpu_kern_leave(void);
 
diff -r e7941432a3cd -r 5f0c9efc2bac sys/arch/aarch64/include/proc.h
--- a/sys/arch/aarch64/include/proc.h   Thu Jun 04 03:23:00 2020 +0000
+++ b/sys/arch/aarch64/include/proc.h   Wed Jun 17 18:29:42 2020 +0000
@@ -43,6 +43,7 @@
        struct trapframe *md_utf;
        uint64_t md_cpacr;
        uint32_t md_flags;
+#define        MDL_SYSTEM_FPU          __BIT(0)
 
        uint64_t md_ia_kern[2]; /* APIAKey{Lo,Hi}_EL1 used in the kernel */
        uint64_t md_ia_user[2]; /* APIAKey{Lo,Hi}_EL1 used in user-process */



Home | Main Index | Thread Index | Old Index