Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Mar 2009 17:10:14 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org
Subject:   svn commit: r189310 - in stable/6/sys: . boot/i386/btx/btx contrib/pf dev/cxgb
Message-ID:  <200903031710.n23HAENx016548@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Tue Mar  3 17:10:14 2009
New Revision: 189310
URL: http://svn.freebsd.org/changeset/base/189310

Log:
  MFC: Use a clean slate of register state when executing hardware interrupt
  handlers to avoid leaking values into the upper 16-bits of general purpose
  registers when executing these routines.

Modified:
  stable/6/sys/   (props changed)
  stable/6/sys/boot/i386/btx/btx/btx.S
  stable/6/sys/contrib/pf/   (props changed)
  stable/6/sys/dev/cxgb/   (props changed)

Modified: stable/6/sys/boot/i386/btx/btx/btx.S
==============================================================================
--- stable/6/sys/boot/i386/btx/btx/btx.S	Tue Mar  3 17:07:27 2009	(r189309)
+++ stable/6/sys/boot/i386/btx/btx/btx.S	Tue Mar  3 17:10:14 2009	(r189310)
@@ -36,6 +36,7 @@
 /*
  * Fields in %eflags.
  */
+		.set PSL_RESERVED_DEFAULT,0x00000002
 		.set PSL_T,0x00000100		# Trap flag
 		.set PSL_I,0x00000200		# Interrupt enable flag
 		.set PSL_VM,0x00020000		# Virtual 8086 mode flag
@@ -455,6 +456,18 @@ intx31: 	pushl $-1			# Dummy int no for 
  * -0x3c %fs
  * -0x40 %ds
  * -0x44 %es
+ * -0x48 zero %eax (hardware int only)	
+ * -0x4c zero %ecx (hardware int only)
+ * -0x50 zero %edx (hardware int only)
+ * -0x54 zero %ebx (hardware int only)
+ * -0x58 zero %esp (hardware int only)
+ * -0x5c zero %ebp (hardware int only)
+ * -0x60 zero %esi (hardware int only)
+ * -0x64 zero %edi (hardware int only)
+ * -0x68 zero %gs (hardware int only)
+ * -0x6c zero %fs (hardware int only)
+ * -0x70 zero %ds (hardware int only)
+ * -0x74 zero %es (hardware int only)
  */
 int_hw: 	cld				# String ops inc
 		pusha				# Save gp regs
@@ -467,12 +480,15 @@ int_hw: 	cld				# String ops inc
 		pushl %ds			#  address
 		popl %es			#  data
 		leal 0x44(%esp,1),%esi		# Base of frame
+		movl %esp,MEM_ESPR-0x04		# Save kernel stack pointer
 		movl -0x14(%esi),%eax		# Get Int no
 		cmpl $-1,%eax			# Hardware interrupt?
-		jne intusr.2			# Yes
+		jne intusr.1			# Yes
 /*
- * v86 calls save the btx_v86 pointer on the real mode stack and read the
- * address and flags from the btx_v86 structure.
+ * v86 calls save the btx_v86 pointer on the real mode stack and read
+ * the address and flags from the btx_v86 structure.  For interrupt
+ * handler invocations (VM86 INTx requests), disable interrupts,
+ * tracing, and alignment checking while the handler runs.
  */
 		movl $MEM_USR,%ebx		# User base
 		movl %ebx,%edx			#  address
@@ -482,35 +498,36 @@ int_hw: 	cld				# String ops inc
 		movl %edx,MEM_ESPR-0x08		# Save btx_v86 ptr
 		movl V86_ADDR(%edx),%eax	# Get int no/address
 		movl V86_CTL(%edx),%edx		# Get control flags
+		movl -0x08(%esi),%ebx		# Save user flags in %ebx
+		testl $V86F_ADDR,%edx		# Segment:offset?
+		jnz intusr.4			# Yes
+		andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing,
+						#  and alignment checking for
+						#  interrupt handler
 		jmp intusr.3			# Skip hardware interrupt
 /*
- * Hardware interrupts store a NULL btx_v86 pointer and use the address
- * (interrupt number) from the stack with empty flags.  Also, we clear
- * the segment registers for the interrupt handler.
+ * Hardware interrupts store a NULL btx_v86 pointer and use the
+ * address (interrupt number) from the stack with empty flags.  Also,
+ * push a dummy frame of zeros onto the stack for all the general
+ * purpose and segment registers and clear %eflags.  This gives the
+ * hardware interrupt handler a clean slate.
  */
-intusr.2:	xorl %edx,%edx			# Control flags
+intusr.1:	xorl %edx,%edx			# Control flags
 		movl %edx,MEM_ESPR-0x08		# NULL btx_v86 ptr
-		movl %edx,-0x38(%esi)		# Real mode %gs of 0
-		movl %edx,-0x3c(%esi)		# Real mode %fs of 0
-		movl %edx,-0x40(%esi)		# Real mode %ds of 0
-		movl %edx,-0x44(%esi)		# Real mode %es of 0
+		movl $12,%ecx			# Frame is 12 dwords
+intusr.2:	pushl $0x0			# Fill frame
+		loop intusr.2			#  with zeros
+		movl $PSL_RESERVED_DEFAULT,%ebx # Set clean %eflags
 /*
- * %eax now holds either the interrupt number or segment:offset of function.
- * %edx now holds the V86F_* flags.
- *
- * For interrupt handler invocations (either hardware interrupts or VM86
- * INTx requests) we also disable interrupts, tracing, and alignment checking
- * while the handler runs.
+ * Look up real mode IDT entry for hardware interrupts and VM86 INTx
+ * requests.
  */
-intusr.3:	movl -0x08(%esi),%ebx		# Save user flags in %ebx
-		testl $V86F_ADDR,%edx		# Segment:offset?
-		jnz intusr.4			# Yes
-		shll $0x2,%eax			# Scale
+intusr.3:	shll $0x2,%eax			# Scale
 		movl (%eax),%eax		# Load int vector
-		andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing,
-						#  and alignment checking for
-						#  interrupt handler
 		jmp intusr.5			# Skip CALLF test
+/*
+ * Panic if V86F_CALLF isn't set with V86F_ADDR.
+ */
 intusr.4:	testl $V86F_CALLF,%edx		# Far call?
 		jnz intusr.5			# Ok
 		movl %edx,0x30(%esp,1)		# Place VM86 flags in int no
@@ -522,6 +539,11 @@ intusr.4:	testl $V86F_CALLF,%edx		# Far 
 		popl %gs
 		popal				# Restore gp regs
 		jmp ex_noc			# Panic
+/*
+ * %eax now holds the segment:offset of the function.
+ * %ebx now holds the %eflags to pass to real mode.
+ * %edx now holds the V86F_* flags.
+ */
 intusr.5:	movw %bx,MEM_ESPR-0x12		# Pass user flags to real mode
 						#  target
 /*
@@ -536,8 +558,7 @@ intusr.5:	movw %bx,MEM_ESPR-0x12		# Pass
 		rep				#  from btx_v86
 		movsl				#  to kernel stack
 		popl %esi			# Restore
-intusr.6:	movl %esp,MEM_ESPR-0x04		# Save kernel stack pointer
-		movl -0x08(%esi),%ebx		# Copy user flags to real
+intusr.6:	movl -0x08(%esi),%ebx		# Copy user flags to real
 		movl %ebx,MEM_ESPR-0x0c		#  mode return trampoline
 		movl $rret_tramp,%ebx		# Set return trampoline
 		movl %ebx,MEM_ESPR-0x10		#  CS:IP
@@ -611,9 +632,16 @@ rret_tramp.1:	xorl %ecx,%ecx			# Zero
 		movb $SEL_TSS,%cl		# Set task
 		ltr %cx				#  register
 /*
- * Now we are back in protected mode.  Copy the registers off of the real
- * mode stack onto the kernel stack.  Also, initialize all the seg regs on
- * the kernel stack.
+ * Now we are back in protected mode.  The kernel stack frame set up
+ * before entering real mode is still intact. For hardware interrupts,
+ * leave the frame unchanged.
+ */
+		cmpl $0,MEM_ESPR-0x08		# Leave saved regs unchanged
+		jz rret_tramp.3			#  for hardware ints
+/*
+ * For V86 calls, copy the registers off of the real mode stack onto
+ * the kernel stack as we want their updated values.  Also, initialize
+ * the segment registers on the kernel stack.
  *
  * Note that the %esp in the kernel stack after this is garbage, but popa
  * ignores it, so we don't have to fix it up.
@@ -624,20 +652,17 @@ rret_tramp.1:	xorl %ecx,%ecx			# Zero
 		movl $8,%ecx			# Copy GP regs from
 		rep				#  real mode stack
 		movsl				#  to kernel stack
-		popl %esi			# Restore
 		movl $SEL_UDATA,%eax		# Selector for data seg regs
 		movl $4,%ecx			# Initialize %ds,
 		rep				#  %es, %fs, and
 		stosl				#  %gs
 /*
- * If this was a V86 call, copy the saved seg regs on the real mode stack
- * back over to the btx_v86 structure.  Also, conditionally update the saved
- * eflags on the kernel stack based on the flags from the user.
+ * For V86 calls, copy the saved seg regs on the real mode stack back
+ * over to the btx_v86 structure.  Also, conditionally update the
+ * saved eflags on the kernel stack based on the flags from the user.
  */
 		movl MEM_ESPR-0x08,%ecx		# Get btx_v86 ptr
-		jecxz rret_tramp.3		# Skip for hardware ints
 		leal V86_GS(%ecx),%edi		# %edi => btx_v86 seg regs
-		pushl %esi			# Save
 		leal MEM_ESPR-0x2c,%esi		# %esi => real mode seg regs
 		xchgl %ecx,%edx			# Save btx_v86 ptr
 		movl $4,%ecx			# Copy seg regs



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903031710.n23HAENx016548>