Module Name:    src
Committed By:   maxv
Date:           Sat Jan 20 08:30:53 UTC 2018

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

Log Message:
Fix the double-fault handler. We're executing on ist1 and must not jump
out of it, so don't enable interrupts. And use the SVS_*_ALTSTACK macros.

While here, fix the NMI handler too: it should use SVS_LEAVE_ALTSTACK.


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/amd64/amd64/amd64_trap.S
cvs rdiff -u -r1.110 -r1.111 src/sys/arch/amd64/amd64/trap.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.18 src/sys/arch/amd64/amd64/amd64_trap.S:1.19
--- src/sys/arch/amd64/amd64/amd64_trap.S:1.18	Thu Jan 18 07:25:34 2018
+++ src/sys/arch/amd64/amd64/amd64_trap.S	Sat Jan 20 08:30:53 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: amd64_trap.S,v 1.18 2018/01/18 07:25:34 maxv Exp $	*/
+/*	$NetBSD: amd64_trap.S,v 1.19 2018/01/20 08:30:53 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2007, 2008, 2017 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
 
 #if 0
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.18 2018/01/18 07:25:34 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: amd64_trap.S,v 1.19 2018/01/20 08:30:53 maxv Exp $");
 #endif
 
 /*
@@ -146,7 +146,7 @@ IDTVEC(trap02)
 	movq	%rsp,%rdi
 	incq	CPUVAR(NTRAP)
 	call	_C_LABEL(nmitrap)
-	SVS_LEAVE
+	SVS_LEAVE_ALTSTACK
 
 .Lnmileave:
 	movw	TF_ES(%rsp),%es
@@ -224,8 +224,43 @@ IDTVEC(trap07)
 	jmp	.Lalltraps_checkusr
 IDTVEC_END(trap07)
 
+/*
+ * Double faults execute on a particular stack, and we must not jump out
+ * of it. So don't enable interrupts.
+ */
 IDTVEC(trap08)
+#if defined(XEN)
 	TRAP(T_DOUBLEFLT)
+#else
+	TRAP_NJ(T_DOUBLEFLT)
+	subq	$TF_REGSIZE,%rsp
+	INTR_SAVE_GPRS
+	SVS_ENTER_ALTSTACK
+	testb	$SEL_UPL,TF_CS(%rsp)
+	jz	1f
+	swapgs
+1:
+	cld
+	SMAP_ENABLE
+	movw	%gs,TF_GS(%rsp)
+	movw	%fs,TF_FS(%rsp)
+	movw	%es,TF_ES(%rsp)
+	movw	%ds,TF_DS(%rsp)
+
+	movq	%rsp,%rdi
+	incq	CPUVAR(NTRAP)
+	call	_C_LABEL(doubletrap)
+
+	SVS_LEAVE_ALTSTACK
+	INTR_RESTORE_GPRS
+
+	testb	$SEL_UPL,TF_CS(%rsp)
+	jz	1f
+	swapgs
+1:
+	addq	$TF_REGSIZE+16,%rsp
+	iretq
+#endif
 IDTVEC_END(trap08)
 
 IDTVEC(trap09)

Index: src/sys/arch/amd64/amd64/trap.c
diff -u src/sys/arch/amd64/amd64/trap.c:1.110 src/sys/arch/amd64/amd64/trap.c:1.111
--- src/sys/arch/amd64/amd64/trap.c:1.110	Wed Jan 10 20:51:11 2018
+++ src/sys/arch/amd64/amd64/trap.c	Sat Jan 20 08:30:53 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.110 2018/01/10 20:51:11 maxv Exp $	*/
+/*	$NetBSD: trap.c,v 1.111 2018/01/20 08:30:53 maxv Exp $	*/
 
 /*
  * Copyright (c) 1998, 2000, 2017 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.110 2018/01/10 20:51:11 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.111 2018/01/20 08:30:53 maxv Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -121,6 +121,7 @@ dtrace_doubletrap_func_t	dtrace_doubletr
 #endif
 
 void nmitrap(struct trapframe *);
+void doubletrap(struct trapframe *);
 void trap(struct trapframe *);
 void trap_return_fault_return(struct trapframe *) __dead;
 
@@ -228,6 +229,22 @@ nmitrap(struct trapframe *frame)
 	x86_nmi();
 }
 
+void
+doubletrap(struct trapframe *frame)
+{
+	const int type = T_DOUBLEFLT;
+	struct lwp *l = curlwp;
+
+	trap_print(frame, l);
+
+	if (kdb_trap(type, 0, frame))
+		return;
+	if (kgdb_trap(type, frame))
+		return;
+
+	panic("double fault");
+}
+
 /*
  * Did we receive in kernel mode a trap that ought to be considered as a user
  * trap? If this function returns, the answer is no.

Reply via email to