Module Name:    src
Committed By:   dsl
Date:           Wed Feb 12 19:53:49 UTC 2014

Modified Files:
        src/sys/arch/amd64/amd64: amd64_trap.S trap.c
        src/sys/arch/x86/x86: fpu.c

Log Message:
Change the argument to fpudna() to be the trapframe.
Move the checks for fpu traps in kernel into x86/fpu.c.
Remove the code from amd64/trap.c related to fpu traps (they've not gone
  there for ages - expect to panic in kernel mode).
In fpudna():
- Don't actually enable hardware interrupts unless we need to
  allow in IPIs.
- There is no point in enabling them when they are blocked in software
  (by splhigh()).
- Keep the splhigh() to avoid a load of the KASSERTS() firing.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/amd64/amd64/amd64_trap.S
cvs rdiff -u -r1.76 -r1.77 src/sys/arch/amd64/amd64/trap.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/x86/x86/fpu.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/amd64/amd64/amd64_trap.S
diff -u src/sys/arch/amd64/amd64/amd64_trap.S:1.1 src/sys/arch/amd64/amd64/amd64_trap.S:1.2
--- src/sys/arch/amd64/amd64/amd64_trap.S:1.1	Tue Jun 25 00:27:22 2013
+++ src/sys/arch/amd64/amd64/amd64_trap.S	Wed Feb 12 19:53:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: amd64_trap.S,v 1.1 2013/06/25 00:27:22 uebayasi Exp $	*/
+/*	$NetBSD: amd64_trap.S,v 1.2 2014/02/12 19:53:49 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2007, 2008 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
 
 #if 0
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.1 2013/06/25 00:27:22 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.2 2014/02/12 19:53:49 dsl Exp $");
 #endif
 
 /*
@@ -195,12 +195,12 @@ IDTVEC(trap06)
 IDTVEC_END(trap06)
 
 IDTVEC(trap07)
-	ZTRAP_NJ(T_ASTFLT)
+	ZTRAP_NJ(T_DNA)
 	INTRENTRY
 #ifdef DIAGNOSTIC
 	movl	CPUVAR(ILEVEL),%ebx
 #endif /* DIAGNOSTIC */
-	movq	CPUVAR(SELF),%rdi
+	movq	%rsp,%rdi
 	call	_C_LABEL(fpudna)
 	jmp	.Lalltraps_checkusr
 IDTVEC_END(trap07)
@@ -290,14 +290,9 @@ IDTVEC(trap10)
 #ifdef DIAGNOSTIC
 	movl	CPUVAR(ILEVEL),%ebx
 #endif /* DIAGNOSTIC */
-	testb	$SEL_RPL,TF_CS(%rsp)
-	jz	1f
 	movq	%rsp,%rdi
 	call	_C_LABEL(fputrap)
 	jmp	.Lalltraps_checkusr
-1:
-  	STI(si)
-	jmp	calltrap
 IDTVEC_END(trap10)
 
 IDTVEC(trap11)

Index: src/sys/arch/amd64/amd64/trap.c
diff -u src/sys/arch/amd64/amd64/trap.c:1.76 src/sys/arch/amd64/amd64/trap.c:1.77
--- src/sys/arch/amd64/amd64/trap.c:1.76	Tue Feb 11 20:17:16 2014
+++ src/sys/arch/amd64/amd64/trap.c	Wed Feb 12 19:53:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.76 2014/02/11 20:17:16 dsl Exp $	*/
+/*	$NetBSD: trap.c,v 1.77 2014/02/12 19:53:49 dsl Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.76 2014/02/11 20:17:16 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.77 2014/02/12 19:53:49 dsl Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -210,6 +210,10 @@ trap_print(const struct trapframe *frame
  * that prepare a suitable stack frame, and restore this frame after the
  * exception has been processed. Note that the effect is as if the arguments
  * were passed call by reference.
+ *
+ * Note that the fpu traps (07 T_DNA, 10 T_ARITHTRAP and 13 T_XMM)
+ * jump directly into the code in x86/fpu.c so they get processed
+ * without interrupts being enabled.
  */
 void
 trap(struct trapframe *frame)
@@ -445,9 +449,6 @@ kernelfault:
 		}
 		goto trapsignal;
 
-	case T_ARITHTRAP|T_USER:
-	case T_XMM|T_USER:
-		/* Already handled by fputrap(), fall through. */
 	case T_ASTFLT|T_USER:
 		/* Allow process switch. */
 		//curcpu()->ci_data.cpu_nast++;
@@ -461,18 +462,6 @@ kernelfault:
 		}
 		goto out;
 
-#if 0 /* handled by fpudna() */
-	case T_DNA|T_USER: {
-		printf("pid %d.%d killed due to lack of floating point\n",
-		    p->p_pid, l->l_lid);
-		KSI_INIT_TRAP(&ksi);
-		ksi.ksi_signo = SIGKILL;
-		ksi.ksi_trap = type & ~T_USER;
-		ksi.ksi_addr = (void *)frame->tf_rip;
-		goto trapsignal;
-	}
-#endif
-
 	case T_BOUND|T_USER:
 	case T_OFLOW|T_USER:
 	case T_DIVIDE|T_USER:

Index: src/sys/arch/x86/x86/fpu.c
diff -u src/sys/arch/x86/x86/fpu.c:1.1 src/sys/arch/x86/x86/fpu.c:1.2
--- src/sys/arch/x86/x86/fpu.c:1.1	Tue Feb 11 20:17:16 2014
+++ src/sys/arch/x86/x86/fpu.c	Wed Feb 12 19:53:49 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: fpu.c,v 1.1 2014/02/11 20:17:16 dsl Exp $	*/
+/*	$NetBSD: fpu.c,v 1.2 2014/02/12 19:53:49 dsl Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.  All
@@ -100,7 +100,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.1 2014/02/11 20:17:16 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.2 2014/02/12 19:53:49 dsl Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -143,7 +143,7 @@ __KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.1 
  * state is saved.
  */
 
-void		fpudna(struct cpu_info *);
+void fpudna(struct trapframe *frame);
 
 /* 
  * The following table is used to ensure that the FPE_... value
@@ -265,6 +265,9 @@ fputrap(struct trapframe *frame)
 	uint32_t statbits;
 	ksiginfo_t ksi;
 
+	if (!USERMODE(frame->tf_cs, frame->tf_eflags))
+		panic("fpu trap from kernel, trapframe %p\n", frame);
+
 	/*
 	 * At this point, fpcurlwp should be curlwp.  If it wasn't, the TS bit
 	 * should be set, and we should have gotten a DNA exception.
@@ -312,19 +315,26 @@ fputrap(struct trapframe *frame)
  * If we were the last lwp to use the FPU, we can simply return.
  * Otherwise, we save the previous state, if necessary, and restore
  * our last saved state.
+ *
+ * Called directly from the trap 0x13 entry with interrupts still disabled.
  */
 void
-fpudna(struct cpu_info *ci)
+fpudna(struct trapframe *frame)
 {
+	struct cpu_info *ci;
 	uint16_t cw;
 	uint32_t mxcsr;
 	struct lwp *l, *fl;
 	struct pcb *pcb;
 	int s;
 
-	/* Lock out IPIs and disable preemption. */
+	if (!USERMODE(frame->tf_cs, frame->tf_eflags))
+		panic("fpudna from kernel, trapframe %p\n", frame);
+
+	ci = curcpu();
+
+	/* Save soft spl level - interrupts are hard disabled */
 	s = splhigh();
-	x86_enable_intr();
 
 	/* Save state on current CPU. */
 	l = ci->ci_curlwp;
@@ -341,9 +351,7 @@ fpudna(struct cpu_info *ci)
 			splx(s);
 			return;
 		}
-		KASSERT(fl != l);
 		fpusave_cpu(true);
-		KASSERT(ci->ci_fpcurlwp == NULL);
 	}
 
 	/* Save our state if on a remote CPU. */
@@ -351,6 +359,10 @@ fpudna(struct cpu_info *ci)
 		/* Explicitly disable preemption before dropping spl. */
 		KPREEMPT_DISABLE(l);
 		splx(s);
+
+		/* Actually enable interrupts */
+		x86_enable_intr();
+
 		fpusave_lwp(l, true);
 		KASSERT(pcb->pcb_fpcpu == NULL);
 		s = splhigh();

Reply via email to