debuggers.hg

annotate xen/arch/x86/x86_32/entry.S @ 3198:a46548db5e52

bitkeeper revision 1.1159.187.20 (41a77433rez_BGuifdBbTI3Y34kiag)

Deal with exception from guest context with real interrupts disabled.
This can happen because IOPL != 0 and even a well-behaved guest may
execute random BIOS code if it is a privileged hardware-controlling
domain (e.g., DOM0 X server).
author kaf24@scramble.cl.cam.ac.uk
date Fri Nov 26 18:21:39 2004 +0000 (2004-11-26)
parents b013a6b30d9e
children 20290eb62e95 861d3cdc1dc5
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@2954 59 #include <asm/x86_32/asm_defns.h>
kaf24@2827 60 #include <public/xen.h>
kaf24@1710 61
kaf24@1710 62 #define GET_CURRENT(reg) \
kaf24@3010 63 movl $8192-4, reg; \
kaf24@1710 64 orl %esp, reg; \
kaf24@1710 65 andl $~3,reg; \
kaf24@1710 66 movl (reg),reg;
kaf24@1710 67
kaf24@1710 68 ENTRY(continue_nonidle_task)
kaf24@1710 69 GET_CURRENT(%ebx)
kaf24@1710 70 jmp test_all_events
kaf24@1710 71
kaf24@1710 72 ALIGN
kaf24@1710 73 restore_all_guest:
kaf24@3127 74 testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
kaf24@3127 75 jnz failsafe_callback
kaf24@3127 76 FLT1: movl XREGS_ds(%esp),%ds
kaf24@3127 77 FLT2: movl XREGS_es(%esp),%es
kaf24@3127 78 FLT3: movl XREGS_fs(%esp),%fs
kaf24@3127 79 FLT4: movl XREGS_gs(%esp),%gs
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@1710 221 create_bounce_frame:
kaf24@3127 222 movb XREGS_cs+4(%esp),%cl
kaf24@3127 223 testb $2,%cl
kaf24@1710 224 jz 1f /* jump if returning to an existing ring-1 activation */
kaf24@1710 225 /* obtain ss/esp from TSS -- no current ring-1 activations */
kaf24@2954 226 movl DOMAIN_processor(%ebx),%eax
kaf24@1710 227 /* next 4 lines multiply %eax by 8320, which is sizeof(tss_struct) */
kaf24@1710 228 movl %eax, %ecx
kaf24@1710 229 shll $7, %ecx
kaf24@1710 230 shll $13, %eax
kaf24@1710 231 addl %ecx,%eax
kaf24@1710 232 addl $init_tss + 12,%eax
kaf24@1710 233 movl (%eax),%esi /* tss->esp1 */
kaf24@3127 234 FLT7: movl 4(%eax),%gs /* tss->ss1 */
kaf24@1710 235 /* base of stack frame must contain ss/esp (inter-priv iret) */
kaf24@1710 236 subl $8,%esi
kaf24@2954 237 movl XREGS_esp+4(%esp),%eax
kaf24@3127 238 FLT8: movl %eax,%gs:(%esi)
kaf24@2954 239 movl XREGS_ss+4(%esp),%eax
kaf24@3127 240 FLT9: movl %eax,%gs:4(%esi)
kaf24@1710 241 jmp 2f
kaf24@1710 242 1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */
kaf24@2954 243 movl XREGS_esp+4(%esp),%esi
kaf24@3127 244 FLT10: movl XREGS_ss+4(%esp),%gs
kaf24@1710 245 2: /* Construct a stack frame: EFLAGS, CS/EIP */
kaf24@1710 246 subl $12,%esi
kaf24@2954 247 movl XREGS_eip+4(%esp),%eax
kaf24@3127 248 FLT11: movl %eax,%gs:(%esi)
kaf24@2954 249 movl XREGS_cs+4(%esp),%eax
kaf24@3127 250 FLT12: movl %eax,%gs:4(%esi)
kaf24@2954 251 movl XREGS_eflags+4(%esp),%eax
kaf24@3127 252 FLT13: movl %eax,%gs:8(%esi)
kaf24@3127 253 movb TRAPBOUNCE_flags(%edx),%cl
kaf24@3127 254 test $TBF_EXCEPTION_ERRCODE,%cl
kaf24@3127 255 jz 1f
kaf24@3127 256 subl $4,%esi # push error_code onto guest frame
kaf24@3127 257 movl TRAPBOUNCE_error_code(%edx),%eax
kaf24@3127 258 FLT14: movl %eax,%gs:(%esi)
kaf24@3127 259 testb $TBF_EXCEPTION_CR2,%cl
kaf24@3127 260 jz 2f
kaf24@3127 261 subl $4,%esi # push %cr2 onto guest frame
kaf24@3127 262 movl TRAPBOUNCE_cr2(%edx),%eax
kaf24@3127 263 FLT15: movl %eax,%gs:(%esi)
kaf24@3127 264 1: testb $TBF_FAILSAFE,%cl
kaf24@3127 265 jz 2f
kaf24@3127 266 subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame
kaf24@3127 267 movl XREGS_ds+4(%esp),%eax
kaf24@3127 268 FLT16: movl %eax,%gs:(%esi)
kaf24@3127 269 movl XREGS_es+4(%esp),%eax
kaf24@3127 270 FLT17: movl %eax,%gs:4(%esi)
kaf24@3127 271 movl XREGS_fs+4(%esp),%eax
kaf24@3127 272 FLT18: movl %eax,%gs:8(%esi)
kaf24@3127 273 movl XREGS_gs+4(%esp),%eax
kaf24@3127 274 FLT19: movl %eax,%gs:12(%esi)
kaf24@3127 275 2: movb $0,TRAPBOUNCE_flags(%edx)
kaf24@1710 276 /* Rewrite our stack frame and return to ring 1. */
kaf24@1710 277 /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
kaf24@3127 278 andl $0xfffcbeff,XREGS_eflags+4(%esp)
kaf24@2954 279 movl %gs,XREGS_ss+4(%esp)
kaf24@2954 280 movl %esi,XREGS_esp+4(%esp)
kaf24@3081 281 movzwl TRAPBOUNCE_cs(%edx),%eax
kaf24@2954 282 movl %eax,XREGS_cs+4(%esp)
kaf24@3081 283 movl TRAPBOUNCE_eip(%edx),%eax
kaf24@2954 284 movl %eax,XREGS_eip+4(%esp)
kaf24@1710 285 ret
kaf24@3127 286 .section .fixup,"ax"
kaf24@3127 287 FIX7: sti
kaf24@3127 288 popl %esi
kaf24@3127 289 addl $4,%esp # Discard create_b_frame return address
kaf24@3127 290 pushfl # EFLAGS
kaf24@3127 291 movl $__HYPERVISOR_CS,%eax
kaf24@3127 292 pushl %eax # CS
kaf24@3127 293 movl $DBLFLT2,%eax
kaf24@3127 294 pushl %eax # EIP
kaf24@3127 295 pushl %esi # error_code/entry_vector
kaf24@3127 296 jmp error_code
kaf24@3127 297 DBLFLT2:jmp process_guest_exception_and_events
kaf24@3127 298 .previous
kaf24@3127 299 .section __pre_ex_table,"a"
kaf24@3127 300 .long FLT7,FIX7
kaf24@3127 301 .long FLT8,FIX7
kaf24@3127 302 .long FLT9,FIX7
kaf24@3127 303 .long FLT10,FIX7
kaf24@3127 304 .long FLT11,FIX7
kaf24@3127 305 .long FLT12,FIX7
kaf24@3127 306 .long FLT13,FIX7
kaf24@3127 307 .long FLT14,FIX7
kaf24@3127 308 .long FLT15,FIX7
kaf24@3127 309 .long FLT16,FIX7
kaf24@3127 310 .long FLT17,FIX7
kaf24@3127 311 .long FLT18,FIX7
kaf24@3127 312 .long FLT19,FIX7
kaf24@3127 313 .previous
kaf24@1710 314 .section __ex_table,"a"
kaf24@3127 315 .long DBLFLT2,domain_crash
kaf24@1710 316 .previous
kaf24@1710 317
kaf24@1710 318 ALIGN
kaf24@3127 319 process_guest_exception_and_events:
kaf24@3081 320 leal DOMAIN_trap_bounce(%ebx),%edx
kaf24@3127 321 testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%edx)
kaf24@1710 322 jz test_all_events
kaf24@3127 323 call create_bounce_frame
kaf24@1710 324 jmp test_all_events
kaf24@1710 325
kaf24@1710 326 ALIGN
kaf24@1710 327 ENTRY(ret_from_intr)
kaf24@1710 328 GET_CURRENT(%ebx)
kaf24@2954 329 movb XREGS_cs(%esp),%al
kaf24@1710 330 testb $3,%al # return to non-supervisor?
kaf24@3127 331 jnz test_all_events
kaf24@1710 332 jmp restore_all_xen
kaf24@1710 333
kaf24@1710 334 ENTRY(divide_error)
kaf24@3127 335 pushl $TRAP_divide_error<<16
kaf24@1710 336 ALIGN
kaf24@1710 337 error_code:
kaf24@3127 338 SAVE_ALL_NOSEGREGS(a)
kaf24@3127 339 SET_XEN_SEGMENTS(a)
kaf24@3127 340 testb $X86_EFLAGS_IF>>8,XREGS_eflags+1(%esp)
kaf24@3127 341 jz exception_with_ints_disabled
kaf24@3198 342 1: sti # re-enable interrupts
kaf24@3127 343 xorl %eax,%eax
kaf24@3127 344 movw XREGS_entry_vector(%esp),%ax
kaf24@3127 345 movl %esp,%edx
ach61@2843 346 pushl %edx # push the xen_regs pointer
kaf24@1710 347 GET_CURRENT(%ebx)
kaf24@3127 348 call *SYMBOL_NAME(exception_table)(,%eax,4)
kaf24@3127 349 addl $4,%esp
kaf24@2954 350 movb XREGS_cs(%esp),%al
kaf24@1710 351 testb $3,%al
kaf24@3127 352 jz restore_all_xen
kaf24@1710 353 jmp process_guest_exception_and_events
kaf24@1710 354
kaf24@3127 355 exception_with_ints_disabled:
kaf24@3127 356 movb XREGS_cs(%esp),%al
kaf24@3198 357 testb $3,%al # interrupts disabled outside Xen?
kaf24@3198 358 jnz 1b # it really does happen! (e.g., DOM0 X server)
kaf24@3127 359 pushl XREGS_eip(%esp)
kaf24@3127 360 call search_pre_exception_table
kaf24@3127 361 addl $4,%esp
kaf24@3127 362 testl %eax,%eax # no fixup code for faulting EIP?
kaf24@3127 363 jz FATAL_exception_with_ints_disabled
kaf24@3127 364 movl %eax,XREGS_eip(%esp)
kaf24@3127 365 movl %esp,%esi
kaf24@3127 366 subl $4,%esp
kaf24@3127 367 movl %esp,%edi
kaf24@3127 368 movl $XREGS_kernel_sizeof/4,%ecx
kaf24@3127 369 rep; movsl # make room for error_code/entry_vector
kaf24@3127 370 movl XREGS_error_code(%esp),%eax # error_code/entry_vector
kaf24@3127 371 movl %eax,XREGS_kernel_sizeof(%esp)
kaf24@3127 372 jmp restore_all_xen # return to fixup code
kaf24@3127 373
kaf24@3127 374 FATAL_exception_with_ints_disabled:
kaf24@3127 375 xorl %esi,%esi
kaf24@3127 376 movw XREGS_entry_vector(%esp),%si
kaf24@3127 377 movl %esp,%edx
kaf24@3127 378 pushl %edx # push the xen_regs pointer
kaf24@3127 379 pushl %esi # push the trapnr (entry vector)
kaf24@3127 380 call SYMBOL_NAME(fatal_trap)
kaf24@3127 381 ud2
kaf24@3127 382
kaf24@1710 383 ENTRY(coprocessor_error)
kaf24@3127 384 pushl $TRAP_copro_error<<16
kaf24@1710 385 jmp error_code
kaf24@1710 386
kaf24@1710 387 ENTRY(simd_coprocessor_error)
kaf24@3127 388 pushl $TRAP_simd_error<<16
kaf24@1710 389 jmp error_code
kaf24@1710 390
kaf24@1710 391 ENTRY(device_not_available)
kaf24@3127 392 pushl $TRAP_no_device<<16
kaf24@1710 393 jmp error_code
kaf24@1710 394
kaf24@1710 395 ENTRY(debug)
kaf24@3127 396 pushl $TRAP_debug<<16
kaf24@1710 397 jmp error_code
kaf24@1710 398
kaf24@1710 399 ENTRY(int3)
kaf24@3127 400 pushl $TRAP_int3<<16
kaf24@1710 401 jmp error_code
kaf24@1710 402
kaf24@1710 403 ENTRY(overflow)
kaf24@3127 404 pushl $TRAP_overflow<<16
kaf24@1710 405 jmp error_code
kaf24@1710 406
kaf24@1710 407 ENTRY(bounds)
kaf24@3127 408 pushl $TRAP_bounds<<16
kaf24@1710 409 jmp error_code
kaf24@1710 410
kaf24@1710 411 ENTRY(invalid_op)
kaf24@3127 412 pushl $TRAP_invalid_op<<16
kaf24@1710 413 jmp error_code
kaf24@1710 414
kaf24@1710 415 ENTRY(coprocessor_segment_overrun)
kaf24@3127 416 pushl $TRAP_copro_seg<<16
kaf24@1710 417 jmp error_code
kaf24@1710 418
kaf24@1710 419 ENTRY(invalid_TSS)
kaf24@3127 420 movw $TRAP_invalid_tss,2(%esp)
kaf24@1710 421 jmp error_code
kaf24@1710 422
kaf24@1710 423 ENTRY(segment_not_present)
kaf24@3127 424 movw $TRAP_no_segment,2(%esp)
kaf24@1710 425 jmp error_code
kaf24@1710 426
kaf24@1710 427 ENTRY(stack_segment)
kaf24@3127 428 movw $TRAP_stack_error,2(%esp)
kaf24@1710 429 jmp error_code
kaf24@1710 430
kaf24@1710 431 ENTRY(general_protection)
kaf24@3127 432 movw $TRAP_gp_fault,2(%esp)
kaf24@1710 433 jmp error_code
kaf24@1710 434
kaf24@1710 435 ENTRY(alignment_check)
kaf24@3127 436 movw $TRAP_alignment_check,2(%esp)
kaf24@1710 437 jmp error_code
kaf24@1710 438
kaf24@1710 439 ENTRY(page_fault)
kaf24@3127 440 movw $TRAP_page_fault,2(%esp)
kaf24@1710 441 jmp error_code
kaf24@1710 442
kaf24@1710 443 ENTRY(machine_check)
kaf24@3127 444 pushl $TRAP_machine_check<<16
kaf24@1710 445 jmp error_code
kaf24@1710 446
kaf24@1710 447 ENTRY(spurious_interrupt_bug)
kaf24@3127 448 pushl $TRAP_spurious_int<<16
kaf24@1710 449 jmp error_code
kaf24@1710 450
kaf24@1710 451 ENTRY(nmi)
kaf24@1710 452 # Save state but do not trash the segment registers!
kaf24@1710 453 # We may otherwise be unable to reload them or copy them to ring 1.
kaf24@1710 454 pushl %eax
kaf24@2955 455 SAVE_ALL_NOSEGREGS(a)
kaf24@1710 456
kaf24@2085 457 # Check for hardware problems.
kaf24@1710 458 inb $0x61,%al
kaf24@1710 459 testb $0x80,%al
kaf24@2080 460 jne nmi_parity_err
kaf24@1710 461 testb $0x40,%al
kaf24@1710 462 jne nmi_io_err
kaf24@1710 463 movl %eax,%ebx
kaf24@1710 464
kaf24@1710 465 # Okay, its almost a normal NMI tick. We can only process it if:
kaf24@1710 466 # A. We are the outermost Xen activation (in which case we have
kaf24@1710 467 # the selectors safely saved on our stack)
kaf24@1710 468 # B. DS-GS all contain sane Xen values.
kaf24@1710 469 # In all other cases we bail without touching DS-GS, as we have
kaf24@1710 470 # interrupted an enclosing Xen activation in tricky prologue or
kaf24@1710 471 # epilogue code.
kaf24@2954 472 movb XREGS_cs(%esp),%al
kaf24@1710 473 testb $3,%al
kaf24@3127 474 jnz do_watchdog_tick
kaf24@2954 475 movl XREGS_ds(%esp),%eax
kaf24@1710 476 cmpw $(__HYPERVISOR_DS),%ax
kaf24@2954 477 jne restore_all_xen
kaf24@2954 478 movl XREGS_es(%esp),%eax
kaf24@1710 479 cmpw $(__HYPERVISOR_DS),%ax
kaf24@2954 480 jne restore_all_xen
kaf24@2954 481 movl XREGS_fs(%esp),%eax
kaf24@1710 482 cmpw $(__HYPERVISOR_DS),%ax
kaf24@2954 483 jne restore_all_xen
kaf24@2954 484 movl XREGS_gs(%esp),%eax
kaf24@1710 485 cmpw $(__HYPERVISOR_DS),%ax
kaf24@2954 486 jne restore_all_xen
kaf24@1710 487
kaf24@1710 488 do_watchdog_tick:
kaf24@1710 489 movl $(__HYPERVISOR_DS),%edx
kaf24@1710 490 movl %edx,%ds
kaf24@1710 491 movl %edx,%es
kaf24@1710 492 movl %esp,%edx
kaf24@1710 493 pushl %ebx # reason
kaf24@1710 494 pushl %edx # regs
kaf24@1710 495 call SYMBOL_NAME(do_nmi)
kaf24@1710 496 addl $8,%esp
kaf24@2954 497 movb XREGS_cs(%esp),%al
kaf24@1710 498 testb $3,%al
kaf24@3127 499 jz restore_all_xen
kaf24@1710 500 GET_CURRENT(%ebx)
kaf24@1710 501 jmp restore_all_guest
kaf24@1710 502
kaf24@2085 503 nmi_parity_err:
kaf24@2085 504 # Clear and disable the parity-error line
kaf24@2085 505 andb $0xf,%al
kaf24@2085 506 orb $0x4,%al
kaf24@2085 507 outb %al,$0x61
kaf24@2085 508 cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
kaf24@2954 509 je restore_all_xen
kaf24@2085 510 bts $0,%ss:SYMBOL_NAME(nmi_softirq_reason)
kaf24@2085 511 bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
kaf24@2085 512 cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
kaf24@2954 513 je restore_all_xen
kaf24@2085 514 movl $(__HYPERVISOR_DS),%edx # nmi=fatal
kaf24@1710 515 movl %edx,%ds
kaf24@1710 516 movl %edx,%es
kaf24@2079 517 movl %esp,%edx
kaf24@2079 518 push %edx
kaf24@2079 519 call SYMBOL_NAME(mem_parity_error)
kaf24@2085 520 addl $4,%esp
kaf24@2085 521 jmp ret_from_intr
kaf24@2085 522
kaf24@1710 523 nmi_io_err:
kaf24@2085 524 # Clear and disable the I/O-error line
kaf24@2085 525 andb $0xf,%al
kaf24@2085 526 orb $0x8,%al
kaf24@2085 527 outb %al,$0x61
kaf24@2085 528 cmpb $'i',%ss:SYMBOL_NAME(opt_nmi) # nmi=ignore
kaf24@2954 529 je restore_all_xen
kaf24@2085 530 bts $1,%ss:SYMBOL_NAME(nmi_softirq_reason)
kaf24@2085 531 bts $NMI_SOFTIRQ,%ss:SYMBOL_NAME(irq_stat)
kaf24@2085 532 cmpb $'d',%ss:SYMBOL_NAME(opt_nmi) # nmi=dom0
kaf24@2954 533 je restore_all_xen
kaf24@2085 534 movl $(__HYPERVISOR_DS),%edx # nmi=fatal
kaf24@1710 535 movl %edx,%ds
kaf24@1710 536 movl %edx,%es
kaf24@2079 537 movl %esp,%edx
kaf24@2079 538 push %edx
kaf24@2079 539 call SYMBOL_NAME(io_check_error)
kaf24@2085 540 addl $4,%esp
kaf24@2085 541 jmp ret_from_intr
kaf24@2079 542
kaf24@1710 543 .data
kaf24@3127 544
kaf24@3127 545 ENTRY(exception_table)
kaf24@3127 546 .long SYMBOL_NAME(do_divide_error)
kaf24@3127 547 .long SYMBOL_NAME(do_debug)
kaf24@3127 548 .long 0 # nmi
kaf24@3127 549 .long SYMBOL_NAME(do_int3)
kaf24@3127 550 .long SYMBOL_NAME(do_overflow)
kaf24@3127 551 .long SYMBOL_NAME(do_bounds)
kaf24@3127 552 .long SYMBOL_NAME(do_invalid_op)
kaf24@3127 553 .long SYMBOL_NAME(math_state_restore)
kaf24@3127 554 .long 0 # double fault
kaf24@3127 555 .long SYMBOL_NAME(do_coprocessor_segment_overrun)
kaf24@3127 556 .long SYMBOL_NAME(do_invalid_TSS)
kaf24@3127 557 .long SYMBOL_NAME(do_segment_not_present)
kaf24@3127 558 .long SYMBOL_NAME(do_stack_segment)
kaf24@3127 559 .long SYMBOL_NAME(do_general_protection)
kaf24@3127 560 .long SYMBOL_NAME(do_page_fault)
kaf24@3127 561 .long SYMBOL_NAME(do_spurious_interrupt_bug)
kaf24@3127 562 .long SYMBOL_NAME(do_coprocessor_error)
kaf24@3127 563 .long SYMBOL_NAME(do_alignment_check)
kaf24@3127 564 .long SYMBOL_NAME(do_machine_check)
kaf24@3127 565 .long SYMBOL_NAME(do_simd_coprocessor_error)
kaf24@3127 566
kaf24@1710 567 ENTRY(hypercall_table)
kaf24@1710 568 .long SYMBOL_NAME(do_set_trap_table) /* 0 */
kaf24@1710 569 .long SYMBOL_NAME(do_mmu_update)
kaf24@1710 570 .long SYMBOL_NAME(do_set_gdt)
kaf24@1710 571 .long SYMBOL_NAME(do_stack_switch)
kaf24@1710 572 .long SYMBOL_NAME(do_set_callbacks)
kaf24@1710 573 .long SYMBOL_NAME(do_fpu_taskswitch) /* 5 */
kaf24@1710 574 .long SYMBOL_NAME(do_sched_op)
kaf24@1710 575 .long SYMBOL_NAME(do_dom0_op)
kaf24@1710 576 .long SYMBOL_NAME(do_set_debugreg)
kaf24@1710 577 .long SYMBOL_NAME(do_get_debugreg)
kaf24@1710 578 .long SYMBOL_NAME(do_update_descriptor) /* 10 */
kaf24@1710 579 .long SYMBOL_NAME(do_set_fast_trap)
kaf24@1710 580 .long SYMBOL_NAME(do_dom_mem_op)
kaf24@1710 581 .long SYMBOL_NAME(do_multicall)
kaf24@1710 582 .long SYMBOL_NAME(do_update_va_mapping)
kaf24@1710 583 .long SYMBOL_NAME(do_set_timer_op) /* 15 */
kaf24@1710 584 .long SYMBOL_NAME(do_event_channel_op)
kaf24@1710 585 .long SYMBOL_NAME(do_xen_version)
kaf24@1710 586 .long SYMBOL_NAME(do_console_io)
kaf24@1710 587 .long SYMBOL_NAME(do_physdev_op)
kaf24@2375 588 .long SYMBOL_NAME(do_grant_table_op) /* 20 */
kaf24@2111 589 .long SYMBOL_NAME(do_vm_assist)
kaf24@2375 590 .long SYMBOL_NAME(do_update_va_mapping_otherdomain)
kaf24@1710 591 .rept NR_hypercalls-((.-hypercall_table)/4)
kaf24@1710 592 .long SYMBOL_NAME(do_ni_hypercall)
kaf24@1710 593 .endr