debuggers.hg

annotate xen/arch/x86/x86_32/entry.S @ 3674:fb875591fd72

bitkeeper revision 1.1159.223.63 (42028527-fv-d9BM0_LRp8UKGP19gQ)

Fix NMI deferral.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Thu Feb 03 20:10:15 2005 +0000 (2005-02-03)
parents a5f1a6abfc46
children 8710698e57e1 2ba061595230
rev   line source
kaf24@1710 1 /*
kaf24@1710 2 * Hypercall and fault low-level handling routines.
kaf24@1710 3 *
kaf24@1710 4 * Copyright (c) 2002-2004, K A Fraser
kaf24@1710 5 * Copyright (c) 1991, 1992 Linus Torvalds
kaf24@3127 6 *
kaf24@3127 7 * Calling back to a guest OS:
kaf24@3127 8 * ===========================
kaf24@3127 9 *
kaf24@1710 10 * First, we require that all callbacks (either via a supplied
kaf24@1710 11 * interrupt-descriptor-table, or via the special event or failsafe callbacks
kaf24@1710 12 * in the shared-info-structure) are to ring 1. This just makes life easier,
kaf24@1710 13 * in that it means we don't have to do messy GDT/LDT lookups to find
kaf24@1710 14 * out which the privilege-level of the return code-selector. That code
kaf24@1710 15 * would just be a hassle to write, and would need to account for running
kaf24@1710 16 * off the end of the GDT/LDT, for example. For all callbacks we check
kaf24@3127 17 * that the provided return CS is not == __HYPERVISOR_{CS,DS}. Apart from that
kaf24@3127 18 * we're safe as don't allow a guest OS to install ring-0 privileges into the
kaf24@3127 19 * GDT/LDT. It's up to the guest OS to ensure all returns via the IDT are to
kaf24@3127 20 * ring 1. If not, we load incorrect SS/ESP values from the TSS (for ring 1
kaf24@3127 21 * rather than the correct ring) and bad things are bound to ensue -- IRET is
kaf24@1710 22 * likely to fault, and we may end up killing the domain (no harm can
kaf24@1710 23 * come to Xen, though).
kaf24@1710 24 *
kaf24@1710 25 * When doing a callback, we check if the return CS is in ring 0. If so,
kaf24@1710 26 * callback is delayed until next return to ring != 0.
kaf24@1710 27 * If return CS is in ring 1, then we create a callback frame
kaf24@1710 28 * starting at return SS/ESP. The base of the frame does an intra-privilege
kaf24@1710 29 * interrupt-return.
kaf24@1710 30 * If return CS is in ring > 1, we create a callback frame starting
kaf24@1710 31 * at SS/ESP taken from appropriate section of the current TSS. The base
kaf24@1710 32 * of the frame does an inter-privilege interrupt-return.
kaf24@1710 33 *
kaf24@1710 34 * Note that the "failsafe callback" uses a special stackframe:
kaf24@1710 35 * { return_DS, return_ES, return_FS, return_GS, return_EIP,
kaf24@1710 36 * return_CS, return_EFLAGS[, return_ESP, return_SS] }
kaf24@1710 37 * That is, original values for DS/ES/FS/GS are placed on stack rather than
kaf24@1710 38 * in DS/ES/FS/GS themselves. Why? It saves us loading them, only to have them
kaf24@1710 39 * saved/restored in guest OS. Furthermore, if we load them we may cause
kaf24@1710 40 * a fault if they are invalid, which is a hassle to deal with. We avoid
kaf24@1710 41 * that problem if we don't load them :-) This property allows us to use
kaf24@1710 42 * the failsafe callback as a fallback: if we ever fault on loading DS/ES/FS/GS
kaf24@1710 43 * on return to ring != 0, we can simply package it up as a return via
kaf24@1710 44 * the failsafe callback, and let the guest OS sort it out (perhaps by
kaf24@1710 45 * killing an application process). Note that we also do this for any
kaf24@1710 46 * faulting IRET -- just let the guest OS handle it via the event
kaf24@1710 47 * callback.
kaf24@1710 48 *
kaf24@1710 49 * We terminate a domain in the following cases:
kaf24@1710 50 * - creating a callback stack frame (due to bad ring-1 stack).
kaf24@1710 51 * - faulting IRET on entry to failsafe callback handler.
kaf24@1710 52 * So, each domain must keep its ring-1 %ss/%esp and failsafe callback
kaf24@1710 53 * handler in good order (absolutely no faults allowed!).
kaf24@1710 54 */
kaf24@1710 55
kaf24@1710 56 #include <xen/config.h>
kaf24@1710 57 #include <xen/errno.h>
kaf24@2085 58 #include <xen/softirq.h>
kaf24@3314 59 #include <asm/asm_defns.h>
kaf24@3633 60 #include <asm/apicdef.h>
kaf24@2827 61 #include <public/xen.h>
kaf24@1710 62
kaf24@1710 63 #define GET_CURRENT(reg) \
kaf24@3010 64 movl $8192-4, reg; \
kaf24@1710 65 orl %esp, reg; \
kaf24@1710 66 andl $~3,reg; \
kaf24@1710 67 movl (reg),reg;
kaf24@1710 68
kaf24@1710 69 ALIGN
kaf24@1710 70 restore_all_guest:
kaf24@3127 71 testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
kaf24@3127 72 jnz failsafe_callback
kaf24@3207 73 testl $X86_EFLAGS_VM,XREGS_eflags(%esp)
kaf24@3207 74 jnz restore_all_vm86
kaf24@3127 75 FLT1: movl XREGS_ds(%esp),%ds
kaf24@3127 76 FLT2: movl XREGS_es(%esp),%es
kaf24@3127 77 FLT3: movl XREGS_fs(%esp),%fs
kaf24@3127 78 FLT4: movl XREGS_gs(%esp),%gs
kaf24@3207 79 restore_all_vm86:
kaf24@1710 80 popl %ebx
kaf24@1710 81 popl %ecx
kaf24@1710 82 popl %edx
kaf24@1710 83 popl %esi
kaf24@1710 84 popl %edi
kaf24@1710 85 popl %ebp
kaf24@1710 86 popl %eax
kaf24@2954 87 addl $4,%esp
kaf24@3127 88 FLT5: iret
kaf24@3127 89 .section .fixup,"ax"
kaf24@3127 90 FIX5: subl $28,%esp
kaf24@3127 91 pushl 28(%esp) # error_code/entry_vector
kaf24@3127 92 movl %eax,XREGS_eax+4(%esp)
kaf24@3127 93 movl %ebp,XREGS_ebp+4(%esp)
kaf24@3127 94 movl %edi,XREGS_edi+4(%esp)
kaf24@3127 95 movl %esi,XREGS_esi+4(%esp)
kaf24@3127 96 movl %edx,XREGS_edx+4(%esp)
kaf24@3127 97 movl %ecx,XREGS_ecx+4(%esp)
kaf24@3127 98 movl %ebx,XREGS_ebx+4(%esp)
kaf24@3127 99 FIX1: SET_XEN_SEGMENTS(a)
kaf24@3127 100 movl %eax,%fs
kaf24@3127 101 movl %eax,%gs
kaf24@3127 102 sti
kaf24@3127 103 popl %esi
kaf24@3127 104 pushfl # EFLAGS
kaf24@3127 105 movl $__HYPERVISOR_CS,%eax
kaf24@3127 106 pushl %eax # CS
kaf24@3127 107 movl $DBLFLT1,%eax
kaf24@3127 108 pushl %eax # EIP
kaf24@3127 109 pushl %esi # error_code/entry_vector
kaf24@3127 110 jmp error_code
kaf24@3127 111 DBLFLT1:GET_CURRENT(%ebx)
kaf24@3127 112 jmp test_all_events
kaf24@3127 113 DBLFIX1:GET_CURRENT(%ebx)
kaf24@3127 114 testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
kaf24@3127 115 jnz domain_crash # cannot reenter failsafe code
kaf24@3127 116 orb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
kaf24@3127 117 jmp test_all_events # will return via failsafe code
kaf24@3127 118 .previous
kaf24@3127 119 .section __pre_ex_table,"a"
kaf24@3127 120 .long FLT1,FIX1
kaf24@3127 121 .long FLT2,FIX1
kaf24@3127 122 .long FLT3,FIX1
kaf24@3127 123 .long FLT4,FIX1
kaf24@3127 124 .long FLT5,FIX5
kaf24@3127 125 .previous
kaf24@3127 126 .section __ex_table,"a"
kaf24@3127 127 .long DBLFLT1,DBLFIX1
kaf24@3127 128 .previous
kaf24@3127 129
kaf24@3127 130 /* No special register assumptions */
kaf24@3127 131 failsafe_callback:
kaf24@3127 132 GET_CURRENT(%ebx)
kaf24@3127 133 andb $~TF_failsafe_return,DOMAIN_thread_flags(%ebx)
kaf24@3127 134 leal DOMAIN_trap_bounce(%ebx),%edx
kaf24@3127 135 movl DOMAIN_failsafe_addr(%ebx),%eax
kaf24@3127 136 movl %eax,TRAPBOUNCE_eip(%edx)
kaf24@3127 137 movl DOMAIN_failsafe_sel(%ebx),%eax
kaf24@3127 138 movw %ax,TRAPBOUNCE_cs(%edx)
kaf24@3127 139 movw $TBF_FAILSAFE,TRAPBOUNCE_flags(%edx)
kaf24@3127 140 call create_bounce_frame
kaf24@3127 141 popl %ebx
kaf24@3127 142 popl %ecx
kaf24@3127 143 popl %edx
kaf24@3127 144 popl %esi
kaf24@3127 145 popl %edi
kaf24@3127 146 popl %ebp
kaf24@3127 147 popl %eax
kaf24@3127 148 addl $4,%esp
kaf24@3127 149 FLT6: iret
kaf24@3127 150 .section .fixup,"ax"
kaf24@3127 151 FIX6: pushl %ebx
kaf24@3127 152 GET_CURRENT(%ebx)
kaf24@3127 153 orb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
kaf24@3127 154 pop %ebx
kaf24@3127 155 jmp FIX5
kaf24@3127 156 .section __pre_ex_table,"a"
kaf24@3127 157 .long FLT6,FIX6
kaf24@3127 158 .previous
kaf24@1710 159
kaf24@1710 160 ALIGN
kaf24@1710 161 restore_all_xen:
kaf24@1710 162 popl %ebx
kaf24@1710 163 popl %ecx
kaf24@1710 164 popl %edx
kaf24@1710 165 popl %esi
kaf24@1710 166 popl %edi
kaf24@1710 167 popl %ebp
kaf24@1710 168 popl %eax
kaf24@1710 169 addl $4,%esp
kaf24@1710 170 iret
kaf24@1710 171
kaf24@1710 172 ALIGN
kaf24@1710 173 ENTRY(hypercall)
kaf24@3127 174 subl $4,%esp
kaf24@2955 175 SAVE_ALL(b)
kaf24@2954 176 sti
kaf24@2954 177 GET_CURRENT(%ebx)
kaf24@1710 178 andl $(NR_hypercalls-1),%eax
kaf24@1710 179 call *SYMBOL_NAME(hypercall_table)(,%eax,4)
kaf24@1710 180
kaf24@1710 181 ret_from_hypercall:
kaf24@3127 182 movl %eax,XREGS_eax(%esp) # save the return value
kaf24@1710 183
kaf24@1710 184 test_all_events:
kaf24@1710 185 xorl %ecx,%ecx
kaf24@1710 186 notl %ecx
kaf24@1710 187 cli # tests must not race interrupts
kaf24@1710 188 /*test_softirqs:*/
kaf24@2954 189 movl DOMAIN_processor(%ebx),%eax
kaf24@1710 190 shl $6,%eax # sizeof(irq_cpustat) == 64
kaf24@1710 191 test %ecx,SYMBOL_NAME(irq_stat)(%eax,1)
kaf24@1710 192 jnz process_softirqs
kaf24@1710 193 /*test_guest_events:*/
kaf24@2954 194 movl DOMAIN_shared_info(%ebx),%eax
kaf24@2954 195 testb $0xFF,SHINFO_upcall_mask(%eax)
kaf24@1710 196 jnz restore_all_guest
kaf24@2954 197 testb $0xFF,SHINFO_upcall_pending(%eax)
kaf24@1710 198 jz restore_all_guest
kaf24@1710 199 /*process_guest_events:*/
kaf24@3081 200 leal DOMAIN_trap_bounce(%ebx),%edx
kaf24@2954 201 movl DOMAIN_event_addr(%ebx),%eax
kaf24@3081 202 movl %eax,TRAPBOUNCE_eip(%edx)
kaf24@2954 203 movl DOMAIN_event_sel(%ebx),%eax
kaf24@3081 204 movw %ax,TRAPBOUNCE_cs(%edx)
kaf24@3127 205 movw $TBF_INTERRUPT,TRAPBOUNCE_flags(%edx)
kaf24@1710 206 call create_bounce_frame
kaf24@3127 207 movl DOMAIN_shared_info(%ebx),%eax
kaf24@3127 208 movb $1,SHINFO_upcall_mask(%eax) # Upcalls are masked during delivery
kaf24@1710 209 jmp restore_all_guest
kaf24@1710 210
kaf24@1710 211 ALIGN
kaf24@1710 212 process_softirqs:
kaf24@1710 213 sti
kaf24@1710 214 call SYMBOL_NAME(do_softirq)
kaf24@1710 215 jmp test_all_events
kaf24@1710 216
kaf24@2954 217 /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK: */
kaf24@2954 218 /* {EIP, CS, EFLAGS, [ESP, SS]} */
kaf24@3081 219 /* %edx == trap_bounce, %ebx == task_struct */
kaf24@2954 220 /* %eax,%ecx are clobbered. %gs:%esi contain new XREGS_ss/XREGS_esp. */
kaf24@3207 221 create_bounce_frame:
kaf24@3207 222 movl XREGS_eflags+4(%esp),%ecx
kaf24@3127 223 movb XREGS_cs+4(%esp),%cl
kaf24@3207 224 testl $(2|X86_EFLAGS_VM),%ecx
kaf24@3207 225 jz ring1 /* jump if returning to an existing ring-1 activation */
kaf24@1710 226 /* obtain ss/esp from TSS -- no current ring-1 activations */
kaf24@2954 227 movl DOMAIN_processor(%ebx),%eax
kaf24@1710 228 /* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */
kaf24@1710 229 movl %eax, %ecx
kaf24@1710 230 shll $7, %ecx
kaf24@1710 231 shll $13, %eax
kaf24@1710 232 addl %ecx,%eax
kaf24@1710 233 addl $init_tss + 12,%eax
kaf24@1710 234 movl (%eax),%esi /* tss->esp1 */
kaf24@3127 235 FLT7: movl 4(%eax),%gs /* tss->ss1 */
kaf24@3207 236 testl $X86_EFLAGS_VM,XREGS_eflags+4(%esp)
kaf24@3207 237 jz nvm86_1
kaf24@3207 238 subl $16,%esi /* push ES/DS/FS/GS (VM86 stack frame) */
kaf24@3207 239 movl XREGS_es+4(%esp),%eax
kaf24@3207 240 FLT8: movl %eax,%gs:(%esi)
kaf24@3207 241 movl XREGS_ds+4(%esp),%eax
kaf24@3207 242 FLT9: movl %eax,%gs:4(%esi)
kaf24@3207 243 movl XREGS_fs+4(%esp),%eax
kaf24@3207 244 FLT10: movl %eax,%gs:8(%esi)
kaf24@3207 245 movl XREGS_gs+4(%esp),%eax
kaf24@3207 246 FLT11: movl %eax,%gs:12(%esi)
kaf24@3207 247 nvm86_1:subl $8,%esi /* push SS/ESP (inter-priv iret) */
kaf24@2954 248 movl XREGS_esp+4(%esp),%eax
kaf24@3207 249 FLT12: movl %eax,%gs:(%esi)
kaf24@2954 250 movl XREGS_ss+4(%esp),%eax
kaf24@3207 251 FLT13: movl %eax,%gs:4(%esi)
kaf24@3207 252 jmp 1f
kaf24@3207 253 ring1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
kaf24@2954 254 movl XREGS_esp+4(%esp),%esi
kaf24@3207 255 FLT14: movl XREGS_ss+4(%esp),%gs
kaf24@3207 256 1: /* Construct a stack frame: EFLAGS, CS/EIP */
kaf24@1710 257 subl $12,%esi
kaf24@2954 258 movl XREGS_eip+4(%esp),%eax
kaf24@3207 259 FLT15: movl %eax,%gs:(%esi)
kaf24@2954 260 movl XREGS_cs+4(%esp),%eax
kaf24@3207 261 FLT16: movl %eax,%gs:4(%esi)
kaf24@2954 262 movl XREGS_eflags+4(%esp),%eax
kaf24@3207 263 FLT17: movl %eax,%gs:8(%esi)
kaf24@3127 264 movb TRAPBOUNCE_flags(%edx),%cl
kaf24@3127 265 test $TBF_EXCEPTION_ERRCODE,%cl
kaf24@3127 266 jz 1f
kaf24@3127 267 subl $4,%esi # push error_code onto guest frame
kaf24@3127 268 movl TRAPBOUNCE_error_code(%edx),%eax
kaf24@3207 269 FLT18: movl %eax,%gs:(%esi)
kaf24@3127 270 testb $TBF_EXCEPTION_CR2,%cl
kaf24@3127 271 jz 2f
kaf24@3127 272 subl $4,%esi # push %cr2 onto guest frame
kaf24@3127 273 movl TRAPBOUNCE_cr2(%edx),%eax
kaf24@3207 274 FLT19: movl %eax,%gs:(%esi)
kaf24@3127 275 1: testb $TBF_FAILSAFE,%cl
kaf24@3127 276 jz 2f
kaf24@3127 277 subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame
kaf24@3207 278 testl $X86_EFLAGS_VM,XREGS_eflags+4(%esp)
kaf24@3207 279 jz nvm86_2
kaf24@3207 280 xorl %eax,%eax # VM86: we write zero selector values
kaf24@3207 281 FLT20: movl %eax,%gs:(%esi)
kaf24@3207 282 FLT21: movl %eax,%gs:4(%esi)
kaf24@3207 283 FLT22: movl %eax,%gs:8(%esi)
kaf24@3207 284 FLT23: movl %eax,%gs:12(%esi)
kaf24@3207 285 jmp 2f
kaf24@3207 286 nvm86_2:movl XREGS_ds+4(%esp),%eax # non-VM86: write real selector values
kaf24@3207 287 FLT24: movl %eax,%gs:(%esi)
kaf24@3127 288 movl XREGS_es+4(%esp),%eax
kaf24@3207 289 FLT25: movl %eax,%gs:4(%esi)
kaf24@3127 290 movl XREGS_fs+4(%esp),%eax
kaf24@3207 291 FLT26: movl %eax,%gs:8(%esi)
kaf24@3127 292 movl XREGS_gs+4(%esp),%eax
kaf24@3207 293 FLT27: movl %eax,%gs:12(%esi)
kaf24@3127 294 2: movb $0,TRAPBOUNCE_flags(%edx)
kaf24@3207 295 testl $X86_EFLAGS_VM,XREGS_eflags+4(%esp)
kaf24@3207 296 jz nvm86_3
kaf24@3207 297 xorl %eax,%eax /* zero DS-GS, just as a real CPU would */
kaf24@3207 298 movl %eax,XREGS_ds+4(%esp)
kaf24@3207 299 movl %eax,XREGS_es+4(%esp)
kaf24@3207 300 movl %eax,XREGS_fs+4(%esp)
kaf24@3207 301 movl %eax,XREGS_gs+4(%esp)
kaf24@3207 302 nvm86_3:/* Rewrite our stack frame and return to ring 1. */
kaf24@1710 303 /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
kaf24@3127 304 andl $0xfffcbeff,XREGS_eflags+4(%esp)
kaf24@2954 305 movl %gs,XREGS_ss+4(%esp)
kaf24@2954 306 movl %esi,XREGS_esp+4(%esp)
kaf24@3081 307 movzwl TRAPBOUNCE_cs(%edx),%eax
kaf24@2954 308 movl %eax,XREGS_cs+4(%esp)
kaf24@3081 309 movl TRAPBOUNCE_eip(%edx),%eax
kaf24@2954 310 movl %eax,XREGS_eip+4(%esp)
kaf24@1710 311 ret
kaf24@3127 312 .section .fixup,"ax"
kaf24@3127 313 FIX7: sti
kaf24@3127 314 popl %esi
kaf24@3127 315 addl $4,%esp # Discard create_b_frame return address
kaf24@3127 316 pushfl # EFLAGS
kaf24@3127 317 movl $__HYPERVISOR_CS,%eax
kaf24@3127 318 pushl %eax # CS
kaf24@3127 319 movl $DBLFLT2,%eax
kaf24@3127 320 pushl %eax # EIP
kaf24@3127 321 pushl %esi # error_code/entry_vector
kaf24@3127 322 jmp error_code
kaf24@3127 323 DBLFLT2:jmp process_guest_exception_and_events
kaf24@3127 324 .previous
kaf24@3127 325 .section __pre_ex_table,"a"
kaf24@3207 326 .long FLT7,FIX7 , FLT8,FIX7 , FLT9,FIX7 , FLT10,FIX7
kaf24@3207 327 .long FLT11,FIX7 , FLT12,FIX7 , FLT13,FIX7 , FLT14,FIX7
kaf24@3207 328 .long FLT15,FIX7 , FLT16,FIX7 , FLT17,FIX7 , FLT18,FIX7
kaf24@3207 329 .long FLT19,FIX7 , FLT20,FIX7 , FLT21,FIX7 , FLT22,FIX7
kaf24@3207 330 .long FLT23,FIX7 , FLT24,FIX7 , FLT25,FIX7 , FLT26,FIX7 , FLT27,FIX7
kaf24@3127 331 .previous
kaf24@1710 332 .section __ex_table,"a"
kaf24@3127 333 .long DBLFLT2,domain_crash
kaf24@1710 334 .previous
kaf24@1710 335
kaf24@1710 336 ALIGN
kaf24@3127 337 process_guest_exception_and_events:
kaf24@3081 338 leal DOMAIN_trap_bounce(%ebx),%edx
kaf24@3127 339 testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%edx)
kaf24@1710 340 jz test_all_events
kaf24@3257 341 cli # create_bounce_frame needs CLI for pre-exceptions to work
kaf24@3127 342 call create_bounce_frame
kaf24@1710 343 jmp test_all_events
kaf24@1710 344
kaf24@1710 345 ALIGN
kaf24@1710 346 ENTRY(ret_from_intr)
kaf24@3207 347 GET_CURRENT(%ebx)
kaf24@3207 348 movl XREGS_eflags(%esp),%eax
kaf24@3207 349 movb XREGS_cs(%esp),%al
kaf24@3207 350 testl $(3|X86_EFLAGS_VM),%eax
kaf24@3207 351 jnz test_all_events
kaf24@3207 352 jmp restore_all_xen
kaf24@1710 353
kaf24@1710 354 ENTRY(divide_error)
kaf24@3127 355 pushl $TRAP_divide_error<<16
kaf24@1710 356 ALIGN
kaf24@1710 357 error_code:
kaf24@3127 358 SAVE_ALL_NOSEGREGS(a)
kaf24@3127 359 SET_XEN_SEGMENTS(a)
kaf24@3127 360 testb $X86_EFLAGS_IF>>8,XREGS_eflags+1(%esp)
kaf24@3127 361 jz exception_with_ints_disabled
kaf24@3198 362 1: sti # re-enable interrupts
kaf24@3127 363 xorl %eax,%eax
kaf24@3127 364 movw XREGS_entry_vector(%esp),%ax
kaf24@3127 365 movl %esp,%edx
ach61@2843 366 pushl %edx # push the xen_regs pointer
kaf24@1710 367 GET_CURRENT(%ebx)
kaf24@3127 368 call *SYMBOL_NAME(exception_table)(,%eax,4)
kaf24@3127 369 addl $4,%esp
kaf24@3207 370 movl XREGS_eflags(%esp),%eax
kaf24@2954 371 movb XREGS_cs(%esp),%al
kaf24@3207 372 testl $(3|X86_EFLAGS_VM),%eax
kaf24@3127 373 jz restore_all_xen
kaf24@1710 374 jmp process_guest_exception_and_events
kaf24@1710 375
kaf24@3127 376 exception_with_ints_disabled:
kaf24@3207 377 movl XREGS_eflags(%esp),%eax
kaf24@3127 378 movb XREGS_cs(%esp),%al
kaf24@3207 379 testl $(3|X86_EFLAGS_VM),%eax # interrupts disabled outside Xen?
kaf24@3207 380 jnz 1b # it really does happen!
kaf24@3207 381 # (e.g., DOM0 X server)
kaf24@3127 382 pushl XREGS_eip(%esp)
kaf24@3127 383 call search_pre_exception_table
kaf24@3127 384 addl $4,%esp
kaf24@3127 385 testl %eax,%eax # no fixup code for faulting EIP?
kaf24@3127 386 jz FATAL_exception_with_ints_disabled
kaf24@3127 387 movl %eax,XREGS_eip(%esp)
kaf24@3127 388 movl %esp,%esi
kaf24@3127 389 subl $4,%esp
kaf24@3127 390 movl %esp,%edi
kaf24@3127 391 movl $XREGS_kernel_sizeof/4,%ecx
kaf24@3127 392 rep; movsl # make room for error_code/entry_vector
kaf24@3127 393 movl XREGS_error_code(%esp),%eax # error_code/entry_vector
kaf24@3127 394 movl %eax,XREGS_kernel_sizeof(%esp)
kaf24@3127 395 jmp restore_all_xen # return to fixup code
kaf24@3127 396
kaf24@3127 397 FATAL_exception_with_ints_disabled:
kaf24@3127 398 xorl %esi,%esi
kaf24@3127 399 movw XREGS_entry_vector(%esp),%si
kaf24@3127 400 movl %esp,%edx
kaf24@3127 401 pushl %edx # push the xen_regs pointer
kaf24@3127 402 pushl %esi # push the trapnr (entry vector)
kaf24@3127 403 call SYMBOL_NAME(fatal_trap)
kaf24@3127 404 ud2
kaf24@3127 405
kaf24@1710 406 ENTRY(coprocessor_error)
kaf24@3127 407 pushl $TRAP_copro_error<<16
kaf24@1710 408 jmp error_code
kaf24@1710 409
kaf24@1710 410 ENTRY(simd_coprocessor_error)
kaf24@3127 411 pushl $TRAP_simd_error<<16
kaf24@1710 412 jmp error_code
kaf24@1710 413
kaf24@1710 414 ENTRY(device_not_available)
kaf24@3127 415 pushl $TRAP_no_device<<16
kaf24@1710 416 jmp error_code
kaf24@1710 417
kaf24@1710 418 ENTRY(debug)
kaf24@3127 419 pushl $TRAP_debug<<16
kaf24@1710 420 jmp error_code
kaf24@1710 421
kaf24@1710 422 ENTRY(int3)
kaf24@3127 423 pushl $TRAP_int3<<16
kaf24@1710 424 jmp error_code
kaf24@1710 425
kaf24@1710 426 ENTRY(overflow)
kaf24@3127 427 pushl $TRAP_overflow<<16
kaf24@1710 428 jmp error_code
kaf24@1710 429
kaf24@1710 430 ENTRY(bounds)
kaf24@3127 431 pushl $TRAP_bounds<<16
kaf24@1710 432 jmp error_code
kaf24@1710 433
kaf24@1710 434 ENTRY(invalid_op)
kaf24@3127 435 pushl $TRAP_invalid_op<<16
kaf24@1710 436 jmp error_code
kaf24@1710 437
kaf24@1710 438 ENTRY(coprocessor_segment_overrun)
kaf24@3127 439 pushl $TRAP_copro_seg<<16
kaf24@1710 440 jmp error_code
kaf24@1710 441
kaf24@1710 442 ENTRY(invalid_TSS)
kaf24@3127 443 movw $TRAP_invalid_tss,2(%esp)
kaf24@1710 444 jmp error_code
kaf24@1710 445
kaf24@1710 446 ENTRY(segment_not_present)
kaf24@3127 447 movw $TRAP_no_segment,2(%esp)
kaf24@1710 448 jmp error_code
kaf24@1710 449
kaf24@1710 450 ENTRY(stack_segment)
kaf24@3127 451 movw $TRAP_stack_error,2(%esp)
kaf24@1710 452 jmp error_code
kaf24@1710 453
kaf24@1710 454 ENTRY(general_protection)
kaf24@3127 455 movw $TRAP_gp_fault,2(%esp)
kaf24@1710 456 jmp error_code
kaf24@1710 457
kaf24@1710 458 ENTRY(alignment_check)
kaf24@3127 459 movw $TRAP_alignment_check,2(%esp)
kaf24@1710 460 jmp error_code
kaf24@1710 461
kaf24@1710 462 ENTRY(page_fault)
kaf24@3127 463 movw $TRAP_page_fault,2(%esp)
kaf24@1710 464 jmp error_code
kaf24@1710 465
kaf24@1710 466 ENTRY(machine_check)
kaf24@3127 467 pushl $TRAP_machine_check<<16
kaf24@1710 468 jmp error_code
kaf24@1710 469
kaf24@1710 470 ENTRY(spurious_interrupt_bug)
kaf24@3127 471 pushl $TRAP_spurious_int<<16
kaf24@1710 472 jmp error_code
kaf24@1710 473
kaf24@1710 474 ENTRY(nmi)
kaf24@1710 475 # Save state but do not trash the segment registers!
kaf24@1710 476 # We may otherwise be unable to reload them or copy them to ring 1.
kaf24@1710 477 pushl %eax
kaf24@2955 478 SAVE_ALL_NOSEGREGS(a)
kaf24@1710 479
kaf24@2085 480 # Check for hardware problems.
kaf24@1710 481 inb $0x61,%al
kaf24@1710 482 testb $0x80,%al
kaf24@2080 483 jne nmi_parity_err
kaf24@1710 484 testb $0x40,%al
kaf24@1710 485 jne nmi_io_err
kaf24@1710 486 movl %eax,%ebx
kaf24@1710 487
kaf24@1710 488 # Okay, its almost a normal NMI tick. We can only process it if:
kaf24@1710 489 # A. We are the outermost Xen activation (in which case we have
kaf24@1710 490 # the selectors safely saved on our stack)
kaf24@1710 491 # B. DS-GS all contain sane Xen values.
kaf24@1710 492 # In all other cases we bail without touching DS-GS, as we have
kaf24@1710 493 # interrupted an enclosing Xen activation in tricky prologue or
kaf24@1710 494 # epilogue code.
kaf24@3207 495 movl XREGS_eflags(%esp),%eax
kaf24@2954 496 movb XREGS_cs(%esp),%al
kaf24@3207 497 testl $(3|X86_EFLAGS_VM),%eax
kaf24@3127 498 jnz do_watchdog_tick
kaf24@3373 499 movl %ds,%eax
kaf24@1710 500 cmpw $(__HYPERVISOR_DS),%ax
kaf24@3633 501 jne defer_nmi
kaf24@3373 502 movl %es,%eax
kaf24@1710 503 cmpw $(__HYPERVISOR_DS),%ax
kaf24@3633 504 jne defer_nmi
kaf24@1710 505
kaf24@1710 506 do_watchdog_tick:
kaf24@1710 507 movl $(__HYPERVISOR_DS),%edx
kaf24@1710 508 movl %edx,%ds
kaf24@1710 509 movl %edx,%es
kaf24@1710 510 movl %esp,%edx
kaf24@1710 511 pushl %ebx # reason
kaf24@1710 512 pushl %edx # regs
kaf24@1710 513 call SYMBOL_NAME(do_nmi)
kaf24@1710 514 addl $8,%esp
kaf24@3207 515 movl XREGS_eflags(%esp),%eax
kaf24@2954 516 movb XREGS_cs(%esp),%al
kaf24@3207 517 testl $(3|X86_EFLAGS_VM),%eax
kaf24@3127 518 jz restore_all_xen
kaf24@1710 519 GET_CURRENT(%ebx)
kaf24@1710 520 jmp restore_all_guest
kaf24@1710 521
kaf24@3633 522 defer_nmi:
kaf24@3633 523 movl $FIXMAP_apic_base,%eax
kaf24@3633 524 # apic_wait_icr_idle()
kaf24@3674 525 1: movl %ss:APIC_ICR(%eax),%ebx
kaf24@3633 526 testl $APIC_ICR_BUSY,%ebx
kaf24@3633 527 jnz 1b
kaf24@3633 528 # __send_IPI_shortcut(APIC_DEST_SELF, TRAP_deferred_nmi)
kaf24@3633 529 movl $(APIC_DM_FIXED | APIC_DEST_SELF | APIC_DEST_LOGICAL | \
kaf24@3674 530 TRAP_deferred_nmi),%ss:APIC_ICR(%eax)
kaf24@3633 531 jmp restore_all_xen
kaf24@3633 532
kaf24@2085 533 nmi_parity_err:
kaf24@2085 534 # Clear and disable the parity-error line
kaf24@2085 535 andb $0xf,%al
kaf24@2085 536 orb $0x4,%al
kaf24@2085 537 outb %al,$0x61
kaf24@2085 538 cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
kaf24@2954 539 je restore_all_xen
kaf24@2085 540 bts $0,%ss:SYMBOL_NAME(nmi_softirq_reason)
kaf24@2085 541 bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
kaf24@2085 542 cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
kaf24@2954 543 je restore_all_xen
kaf24@2085 544 movl $(__HYPERVISOR_DS),%edx # nmi=fatal
kaf24@1710 545 movl %edx,%ds
kaf24@1710 546 movl %edx,%es
kaf24@2079 547 movl %esp,%edx
kaf24@2079 548 push %edx
kaf24@2079 549 call SYMBOL_NAME(mem_parity_error)
kaf24@2085 550 addl $4,%esp
kaf24@2085 551 jmp ret_from_intr
kaf24@2085 552
kaf24@1710 553 nmi_io_err:
kaf24@2085 554 # Clear and disable the I/O-error line
kaf24@2085 555 andb $0xf,%al
kaf24@2085 556 orb $0x8,%al
kaf24@2085 557 outb %al,$0x61
kaf24@2085 558 cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
kaf24@2954 559 je restore_all_xen
kaf24@2085 560 bts $1,%ss:SYMBOL_NAME(nmi_softirq_reason)
kaf24@2085 561 bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
kaf24@2085 562 cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
kaf24@2954 563 je restore_all_xen
kaf24@2085 564 movl $(__HYPERVISOR_DS),%edx # nmi=fatal
kaf24@1710 565 movl %edx,%ds
kaf24@1710 566 movl %edx,%es
kaf24@2079 567 movl %esp,%edx
kaf24@2079 568 push %edx
kaf24@2079 569 call SYMBOL_NAME(io_check_error)
kaf24@2085 570 addl $4,%esp
kaf24@2085 571 jmp ret_from_intr
kaf24@3207 572
kaf24@3207 573
kaf24@3207 574 ENTRY(setup_vm86_frame)
kaf24@3207 575 # Copies the entire stack frame forwards by 16 bytes.
kaf24@3207 576 .macro copy_vm86_words count=18
kaf24@3207 577 .if \count
kaf24@3207 578 pushl ((\count-1)*4)(%esp)
kaf24@3207 579 popl ((\count-1)*4)+16(%esp)
kaf24@3207 580 copy_vm86_words "(\count-1)"
kaf24@3207 581 .endif
kaf24@3207 582 .endm
kaf24@3207 583 copy_vm86_words
kaf24@3207 584 addl $16,%esp
kaf24@3207 585 ret
kaf24@3207 586
kaf24@3207 587 do_switch_vm86:
kaf24@3207 588 # Discard the return address
kaf24@3207 589 addl $4,%esp
kaf24@3207 590
kaf24@3218 591 movl XREGS_eflags(%esp),%edx
kaf24@3218 592
kaf24@3207 593 # GS:ESI == Ring-1 stack activation
kaf24@3207 594 movl XREGS_esp(%esp),%esi
kaf24@3207 595 VFLT1: movl XREGS_ss(%esp),%gs
kaf24@3207 596
kaf24@3207 597 # ES:EDI == Ring-0 stack activation
kaf24@3207 598 leal XREGS_eip(%esp),%edi
kaf24@3207 599
kaf24@3207 600 # Restore the hypercall-number-clobbered EAX on our stack frame
kaf24@3207 601 VFLT2: movl %gs:(%esi),%eax
kaf24@3207 602 movl %eax,XREGS_eax(%esp)
kaf24@3207 603 addl $4,%esi
kaf24@3207 604
kaf24@3207 605 # Copy the VM86 activation from the ring-1 stack to the ring-0 stack
kaf24@3207 606 movl $(XREGS_user_sizeof-XREGS_eip)/4,%ecx
kaf24@3207 607 VFLT3: movl %gs:(%esi),%eax
kaf24@3207 608 stosl
kaf24@3207 609 addl $4,%esi
kaf24@3207 610 loop VFLT3
kaf24@3207 611
kaf24@3207 612 # Fix up EFLAGS
kaf24@3207 613 andl $~X86_EFLAGS_IOPL,XREGS_eflags(%esp)
kaf24@3218 614 andl $X86_EFLAGS_IOPL,%edx # Ignore attempts to change EFLAGS.IOPL
kaf24@3207 615 jnz 1f
kaf24@3218 616 orl $X86_EFLAGS_IF,%edx # EFLAGS.IOPL=0 => no messing with EFLAGS.IF
kaf24@3218 617 1: orl $X86_EFLAGS_VM,%edx # Force EFLAGS.VM
kaf24@3218 618 orl %edx,XREGS_eflags(%esp)
kaf24@3207 619
kaf24@3207 620 jmp test_all_events
kaf24@3207 621
kaf24@3207 622 .section __ex_table,"a"
kaf24@3207 623 .long VFLT1,domain_crash
kaf24@3207 624 .long VFLT2,domain_crash
kaf24@3207 625 .long VFLT3,domain_crash
kaf24@3207 626 .previous
kaf24@3207 627
kaf24@1710 628 .data
kaf24@3127 629
kaf24@3127 630 ENTRY(exception_table)
kaf24@3127 631 .long SYMBOL_NAME(do_divide_error)
kaf24@3127 632 .long SYMBOL_NAME(do_debug)
kaf24@3127 633 .long 0 # nmi
kaf24@3127 634 .long SYMBOL_NAME(do_int3)
kaf24@3127 635 .long SYMBOL_NAME(do_overflow)
kaf24@3127 636 .long SYMBOL_NAME(do_bounds)
kaf24@3127 637 .long SYMBOL_NAME(do_invalid_op)
kaf24@3127 638 .long SYMBOL_NAME(math_state_restore)
kaf24@3127 639 .long 0 # double fault
kaf24@3127 640 .long SYMBOL_NAME(do_coprocessor_segment_overrun)
kaf24@3127 641 .long SYMBOL_NAME(do_invalid_TSS)
kaf24@3127 642 .long SYMBOL_NAME(do_segment_not_present)
kaf24@3127 643 .long SYMBOL_NAME(do_stack_segment)
kaf24@3127 644 .long SYMBOL_NAME(do_general_protection)
kaf24@3127 645 .long SYMBOL_NAME(do_page_fault)
kaf24@3127 646 .long SYMBOL_NAME(do_spurious_interrupt_bug)
kaf24@3127 647 .long SYMBOL_NAME(do_coprocessor_error)
kaf24@3127 648 .long SYMBOL_NAME(do_alignment_check)
kaf24@3127 649 .long SYMBOL_NAME(do_machine_check)
kaf24@3127 650 .long SYMBOL_NAME(do_simd_coprocessor_error)
kaf24@3127 651
kaf24@1710 652 ENTRY(hypercall_table)
kaf24@1710 653 .long SYMBOL_NAME(do_set_trap_table) /* 0 */
kaf24@1710 654 .long SYMBOL_NAME(do_mmu_update)
kaf24@1710 655 .long SYMBOL_NAME(do_set_gdt)
kaf24@1710 656 .long SYMBOL_NAME(do_stack_switch)
kaf24@1710 657 .long SYMBOL_NAME(do_set_callbacks)
kaf24@1710 658 .long SYMBOL_NAME(do_fpu_taskswitch) /* 5 */
kaf24@1710 659 .long SYMBOL_NAME(do_sched_op)
kaf24@1710 660 .long SYMBOL_NAME(do_dom0_op)
kaf24@1710 661 .long SYMBOL_NAME(do_set_debugreg)
kaf24@1710 662 .long SYMBOL_NAME(do_get_debugreg)
kaf24@1710 663 .long SYMBOL_NAME(do_update_descriptor) /* 10 */
kaf24@1710 664 .long SYMBOL_NAME(do_set_fast_trap)
kaf24@1710 665 .long SYMBOL_NAME(do_dom_mem_op)
kaf24@1710 666 .long SYMBOL_NAME(do_multicall)
kaf24@1710 667 .long SYMBOL_NAME(do_update_va_mapping)
kaf24@1710 668 .long SYMBOL_NAME(do_set_timer_op) /* 15 */
kaf24@1710 669 .long SYMBOL_NAME(do_event_channel_op)
kaf24@1710 670 .long SYMBOL_NAME(do_xen_version)
kaf24@1710 671 .long SYMBOL_NAME(do_console_io)
kaf24@1710 672 .long SYMBOL_NAME(do_physdev_op)
kaf24@2375 673 .long SYMBOL_NAME(do_grant_table_op) /* 20 */
kaf24@2111 674 .long SYMBOL_NAME(do_vm_assist)
kaf24@2375 675 .long SYMBOL_NAME(do_update_va_mapping_otherdomain)
kaf24@3207 676 .long SYMBOL_NAME(do_switch_vm86)
kaf24@1710 677 .rept NR_hypercalls-((.-hypercall_table)/4)
kaf24@1710 678 .long SYMBOL_NAME(do_ni_hypercall)
kaf24@1710 679 .endr