PERFORCE change 31003 for review

Peter Wemm peter at FreeBSD.org
Mon May 12 02:22:27 PDT 2003


http://perforce.freebsd.org/chv.cgi?CH=31003

Change 31003 by peter at peter_hammer on 2003/05/12 02:21:50

	create tf_addr in trapframe to store the fault address.
	This avoids having to run the page fault handler with interrupts
	disabled for so long. Adjust exception.S to enable this.

Affected files ...

.. //depot/projects/hammer/sys/amd64/amd64/exception.S#8 edit
.. //depot/projects/hammer/sys/amd64/amd64/genassym.c#10 edit
.. //depot/projects/hammer/sys/amd64/amd64/machdep.c#26 edit
.. //depot/projects/hammer/sys/amd64/amd64/trap.c#12 edit
.. //depot/projects/hammer/sys/amd64/include/frame.h#6 edit
.. //depot/projects/hammer/sys/amd64/include/ucontext.h#6 edit

Differences ...

==== //depot/projects/hammer/sys/amd64/amd64/exception.S#8 (text+ko) ====

@@ -74,50 +74,63 @@
  */
 #define	IDTVEC(name)	ALIGN_TEXT; .globl __CONCAT(X,name); \
 			.type __CONCAT(X,name), at function; __CONCAT(X,name):
-#define	TRAP(a)		pushq $(a) ; jmp alltraps
-#define	TRAP_NOEN(a)	pushq $(a) ; jmp alltraps_noen
 
 MCOUNT_LABEL(user)
 MCOUNT_LABEL(btrap)
 
+/* Traps that we leave interrupts disabled for.. */
+#define	TRAP_NOEN(a)	\
+	subq $TF_RIP,%rsp; \
+	movq $(a),TF_TRAPNO(%rsp) ; \
+	jmp alltraps_noen
+IDTVEC(dbg)
+	TRAP_NOEN(T_TRCTRAP)
+IDTVEC(bpt)
+	TRAP_NOEN(T_BPTFLT)
+
+/* Regular traps */
+#define	TRAP(a)	 \
+	subq $TF_RIP,%rsp; \
+	movq $(a),TF_TRAPNO(%rsp) ; \
+	jmp alltraps
 IDTVEC(div)
-	pushq $0; TRAP(T_DIVIDE)
-IDTVEC(dbg)
-	pushq $0; TRAP_NOEN(T_TRCTRAP)
+	TRAP(T_DIVIDE)
 IDTVEC(nmi)
-	pushq $0; TRAP(T_NMI)
-IDTVEC(bpt)
-	pushq $0; TRAP_NOEN(T_BPTFLT)
+	TRAP(T_NMI)
 IDTVEC(ofl)
-	pushq $0; TRAP(T_OFLOW)
+	TRAP(T_OFLOW)
 IDTVEC(bnd)
-	pushq $0; TRAP(T_BOUND)
+	TRAP(T_BOUND)
 IDTVEC(ill)
-	pushq $0; TRAP(T_PRIVINFLT)
+	TRAP(T_PRIVINFLT)
 IDTVEC(dna)
-	pushq $0; TRAP(T_DNA)
+	TRAP(T_DNA)
 IDTVEC(fpusegm)
-	pushq $0; TRAP(T_FPOPFLT)
+	TRAP(T_FPOPFLT)
+IDTVEC(mchk)
+	TRAP(T_MCHK)
+IDTVEC(rsvd)
+	TRAP(T_RESERVED)
+IDTVEC(fpu)
+	TRAP(T_ARITHTRAP)
+IDTVEC(xmm)
+	TRAP(T_XMMFLT)
+
+/* This group of traps have tf_err already pushed by the cpu */
+#define	TRAP_ERR(a)	\
+	subq $TF_ERR,%rsp; \
+	movq $(a),TF_TRAPNO(%rsp) ; \
+	jmp alltraps_noen
 IDTVEC(tss)
-	TRAP(T_TSSFLT)
+	TRAP_ERR(T_TSSFLT)
 IDTVEC(missing)
-	TRAP(T_SEGNPFLT)
+	TRAP_ERR(T_SEGNPFLT)
 IDTVEC(stk)
-	TRAP(T_STKFLT)
+	TRAP_ERR(T_STKFLT)
 IDTVEC(prot)
-	TRAP(T_PROTFLT)
-IDTVEC(page)
-	TRAP_NOEN(T_PAGEFLT)
-IDTVEC(mchk)
-	pushq $0; TRAP(T_MCHK)
-IDTVEC(rsvd)
-	pushq $0; TRAP(T_RESERVED)
-IDTVEC(fpu)
-	pushq $0; TRAP(T_ARITHTRAP)
+	TRAP_ERR(T_PROTFLT)
 IDTVEC(align)
-	TRAP(T_ALIGNFLT)
-IDTVEC(xmm)
-	pushq $0; TRAP(T_XMMFLT)
+	TRAP_ERR(T_ALIGNFLT)
 	
 	/*
 	 * alltraps entry point.  Use swapgs if this is the first time in the
@@ -129,7 +142,6 @@
 	.globl	alltraps
 	.type	alltraps, at function
 alltraps:
-	subq	$TF_TRAPNO,%rsp		/* tf_err and tf_trapno already pushed */
 	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
 	jz	alltraps_testi		/* already running with kernel GS.base */
 	swapgs
@@ -139,6 +151,7 @@
 	sti
 alltraps_pushregs:
 	movq	%rdi,TF_RDI(%rsp)
+alltraps_pushregs_no_rdi:
 	movq	%rsi,TF_RSI(%rsp)
 	movq	%rdx,TF_RDX(%rsp)
 	movq	%rcx,TF_RCX(%rsp)
@@ -170,15 +183,14 @@
 	.globl	alltraps_noen
 	.type	alltraps_noen, at function
 alltraps_noen:
-	subq	$TF_TRAPNO,%rsp		/* tf_err and tf_trapno already pushed */
 	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
 	jz	alltraps_pushregs	/* already running with kernel GS.base */
 	swapgs
 	jmp	alltraps_pushregs
 
 IDTVEC(dblfault)
-	pushq	$T_DOUBLEFLT
-	subq	$TF_TRAPNO,%rsp		/* tf_err and tf_trapno already pushed */
+	subq	$TF_ERR,%rsp
+	movq	$T_DOUBLEFLT,TF_TRAPNO(%rsp)
 	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
 	jz	1f			/* already running with kernel GS.base */
 	swapgs
@@ -186,6 +198,20 @@
 2:	hlt
 	jmp	2b
 
+IDTVEC(page)
+	subq	$TF_ERR,%rsp
+	movq	$T_PAGEFLT,TF_TRAPNO(%rsp)
+	testb	$SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
+	jz	1f			/* already running with kernel GS.base */
+	swapgs
+1:	movq	%rdi,TF_RDI(%rsp)
+	movq	%cr2,%rdi
+	movq	%rdi,TF_ADDR(%rsp)
+	testl	$PSL_I,TF_RFLAGS(%rsp)
+	jz	alltraps_pushregs_no_rdi
+	sti
+	jmp	alltraps_pushregs_no_rdi
+
 /*
  * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
  *

==== //depot/projects/hammer/sys/amd64/amd64/genassym.c#10 (text+ko) ====

@@ -152,6 +152,7 @@
 ASSYM(TF_RCX, offsetof(struct trapframe, tf_rcx));
 ASSYM(TF_RAX, offsetof(struct trapframe, tf_rax));
 ASSYM(TF_TRAPNO, offsetof(struct trapframe, tf_trapno));
+ASSYM(TF_ADDR, offsetof(struct trapframe, tf_addr));
 ASSYM(TF_ERR, offsetof(struct trapframe, tf_err));
 ASSYM(TF_RIP, offsetof(struct trapframe, tf_rip));
 ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));

==== //depot/projects/hammer/sys/amd64/amd64/machdep.c#26 (text+ko) ====

@@ -245,7 +245,7 @@
 	sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK)
 	    ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
 	sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
-	bcopy(regs, &sf.sf_uc.uc_mcontext.mc_r15, sizeof(*regs));
+	bcopy(regs, &sf.sf_uc.uc_mcontext.mc_rdi, sizeof(*regs));
 	sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
 	get_fpcontext(td, &sf.sf_uc.uc_mcontext);
 	fpstate_drop(td);
@@ -280,11 +280,11 @@
 		/* Fill in POSIX parts */
 		sf.sf_si.si_signo = sig;
 		sf.sf_si.si_code = code;
-		regs->tf_rcx = regs->tf_err;	/* arg 4 in %rcx */
+		regs->tf_rcx = regs->tf_addr;	/* arg 4 in %rcx */
 	} else {
 		/* Old FreeBSD-style arguments. */
 		regs->tf_rsi = code;		/* arg 2 in %rsi */
-		regs->tf_rcx = regs->tf_err;	/* arg 4 in %rcx */
+		regs->tf_rcx = regs->tf_addr;	/* arg 4 in %rcx */
 		sf.sf_ahu.sf_handler = catcher;
 	}
 	PROC_UNLOCK(p);
@@ -371,7 +371,7 @@
 	ret = set_fpcontext(td, &ucp->uc_mcontext);
 	if (ret != 0)
 		return (ret);
-	bcopy(&ucp->uc_mcontext.mc_r15, regs, sizeof(*regs));
+	bcopy(&ucp->uc_mcontext.mc_rdi, regs, sizeof(*regs));
 
 	PROC_LOCK(p);
 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)

==== //depot/projects/hammer/sys/amd64/amd64/trap.c#12 (text+ko) ====

@@ -168,7 +168,7 @@
 
 #ifdef DDB
 	if (db_active) {
-		eva = (type == T_PAGEFLT ? rcr2() : 0);
+		eva = (type == T_PAGEFLT ? frame.tf_addr : 0);
 		trap_fatal(&frame, eva);
 		goto out;
 	}
@@ -194,11 +194,10 @@
 			printf("kernel trap %d with interrupts disabled\n",
 			    type);
 			/*
-			 * Page faults need interrupts diasabled until later,
-			 * and we shouldn't enable interrupts while holding a
+			 * We shouldn't enable interrupts while holding a
 			 * spin lock.
 			 */
-			if (type != T_PAGEFLT && PCPU_GET(spinlocks) == NULL)
+			if (PCPU_GET(spinlocks) == NULL)
 				enable_intr();
 		}
 	}
@@ -213,17 +212,9 @@
 		 * do the VM lookup, so just consider it a fatal trap so the
 		 * kernel can print out a useful trap message and even get
 		 * to the debugger.
-		 *
-		 * Note that T_PAGEFLT is registered as an interrupt gate.  This
-		 * is just like a trap gate, except interrupts are disabled.  This
-		 * happens to be critically important, because we could otherwise
-		 * preempt and run another process that may cause %cr2 to be
-		 * clobbered for something else.
 		 */
-		eva = rcr2();
-		if (PCPU_GET(spinlocks) == NULL)
-			enable_intr();
-		else
+		eva = frame.tf_addr;
+		if (PCPU_GET(spinlocks) != NULL)
 			trap_fatal(&frame, eva);
 	}
 
@@ -454,7 +445,7 @@
 		uprintf("fatal process exception: %s",
 			trap_msg[type]);
 		if ((type == T_PAGEFLT) || (type == T_PROTFLT))
-			uprintf(", fault VA = 0x%lx", (u_long)eva);
+			uprintf(", fault VA = 0x%lx", eva);
 		uprintf("\n");
 	}
 #endif
@@ -556,8 +547,6 @@
 			frame->tf_err & PGEX_W ? "write" : "read",
 			frame->tf_err & PGEX_P ? "protection violation" : "page not present",
 (void *)eva, (void *)frame->tf_rip, (void *)frame->tf_rax, (void *)frame->tf_rbx, (void *)frame->tf_rcx, (void *)frame->tf_rdx, (void *)frame->tf_rsp, (void *)frame->tf_rbp, (void *)frame->tf_rsi, (void *)frame->tf_rdi);
-	/* kludge to pass faulting virtual address to sendsig */
-	frame->tf_err = eva;
 
 	return((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
 }

==== //depot/projects/hammer/sys/amd64/include/frame.h#6 (text+ko) ====

@@ -68,6 +68,7 @@
 	register_t	tf_r14;
 	register_t	tf_r15;
 	register_t	tf_trapno;
+	register_t	tf_addr;
 	/* below portion defined in hardware */
 	register_t	tf_err;
 	register_t	tf_rip;
@@ -96,6 +97,7 @@
 	register_t	if_r14;
 	register_t	if_r15;
 	register_t	:64;		/* compat with trap frame - trapno */
+	register_t	:64;		/* compat with trap frame - addr */
 	register_t	:64;		/* compat with trap frame - err */
 	/* below portion defined in hardware */
 	register_t	if_rip;
@@ -124,6 +126,7 @@
 	register_t	cf_r14;
 	register_t	cf_r15;
 	register_t	:64;		/* compat with trap frame - trapno */
+	register_t	:64;		/* compat with trap frame - addr */
 	register_t	:64;		/* compat with trap frame - err */
 	/* below portion defined in hardware */
 	register_t	cf_rip;

==== //depot/projects/hammer/sys/amd64/include/ucontext.h#6 (text+ko) ====

@@ -38,22 +38,24 @@
 	 * and ucontext_t at the same time.
 	 */
 	register_t	mc_onstack;		/* XXX - sigcontext compat. */
-	register_t	mc_r15;			/* machine state (struct trapframe) */
-	register_t	mc_r14;
-	register_t	mc_r13;
-	register_t	mc_r12;
-	register_t	mc_r11;
-	register_t	mc_r10;
-	register_t	mc_r9;
-	register_t	mc_r8;
-	register_t	mc_rdi;
+
+	register_t	mc_rdi;			/* machine state (struct trapframe) */
 	register_t	mc_rsi;
-	register_t	mc_rbp;
-	register_t	mc_rbx;
 	register_t	mc_rdx;
 	register_t	mc_rcx;
+	register_t	mc_r8;
+	register_t	mc_r9;
 	register_t	mc_rax;
+	register_t	mc_rbx;
+	register_t	mc_rbp;
+	register_t	mc_r10;
+	register_t	mc_r11;
+	register_t	mc_r12;
+	register_t	mc_r13;
+	register_t	mc_r14;
+	register_t	mc_r15;
 	register_t	mc_trapno;
+	register_t	mc_addr;
 	register_t	mc_err;
 	register_t	mc_rip;
 	register_t	mc_cs;


More information about the p4-projects mailing list