Module Name:    src
Committed By:   riastradh
Date:           Sat Aug  1 02:13:04 UTC 2020

Modified Files:
        src/sys/arch/arm/vfp: vfp_init.c

Log Message:
Add kthread_fpu_enter/exit support to arm.


To generate a diff of this commit:
cvs rdiff -u -r1.70 -r1.71 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/vfp/vfp_init.c
diff -u src/sys/arch/arm/vfp/vfp_init.c:1.70 src/sys/arch/arm/vfp/vfp_init.c:1.71
--- src/sys/arch/arm/vfp/vfp_init.c:1.70	Mon Jul 27 20:51:29 2020
+++ src/sys/arch/arm/vfp/vfp_init.c	Sat Aug  1 02:13:04 2020
@@ -1,4 +1,4 @@
-/*      $NetBSD: vfp_init.c,v 1.70 2020/07/27 20:51:29 riastradh Exp $ */
+/*      $NetBSD: vfp_init.c,v 1.71 2020/08/01 02:13:04 riastradh Exp $ */
 
 /*
  * Copyright (c) 2008 ARM Ltd
@@ -32,12 +32,13 @@
 #include "opt_cputypes.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.70 2020/07/27 20:51:29 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfp_init.c,v 1.71 2020/08/01 02:13:04 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/systm.h>
 #include <sys/device.h>
+#include <sys/kthread.h>
 #include <sys/proc.h>
 #include <sys/cpu.h>
 
@@ -424,7 +425,8 @@ vfp_handler(u_int address, u_int insn, t
 	struct cpu_info * const ci = curcpu();
 
 	/* This shouldn't ever happen.  */
-	if (fault_code != FAULT_USER)
+	if (fault_code != FAULT_USER &&
+	    (curlwp->l_flag & (LW_SYSTEM|LW_SYSTEM_FPU)) == LW_SYSTEM)
 		panic("VFP fault at %#x in non-user mode", frame->tf_pc);
 
 	if (ci->ci_vfp_id == 0) {
@@ -504,7 +506,8 @@ neon_handler(u_int address, u_int insn, 
 		return 1;
 
 	/* This shouldn't ever happen.  */
-	if (fault_code != FAULT_USER)
+	if (fault_code != FAULT_USER &&
+	    (curlwp->l_flag & (LW_SYSTEM|LW_SYSTEM_FPU)) == LW_SYSTEM)
 		panic("NEON fault in non-user mode");
 
 	/* if we already own the FPU and it's enabled, raise SIGILL */
@@ -668,6 +671,19 @@ vfp_setcontext(struct lwp *l, const mcon
 	    sizeof(mcp->__fpu.__vfpregs.__vfp_fstmx));
 }
 
+/*
+ * True if this is a system thread with its own private FPU state.
+ */
+static inline bool
+lwp_system_fpu_p(struct lwp *l)
+{
+
+	return (l->l_flag & (LW_SYSTEM|LW_SYSTEM_FPU)) ==
+	    (LW_SYSTEM|LW_SYSTEM_FPU);
+}
+
+static const struct vfpreg zero_vfpreg;
+
 void
 fpu_kern_enter(void)
 {
@@ -675,6 +691,11 @@ fpu_kern_enter(void)
 	uint32_t fpexc;
 	int s;
 
+	if (lwp_system_fpu_p(curlwp) && !cpu_intr_p()) {
+		KASSERT(!cpu_softintr_p());
+		return;
+	}
+
 	/*
 	 * Block interrupts up to IPL_VM.  We must block preemption
 	 * since -- if this is a user thread -- there is nowhere to
@@ -701,11 +722,15 @@ fpu_kern_enter(void)
 void
 fpu_kern_leave(void)
 {
-	static const struct vfpreg zero_vfpreg;
 	struct cpu_info *ci = curcpu();
 	int s;
 	uint32_t fpexc;
 
+	if (lwp_system_fpu_p(curlwp) && !cpu_intr_p()) {
+		KASSERT(!cpu_softintr_p());
+		return;
+	}
+
 	KASSERT(ci->ci_cpl == IPL_VM);
 	KASSERT(ci->ci_kfpu_spl != -1);
 
@@ -730,4 +755,20 @@ fpu_kern_leave(void)
 	splx(s);
 }
 
+void
+kthread_fpu_enter_md(void)
+{
+
+	pcu_load(&arm_vfp_ops);
+}
+
+void
+kthread_fpu_exit_md(void)
+{
+
+	/* XXX Should vfp_state_release zero the registers itself?  */
+	load_vfpregs(&zero_vfpreg);
+	vfp_discardcontext(curlwp, 0);
+}
+
 #endif /* FPU_VFP */

Reply via email to