svn commit: r251988 - in head/sys: amd64/amd64 i386/i386

Konstantin Belousov kib at FreeBSD.org
Wed Jun 19 05:05:17 UTC 2013


Author: kib
Date: Wed Jun 19 05:05:16 2013
New Revision: 251988
URL: http://svnweb.freebsd.org/changeset/base/251988

Log:
  Some clarifications and updates for the comments, mostly retrieved
  from Bruce Evans.  Trim the trailing spaces.
  
  MFC after:	1 week

Modified:
  head/sys/amd64/amd64/exception.S
  head/sys/i386/i386/exception.s

Modified: head/sys/amd64/amd64/exception.S
==============================================================================
--- head/sys/amd64/amd64/exception.S	Wed Jun 19 05:02:25 2013	(r251987)
+++ head/sys/amd64/amd64/exception.S	Wed Jun 19 05:05:16 2013	(r251988)
@@ -80,18 +80,22 @@ dtrace_invop_calltrap_addr:
  * This is equivalent to the i386 port's use of SDT_SYS386TGT.
  *
  * The cpu will push a certain amount of state onto the kernel stack for
- * the current process.  See amd64/include/frame.h.  
- * This includes the current RFLAGS (status register, which includes 
+ * the current process.  See amd64/include/frame.h.
+ * This includes the current RFLAGS (status register, which includes
  * the interrupt disable state prior to the trap), the code segment register,
- * and the return instruction pointer are pushed by the cpu.  The cpu 
- * will also push an 'error' code for certain traps.  We push a dummy 
- * error code for those traps where the cpu doesn't in order to maintain 
+ * and the return instruction pointer are pushed by the cpu.  The cpu
+ * will also push an 'error' code for certain traps.  We push a dummy
+ * error code for those traps where the cpu doesn't in order to maintain
  * a consistent frame.  We also push a contrived 'trap number'.
  *
- * The cpu does not push the general registers, we must do that, and we 
- * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
- * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
- * must load them with appropriate values for supervisor mode operation.
+ * The CPU does not push the general registers, so we must do that, and we
+ * must restore them prior to calling 'iret'.  The CPU adjusts %cs and %ss
+ * but does not mess with %ds, %es, %gs or %fs.  We swap the %gs base for
+ * for the kernel mode operation shortly, without changes to the selector
+ * loaded.  Since superuser long mode works with any selectors loaded into
+ * segment registers other then %cs, which makes them mostly unused in long
+ * mode, and kernel does not reference %fs, leave them alone.  The segment
+ * registers are reloaded on return to the usermode.
  */
 
 MCOUNT_LABEL(user)
@@ -503,7 +507,7 @@ nmi_calltrap:
 #ifdef HWPMC_HOOKS
 	/*
 	 * Capture a userspace callchain if needed.
-	 * 
+	 *
 	 * - Check if the current trap was from user mode.
 	 * - Check if the current thread is valid.
 	 * - Check if the thread requires a user call chain to be
@@ -549,7 +553,7 @@ outofnmi:
 	 * At this point the processor has exited NMI mode and is running
 	 * with interrupts turned off on the normal kernel stack.
 	 *
-	 * If a pending NMI gets recognized at or after this point, it 
+	 * If a pending NMI gets recognized at or after this point, it
 	 * will cause a kernel callchain to be traced.
 	 *
 	 * We turn interrupts back on, and call the user callchain capture hook.
@@ -567,7 +571,7 @@ nocallchain:
 #endif
 	testl	%ebx,%ebx
 	jnz	doreti_exit
-nmi_kernelexit:	
+nmi_kernelexit:
 	/*
 	 * Put back the preserved MSR_GSBASE value.
 	 */

Modified: head/sys/i386/i386/exception.s
==============================================================================
--- head/sys/i386/i386/exception.s	Wed Jun 19 05:02:25 2013	(r251987)
+++ head/sys/i386/i386/exception.s	Wed Jun 19 05:05:16 2013	(r251988)
@@ -54,13 +54,13 @@
 	.globl	dtrace_invop_jump_addr
 	.align	4
 	.type	dtrace_invop_jump_addr, @object
-        .size	dtrace_invop_jump_addr, 4
+	.size	dtrace_invop_jump_addr, 4
 dtrace_invop_jump_addr:
 	.zero	4
 	.globl	dtrace_invop_calltrap_addr
 	.align	4
 	.type	dtrace_invop_calltrap_addr, @object
-        .size	dtrace_invop_calltrap_addr, 4
+	.size	dtrace_invop_calltrap_addr, 4
 dtrace_invop_calltrap_addr:
 	.zero	8
 #endif
@@ -75,22 +75,22 @@ dtrace_invop_calltrap_addr:
  * Trap and fault vector routines.
  *
  * Most traps are 'trap gates', SDT_SYS386TGT.  A trap gate pushes state on
- * the stack that mostly looks like an interrupt, but does not disable 
- * interrupts.  A few of the traps we are use are interrupt gates, 
+ * the stack that mostly looks like an interrupt, but does not disable
+ * interrupts.  A few of the traps we are use are interrupt gates,
  * SDT_SYS386IGT, which are nearly the same thing except interrupts are
  * disabled on entry.
  *
  * The cpu will push a certain amount of state onto the kernel stack for
- * the current process.  The amount of state depends on the type of trap 
- * and whether the trap crossed rings or not.  See i386/include/frame.h.  
- * At the very least the current EFLAGS (status register, which includes 
+ * the current process.  The amount of state depends on the type of trap
+ * and whether the trap crossed rings or not.  See i386/include/frame.h.
+ * At the very least the current EFLAGS (status register, which includes
  * the interrupt disable state prior to the trap), the code segment register,
- * and the return instruction pointer are pushed by the cpu.  The cpu 
- * will also push an 'error' code for certain traps.  We push a dummy 
- * error code for those traps where the cpu doesn't in order to maintain 
+ * and the return instruction pointer are pushed by the cpu.  The cpu
+ * will also push an 'error' code for certain traps.  We push a dummy
+ * error code for those traps where the cpu doesn't in order to maintain
  * a consistent frame.  We also push a contrived 'trap number'.
  *
- * The cpu does not push the general registers, we must do that, and we 
+ * The cpu does not push the general registers, we must do that, and we
  * must restore them prior to calling 'iret'.  The cpu adjusts the %cs and
  * %ss segment registers, but does not mess with %ds, %es, or %fs.  Thus we
  * must load them with appropriate values for supervisor mode operation.
@@ -145,13 +145,14 @@ IDTVEC(xmm)
 	pushl $0; TRAP(T_XMMFLT)
 
 	/*
-	 * alltraps entry point.  Interrupts are enabled if this was a trap
-	 * gate (TGT), else disabled if this was an interrupt gate (IGT).
-	 * Note that int0x80_syscall is a trap gate.   Interrupt gates are
-	 * used by page faults, non-maskable interrupts, debug and breakpoint
+	 * All traps except ones for syscalls jump to alltraps.  If
+	 * interrupts were enabled when the trap occurred, then interrupts
+	 * are enabled now if the trap was through a trap gate, else
+	 * disabled if the trap was through an interrupt gate.  Note that
+	 * int0x80_syscall is a trap gate.   Interrupt gates are used by
+	 * page faults, non-maskable interrupts, debug and breakpoint
 	 * exceptions.
 	 */
-
 	SUPERALIGN_TEXT
 	.globl	alltraps
 	.type	alltraps, at function
@@ -168,7 +169,7 @@ calltrap:
 	pushl	%esp
 	call	trap
 	add	$4, %esp
-	
+
 	/*
 	 * Return via doreti to handle ASTs.
 	 */
@@ -187,10 +188,10 @@ IDTVEC(ill)
 
 	/* Check if this is a user fault. */
 	cmpl	$GSEL_KPL, 4(%esp)	/* Check the code segment. */
-              
+
 	/* If so, just handle it as a normal trap. */
 	jne	norm_ill
-              
+
 	/*
 	 * This is a kernel instruction fault that might have been caused
 	 * by a DTrace provider.
@@ -215,10 +216,10 @@ norm_ill:
 #endif
 
 /*
- * SYSCALL CALL GATE (old entry point for a.out binaries)
+ * Call gate entry for syscalls (lcall 7,0).
+ * This is used by FreeBSD 1.x a.out executables and "old" NetBSD executables.
  *
  * The intersegment call has been set up to specify one dummy parameter.
- *
  * This leaves a place to put eflags so that the call frame can be
  * converted to a trap frame. Note that the eflags is (semi-)bogusly
  * pushed into (what will be) tf_err and then copied later into the
@@ -246,11 +247,13 @@ IDTVEC(lcall_syscall)
 	jmp	doreti
 
 /*
- * Call gate entry for FreeBSD ELF and Linux/NetBSD syscall (int 0x80)
+ * Trap gate entry for syscalls (int 0x80).
+ * This is used by FreeBSD ELF executables, "new" NetBSD executables, and all
+ * Linux executables.
  *
- * Even though the name says 'int0x80', this is actually a TGT (trap gate)
- * rather then an IGT (interrupt gate).  Thus interrupts are enabled on
- * entry just as they are for a normal syscall.
+ * Even though the name says 'int0x80', this is actually a trap gate, not an
+ * interrupt gate.  Thus interrupts are enabled on entry just as they are for
+ * a normal syscall.
  */
 	SUPERALIGN_TEXT
 IDTVEC(int0x80_syscall)
@@ -348,13 +351,14 @@ doreti_next:
 	/*
 	 * PSL_VM must be checked first since segment registers only
 	 * have an RPL in non-VM86 mode.
+	 * ASTs can not be handled now if we are in a vm86 call.
 	 */
-	testl	$PSL_VM,TF_EFLAGS(%esp)	/* are we in vm86 mode? */
+	testl	$PSL_VM,TF_EFLAGS(%esp)
 	jz	doreti_notvm86
 	movl	PCPU(CURPCB),%ecx
-	testl	$PCB_VM86CALL,PCB_FLAGS(%ecx)	/* are we in a vm86 call? */
-	jz	doreti_ast		/* can handle ASTS now if not */
-  	jmp	doreti_exit
+	testl	$PCB_VM86CALL,PCB_FLAGS(%ecx)
+	jz	doreti_ast
+	jmp	doreti_exit
 
 doreti_notvm86:
 	testb	$SEL_RPL_MASK,TF_CS(%esp) /* are we returning to user mode? */
@@ -401,7 +405,7 @@ doreti_popl_ds:
 doreti_iret:
 	iret
 
-  	/*
+	/*
 	 * doreti_iret_fault and friends.  Alternative return code for
 	 * the case where we get a fault in the doreti_exit code
 	 * above.  trap() (i386/i386/trap.c) catches this specific


More information about the svn-src-head mailing list