direct-io.hg

changeset 831:832c781c16db

bitkeeper revision 1.510.1.1 (3f8c044fubZknMoFWYMcHcTrrIOO3Q)

sched.h, irq.h, traps.c, entry.S, boot.S:
A final cleanup of segment-register handling in Xen. We now safely propagate invalid segment register contents to the guest-OS failsafe handler in all cases.
author kaf24@scramble.cl.cam.ac.uk
date Tue Oct 14 14:12:31 2003 +0000 (2003-10-14)
parents d0e35aa76dc3
children e7184dc0e284
files xen/arch/i386/boot/boot.S xen/arch/i386/entry.S xen/arch/i386/traps.c xen/include/asm-i386/irq.h xen/include/xeno/sched.h
line diff
     1.1 --- a/xen/arch/i386/boot/boot.S	Mon Oct 13 22:09:23 2003 +0000
     1.2 +++ b/xen/arch/i386/boot/boot.S	Tue Oct 14 14:12:31 2003 +0000
     1.3 @@ -25,6 +25,8 @@ hal_entry:
     1.4          mov     $(__HYPERVISOR_DS),%ecx
     1.5          mov     %ecx,%ds
     1.6          mov     %ecx,%es
     1.7 +        mov     %ecx,%fs
     1.8 +        mov     %ecx,%gs
     1.9          ljmp    $(__HYPERVISOR_CS),$(1f)-__PAGE_OFFSET
    1.10  1:      lss     stack_start-__PAGE_OFFSET,%esp
    1.11  
     2.1 --- a/xen/arch/i386/entry.S	Mon Oct 13 22:09:23 2003 +0000
     2.2 +++ b/xen/arch/i386/entry.S	Tue Oct 14 14:12:31 2003 +0000
     2.3 @@ -104,14 +104,13 @@ OLDSS		= 0x40
     2.4  
     2.5  /* Offsets in task_struct */
     2.6  PROCESSOR       =  0
     2.7 -STATE           =  4
     2.8 -HYP_EVENTS      =  8
     2.9 -DOMAIN          = 12        
    2.10 -SHARED_INFO     = 16
    2.11 -EVENT_SEL       = 20
    2.12 -EVENT_ADDR      = 24
    2.13 -FAILSAFE_SEL    = 28
    2.14 -FAILSAFE_ADDR   = 32
    2.15 +HYP_EVENTS      =  2
    2.16 +SHARED_INFO     =  4
    2.17 +EVENT_SEL       =  8
    2.18 +EVENT_ADDR      = 12
    2.19 +FAILSAFE_BUFFER = 16
    2.20 +FAILSAFE_SEL    = 32
    2.21 +FAILSAFE_ADDR   = 36
    2.22  
    2.23  /* Offsets in shared_info_t */
    2.24  EVENTS          =  0
    2.25 @@ -131,77 +130,42 @@ CF_MASK		= 0x00000001
    2.26  IF_MASK		= 0x00000200
    2.27  NT_MASK		= 0x00004000
    2.28  
    2.29 -#define SAVE_ALL_NOSTI \
    2.30 -	cld; \
    2.31 -	pushl %gs; \
    2.32 -	pushl %fs; \
    2.33 -	pushl %es; \
    2.34 -	pushl %ds; \
    2.35 -	pushl %eax; \
    2.36 -	pushl %ebp; \
    2.37 -	pushl %edi; \
    2.38 -	pushl %esi; \
    2.39 -	pushl %edx; \
    2.40 -	pushl %ecx; \
    2.41 -	pushl %ebx; \
    2.42 -	movl $(__HYPERVISOR_DS),%edx; \
    2.43 -	movl %edx,%ds; \
    2.44 -	movl %edx,%es;
    2.45 +
    2.46 +        
    2.47 +#define SAVE_ALL_NOSEGREGS \
    2.48 +        cld; \
    2.49 +        pushl %gs; \
    2.50 +        pushl %fs; \
    2.51 +        pushl %es; \
    2.52 +        pushl %ds; \
    2.53 +        pushl %eax; \
    2.54 +        pushl %ebp; \
    2.55 +        pushl %edi; \
    2.56 +        pushl %esi; \
    2.57 +        pushl %edx; \
    2.58 +        pushl %ecx; \
    2.59 +        pushl %ebx; \
    2.60 +
    2.61 +#define SAVE_ALL_NOSTI     \
    2.62 +        SAVE_ALL_NOSEGREGS \
    2.63 +        movl $(__HYPERVISOR_DS),%edx; \
    2.64 +        movl %edx,%ds; \
    2.65 +        movl %edx,%es; \
    2.66 +        movl %edx,%fs; \
    2.67 +        movl %edx,%gs;
    2.68  
    2.69  #define SAVE_ALL \
    2.70 -	SAVE_ALL_NOSTI \
    2.71 -	sti;
    2.72 -
    2.73 -#define RESTORE_ALL	\
    2.74 -	popl %ebx;	\
    2.75 -	popl %ecx;	\
    2.76 -	popl %edx;	\
    2.77 -	popl %esi;	\
    2.78 -	popl %edi;	\
    2.79 -	popl %ebp;	\
    2.80 -	popl %eax;	\
    2.81 -1:	popl %ds;	\
    2.82 -2:	popl %es;	\
    2.83 -3:	popl %fs;	\
    2.84 -4:	popl %gs;	\
    2.85 -        addl $4,%esp;	\
    2.86 -5:      iret;		\
    2.87 -.section .fixup,"ax";	\
    2.88 -10:     subl $4,%esp;   \
    2.89 -        pushl %gs;      \
    2.90 -9:      pushl %fs;      \
    2.91 -8:      pushl %es;      \
    2.92 -7:      pushl %ds;      \
    2.93 -6:      pushl %eax;     \
    2.94 -	pushl %ebp;     \
    2.95 -	pushl %edi;     \
    2.96 -	pushl %esi;     \
    2.97 -	pushl %edx;     \
    2.98 -	pushl %ecx;     \
    2.99 -	pushl %ebx;     \
   2.100 -	pushl %ss;           \
   2.101 -	popl  %ds;           \
   2.102 -	pushl %ss;           \
   2.103 -	popl  %es;           \
   2.104 -	jmp  failsafe_callback;      \
   2.105 -.previous;                           \
   2.106 -.section __ex_table,"a";             \
   2.107 -	.align 4;	             \
   2.108 -	.long 1b,6b;       	     \
   2.109 -	.long 2b,7b;	             \
   2.110 -	.long 3b,8b;	             \
   2.111 -	.long 4b,9b;	             \
   2.112 -	.long 5b,10b;	             \
   2.113 -.previous
   2.114 +        SAVE_ALL_NOSTI \
   2.115 +        sti;
   2.116  
   2.117  #define GET_CURRENT(reg)   \
   2.118 -	movl $4096-4, reg; \
   2.119 +        movl $4096-4, reg; \
   2.120          orl  %esp, reg;    \
   2.121          movl (reg),reg     \
   2.122  
   2.123  ENTRY(continue_nonidle_task)
   2.124 -	GET_CURRENT(%ebx)
   2.125 -	jmp test_all_events
   2.126 +        GET_CURRENT(%ebx)
   2.127 +        jmp test_all_events
   2.128  
   2.129          ALIGN
   2.130  /*
   2.131 @@ -273,8 +237,111 @@ multicall_fixup1:
   2.132  .previous        
   2.133                  
   2.134          ALIGN
   2.135 -restore_all:
   2.136 -	RESTORE_ALL
   2.137 +restore_all_guest:
   2.138 +        # First, may need to restore %ds if clobbered by create_bounce_frame
   2.139 +        pushl %ss
   2.140 +        popl  %ds
   2.141 +        # Second, create a failsafe copy of DS,ES,FS,GS in case any are bad
   2.142 +        leal  DS(%esp),%esi
   2.143 +        leal  FAILSAFE_BUFFER(%ebx),%edi
   2.144 +        movsl
   2.145 +        movsl
   2.146 +        movsl
   2.147 +        movsl
   2.148 +        # Finally, restore guest registers -- faults will cause failsafe
   2.149 +        popl %ebx
   2.150 +	popl %ecx
   2.151 +	popl %edx
   2.152 +	popl %esi
   2.153 +	popl %edi
   2.154 +	popl %ebp
   2.155 +	popl %eax
   2.156 +1:	popl %ds
   2.157 +2:	popl %es
   2.158 +3:	popl %fs
   2.159 +4:	popl %gs
   2.160 +        addl $4,%esp
   2.161 +5:      iret
   2.162 +.section .fixup,"ax"
   2.163 +10:     subl $4,%esp
   2.164 +        pushl %gs
   2.165 +9:      pushl %fs
   2.166 +8:      pushl %es
   2.167 +7:      pushl %ds
   2.168 +6:      pushl %eax
   2.169 +	pushl %ebp
   2.170 +	pushl %edi
   2.171 +	pushl %esi
   2.172 +	pushl %edx
   2.173 +	pushl %ecx
   2.174 +	pushl %ebx
   2.175 +	pushl %ss
   2.176 +	popl  %ds
   2.177 +	pushl %ss
   2.178 +	popl  %es
   2.179 +	jmp  failsafe_callback
   2.180 +.previous
   2.181 +.section __ex_table,"a"
   2.182 +	.align 4
   2.183 +	.long 1b,6b
   2.184 +	.long 2b,7b
   2.185 +	.long 3b,8b
   2.186 +	.long 4b,9b
   2.187 +	.long 5b,10b
   2.188 +.previous
   2.189 +
   2.190 +/* No special register assumptions */
   2.191 +failsafe_callback:
   2.192 +        GET_CURRENT(%ebx)
   2.193 +        movzwl PROCESSOR(%ebx),%eax
   2.194 +        shl  $4,%eax
   2.195 +        lea  guest_trap_bounce(%eax),%edx
   2.196 +        movl FAILSAFE_ADDR(%ebx),%eax
   2.197 +        movl %eax,GTB_EIP(%edx)
   2.198 +        movl FAILSAFE_SEL(%ebx),%eax
   2.199 +        movw %ax,GTB_CS(%edx)
   2.200 +        call create_bounce_frame
   2.201 +        subl $16,%esi                # add DS/ES/FS/GS to failsafe stack frame
   2.202 +        leal FAILSAFE_BUFFER(%ebx),%ebp
   2.203 +        movl  0(%ebp),%eax           # DS
   2.204 +FAULT1: movl %eax,(%esi) 
   2.205 +        movl  4(%ebp),%eax           # ES
   2.206 +FAULT2: movl %eax,4(%esi)
   2.207 +        movl  8(%ebp),%eax           # FS
   2.208 +FAULT3: movl %eax,8(%esi) 
   2.209 +        movl 12(%ebp),%eax           # GS
   2.210 +FAULT4: movl %eax,12(%esi)
   2.211 +        movl %esi,OLDESP(%esp)
   2.212 +        popl %ebx
   2.213 +        popl %ecx
   2.214 +        popl %edx
   2.215 +        popl %esi
   2.216 +        popl %edi
   2.217 +        popl %ebp
   2.218 +        popl %eax
   2.219 +        addl $20,%esp                # skip DS/ES/FS/GS/ORIG_EAX
   2.220 +FAULT5: iret 
   2.221 +
   2.222 +
   2.223 +        ALIGN
   2.224 +# Simple restore -- we should never fault as we we will only interrupt ring 0
   2.225 +# when sane values have been placed in all registers. The only exception is
   2.226 +# NMI, which may interrupt before good values have been placed in DS-GS.
   2.227 +# The NMI return code deals with this problem itself.
   2.228 +restore_all_xen:
   2.229 +	popl %ebx
   2.230 +	popl %ecx
   2.231 +	popl %edx
   2.232 +	popl %esi
   2.233 +	popl %edi
   2.234 +	popl %ebp
   2.235 +	popl %eax
   2.236 +	popl %ds
   2.237 +	popl %es
   2.238 +	popl %fs
   2.239 +	popl %gs
   2.240 +        addl $4,%esp
   2.241 +        iret
   2.242  
   2.243          ALIGN
   2.244  ENTRY(hypervisor_call)
   2.245 @@ -292,26 +359,26 @@ test_all_events:
   2.246          notl %ecx
   2.247          cli                             # tests must not race interrupts
   2.248  /*test_softirqs:*/  
   2.249 -        mov  PROCESSOR(%ebx),%eax
   2.250 +        movzwl PROCESSOR(%ebx),%eax
   2.251          shl  $6,%eax                    # sizeof(irq_cpustat) == 64
   2.252          test %ecx,SYMBOL_NAME(irq_stat)(%eax,1)
   2.253          jnz  process_softirqs
   2.254  /*test_hyp_events:*/
   2.255 -        test %ecx, HYP_EVENTS(%ebx)
   2.256 +        testw %cx, HYP_EVENTS(%ebx)
   2.257          jnz  process_hyp_events
   2.258  /*test_guest_events:*/
   2.259          movl SHARED_INFO(%ebx),%eax
   2.260          shl  $31,%ecx                   # %ecx = EVENTS_MASTER_ENABLE_MASK
   2.261          test %ecx,EVENTS_MASK(%eax)     
   2.262 -        jz   restore_all                # only notify if master switch enabled
   2.263 +        jz   restore_all_guest          # only notify if master switch enabled
   2.264          movl EVENTS(%eax),%ecx
   2.265          andl EVENTS_MASK(%eax),%ecx
   2.266 -        jz   restore_all                # skip if no events to deliver
   2.267 +        jz   restore_all_guest          # skip if no events to deliver
   2.268          notl %ecx
   2.269          btrl $31,%ecx                   # NB. We clear all events that are
   2.270          andl %ecx,EVENTS_MASK(%eax)     # being delivered + master enable.
   2.271  /*process_guest_events:*/
   2.272 -        mov  PROCESSOR(%ebx),%edx
   2.273 +        movzwl PROCESSOR(%ebx),%edx
   2.274          shl  $4,%edx                    # sizeof(guest_trap_bounce) == 16
   2.275          lea  guest_trap_bounce(%edx),%edx
   2.276          movl EVENT_ADDR(%ebx),%eax
   2.277 @@ -319,7 +386,7 @@ test_all_events:
   2.278          movl EVENT_SEL(%ebx),%eax
   2.279          movw %ax,GTB_CS(%edx)
   2.280          call create_bounce_frame
   2.281 -        jmp  restore_all
   2.282 +        jmp  restore_all_guest
   2.283  
   2.284          ALIGN
   2.285  process_softirqs:
   2.286 @@ -332,53 +399,6 @@ process_hyp_events:
   2.287          sti
   2.288          call SYMBOL_NAME(do_hyp_events)
   2.289          jmp  test_all_events
   2.290 -
   2.291 -/* No special register assumptions */
   2.292 -failsafe_callback:
   2.293 -        # Check that we are actually returning to ring != 0 because
   2.294 -        # we may fault when returning to another ring 0 activation.
   2.295 -        # This can only occur when restoring FS and GS, which can be avoided
   2.296 -        # by zeroing those registers and trying again. The outermost ring 0
   2.297 -        # activation will do a full failsafe callback to the guest OS.
   2.298 -        # Note that the outermost activation certainly has the "bad" selector
   2.299 -        # value saved away, since interrupts are always disabled in ring 0
   2.300 -        # until all segment registers have been saved.
   2.301 -        movb CS(%esp),%al
   2.302 -        test $3,%al
   2.303 -        jnz  1f
   2.304 -        xorl %eax,%eax
   2.305 -        movl %eax,FS(%esp)
   2.306 -        movl %eax,GS(%esp)
   2.307 -        jmp  restore_all   
   2.308 -1:      GET_CURRENT(%ebx)
   2.309 -        mov  PROCESSOR(%ebx),%eax
   2.310 -        shl  $4,%eax
   2.311 -        lea  guest_trap_bounce(%eax),%edx
   2.312 -        movl FAILSAFE_ADDR(%ebx),%eax
   2.313 -        movl %eax,GTB_EIP(%edx)
   2.314 -        movl FAILSAFE_SEL(%ebx),%eax
   2.315 -        movw %ax,GTB_CS(%edx)
   2.316 -        call create_bounce_frame
   2.317 -        subl $16,%esi                # add DS/ES/FS/GS to failsafe stack frame
   2.318 -        movl DS(%esp),%eax
   2.319 -FAULT1: movl %eax,(%esi) 
   2.320 -        movl ES(%esp),%eax
   2.321 -FAULT2: movl %eax,4(%esi)
   2.322 -        movl FS(%esp),%eax
   2.323 -FAULT3: movl %eax,8(%esi) 
   2.324 -        movl GS(%esp),%eax
   2.325 -FAULT4: movl %eax,12(%esi)
   2.326 -        movl %esi,OLDESP(%esp)
   2.327 -        popl %ebx
   2.328 -        popl %ecx
   2.329 -        popl %edx
   2.330 -        popl %esi
   2.331 -        popl %edi
   2.332 -        popl %ebp
   2.333 -        popl %eax
   2.334 -        addl $20,%esp                # skip DS/ES/FS/GS/ORIG_EAX
   2.335 -FAULT5: iret 
   2.336 -
   2.337          
   2.338  /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK:         */
   2.339  /*   {EIP, CS, EFLAGS, [ESP, SS]}                                     */
   2.340 @@ -389,7 +409,7 @@ create_bounce_frame:
   2.341          test $2,%cl
   2.342          jz   1f /* jump if returning to an existing ring-1 activation */
   2.343          /* obtain ss/esp from TSS -- no current ring-1 activations */
   2.344 -        movl PROCESSOR(%ebx),%eax
   2.345 +        movzwl PROCESSOR(%ebx),%eax
   2.346          shll $8,%eax /* multiply by 256 */
   2.347          addl $init_tss + 12,%eax
   2.348          movl (%eax),%esi /* tss->esp1 */
   2.349 @@ -459,7 +479,7 @@ kill_domain_fixup3:
   2.350  
   2.351          ALIGN
   2.352  process_guest_exception_and_events:        
   2.353 -        mov  PROCESSOR(%ebx),%eax
   2.354 +        movzwl PROCESSOR(%ebx),%eax
   2.355          shl  $4,%eax
   2.356          lea  guest_trap_bounce(%eax),%edx
   2.357          testb $~0,GTB_FLAGS(%edx)
   2.358 @@ -488,7 +508,7 @@ ENTRY(ret_from_intr)
   2.359          movb CS(%esp),%al
   2.360  	testb $3,%al	# return to non-supervisor?
   2.361  	jne test_all_events
   2.362 -	jmp restore_all
   2.363 +	jmp restore_all_xen
   2.364  
   2.365  ENTRY(divide_error)
   2.366  	pushl $0		# no error code
   2.367 @@ -524,7 +544,7 @@ error_code:
   2.368          addl  $8,%esp
   2.369          movb  CS(%esp),%al
   2.370  	testb $3,%al
   2.371 -	je    restore_all
   2.372 +	je    restore_all_xen
   2.373          jmp   process_guest_exception_and_events
   2.374  
   2.375  ENTRY(coprocessor_error)
   2.376 @@ -547,16 +567,6 @@ ENTRY(debug)
   2.377  	pushl $ SYMBOL_NAME(do_debug)
   2.378  	jmp error_code
   2.379  
   2.380 -ENTRY(nmi)
   2.381 -	pushl %eax
   2.382 -	SAVE_ALL_NOSTI
   2.383 -	movl %esp,%edx
   2.384 -	pushl $0
   2.385 -	pushl %edx
   2.386 -	call SYMBOL_NAME(do_nmi)
   2.387 -	addl $8,%esp
   2.388 -        jmp  restore_all
   2.389 -
   2.390  ENTRY(int3)
   2.391  	pushl $0
   2.392  	pushl $ SYMBOL_NAME(do_int3)
   2.393 @@ -616,6 +626,82 @@ ENTRY(spurious_interrupt_bug)
   2.394  	pushl $ SYMBOL_NAME(do_spurious_interrupt_bug)
   2.395  	jmp error_code
   2.396  
   2.397 +ENTRY(nmi)
   2.398 +        # Save state but do not trash the segment registers!
   2.399 +        # We may otherwise be unable to reload them or copy them to ring 1. 
   2.400 +	pushl %eax
   2.401 +	SAVE_ALL_NOSEGREGS
   2.402 +
   2.403 +        # Check for hardware problems. These are always fatal so we can
   2.404 +        # reload DS and ES when handling them.
   2.405 +        inb   $0x61,%al
   2.406 +        testb $0x80,%al
   2.407 +        jne   nmi_parity_err
   2.408 +        testb $0x40,%al
   2.409 +        jne   nmi_io_err
   2.410 +        movl  %eax,%ebx
   2.411 +        
   2.412 +        # Okay, it's almost a normal NMI tick. We can only process it if:
   2.413 +        #  1. We're the outermost Xen activation (in which case we have
   2.414 +        #     the selectors safely saved on our stack)
   2.415 +        #  2. DS-GS all contain sane Xen values.
   2.416 +        # In all other cases we bail without touching DS-GS, as we've
   2.417 +        # interrupted an enclosing Xen activation in tricky prologue or
   2.418 +        # epilogue code.
   2.419 +        movb  CS(%esp),%al
   2.420 +	testb $3,%al
   2.421 +        jne   do_watchdog_tick
   2.422 +        movl  DS(%esp),%eax
   2.423 +        cmpw  $(__HYPERVISOR_DS),%ax
   2.424 +        jne   nmi_badseg
   2.425 +        movl  ES(%esp),%eax
   2.426 +        cmpw  $(__HYPERVISOR_DS),%ax
   2.427 +        jne   nmi_badseg
   2.428 +        movl  FS(%esp),%eax
   2.429 +        cmpw  $(__HYPERVISOR_DS),%ax
   2.430 +        jne   nmi_badseg
   2.431 +        movl  GS(%esp),%eax
   2.432 +        cmpw  $(__HYPERVISOR_DS),%ax
   2.433 +        jne   nmi_badseg
   2.434 +
   2.435 +do_watchdog_tick:
   2.436 +        movl  $(__HYPERVISOR_DS),%edx
   2.437 +        movl  %edx,%ds
   2.438 +        movl  %edx,%es
   2.439 +        movl  %esp,%edx
   2.440 +	pushl %ebx   # reason
   2.441 +	pushl %edx   # regs
   2.442 +        call  SYMBOL_NAME(do_nmi)
   2.443 +	addl  $8,%esp
   2.444 +        movb  CS(%esp),%al
   2.445 +	testb $3,%al
   2.446 +	je    restore_all_xen
   2.447 +        GET_CURRENT(%ebx)
   2.448 +        jmp   restore_all_guest
   2.449 +
   2.450 +nmi_badseg:
   2.451 +	popl %ebx
   2.452 +	popl %ecx
   2.453 +	popl %edx
   2.454 +	popl %esi
   2.455 +	popl %edi
   2.456 +	popl %ebp
   2.457 +	popl %eax
   2.458 +        addl $20,%esp
   2.459 +        iret
   2.460 +
   2.461 +nmi_parity_err: 
   2.462 +        movl $(__HYPERVISOR_DS),%edx
   2.463 +        movl %edx,%ds
   2.464 +        movl %edx,%es
   2.465 +        jmp  SYMBOL_NAME(mem_parity_error)
   2.466 +        
   2.467 +nmi_io_err: 
   2.468 +        movl $(__HYPERVISOR_DS),%edx
   2.469 +        movl %edx,%ds
   2.470 +        movl %edx,%es
   2.471 +        jmp  SYMBOL_NAME(io_check_error)                        
   2.472 +        
   2.473  .data
   2.474  ENTRY(hypervisor_call_table)
   2.475          .long SYMBOL_NAME(do_set_trap_table)
     3.1 --- a/xen/arch/i386/traps.c	Mon Oct 13 22:09:23 2003 +0000
     3.2 +++ b/xen/arch/i386/traps.c	Tue Oct 14 14:12:31 2003 +0000
     3.3 @@ -185,44 +185,6 @@ void die(const char * str, struct pt_reg
     3.4      panic("HYPERVISOR DEATH!!\n");
     3.5  }
     3.6  
     3.7 -#define check_selector(_s)                    \
     3.8 -  ({ int err;                                 \
     3.9 -     __asm__ __volatile__ (                   \
    3.10 -             "1: movl %2,%%gs       \n"       \
    3.11 -             "2:                    \n"       \
    3.12 -             ".section .fixup,\"ax\"\n"       \
    3.13 -             "3: incl %0            \n"       \
    3.14 -             "   jmp  2b            \n"       \
    3.15 -             ".previous             \n"       \
    3.16 -             ".section __ex_table,\"a\"\n"    \
    3.17 -             ".align 4              \n"       \
    3.18 -             ".long 1b,3b           \n"       \
    3.19 -             ".previous               "       \
    3.20 -             : "=&r" (err) : "0" (0),         \
    3.21 -               "m" (*(unsigned int *)&(_s))); \
    3.22 -     err; })
    3.23 -
    3.24 -static inline void check_saved_selectors(struct pt_regs *regs)
    3.25 -{
    3.26 -    /* Prevent recursion. */
    3.27 -    __asm__ __volatile__ ( 
    3.28 -        "movl %0,%%fs; movl %0,%%gs" 
    3.29 -        : : "r" (0) );
    3.30 -
    3.31 -    /*
    3.32 -     * NB. We need to check DS and ES as well, since we may have taken
    3.33 -     * an exception after they were restored in 
    3.34 -     */
    3.35 -    if ( check_selector(regs->xds) )
    3.36 -        regs->xds = 0;
    3.37 -    if ( check_selector(regs->xes) )
    3.38 -        regs->xes = 0;
    3.39 -    if ( check_selector(regs->xfs) )
    3.40 -        regs->xfs = 0;
    3.41 -    if ( check_selector(regs->xgs) )
    3.42 -        regs->xgs = 0;
    3.43 -}
    3.44 -
    3.45  
    3.46  static inline void do_trap(int trapnr, char *str,
    3.47  			   struct pt_regs *regs, 
    3.48 @@ -247,10 +209,10 @@ static inline void do_trap(int trapnr, c
    3.49  
    3.50   fault_in_hypervisor:
    3.51  
    3.52 -    if ( (fixup = search_exception_table(regs->eip)) != 0 )
    3.53 +    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
    3.54      {
    3.55          regs->eip = fixup;
    3.56 -        check_saved_selectors(regs);
    3.57 +        regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
    3.58          return;
    3.59      }
    3.60  
    3.61 @@ -331,13 +293,13 @@ asmlinkage void do_page_fault(struct pt_
    3.62  
    3.63      __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
    3.64  
    3.65 +    if ( unlikely(!(regs->xcs & 3)) )
    3.66 +        goto fault_in_hypervisor;
    3.67 +
    3.68      if ( unlikely(addr > PAGE_OFFSET) )
    3.69          goto fault_in_xen_space;
    3.70  
    3.71 - bounce_fault:
    3.72 -
    3.73 -    if ( unlikely(!(regs->xcs & 3)) )
    3.74 -        goto fault_in_hypervisor;
    3.75 + propagate_fault:
    3.76  
    3.77      ti = p->thread.traps + 14;
    3.78      gtb->flags = GTBF_TRAP_CR2; /* page fault pushes %cr2 */
    3.79 @@ -359,7 +321,7 @@ asmlinkage void do_page_fault(struct pt_
    3.80  
    3.81      if ( (addr < LDT_VIRT_START) || 
    3.82           (addr >= (LDT_VIRT_START + (p->mm.ldt_ents*LDT_ENTRY_SIZE))) )
    3.83 -        goto bounce_fault;
    3.84 +        goto propagate_fault;
    3.85  
    3.86      off  = addr - LDT_VIRT_START;
    3.87      addr = p->mm.ldt_base + off;
    3.88 @@ -368,19 +330,19 @@ asmlinkage void do_page_fault(struct pt_
    3.89  
    3.90      __get_user(l1e, (unsigned long *)(linear_pg_table+(addr>>PAGE_SHIFT)));
    3.91      if ( !(l1e & _PAGE_PRESENT) )
    3.92 -        goto unlock_and_bounce_fault;
    3.93 +        goto unlock_and_propagate_fault;
    3.94  
    3.95      page = frame_table + (l1e >> PAGE_SHIFT);
    3.96      if ( (page->flags & PG_type_mask) != PGT_ldt_page )
    3.97      {
    3.98          if ( page->type_count != 0 )
    3.99 -            goto unlock_and_bounce_fault;
   3.100 +            goto unlock_and_propagate_fault;
   3.101  
   3.102          /* Check all potential LDT entries in the page. */
   3.103          ldt_page = (unsigned long *)(addr & PAGE_MASK);
   3.104          for ( i = 0; i < 512; i++ )
   3.105              if ( !check_descriptor(ldt_page[i*2], ldt_page[i*2+1]) )
   3.106 -                goto unlock_and_bounce_fault;
   3.107 +                goto unlock_and_propagate_fault;
   3.108  
   3.109          if ( page->flags & PG_need_flush )
   3.110          {
   3.111 @@ -403,18 +365,18 @@ asmlinkage void do_page_fault(struct pt_
   3.112      return;
   3.113  
   3.114  
   3.115 - unlock_and_bounce_fault:
   3.116 + unlock_and_propagate_fault:
   3.117  
   3.118      spin_unlock(&p->page_lock);
   3.119 -    goto bounce_fault;
   3.120 +    goto propagate_fault;
   3.121  
   3.122  
   3.123   fault_in_hypervisor:
   3.124  
   3.125 -    if ( (fixup = search_exception_table(regs->eip)) != 0 )
   3.126 +    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
   3.127      {
   3.128          regs->eip = fixup;
   3.129 -        check_saved_selectors(regs);
   3.130 +        regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
   3.131          return;
   3.132      }
   3.133  
   3.134 @@ -445,8 +407,8 @@ asmlinkage void do_general_protection(st
   3.135      trap_info_t *ti;
   3.136      unsigned long fixup;
   3.137  
   3.138 -    /* Bad shit if error in ring 0, or result of an interrupt. */
   3.139 -    if (!(regs->xcs & 3) || (error_code & 1))
   3.140 +    /* Badness if error in ring 0, or result of an interrupt. */
   3.141 +    if ( !(regs->xcs & 3) || (error_code & 1) )
   3.142          goto gp_in_kernel;
   3.143  
   3.144      /*
   3.145 @@ -494,40 +456,38 @@ asmlinkage void do_general_protection(st
   3.146  
   3.147   gp_in_kernel:
   3.148  
   3.149 -    if ( (fixup = search_exception_table(regs->eip)) != 0 )
   3.150 +    if ( likely((fixup = search_exception_table(regs->eip)) != 0) )
   3.151      {
   3.152          regs->eip = fixup;
   3.153 -        check_saved_selectors(regs);
   3.154 +        regs->xds = regs->xes = regs->xfs = regs->xgs = __HYPERVISOR_DS;
   3.155          return;
   3.156      }
   3.157  
   3.158      die("general protection fault", regs, error_code);
   3.159  }
   3.160  
   3.161 -static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
   3.162 +asmlinkage void mem_parity_error(unsigned char reason, struct pt_regs * regs)
   3.163  {
   3.164 -    printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
   3.165 +    printk("NMI received. Dazed and confused, but trying to continue\n");
   3.166      printk("You probably have a hardware problem with your RAM chips\n");
   3.167  
   3.168      /* Clear and disable the memory parity error line. */
   3.169      reason = (reason & 0xf) | 4;
   3.170      outb(reason, 0x61);
   3.171 +
   3.172 +    show_registers(regs);
   3.173 +    panic("PARITY ERROR");
   3.174  }
   3.175  
   3.176 -static void io_check_error(unsigned char reason, struct pt_regs * regs)
   3.177 +asmlinkage void io_check_error(unsigned char reason, struct pt_regs * regs)
   3.178  {
   3.179 -    unsigned long i;
   3.180 +    printk("NMI: IOCK error (debug interrupt?)\n");
   3.181  
   3.182 -    printk("NMI: IOCK error (debug interrupt?)\n");
   3.183 -    show_registers(regs);
   3.184 -
   3.185 -    /* Re-enable the IOCK line, wait for a few seconds */
   3.186      reason = (reason & 0xf) | 8;
   3.187      outb(reason, 0x61);
   3.188 -    i = 2000;
   3.189 -    while (--i) udelay(1000);
   3.190 -    reason &= ~8;
   3.191 -    outb(reason, 0x61);
   3.192 +
   3.193 +    show_registers(regs);
   3.194 +    panic("IOCK ERROR");
   3.195  }
   3.196  
   3.197  static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
   3.198 @@ -537,34 +497,16 @@ static void unknown_nmi_error(unsigned c
   3.199      printk("Do you have a strange power saving mode enabled?\n");
   3.200  }
   3.201  
   3.202 -asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
   3.203 +asmlinkage void do_nmi(struct pt_regs * regs, unsigned long reason)
   3.204  {
   3.205 -    unsigned char reason = inb(0x61);
   3.206 -
   3.207      ++nmi_count(smp_processor_id());
   3.208  
   3.209 -    if (!(reason & 0xc0)) {
   3.210  #if CONFIG_X86_LOCAL_APIC
   3.211 -        if (nmi_watchdog) {
   3.212 -            nmi_watchdog_tick(regs);
   3.213 -            return;
   3.214 -        }
   3.215 +    if ( nmi_watchdog )
   3.216 +        nmi_watchdog_tick(regs);
   3.217 +    else
   3.218  #endif
   3.219 -        unknown_nmi_error(reason, regs);
   3.220 -        return;
   3.221 -    }
   3.222 -    if (reason & 0x80)
   3.223 -        mem_parity_error(reason, regs);
   3.224 -    if (reason & 0x40)
   3.225 -        io_check_error(reason, regs);
   3.226 -    /*
   3.227 -     * Reassert NMI in case it became active meanwhile
   3.228 -     * as it's edge-triggered.
   3.229 -     */
   3.230 -    outb(0x8f, 0x70);
   3.231 -    inb(0x71);		/* dummy */
   3.232 -    outb(0x0f, 0x70);
   3.233 -    inb(0x71);		/* dummy */
   3.234 +        unknown_nmi_error((unsigned char)(reason&0xff), regs);
   3.235  }
   3.236  
   3.237  asmlinkage void math_state_restore(struct pt_regs *regs, long error_code)
     4.1 --- a/xen/include/asm-i386/irq.h	Mon Oct 13 22:09:23 2003 +0000
     4.2 +++ b/xen/include/asm-i386/irq.h	Tue Oct 14 14:12:31 2003 +0000
     4.3 @@ -115,7 +115,9 @@ extern char _stext, _etext;
     4.4  	"pushl %ebx\n\t" \
     4.5  	"movl $" STR(__HYPERVISOR_DS) ",%edx\n\t" \
     4.6  	"movl %edx,%ds\n\t" \
     4.7 -	"movl %edx,%es\n\t"
     4.8 +	"movl %edx,%es\n\t" \
     4.9 +	"movl %edx,%fs\n\t" \
    4.10 +	"movl %edx,%gs\n\t"
    4.11  
    4.12  #define IRQ_NAME2(nr) nr##_interrupt(void)
    4.13  #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
     5.1 --- a/xen/include/xeno/sched.h	Mon Oct 13 22:09:23 2003 +0000
     5.2 +++ b/xen/include/xeno/sched.h	Tue Oct 14 14:12:31 2003 +0000
     5.3 @@ -74,13 +74,11 @@ struct task_struct
     5.4       * Their offsets are hardcoded in entry.S
     5.5       */
     5.6  
     5.7 -    int processor;               /* 00: current processor */
     5.8 -    int state;                   /* 04: current run state */
     5.9 -    int hyp_events;              /* 08: pending intra-Xen events */
    5.10 -    unsigned int domain;         /* 12: domain id */
    5.11 +    unsigned short processor;    /* 00: current processor */
    5.12 +    unsigned short hyp_events;   /* 02: pending intra-Xen events */
    5.13  
    5.14      /* An unsafe pointer into a shared data area. */
    5.15 -    shared_info_t *shared_info;  /* 16: shared data area */
    5.16 +    shared_info_t *shared_info;  /* 04: shared data area */
    5.17  
    5.18      /*
    5.19       * Return vectors pushed to us by guest OS.
    5.20 @@ -89,15 +87,25 @@ struct task_struct
    5.21       * for segment registers %ds, %es, %fs and %gs:
    5.22       * 	%ds, %es, %fs, %gs, %eip, %cs, %eflags [, %oldesp, %oldss]
    5.23       */
    5.24 -    unsigned long event_selector;    /* 20: entry CS  */
    5.25 -    unsigned long event_address;     /* 24: entry EIP */
    5.26 -    unsigned long failsafe_selector; /* 28: entry CS  */
    5.27 -    unsigned long failsafe_address;  /* 32: entry EIP */
    5.28 +    unsigned long event_selector;    /* 08: entry CS  */
    5.29 +    unsigned long event_address;     /* 12: entry EIP */
    5.30 +
    5.31 +    /* Saved DS,ES,FS,GS immediately before return to guest OS. */
    5.32 +    unsigned long failsafe_selectors[4]; /* 16-32 */ 
    5.33 +
    5.34 +    /*
    5.35 +     * END OF FIRST CACHELINE. Stuff above is touched a lot!
    5.36 +     */
    5.37 +
    5.38 +    unsigned long failsafe_selector; /* 32: entry CS  */
    5.39 +    unsigned long failsafe_address;  /* 36: entry EIP */
    5.40  
    5.41      /*
    5.42       * From here on things can be added and shuffled without special attention
    5.43       */
    5.44      
    5.45 +    unsigned int domain;        /* domain id */
    5.46 +
    5.47      struct list_head pg_head;
    5.48      unsigned int tot_pages;     /* number of pages currently possesed */
    5.49      unsigned int max_pages;     /* max number of pages that can be possesed */
    5.50 @@ -105,6 +113,7 @@ struct task_struct
    5.51      /* scheduling */
    5.52      struct list_head run_list;
    5.53      int              has_cpu;
    5.54 +    int state;                  /* current run state */
    5.55      
    5.56      s_time_t lastschd;              /* time this domain was last scheduled */
    5.57      s_time_t cpu_time;              /* total CPU time received till now */
    5.58 @@ -134,17 +143,14 @@ struct task_struct
    5.59  				       the process can do raw access
    5.60  				       to. */
    5.61      spinlock_t physdev_lock;
    5.62 -    segment_t *segment_list[XEN_MAX_SEGMENTS];                        /* xvd */
    5.63 +    segment_t *segment_list[XEN_MAX_SEGMENTS];
    5.64  
    5.65      /* VM */
    5.66      struct mm_struct mm;
    5.67      /* We need this lock to check page types and frob reference counts. */
    5.68      spinlock_t page_lock;
    5.69  
    5.70 -    mm_segment_t addr_limit;        /* thread address space:
    5.71 -                                       0-0xBFFFFFFF for user-thead
    5.72 -                                       0-0xFFFFFFFF for kernel-thread
    5.73 -                                     */
    5.74 +    mm_segment_t addr_limit;
    5.75  
    5.76      char name[MAX_DOMAIN_NAME];
    5.77