Module Name:    src
Committed By:   msaitoh
Date:           Fri Mar 27 17:25:15 UTC 2009

Modified Files:
        src/sys/arch/i386/i386 [netbsd-5]: trap.c vector.S

Log Message:
Pull up following revision(s) (requested by mrg in ticket #609):
        sys/arch/i386/i386/vector.S: revision 1.44
        sys/arch/i386/i386/trap.c: revision 1.244
remove a bunch of special casing to handle improperly set segment
registers.  if we faulted trying to set them, just fall into
"we_re_toast", and arrange for a SEGV to be delivered to the
userland process.  fixes kernel mode faults.
from andrew doran.


To generate a diff of this commit:
cvs rdiff -u -r1.241 -r1.241.4.1 src/sys/arch/i386/i386/trap.c
cvs rdiff -u -r1.42 -r1.42.6.1 src/sys/arch/i386/i386/vector.S

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/i386/i386/trap.c
diff -u src/sys/arch/i386/i386/trap.c:1.241 src/sys/arch/i386/i386/trap.c:1.241.4.1
--- src/sys/arch/i386/i386/trap.c:1.241	Wed Oct 15 06:51:17 2008
+++ src/sys/arch/i386/i386/trap.c	Fri Mar 27 17:25:15 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: trap.c,v 1.241 2008/10/15 06:51:17 wrstuden Exp $	*/
+/*	$NetBSD: trap.c,v 1.241.4.1 2009/03/27 17:25:15 msaitoh Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.241 2008/10/15 06:51:17 wrstuden Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.241.4.1 2009/03/27 17:25:15 msaitoh Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -276,13 +276,9 @@
 	struct proc *p;
 	int type = frame->tf_trapno;
 	struct pcb *pcb;
-	extern char fusubail[], kcopy_fault[],
-		    resume_iret[], resume_pop_ds[], resume_pop_es[],
-		    resume_pop_fs[], resume_pop_gs[],
-		    IDTVEC(osyscall)[];
+	extern char fusubail[], kcopy_fault[], trapreturn[], IDTVEC(osyscall)[];
 	struct trapframe *vframe;
 	ksiginfo_t ksi;
-	int resume;
 	void *onfault;
 	int error;
 	uint32_t cr2;
@@ -397,52 +393,25 @@
 		/*
 		 * Check for failure during return to user mode.
 		 *
-		 * We do this by looking at the instruction we faulted on.  The
-		 * specific instructions we recognize only happen when
+		 * We do this by looking at the instruction we faulted on.
+		 * The specific instructions we recognize only happen when
 		 * returning from a trap, syscall, or interrupt.
 		 *
 		 * At this point, there are (at least) two trap frames on
 		 * the kernel stack; we presume here that we faulted while
 		 * loading our registers out of the outer one.
-		 *
-		 * The inner frame does not involve a ring crossing, so it
-		 * ends right before &frame.tf_esp.  The outer frame has
-		 * been partially consumed by the INTRFASTEXIT; exactly
-		 * how much depends which register we were popping when we
-		 * faulted, so we compute the outer frame address based on
-		 * register-dependant offsets computed from &frame.tf_esp
-		 * below.  To decide whether this was a kernel-mode or
-		 * user-mode error, we look at this outer frame's tf_cs
-		 * and tf_eflags, which are (fortunately) not consumed until
-		 * the final instruction of INTRFASTEXIT.
-		 *
-		 * XXX
-		 * The heuristic used here will currently fail for the case of
-		 * one of the 2 pop instructions faulting when returning from a
-		 * a fast interrupt.  This should not be possible.  It can be
-		 * fixed by rearranging the trap frame so that the stack format
-		 * at this point is the same as on exit from a `slow'
-		 * interrupt.
 		 */
 		switch (*(u_char *)frame->tf_eip) {
 		case 0xcf:	/* iret */
 			vframe = (void *)((int)&frame->tf_esp -
 			    offsetof(struct trapframe, tf_eip));
-			resume = (int)resume_iret;
 			break;
 		case 0x8e:
 			switch (*(uint32_t *)frame->tf_eip) {
 			case 0x0c245c8e:	/* movl 0xc(%esp,1),%ds */
-				resume = (int)resume_pop_ds;
-				break;
 			case 0x0824448e:	/* movl 0x8(%esp,1),%es */
-				resume = (int)resume_pop_es;
-				break;
 			case 0x0424648e:	/* movl 0x4(%esp,1),%fs */
-				resume = (int)resume_pop_fs;
-				break;
 			case 0x00246c8e:	/* movl 0x0(%esp,1),%gs */
-				resume = (int)resume_pop_gs;
 				break;
 			default:
 				goto we_re_toast;
@@ -455,18 +424,34 @@
 		if (KERNELMODE(vframe->tf_cs, vframe->tf_eflags))
 			goto we_re_toast;
 
-		frame->tf_eip = resume;
-
 		/*
-		 * clear PSL_NT.  it can be set by userland because setting it
-		 * isn't a privileged operation.
+		 * Arrange to signal the thread, which will reset its
+		 * registers in the outer frame.  This also allows us to
+		 * capture the invalid register state in sigcontext,
+		 * packaged up with the signal delivery.  We restart
+		 * on return at 'trapreturn', acting as if nothing
+		 * happened, restarting the return to user with our new
+		 * set of registers.
+		 *
+		 * Clear PSL_NT.  It can be set by userland because setting
+		 * it isn't a privileged operation.
 		 *
-		 * set PSL_I.  otherwise, if SIGSEGV is ignored, we'll
+		 * Set PSL_I.  Otherwise, if SIGSEGV is ignored, we'll
 		 * continue to generate traps infinitely with
 		 * interrupts disabled.
 		 */
-
+		frame->tf_ds = GSEL(GDATA_SEL, SEL_KPL);
+		frame->tf_es = GSEL(GDATA_SEL, SEL_KPL);
+		frame->tf_gs = GSEL(GDATA_SEL, SEL_KPL);
+		frame->tf_fs = GSEL(GCPU_SEL, SEL_KPL);
+		frame->tf_eip = (uintptr_t)trapreturn;
 		frame->tf_eflags = (frame->tf_eflags & ~PSL_NT) | PSL_I;
+		KSI_INIT_TRAP(&ksi);
+		ksi.ksi_signo = SIGSEGV;
+		ksi.ksi_addr = (void *)rcr2();
+		ksi.ksi_code = SEGV_ACCERR;
+		ksi.ksi_trap = type & ~T_USER;
+		(*p->p_emul->e_trapsignal)(l, &ksi);
 		return;
 
 	case T_PROTFLT|T_USER:		/* protection fault */

Index: src/sys/arch/i386/i386/vector.S
diff -u src/sys/arch/i386/i386/vector.S:1.42 src/sys/arch/i386/i386/vector.S:1.42.6.1
--- src/sys/arch/i386/i386/vector.S:1.42	Mon Jul  7 13:01:16 2008
+++ src/sys/arch/i386/i386/vector.S	Fri Mar 27 17:25:15 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: vector.S,v 1.42 2008/07/07 13:01:16 gmcgarry Exp $	*/
+/*	$NetBSD: vector.S,v 1.42.6.1 2009/03/27 17:25:15 msaitoh Exp $	*/
 
 /*
  * Copyright 2002 (c) Wasabi Systems, Inc.
@@ -65,7 +65,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.42 2008/07/07 13:01:16 gmcgarry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vector.S,v 1.42.6.1 2009/03/27 17:25:15 msaitoh Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -863,7 +863,7 @@
 	addl	$4,%esp
 	testl	%eax,%eax
 	jz	calltrap
-	jmp	.Lalltraps_checkusr
+	jmp	_C_LABEL(trapreturn)
 #else
 #ifndef XEN
 	sti
@@ -999,7 +999,7 @@
 #ifdef DIAGNOSTIC
 	movl	CPUVAR(ILEVEL),%ebx
 #endif
-	jmp	.Lalltraps_checkusr
+	jmp	_C_LABEL(trapreturn)
 
 IDTVEC(trap10)
 #if NNPX > 0
@@ -1018,7 +1018,7 @@
 	incl	_C_LABEL(uvmexp)+V_TRAP
 	call	_C_LABEL(npxintr)
 	addl	$12,%esp
-	jmp	.Lalltraps_checkusr
+	jmp	_C_LABEL(trapreturn)
 #else
 	sti
 	ZTRAP(T_ARITHTRAP)
@@ -1092,7 +1092,7 @@
 	pushl	%esp
 	call	_C_LABEL(trap)
 	addl	$4,%esp
-.Lalltraps_checkusr:
+_C_LABEL(trapreturn):	.globl	trapreturn
 	testb	$CHK_UPL,TF_CS(%esp)
 	jnz	.Lalltraps_checkast
 #ifdef VM86
@@ -1136,7 +1136,7 @@
 	movl    CPUVAR(ISOURCES)(,%eax,4),%eax
 	jmp     *IS_RESUME(%eax)
 7:      movl    %ebx, CPUVAR(ILEVEL) #restore cpl
-	jmp     .Lalltraps_checkusr
+	jmp     _C_LABEL(trapreturn)
 #endif /* XEN */
 #ifndef DIAGNOSTIC
 6:	INTRFASTEXIT
@@ -1210,36 +1210,6 @@
 	ret
 #endif /* IPKDB */
 
-
-/*
- * If an error is detected during trap, syscall, or interrupt exit, trap() will
- * change %eip to point to one of these labels.  We clean up the stack, if
- * necessary, and resume as if we were handling a general protection fault.
- * This will cause the process to get a SIGBUS.
- */
-/* LINTSTUB: Var: char resume_iret[1]; */
-NENTRY(resume_iret)
-	ZTRAP(T_PROTFLT)
-/* LINTSTUB: Var: char resume_pop_ds[1]; */
-NENTRY(resume_pop_ds)
-	movw	%es,TF_ES(%esp)
-	movl	$GSEL(GDATA_SEL, SEL_KPL),%eax
-	movw	%ax,%es
-/* LINTSTUB: Var: char resume_pop_es[1]; */
-NENTRY(resume_pop_es)
-	movw	%fs,TF_FS(%esp)
-	movl	$GSEL(GDATA_SEL, SEL_KPL),%eax
-	movw	%ax,%fs
-/* LINTSTUB: Var: char resume_pop_fs[1]; */
-NENTRY(resume_pop_fs)
-	movw	%gs,TF_GS(%esp)
-	movl	$GSEL(GDATA_SEL, SEL_KPL),%eax
-	movw	%ax,%gs
-/* LINTSTUB: Var: char resume_pop_gs[1]; */
-NENTRY(resume_pop_gs)
-	movl	$T_PROTFLT,TF_TRAPNO(%esp)
-	jmp	calltrap
-
 #ifdef IPKDB
 /* LINTSTUB: Func: int ipkdbfbyte(u_char *c) */
 NENTRY(ipkdbfbyte)

Reply via email to