VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMRC/TRPMRCHandlersA.asm@ 41943

Last change on this file since 41943 was 41943, checked in by vboxsync, 12 years ago

VMM: Avoid stale selector issues in RC so there will be no need to try fix them by recursive trapping (this was broken for GS since forever anyways).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 46.3 KB
Line 
1; $Id: TRPMRCHandlersA.asm 41943 2012-06-28 02:33:43Z vboxsync $
2;; @file
3; TRPM - Raw-mode Context Trap Handlers
4;
5
6;
7; Copyright (C) 2006-2012 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17
18;*******************************************************************************
19;* Header Files *
20;*******************************************************************************
21%include "VMMRC.mac"
22%include "iprt/x86.mac"
23%include "VBox/vmm/cpum.mac"
24%include "VBox/vmm/stam.mac"
25%include "VBox/vmm/vm.mac"
26%include "TRPMInternal.mac"
27%include "VBox/err.mac"
28%include "VBox/vmm/trpm.mac"
29
30
31;*******************************************************************************
32;* External Symbols *
33;*******************************************************************************
34extern IMPNAME(g_TRPM) ; These IMPNAME(g_*) symbols resolve to the import table
35extern IMPNAME(g_TRPMCPU) ; where there is a pointer to the real symbol. PE imports
36extern IMPNAME(g_VM) ; are a bit confusing at first... :-)
37extern IMPNAME(g_trpmGuestCtxCore)
38extern IMPNAME(g_trpmHyperCtxCore)
39extern NAME(trpmRCTrapInGeneric)
40extern NAME(TRPMGCTrap01Handler)
41extern NAME(TRPMGCHyperTrap01Handler)
42%ifdef VBOX_WITH_NMI
43extern NAME(TRPMGCTrap02Handler)
44extern NAME(TRPMGCHyperTrap02Handler)
45%endif
46extern NAME(TRPMGCTrap03Handler)
47extern NAME(TRPMGCHyperTrap03Handler)
48extern NAME(TRPMGCTrap06Handler)
49extern NAME(TRPMGCTrap07Handler)
50extern NAME(TRPMGCTrap0bHandler)
51extern NAME(TRPMGCHyperTrap0bHandler)
52extern NAME(TRPMGCTrap0dHandler)
53extern NAME(TRPMGCHyperTrap0dHandler)
54extern NAME(TRPMGCTrap0eHandler)
55extern NAME(TRPMGCHyperTrap0eHandler)
56
57
58;*******************************************************************************
59;* Defined Constants And Macros *
60;*******************************************************************************
61;; Some conditional COM port debugging.
62;%define DEBUG_STUFF 1
63;%define DEBUG_STUFF_TRPG 1
64;%define DEBUG_STUFF_INT 1
65
66
67BEGINCODE
68
69;;
70; Jump table for trap handlers for hypervisor traps.
71;
72g_apfnStaticTrapHandlersHyper:
73 ; N - M M - T - C - D i
74 ; o - n o - y - o - e p
75 ; - e n - p - d - s t
76 ; - i - e - e - c .
77 ; - c - - - r
78 ; =============================================================
79 dd 0 ; 0 - #DE - F - N - Divide error
80 dd NAME(TRPMGCHyperTrap01Handler) ; 1 - #DB - F/T - N - Single step, INT 1 instruction
81%ifdef VBOX_WITH_NMI
82 dd NAME(TRPMGCHyperTrap02Handler) ; 2 - - I - N - Non-Maskable Interrupt (NMI)
83%else
84 dd 0 ; 2 - - I - N - Non-Maskable Interrupt (NMI)
85%endif
86 dd NAME(TRPMGCHyperTrap03Handler) ; 3 - #BP - T - N - Breakpoint, INT 3 instruction.
87 dd 0 ; 4 - #OF - T - N - Overflow, INTO instruction.
88 dd 0 ; 5 - #BR - F - N - BOUND Range Exceeded, BOUND instruction.
89 dd 0 ; 6 - #UD - F - N - Undefined(/Invalid) Opcode.
90 dd 0 ; 7 - #NM - F - N - Device not available, FP or (F)WAIT instruction.
91 dd 0 ; 8 - #DF - A - 0 - Double fault.
92 dd 0 ; 9 - - F - N - Coprocessor Segment Overrun (obsolete).
93 dd 0 ; a - #TS - F - Y - Invalid TSS, Taskswitch or TSS access.
94 dd NAME(TRPMGCHyperTrap0bHandler) ; b - #NP - F - Y - Segment not present.
95 dd 0 ; c - #SS - F - Y - Stack-Segment fault.
96 dd NAME(TRPMGCHyperTrap0dHandler) ; d - #GP - F - Y - General protection fault.
97 dd NAME(TRPMGCHyperTrap0eHandler) ; e - #PF - F - Y - Page fault.
98 dd 0 ; f - - - - Intel Reserved. Do not use.
99 dd 0 ; 10 - #MF - F - N - x86 FPU Floating-Point Error (Math fault), FP or (F)WAIT instruction.
100 dd 0 ; 11 - #AC - F - 0 - Alignment Check.
101 dd 0 ; 12 - #MC - A - N - Machine Check.
102 dd 0 ; 13 - #XF - F - N - SIMD Floating-Point Exception.
103 dd 0 ; 14 - - - - Intel Reserved. Do not use.
104 dd 0 ; 15 - - - - Intel Reserved. Do not use.
105 dd 0 ; 16 - - - - Intel Reserved. Do not use.
106 dd 0 ; 17 - - - - Intel Reserved. Do not use.
107 dd 0 ; 18 - - - - Intel Reserved. Do not use.
108
109
110;;
111; Jump table for trap handlers for guest traps
112;
113g_apfnStaticTrapHandlersGuest:
114 ; N - M M - T - C - D i
115 ; o - n o - y - o - e p
116 ; - e n - p - d - s t
117 ; - i - e - e - c .
118 ; - c - - - r
119 ; =============================================================
120 dd 0 ; 0 - #DE - F - N - Divide error
121 dd NAME(TRPMGCTrap01Handler) ; 1 - #DB - F/T - N - Single step, INT 1 instruction
122%ifdef VBOX_WITH_NMI
123 dd NAME(TRPMGCTrap02Handler) ; 2 - - I - N - Non-Maskable Interrupt (NMI)
124%else
125 dd 0 ; 2 - - I - N - Non-Maskable Interrupt (NMI)
126%endif
127 dd NAME(TRPMGCTrap03Handler) ; 3 - #BP - T - N - Breakpoint, INT 3 instruction.
128 dd 0 ; 4 - #OF - T - N - Overflow, INTO instruction.
129 dd 0 ; 5 - #BR - F - N - BOUND Range Exceeded, BOUND instruction.
130 dd NAME(TRPMGCTrap06Handler) ; 6 - #UD - F - N - Undefined(/Invalid) Opcode.
131 dd NAME(TRPMGCTrap07Handler) ; 7 - #NM - F - N - Device not available, FP or (F)WAIT instruction.
132 dd 0 ; 8 - #DF - A - 0 - Double fault.
133 dd 0 ; 9 - - F - N - Coprocessor Segment Overrun (obsolete).
134 dd 0 ; a - #TS - F - Y - Invalid TSS, Taskswitch or TSS access.
135 dd NAME(TRPMGCTrap0bHandler) ; b - #NP - F - Y - Segment not present.
136 dd 0 ; c - #SS - F - Y - Stack-Segment fault.
137 dd NAME(TRPMGCTrap0dHandler) ; d - #GP - F - Y - General protection fault.
138 dd NAME(TRPMGCTrap0eHandler) ; e - #PF - F - Y - Page fault.
139 dd 0 ; f - - - - Intel Reserved. Do not use.
140 dd 0 ; 10 - #MF - F - N - x86 FPU Floating-Point Error (Math fault), FP or (F)WAIT instruction.
141 dd 0 ; 11 - #AC - F - 0 - Alignment Check.
142 dd 0 ; 12 - #MC - A - N - Machine Check.
143 dd 0 ; 13 - #XF - F - N - SIMD Floating-Point Exception.
144 dd 0 ; 14 - - - - Intel Reserved. Do not use.
145 dd 0 ; 15 - - - - Intel Reserved. Do not use.
146 dd 0 ; 16 - - - - Intel Reserved. Do not use.
147 dd 0 ; 17 - - - - Intel Reserved. Do not use.
148 dd 0 ; 18 - - - - Intel Reserved. Do not use.
149
150
151
152;;
153; We start by 24 push <vector no.> + jmp <generic entry point>
154;
155ALIGNCODE(16)
156BEGINPROC_EXPORTED TRPMGCHandlerGeneric
157%macro TRPMGenericEntry 1
158 db 06ah, i ; push imm8 - note that this is a signextended value.
159 jmp %1
160 ALIGNCODE(8)
161%assign i i+1
162%endmacro
163
164%assign i 0 ; start counter.
165 TRPMGenericEntry GenericTrap ; 0
166 TRPMGenericEntry GenericTrap ; 1
167 TRPMGenericEntry GenericTrap ; 2
168 TRPMGenericEntry GenericTrap ; 3
169 TRPMGenericEntry GenericTrap ; 4
170 TRPMGenericEntry GenericTrap ; 5
171 TRPMGenericEntry GenericTrap ; 6
172 TRPMGenericEntry GenericTrap ; 7
173 TRPMGenericEntry GenericTrapErrCode ; 8
174 TRPMGenericEntry GenericTrap ; 9
175 TRPMGenericEntry GenericTrapErrCode ; a
176 TRPMGenericEntry GenericTrapErrCode ; b
177 TRPMGenericEntry GenericTrapErrCode ; c
178 TRPMGenericEntry GenericTrapErrCode ; d
179 TRPMGenericEntry GenericTrapErrCode ; e
180 TRPMGenericEntry GenericTrap ; f (reserved)
181 TRPMGenericEntry GenericTrap ; 10
182 TRPMGenericEntry GenericTrapErrCode ; 11
183 TRPMGenericEntry GenericTrap ; 12
184 TRPMGenericEntry GenericTrap ; 13
185 TRPMGenericEntry GenericTrap ; 14 (reserved)
186 TRPMGenericEntry GenericTrap ; 15 (reserved)
187 TRPMGenericEntry GenericTrap ; 16 (reserved)
188 TRPMGenericEntry GenericTrap ; 17 (reserved)
189%undef i
190%undef TRPMGenericEntry
191
192;;
193; Main exception handler for the guest context
194;
195; Stack:
196; 14 SS
197; 10 ESP
198; c EFLAGS
199; 8 CS
200; 4 EIP
201; 0 vector number
202;
203; @uses none
204;
205ALIGNCODE(8)
206GenericTrap:
207 ;
208 ; for the present we fake an error code ~0
209 ;
210 push eax
211 mov eax, 0ffffffffh
212 xchg [esp + 4], eax ; get vector number, set error code
213 xchg [esp], eax ; get saved eax, set vector number
214 jmp short GenericTrapErrCode
215
216
217;;
218; Main exception handler for the guest context with error code
219;
220; Stack:
221; 28 GS (V86 only)
222; 24 FS (V86 only)
223; 20 DS (V86 only)
224; 1C ES (V86 only)
225; 18 SS (only if ring transition.)
226; 14 ESP (only if ring transition.)
227; 10 EFLAGS
228; c CS
229; 8 EIP
230; 4 Error code. (~0 for vectors which don't take an error code.)
231; 0 vector number
232;
233; Error code:
234;
235; 31 16 15 3 2 1 0
236;
237; reserved segment TI IDT EXT
238; selector GDT/LDT (1) IDT External interrupt
239; index (IDT=0) index
240;
241; NOTE: Page faults (trap 14) have a different error code
242;
243; @uses none
244;
245ALIGNCODE(8)
246GenericTrapErrCode:
247 cld
248
249 ;
250 ; Save ds, es, fs, gs, eax and ebx so we have a context pointer (ebx) and
251 ; scratch (eax) register to work with. A sideeffect of using ebx is that
252 ; it's preserved accross cdecl calls.
253 ;
254 ; In order to safely access data, we need to load our flat DS & ES selector,
255 ; clear FS and GS (stale guest selector prevention), and clear make sure
256 ; that CR0.WP is cleared.
257 ;
258 push ds ; +14h
259 push es ; +10h
260 push fs ; +0ch
261 push gs ; +08h
262 push eax ; +04h
263 push ebx ; +00h
264%push StackFrame
265%define %$STK_SAVED_EBX esp
266%define %$STK_SAVED_EAX esp + 04h
267%define %$STK_SAVED_GS esp + 08h
268%define %$STK_SAVED_FS esp + 0ch
269%define %$STK_SAVED_ES esp + 10h
270%define %$STK_SAVED_DS esp + 14h
271%define %$ESPOFF 18h
272%define %$STK_VECTOR esp + 00h + %$ESPOFF
273%define %$STK_ERRCD esp + 04h + %$ESPOFF
274%define %$STK_EIP esp + 08h + %$ESPOFF
275%define %$STK_CS esp + 0ch + %$ESPOFF
276%define %$STK_EFLAGS esp + 10h + %$ESPOFF
277%define %$STK_ESP esp + 14h + %$ESPOFF
278%define %$STK_SS esp + 18h + %$ESPOFF
279%define %$STK_V86_ES esp + 1ch + %$ESPOFF
280%define %$STK_V86_DS esp + 20h + %$ESPOFF
281%define %$STK_V86_FS esp + 24h + %$ESPOFF
282%define %$STK_V86_GS esp + 28h + %$ESPOFF
283
284 mov bx, ss ; load
285 mov ds, bx
286 mov es, bx
287
288 xor bx, bx ; load 0 into gs and fs.
289 mov gs, bx
290 mov fs, bx
291
292 mov eax, cr0 ;; @todo elimitate this read?
293 and eax, ~X86_CR0_WRITE_PROTECT
294 mov cr0, eax
295
296 mov ebx, IMP(g_trpmGuestCtxCore) ; Assume GC as the most common.
297 test byte [%$STK_CS], 3h ; check RPL of the cs selector
298 ;; @todo check this for conforming segments.
299 jnz .save_state
300 test dword [%$STK_EFLAGS], X86_EFL_VM; If in V86, then guest.
301 jnz .save_state
302 mov ebx, IMP(g_trpmHyperCtxCore) ; It's raw-mode context, actually.
303
304 ;
305 ; Save the state.
306 ;
307 ; ASSUMPTION: If trap in hypervisor, we assume that we can read two dword
308 ; under the bottom of the stack. This is atm safe.
309 ;
310.save_state:
311 mov eax, [%$STK_SAVED_EAX]
312 mov [ebx + CPUMCTXCORE.eax], eax
313 mov [ebx + CPUMCTXCORE.ecx], ecx
314 mov [ebx + CPUMCTXCORE.edx], edx
315 mov eax, [%$STK_SAVED_EBX]
316 mov [ebx + CPUMCTXCORE.ebx], eax
317 mov [ebx + CPUMCTXCORE.esi], esi
318 mov [ebx + CPUMCTXCORE.edi], edi
319 mov [ebx + CPUMCTXCORE.ebp], ebp
320
321 mov eax, [%$STK_ESP]
322 mov [ebx + CPUMCTXCORE.esp], eax
323 mov cx, [%$STK_SS]
324 mov [ebx + CPUMCTXCORE.ss.Sel], cx
325
326 mov cx, [%$STK_CS]
327 mov [ebx + CPUMCTXCORE.cs.Sel], cx
328 mov eax, [%$STK_EIP]
329 mov [ebx + CPUMCTXCORE.eip], eax
330 mov eax, [%$STK_EFLAGS]
331 mov [ebx + CPUMCTXCORE.eflags], eax
332
333%if GC_ARCH_BITS == 64 ; zero out the high dwords - probably not necessary any more.
334 mov dword [ebx + CPUMCTXCORE.eax + 4], 0
335 mov dword [ebx + CPUMCTXCORE.ecx + 4], 0
336 mov dword [ebx + CPUMCTXCORE.edx + 4], 0
337 mov dword [ebx + CPUMCTXCORE.ebx + 4], 0
338 mov dword [ebx + CPUMCTXCORE.esi + 4], 0
339 mov dword [ebx + CPUMCTXCORE.edi + 4], 0
340 mov dword [ebx + CPUMCTXCORE.ebp + 4], 0
341 mov dword [ebx + CPUMCTXCORE.esp + 4], 0
342 mov dword [ebx + CPUMCTXCORE.eip + 4], 0
343%endif
344
345 test dword [%$STK_EFLAGS], X86_EFL_VM
346 jnz .save_V86_segregs
347
348 mov cx, [%$STK_SAVED_ES]
349 mov [ebx + CPUMCTXCORE.es.Sel], cx
350 mov cx, [%$STK_SAVED_DS]
351 mov [ebx + CPUMCTXCORE.ds.Sel], cx
352 mov cx, [%$STK_SAVED_FS]
353 mov [ebx + CPUMCTXCORE.fs.Sel], cx
354 mov cx, [%$STK_SAVED_GS]
355 mov [ebx + CPUMCTXCORE.gs.Sel], cx
356 jmp .done_saving
357
358 ;
359 ; The DS, ES, FS and GS registers are zeroed in V86 mode and their real
360 ; values are on the stack.
361 ;
362.save_V86_segregs:
363 mov cx, [%$STK_V86_ES]
364 mov [ebx + CPUMCTXCORE.es.Sel], cx
365 mov cx, [%$STK_V86_DS]
366 mov [ebx + CPUMCTXCORE.ds.Sel], cx
367 mov cx, [%$STK_V86_FS]
368 mov [ebx + CPUMCTXCORE.fs.Sel], cx
369 mov cx, [%$STK_V86_GS]
370 mov [ebx + CPUMCTXCORE.gs.Sel], cx
371
372.done_saving:
373
374%ifdef VBOX_WITH_STATISTICS
375 ;
376 ; Start profiling.
377 ;
378 mov edx, [%$STK_VECTOR]
379 imul edx, edx, byte STAMPROFILEADV_size ; assumes < 128.
380 add edx, TRPM.aStatGCTraps
381 add edx, IMP(g_TRPM)
382 STAM_PROFILE_ADV_START edx
383%endif
384
385 ;
386 ; Store the information about the active trap/interrupt.
387 ;
388 mov esi, IMP(g_TRPMCPU) ; esi = TRPMCPU until resume!
389 movzx edx, byte [%$STK_VECTOR]
390 mov [esi + TRPMCPU.uActiveVector], edx
391 mov edx, [%$STK_ERRCD]
392 mov [esi + TRPMCPU.uActiveErrorCode], edx
393 mov dword [esi + TRPMCPU.enmActiveType], TRPM_TRAP
394 mov edx, cr2 ;; @todo Check how expensive cr2 reads are!
395 mov dword [esi + TRPMCPU.uActiveCR2], edx
396%if GC_ARCH_BITS == 64 ; zero out the high dwords.
397 mov dword [esi + TRPMCPU.uActiveErrorCode + 4], 0
398 mov dword [esi + TRPMCPU.uActiveCR2 + 4], 0
399%endif
400
401 ;
402 ; Check if we're in the raw-mode context (RC / hypervisor) when this happened.
403 ;
404 test dword [%$STK_EFLAGS], X86_EFL_VM
405 jnz short .gc_not_raw_mode_context
406
407 test byte [%$STK_CS], 3h ; check RPL of the cs selector
408 jz .rc_in_raw_mode_context
409
410 ;
411 ; Trap in guest code.
412 ;
413.gc_not_raw_mode_context:
414%ifdef DEBUG_STUFF_TRPG
415 mov eax, [%$STK_ERRCD]
416 mov ecx, 'trpG' ; indicate trap.
417 mov edx, [%$STK_VECTOR]
418 call trpmDbgDumpRegisterFrame
419%endif
420
421 ;
422 ; Do we have a GC handler for these traps?
423 ;
424 mov edx, [%$STK_VECTOR]
425 mov eax, [g_apfnStaticTrapHandlersGuest + edx * 4]
426 or eax, eax
427 jnz short .gc_have_static_handler
428 mov eax, VINF_EM_RAW_GUEST_TRAP
429 jmp short .gc_guest_trap
430
431 ;
432 ; Call static handler.
433 ;
434.gc_have_static_handler:
435 push ebx ; Param 2 - CPUMCTXCORE pointer.
436 push esi ; Param 1 - Pointer to TRPMCPU.
437 call eax
438 add esp, byte 8 ; cleanup stack (cdecl)
439 or eax, eax
440 je near .gc_continue_guest
441
442 ;
443 ; Switch back to the host and process it there.
444 ;
445.gc_guest_trap:
446%ifdef VBOX_WITH_STATISTICS
447 mov edx, [%$STK_VECTOR]
448 imul edx, edx, byte STAMPROFILEADV_size ; assume < 128
449 add edx, IMP(g_TRPM)
450 add edx, TRPM.aStatGCTraps
451 STAM_PROFILE_ADV_STOP edx
452%endif
453 mov edx, IMP(g_VM)
454 call [edx + VM.pfnVMMGCGuestToHostAsm]
455
456 ; We shouldn't ever return this way. So, raise a special IPE if we do.
457.gc_panic_again:
458 mov eax, VERR_TRPM_IPE_3
459 mov edx, IMP(g_VM)
460 call [edx + VM.pfnVMMGCGuestToHostAsm]
461 jmp .gc_panic_again
462
463 ;
464 ; Continue(/Resume/Restart/Whatever) guest execution.
465 ;
466ALIGNCODE(16)
467.gc_continue_guest:
468%ifdef VBOX_WITH_STATISTICS
469 mov edx, [%$STK_VECTOR]
470 imul edx, edx, byte STAMPROFILEADV_size ; assumes < 128
471 add edx, TRPM.aStatGCTraps
472 add edx, IMP(g_TRPM)
473 STAM_PROFILE_ADV_STOP edx
474%endif
475
476 ; enable WP
477 mov eax, cr0 ;; @todo try elimiate this read.
478 or eax, X86_CR0_WRITE_PROTECT
479 mov cr0, eax
480
481 ; restore guest state and start executing again.
482 mov eax, [ebx + CPUMCTXCORE.eax]
483 mov [%$STK_SAVED_EAX], eax
484 mov ecx, [ebx + CPUMCTXCORE.ecx]
485 mov edx, [ebx + CPUMCTXCORE.edx]
486 mov eax, [ebx + CPUMCTXCORE.ebx]
487 mov [%$STK_SAVED_EBX], eax
488 mov ebp, [ebx + CPUMCTXCORE.ebp]
489 mov esi, [ebx + CPUMCTXCORE.esi]
490 mov edi, [ebx + CPUMCTXCORE.edi]
491
492 mov eax, [ebx + CPUMCTXCORE.esp]
493 mov [%$STK_ESP], eax
494 mov eax, dword [ebx + CPUMCTXCORE.ss.Sel]
495 mov [%$STK_SS], eax
496 mov eax, [ebx + CPUMCTXCORE.eflags]
497 mov [%$STK_EFLAGS], eax
498 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
499 mov [%$STK_CS], eax
500 mov eax, [ebx + CPUMCTXCORE.eip]
501 mov [%$STK_EIP], eax
502
503 test dword [ebx + CPUMCTXCORE.eflags], X86_EFL_VM
504 jnz .gc_V86_return
505
506 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
507 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_GS
508 mov gs, ax
509
510 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
511 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_FS
512 mov fs, ax
513
514 mov ax, [ebx + CPUMCTXCORE.es.Sel]
515 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_ES
516 mov es, ax
517
518 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
519 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_DS
520 mov ds, ax
521
522 ; finally restore our scratch register eax and ebx.
523 pop ebx
524 pop eax
525 add esp, 16 + 8 ; skip segregs, error code, and vector number.
526
527 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_IRET
528 iret
529
530ALIGNCODE(16)
531.gc_V86_return:
532 mov eax, dword [ebx + CPUMCTXCORE.es.Sel]
533 mov [%$STK_V86_ES], eax
534 mov eax, dword [ebx + CPUMCTXCORE.ds.Sel]
535 mov [%$STK_V86_DS], eax
536 mov eax, dword [ebx + CPUMCTXCORE.fs.Sel]
537 mov [%$STK_V86_FS], eax
538 mov eax, dword [ebx + CPUMCTXCORE.gs.Sel]
539 mov [%$STK_V86_GS], eax
540
541 ; finally restore our scratch register eax and ebx.
542 pop ebx
543 pop eax
544 add esp, 16 + 8 ; skip segregs, error code, and vector number.
545
546 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_IRET | TRPM_TRAP_IN_V86
547 iret
548
549 ;
550 ; Trap in Hypervisor, try to handle it.
551 ;
552 ; (eax = pTRPMCPU)
553 ;
554ALIGNCODE(16)
555.rc_in_raw_mode_context:
556 ; fix ss:esp.
557 lea ecx, [%$STK_ESP] ; calc esp at trap
558 mov [ebx + CPUMCTXCORE.esp], ecx; update esp in register frame
559 mov [ebx + CPUMCTXCORE.ss.Sel], ss ; update ss in register frame
560
561 ; check for temporary handler.
562 movzx edx, byte [esi + TRPMCPU.uActiveVector]
563 mov edi, IMP(g_TRPM)
564 xor ecx, ecx
565 xchg ecx, [edi + TRPM.aTmpTrapHandlers + edx * 4] ; ecx = Temp handler pointer or 0
566 or ecx, ecx
567 jnz short .rc_have_temporary_handler
568
569 ; check for static trap handler.
570 mov ecx, [g_apfnStaticTrapHandlersHyper + edx * 4] ; ecx = Static handler pointer or 0
571 or ecx, ecx
572 jnz short .rc_have_static_handler
573 jmp .rc_abandon_ship
574
575
576 ;
577 ; Temporary trap handler present, call it (CDECL).
578 ;
579.rc_have_temporary_handler:
580 push ebx ; Param 2 - Pointer to CPUMCTXCORE.
581 push IMP(g_VM) ; Param 1 - Pointer to VM.
582 call ecx
583 add esp, byte 8 ; cleanup stack (cdecl)
584
585 cmp eax, byte VINF_SUCCESS ; If completely handled Then resume execution.
586 je near .rc_continue
587 jmp .rc_abandon_ship
588
589
590 ;
591 ; Static trap handler present, call it (CDECL).
592 ;
593.rc_have_static_handler:
594 push ebx ; Param 2 - Pointer to CPUMCTXCORE.
595 push esi ; Param 1 - Pointer to TRPMCPU
596 call ecx
597 add esp, byte 8 ; cleanup stack (cdecl)
598
599 cmp eax, byte VINF_SUCCESS ; If completely handled Then resume execution.
600 je short .rc_continue
601 cmp eax, VINF_EM_DBG_HYPER_STEPPED
602 je short .rc_to_host
603 cmp eax, VINF_EM_DBG_HYPER_BREAKPOINT
604 je short .rc_to_host
605 cmp eax, VINF_EM_DBG_HYPER_ASSERTION
606 je short .rc_to_host
607 jmp .rc_abandon_ship
608
609 ;
610 ; Pop back to the host to service the error.
611 ;
612.rc_to_host:
613 mov ecx, ebx
614 mov edx, IMP(g_VM)
615 call [edx + VM.pfnVMMGCGuestToHostAsm]
616 jmp short .rc_continue
617
618 ;
619 ; Continue(/Resume/Restart/Whatever) hypervisor execution.
620 ; Don't reset the TRPM state. Caller takes care of that.
621 ;
622ALIGNCODE(16)
623.rc_continue:
624%ifdef DEBUG_STUFF
625 mov eax, [%$STK_ERRCD]
626 mov ecx, 'resH' ; indicate trap.
627 mov edx, [%$STK_VECTOR]
628 call trpmDbgDumpRegisterFrame
629%endif
630
631%ifdef VBOX_WITH_STATISTICS
632 mov edx, [%$STK_VECTOR]
633 imul edx, edx, byte STAMPROFILEADV_size ; assumes < 128
634 add edx, TRPM.aStatGCTraps
635 add edx, IMP(g_TRPM)
636 STAM_PROFILE_ADV_STOP edx
637%endif
638
639 ; restore
640 mov eax, [ebx + CPUMCTXCORE.eax]
641 mov [%$STK_SAVED_EAX], eax
642 mov ecx, [ebx + CPUMCTXCORE.ecx]
643 mov edx, [ebx + CPUMCTXCORE.edx]
644 mov eax, [ebx + CPUMCTXCORE.ebx]
645 mov [%$STK_SAVED_EBX], eax
646 mov ebp, [ebx + CPUMCTXCORE.ebp]
647 mov esi, [ebx + CPUMCTXCORE.esi]
648 mov edi, [ebx + CPUMCTXCORE.edi]
649
650 ; skipping esp & ss.
651
652 mov eax, [ebx + CPUMCTXCORE.eflags]
653 mov [%$STK_EFLAGS], eax
654 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
655 mov [%$STK_CS], eax
656 mov eax, [ebx + CPUMCTXCORE.eip]
657 mov [%$STK_EIP], eax
658
659 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
660 mov gs, ax
661
662 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
663 mov fs, ax
664
665 mov ax, [ebx + CPUMCTXCORE.es.Sel]
666 mov es, ax
667
668 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
669 mov ds, ax
670
671 ; finally restore our scratch register eax and ebx.
672 pop ebx
673 pop eax
674 add esp, 16 + 8 ; skip segregs, error code, and vector number.
675
676 iret
677
678
679 ;
680 ; Internal processing error - don't panic, start meditating!
681 ;
682.rc_abandon_ship:
683%ifdef DEBUG_STUFF
684 mov eax, [%$STK_ERRCD]
685 mov ecx, 'trpH' ; indicate trap.
686 mov edx, [%$STK_VECTOR]
687 call trpmDbgDumpRegisterFrame
688%endif
689
690.rc_do_not_panic:
691 mov edx, IMP(g_VM)
692 mov eax, VERR_TRPM_DONT_PANIC
693 call [edx + VM.pfnVMMGCGuestToHostAsm]
694%ifdef DEBUG_STUFF
695 COM_S_PRINT 'bad!!!'
696%endif
697 jmp .rc_do_not_panic ; this shall never ever happen!
698%pop
699ENDPROC TRPMGCHandlerGeneric
700
701
702
703
704
705;;
706; We start by 256 push <vector no.> + jmp interruptworker
707;
708ALIGNCODE(16)
709BEGINPROC_EXPORTED TRPMGCHandlerInterupt
710 ; NASM has some nice features, here an example of a loop.
711%assign i 0
712%rep 256
713 db 06ah, i ; push imm8 - note that this is a signextended value.
714 jmp ti_GenericInterrupt
715 ALIGNCODE(8)
716%assign i i+1
717%endrep
718
719;;
720; Main interrupt handler for the guest context
721;
722; Stack:
723; 24 GS (V86 only)
724; 20 FS (V86 only)
725; 1C DS (V86 only)
726; 18 ES (V86 only)
727; 14 SS
728; 10 ESP
729; c EFLAGS
730; 8 CS
731; 4 EIP
732; ESP -> 0 Vector number (only use low byte!).
733;
734; @uses none
735ti_GenericInterrupt:
736 cld
737
738 ;
739 ; Save ds, es, fs, gs, eax and ebx so we have a context pointer (ebx) and
740 ; scratch (eax) register to work with. A sideeffect of using ebx is that
741 ; it's preserved accross cdecl calls.
742 ;
743 ; In order to safely access data, we need to load our flat DS & ES selector,
744 ; clear FS and GS (stale guest selector prevention), and clear make sure
745 ; that CR0.WP is cleared.
746 ;
747 push ds ; +14h
748 push es ; +10h
749 push fs ; +0ch
750 push gs ; +08h
751 push eax ; +04h
752 push ebx ; +00h
753%push StackFrame
754%define %$STK_SAVED_EBX esp
755%define %$STK_SAVED_EAX esp + 04h
756%define %$STK_SAVED_GS esp + 08h
757%define %$STK_SAVED_FS esp + 0ch
758%define %$STK_SAVED_ES esp + 10h
759%define %$STK_SAVED_DS esp + 14h
760%define %$ESPOFF 18h
761%define %$STK_VECTOR esp + 00h + %$ESPOFF
762%define %$STK_EIP esp + 04h + %$ESPOFF
763%define %$STK_CS esp + 08h + %$ESPOFF
764%define %$STK_EFLAGS esp + 0ch + %$ESPOFF
765%define %$STK_ESP esp + 10h + %$ESPOFF
766%define %$STK_SS esp + 14h + %$ESPOFF
767%define %$STK_V86_ES esp + 18h + %$ESPOFF
768%define %$STK_V86_DS esp + 1ch + %$ESPOFF
769%define %$STK_V86_FS esp + 20h + %$ESPOFF
770%define %$STK_V86_GS esp + 24h + %$ESPOFF
771
772 mov bx, ss ; load
773 mov ds, bx
774 mov es, bx
775
776 xor bx, bx ; load 0 into gs and fs.
777 mov gs, bx
778 mov fs, bx
779
780 mov eax, cr0 ;; @todo elimitate this read?
781 and eax, ~X86_CR0_WRITE_PROTECT
782 mov cr0, eax
783
784 mov ebx, IMP(g_trpmGuestCtxCore) ; Assume GC as the most common.
785 test byte [%$STK_CS], 3h ; check RPL of the cs selector
786 ;; @todo check this for conforming segments.
787 jnz .save_state
788 test dword [%$STK_EFLAGS], X86_EFL_VM ; If in V86, then guest.
789 jnz .save_state
790 mov ebx, IMP(g_trpmHyperCtxCore) ; It's raw-mode context, actually.
791
792 ;
793 ; Save the state.
794 ;
795 ; ASSUMPTION: If trap in hypervisor, we assume that we can read two dword
796 ; under the bottom of the stack. This is atm safe.
797 ;
798.save_state:
799 mov eax, [%$STK_SAVED_EAX]
800 mov [ebx + CPUMCTXCORE.eax], eax
801 mov [ebx + CPUMCTXCORE.ecx], ecx
802 mov [ebx + CPUMCTXCORE.edx], edx
803 mov eax, [%$STK_SAVED_EBX]
804 mov [ebx + CPUMCTXCORE.ebx], eax
805 mov [ebx + CPUMCTXCORE.esi], esi
806 mov [ebx + CPUMCTXCORE.edi], edi
807 mov [ebx + CPUMCTXCORE.ebp], ebp
808
809 mov eax, [%$STK_ESP]
810 mov [ebx + CPUMCTXCORE.esp], eax
811 mov cx, [%$STK_SS]
812 mov [ebx + CPUMCTXCORE.ss.Sel], cx
813
814 mov cx, [%$STK_CS]
815 mov [ebx + CPUMCTXCORE.cs.Sel], cx
816 mov eax, [%$STK_EIP]
817 mov [ebx + CPUMCTXCORE.eip], eax
818 mov eax, [%$STK_EFLAGS]
819 mov [ebx + CPUMCTXCORE.eflags], eax
820
821%if GC_ARCH_BITS == 64 ; zero out the high dwords - probably not necessary any more.
822 mov dword [ebx + CPUMCTXCORE.eax + 4], 0
823 mov dword [ebx + CPUMCTXCORE.ecx + 4], 0
824 mov dword [ebx + CPUMCTXCORE.edx + 4], 0
825 mov dword [ebx + CPUMCTXCORE.ebx + 4], 0
826 mov dword [ebx + CPUMCTXCORE.esi + 4], 0
827 mov dword [ebx + CPUMCTXCORE.edi + 4], 0
828 mov dword [ebx + CPUMCTXCORE.ebp + 4], 0
829 mov dword [ebx + CPUMCTXCORE.esp + 4], 0
830 mov dword [ebx + CPUMCTXCORE.eip + 4], 0
831%endif
832
833 test dword [%$STK_EFLAGS], X86_EFL_VM
834 jnz .save_V86_segregs
835
836 mov cx, [%$STK_SAVED_ES]
837 mov [ebx + CPUMCTXCORE.es.Sel], cx
838 mov cx, [%$STK_SAVED_DS]
839 mov [ebx + CPUMCTXCORE.ds.Sel], cx
840 mov cx, [%$STK_SAVED_FS]
841 mov [ebx + CPUMCTXCORE.fs.Sel], cx
842 mov cx, [%$STK_SAVED_GS]
843 mov [ebx + CPUMCTXCORE.gs.Sel], cx
844 jmp .done_saving
845
846 ;
847 ; The DS, ES, FS and GS registers are zeroed in V86 mode and their real
848 ; values are on the stack.
849 ;
850.save_V86_segregs:
851 mov cx, [%$STK_V86_ES]
852 mov [ebx + CPUMCTXCORE.es.Sel], cx
853 mov cx, [%$STK_V86_DS]
854 mov [ebx + CPUMCTXCORE.ds.Sel], cx
855 mov cx, [%$STK_V86_FS]
856 mov [ebx + CPUMCTXCORE.fs.Sel], cx
857 mov cx, [%$STK_V86_GS]
858 mov [ebx + CPUMCTXCORE.gs.Sel], cx
859
860.done_saving:
861
862 ;
863 ; Store the information about the active trap/interrupt.
864 ;
865 mov esi, IMP(g_TRPMCPU) ; esi = TRPMCPU until resume!
866 movzx edx, byte [%$STK_VECTOR]
867 mov [esi + TRPMCPU.uActiveVector], edx
868 mov dword [esi + TRPMCPU.uActiveErrorCode], 0
869 mov dword [esi + TRPMCPU.enmActiveType], TRPM_TRAP
870 mov dword [esi + TRPMCPU.uActiveCR2], edx
871%if GC_ARCH_BITS == 64 ; zero out the high dwords.
872 mov dword [esi + TRPMCPU.uActiveErrorCode + 4], 0
873 mov dword [esi + TRPMCPU.uActiveCR2 + 4], 0
874%endif
875
876%ifdef VBOX_WITH_STATISTICS
877 ;
878 ; Update statistics.
879 ;
880 mov edi, IMP(g_TRPM)
881 movzx edx, byte [%$STK_VECTOR] ; vector number
882 imul edx, edx, byte STAMCOUNTER_size
883 add edx, [edi + TRPM.paStatHostIrqRC]
884 STAM_COUNTER_INC edx
885%endif
886
887 ;
888 ; Check if we're in the raw-mode context (RC / hypervisor) when this happened.
889 ;
890 test dword [%$STK_EFLAGS], X86_EFL_VM
891 jnz short .gc_not_raw_mode_context
892
893 test byte [%$STK_CS], 3h ; check RPL of the cs selector
894 jz .rc_in_raw_mode_context
895
896 ;
897 ; Trap in guest code.
898 ;
899.gc_not_raw_mode_context:
900 and dword [ebx + CPUMCTXCORE.eflags], ~X86_EFL_RF ; Clear RF.
901 ; The guest shall not see this in it's state.
902%ifdef DEBUG_STUFF_INT
903 xor eax, eax
904 mov ecx, 'intG' ; indicate trap in GC.
905 movzx edx, byte [%$STK_VECTOR]
906 call trpmDbgDumpRegisterFrame
907%endif
908
909 ;
910 ; Switch back to the host and process it there.
911 ;
912 mov edx, IMP(g_VM)
913 mov eax, VINF_EM_RAW_INTERRUPT
914 call [edx + VM.pfnVMMGCGuestToHostAsm]
915
916 ;
917 ; We've returned!
918 ;
919
920 ; Reset TRPM state
921 xor edx, edx
922 dec edx ; edx = 0ffffffffh
923 xchg [esi + TRPMCPU.uActiveVector], edx
924 mov [esi + TRPMCPU.uPrevVector], edx
925
926 ; enable WP
927 mov eax, cr0 ;; @todo try elimiate this read.
928 or eax, X86_CR0_WRITE_PROTECT
929 mov cr0, eax
930
931 ; restore guest state and start executing again.
932 mov eax, [ebx + CPUMCTXCORE.eax]
933 mov [%$STK_SAVED_EAX], eax
934 mov ecx, [ebx + CPUMCTXCORE.ecx]
935 mov edx, [ebx + CPUMCTXCORE.edx]
936 mov eax, [ebx + CPUMCTXCORE.ebx]
937 mov [%$STK_SAVED_EBX], eax
938 mov ebp, [ebx + CPUMCTXCORE.ebp]
939 mov esi, [ebx + CPUMCTXCORE.esi]
940 mov edi, [ebx + CPUMCTXCORE.edi]
941
942 mov eax, [ebx + CPUMCTXCORE.esp]
943 mov [%$STK_ESP], eax
944 mov eax, dword [ebx + CPUMCTXCORE.ss.Sel]
945 mov [%$STK_SS], eax
946 mov eax, [ebx + CPUMCTXCORE.eflags]
947 mov [%$STK_EFLAGS], eax
948 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
949 mov [%$STK_CS], eax
950 mov eax, [ebx + CPUMCTXCORE.eip]
951 mov [%$STK_EIP], eax
952
953 test dword [ebx + CPUMCTXCORE.eflags], X86_EFL_VM
954 jnz .gc_V86_return
955
956 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
957 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_GS
958 mov gs, ax
959
960 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
961 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_FS
962 mov fs, ax
963
964 mov ax, [ebx + CPUMCTXCORE.es.Sel]
965 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_ES
966 mov es, ax
967
968 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
969 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_DS
970 mov ds, ax
971
972 ; finally restore our scratch register eax and ebx.
973 pop ebx
974 pop eax
975 add esp, 16 + 4 ; skip segregs, and vector number.
976
977 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_IRET
978 iret
979
980ALIGNCODE(16)
981.gc_V86_return:
982 mov eax, dword [ebx + CPUMCTXCORE.es.Sel]
983 mov [%$STK_V86_ES], eax
984 mov eax, dword [ebx + CPUMCTXCORE.ds.Sel]
985 mov [%$STK_V86_DS], eax
986 mov eax, dword [ebx + CPUMCTXCORE.fs.Sel]
987 mov [%$STK_V86_FS], eax
988 mov eax, dword [ebx + CPUMCTXCORE.gs.Sel]
989 mov [%$STK_V86_GS], eax
990
991 ; finally restore our scratch register eax and ebx.
992 pop ebx
993 pop eax
994 add esp, 16 + 4 ; skip segregs, and vector number.
995
996 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_IRET | TRPM_TRAP_IN_V86
997 iret
998
999 ; -+- Entry point -+-
1000 ;
1001 ; We're in hypervisor mode which means no guest context
1002 ; and special care to be taken to restore the hypervisor
1003 ; context correctly.
1004 ;
1005 ; ATM the only place this can happen is when entering a trap handler.
1006 ; We make ASSUMPTIONS about this in respects to the WP CR0 bit
1007 ;
1008ALIGNCODE(16)
1009.rc_in_raw_mode_context:
1010 ; fix ss:esp.
1011 lea ecx, [%$STK_ESP] ; calc esp at trap
1012 mov [ebx + CPUMCTXCORE.esp], ecx ; update esp in register frame
1013 mov [ebx + CPUMCTXCORE.ss.Sel], ss ; update ss in register frame
1014
1015%ifdef DEBUG_STUFF_INT
1016 xor eax, eax
1017 mov ecx, 'intH' ; indicate trap in RC.
1018 movzx edx, byte [%$STK_VECTOR]
1019 call trpmDbgDumpRegisterFrame
1020%endif
1021
1022 mov edx, IMP(g_VM)
1023 mov eax, VINF_EM_RAW_INTERRUPT_HYPER
1024 call [edx + VM.pfnVMMGCGuestToHostAsm]
1025%ifdef DEBUG_STUFF_INT
1026 COM_S_CHAR '!'
1027%endif
1028
1029 ;
1030 ; We've returned!
1031 ; Continue(/Resume/Restart/Whatever) hypervisor execution.
1032 ;
1033
1034 ; Reset TRPM state - don't record this.
1035 ;mov esi, IMP(g_TRPMCPU)
1036 mov dword [esi + TRPMCPU.uActiveVector], 0ffffffffh
1037
1038 ;
1039 ; Restore the hypervisor context and return.
1040 ;
1041 mov eax, [ebx + CPUMCTXCORE.eax]
1042 mov [%$STK_SAVED_EAX], eax
1043 mov ecx, [ebx + CPUMCTXCORE.ecx]
1044 mov edx, [ebx + CPUMCTXCORE.edx]
1045 mov eax, [ebx + CPUMCTXCORE.ebx]
1046 mov [%$STK_SAVED_EBX], eax
1047 mov ebp, [ebx + CPUMCTXCORE.ebp]
1048 mov esi, [ebx + CPUMCTXCORE.esi]
1049 mov edi, [ebx + CPUMCTXCORE.edi]
1050
1051 ; skipping esp & ss.
1052
1053 mov eax, [ebx + CPUMCTXCORE.eflags]
1054 mov [%$STK_EFLAGS], eax
1055 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
1056 mov [%$STK_CS], eax
1057 mov eax, [ebx + CPUMCTXCORE.eip]
1058 mov [%$STK_EIP], eax
1059
1060 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
1061 mov gs, ax
1062
1063 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
1064 mov fs, ax
1065
1066 mov ax, [ebx + CPUMCTXCORE.es.Sel]
1067 mov es, ax
1068
1069 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
1070 mov ds, ax
1071
1072 ; finally restore our scratch register eax and ebx.
1073 pop ebx
1074 pop eax
1075 add esp, 16 + 4 ; skip segregs, and vector number.
1076
1077 iret
1078%pop
1079ENDPROC TRPMGCHandlerInterupt
1080
1081
1082
1083;;
1084; Trap handler for #MC
1085;
1086; This handler will forward the #MC to the host OS. Since this
1087; is generalized in the generic interrupt handler, we just disable
1088; interrupts and push vector number and jump to the generic code.
1089;
1090; Stack:
1091; 10 SS (only if ring transition.)
1092; c ESP (only if ring transition.)
1093; 8 EFLAGS
1094; 4 CS
1095; 0 EIP
1096;
1097; @uses none
1098;
1099ALIGNCODE(16)
1100BEGINPROC_EXPORTED TRPMGCHandlerTrap12
1101 push byte 12h
1102 jmp ti_GenericInterrupt
1103ENDPROC TRPMGCHandlerTrap12
1104
1105
1106
1107
1108;;
1109; Trap handler for double fault (#DF).
1110;
1111; This is a special trap handler executes in separate task with own TSS, with
1112; one of the intermediate memory contexts instead of the shadow context.
1113; The handler will unconditionally print an report to the comport configured
1114; for the COM_S_* macros before attempting to return to the host. If it it ends
1115; up double faulting more than 10 times, it will simply cause an triple fault
1116; to get us out of the mess.
1117;
1118; @param esp Half way down the hypervisor stack + the trap frame.
1119; @param ebp Half way down the hypervisor stack.
1120; @param eflags Interrupts disabled, nested flag is probably set (we don't care).
1121; @param ecx The address of the hypervisor TSS.
1122; @param edi Same as ecx.
1123; @param eax Same as ecx.
1124; @param edx Address of the VM structure.
1125; @param esi Same as edx.
1126; @param ebx Same as edx.
1127; @param ss Hypervisor DS.
1128; @param ds Hypervisor DS.
1129; @param es Hypervisor DS.
1130; @param fs 0
1131; @param gs 0
1132;
1133;
1134; @remark To be able to catch errors with WP turned off, it is required that the
1135; TSS GDT descriptor and the TSSes are writable (X86_PTE_RW). See SELM.cpp
1136; for how to enable this.
1137;
1138; @remark It is *not* safe to resume the VMM after a double fault. (At least not
1139; without clearing the busy flag of the TssTrap8 and fixing whatever cause it.)
1140;
1141ALIGNCODE(16)
1142BEGINPROC_EXPORTED TRPMGCHandlerTrap08
1143 ; be careful.
1144 cli
1145 cld
1146
1147 ;
1148 ; Disable write protection.
1149 ;
1150 mov eax, cr0
1151 and eax, ~X86_CR0_WRITE_PROTECT
1152 mov cr0, eax
1153
1154 ;
1155 ; Load Hypervisor DS and ES (get it from the SS) - paranoia, but the TSS could be overwritten.. :)
1156 ;
1157 mov eax, ss
1158 mov ds, eax
1159 mov es, eax
1160
1161 COM_S_PRINT 10,13,'*** Guru Meditation 00000008 - Double Fault! ***',10,13
1162
1163 COM_S_PRINT 'VM='
1164 COM_S_DWORD_REG edx
1165 COM_S_PRINT ' prevTSS='
1166 COM_S_DWORD_REG ecx
1167 COM_S_PRINT ' prevCR3='
1168 mov eax, [ecx + VBOXTSS.cr3]
1169 COM_S_DWORD_REG eax
1170 COM_S_PRINT ' prevLdtr='
1171 movzx eax, word [ecx + VBOXTSS.selLdt]
1172 COM_S_DWORD_REG eax
1173 COM_S_NEWLINE
1174
1175 ;
1176 ; Create CPUMCTXCORE structure.
1177 ;
1178 mov ebx, IMP(g_trpmHyperCtxCore) ; It's raw-mode context, actually.
1179
1180 mov eax, [ecx + VBOXTSS.eip]
1181 mov [ebx + CPUMCTXCORE.eip], eax
1182%if GC_ARCH_BITS == 64
1183 ; zero out the high dword
1184 mov dword [ebx + CPUMCTXCORE.eip + 4], 0
1185%endif
1186 mov eax, [ecx + VBOXTSS.eflags]
1187 mov [ebx + CPUMCTXCORE.eflags], eax
1188
1189 movzx eax, word [ecx + VBOXTSS.cs]
1190 mov dword [ebx + CPUMCTXCORE.cs.Sel], eax
1191 movzx eax, word [ecx + VBOXTSS.ds]
1192 mov dword [ebx + CPUMCTXCORE.ds.Sel], eax
1193 movzx eax, word [ecx + VBOXTSS.es]
1194 mov dword [ebx + CPUMCTXCORE.es.Sel], eax
1195 movzx eax, word [ecx + VBOXTSS.fs]
1196 mov dword [ebx + CPUMCTXCORE.fs.Sel], eax
1197 movzx eax, word [ecx + VBOXTSS.gs]
1198 mov dword [ebx + CPUMCTXCORE.gs.Sel], eax
1199 movzx eax, word [ecx + VBOXTSS.ss]
1200 mov [ebx + CPUMCTXCORE.ss.Sel], eax
1201 mov eax, [ecx + VBOXTSS.esp]
1202 mov [ebx + CPUMCTXCORE.esp], eax
1203%if GC_ARCH_BITS == 64
1204 ; zero out the high dword
1205 mov dword [ebx + CPUMCTXCORE.esp + 4], 0
1206%endif
1207 mov eax, [ecx + VBOXTSS.ecx]
1208 mov [ebx + CPUMCTXCORE.ecx], eax
1209 mov eax, [ecx + VBOXTSS.edx]
1210 mov [ebx + CPUMCTXCORE.edx], eax
1211 mov eax, [ecx + VBOXTSS.ebx]
1212 mov [ebx + CPUMCTXCORE.ebx], eax
1213 mov eax, [ecx + VBOXTSS.eax]
1214 mov [ebx + CPUMCTXCORE.eax], eax
1215 mov eax, [ecx + VBOXTSS.ebp]
1216 mov [ebx + CPUMCTXCORE.ebp], eax
1217 mov eax, [ecx + VBOXTSS.esi]
1218 mov [ebx + CPUMCTXCORE.esi], eax
1219 mov eax, [ecx + VBOXTSS.edi]
1220 mov [ebx + CPUMCTXCORE.edi], eax
1221
1222 ;
1223 ; Show regs
1224 ;
1225 mov eax, 0ffffffffh
1226 mov ecx, 'trpH' ; indicate trap.
1227 mov edx, 08h ; vector number
1228 call trpmDbgDumpRegisterFrame
1229
1230 ;
1231 ; Should we try go back?
1232 ;
1233 inc dword [df_Count]
1234 cmp dword [df_Count], byte 10
1235 jb df_to_host
1236 jmp df_tripple_fault
1237df_Count: dd 0
1238
1239 ;
1240 ; Try return to the host.
1241 ;
1242df_to_host:
1243 COM_S_PRINT 'Trying to return to host...',10,13
1244 mov edx, IMP(g_VM)
1245 mov eax, VERR_TRPM_PANIC
1246 call [edx + VM.pfnVMMGCGuestToHostAsm]
1247 jmp short df_to_host
1248
1249 ;
1250 ; Perform a tripple fault.
1251 ;
1252df_tripple_fault:
1253 COM_S_PRINT 'Giving up - tripple faulting the machine...',10,13
1254 push byte 0
1255 push byte 0
1256 sidt [esp]
1257 mov word [esp], 0
1258 lidt [esp]
1259 xor eax, eax
1260 mov dword [eax], 0
1261 jmp df_tripple_fault
1262
1263ENDPROC TRPMGCHandlerTrap08
1264
1265
1266
1267
1268;;
1269; Internal procedure used to dump registers.
1270;
1271; @param ebx Pointer to CPUMCTXCORE.
1272; @param edx Vector number
1273; @param ecx 'trap' if trap, 'int' if interrupt.
1274; @param eax Error code if trap.
1275;
1276trpmDbgDumpRegisterFrame:
1277 sub esp, byte 8 ; working space for sidt/sgdt/etc
1278
1279; Init _must_ be done on host before crashing!
1280; push edx
1281; push eax
1282; COM_INIT
1283; pop eax
1284; pop edx
1285
1286 cmp ecx, 'trpH'
1287 je near tddrf_trpH
1288 cmp ecx, 'trpG'
1289 je near tddrf_trpG
1290 cmp ecx, 'intH'
1291 je near tddrf_intH
1292 cmp ecx, 'intG'
1293 je near tddrf_intG
1294 cmp ecx, 'resH'
1295 je near tddrf_resH
1296 COM_S_PRINT 10,13,'*** Bogus Dump Code '
1297 jmp tddrf_regs
1298
1299%if 1 ; the verbose version
1300
1301tddrf_intG:
1302 COM_S_PRINT 10,13,'*** Interrupt (Guest) '
1303 COM_S_DWORD_REG edx
1304 jmp tddrf_regs
1305
1306tddrf_intH:
1307 COM_S_PRINT 10,13,'*** Interrupt (Hypervisor) '
1308 COM_S_DWORD_REG edx
1309 jmp tddrf_regs
1310
1311tddrf_trpG:
1312 COM_S_PRINT 10,13,'*** Trap '
1313 jmp tddrf_trap_rest
1314
1315%else ; the short version
1316
1317tddrf_intG:
1318 COM_S_CHAR 'I'
1319 jmp tddrf_ret
1320
1321tddrf_intH:
1322 COM_S_CHAR 'i'
1323 jmp tddrf_ret
1324
1325tddrf_trpG:
1326 COM_S_CHAR 'T'
1327 jmp tddrf_ret
1328
1329%endif ; the short version
1330
1331tddrf_trpH:
1332 COM_S_PRINT 10,13,'*** Guru Meditation '
1333 jmp tddrf_trap_rest
1334
1335tddrf_resH:
1336 COM_S_PRINT 10,13,'*** Resuming Hypervisor Trap '
1337 jmp tddrf_trap_rest
1338
1339tddrf_trap_rest:
1340 COM_S_DWORD_REG edx
1341 COM_S_PRINT ' ErrorCode='
1342 COM_S_DWORD_REG eax
1343 COM_S_PRINT ' cr2='
1344 mov ecx, cr2
1345 COM_S_DWORD_REG ecx
1346
1347tddrf_regs:
1348 COM_S_PRINT ' ***',10,13,'cs:eip='
1349 movzx ecx, word [ebx + CPUMCTXCORE.cs.Sel]
1350 COM_S_DWORD_REG ecx
1351 COM_S_CHAR ':'
1352 mov ecx, [ebx + CPUMCTXCORE.eip]
1353 COM_S_DWORD_REG ecx
1354
1355 COM_S_PRINT ' ss:esp='
1356 movzx ecx, word [ebx + CPUMCTXCORE.ss.Sel]
1357 COM_S_DWORD_REG ecx
1358 COM_S_CHAR ':'
1359 mov ecx, [ebx + CPUMCTXCORE.esp]
1360 COM_S_DWORD_REG ecx
1361
1362
1363 sgdt [esp]
1364 COM_S_PRINT 10,13,' gdtr='
1365 movzx ecx, word [esp]
1366 COM_S_DWORD_REG ecx
1367 COM_S_CHAR ':'
1368 mov ecx, [esp + 2]
1369 COM_S_DWORD_REG ecx
1370
1371 sidt [esp]
1372 COM_S_PRINT ' idtr='
1373 movzx ecx, word [esp]
1374 COM_S_DWORD_REG ecx
1375 COM_S_CHAR ':'
1376 mov ecx, [esp + 2]
1377 COM_S_DWORD_REG ecx
1378
1379
1380 str [esp] ; yasm BUG! it generates sldt [esp] here! YASMCHECK!
1381 COM_S_PRINT 10,13,' tr='
1382 movzx ecx, word [esp]
1383 COM_S_DWORD_REG ecx
1384
1385 sldt [esp]
1386 COM_S_PRINT ' ldtr='
1387 movzx ecx, word [esp]
1388 COM_S_DWORD_REG ecx
1389
1390 COM_S_PRINT ' eflags='
1391 mov ecx, [ebx + CPUMCTXCORE.eflags]
1392 COM_S_DWORD_REG ecx
1393
1394
1395 COM_S_PRINT 10,13,'cr0='
1396 mov ecx, cr0
1397 COM_S_DWORD_REG ecx
1398
1399 COM_S_PRINT ' cr2='
1400 mov ecx, cr2
1401 COM_S_DWORD_REG ecx
1402
1403 COM_S_PRINT ' cr3='
1404 mov ecx, cr3
1405 COM_S_DWORD_REG ecx
1406 COM_S_PRINT ' cr4='
1407 mov ecx, cr4
1408 COM_S_DWORD_REG ecx
1409
1410
1411 COM_S_PRINT 10,13,' ds='
1412 movzx ecx, word [ebx + CPUMCTXCORE.ds.Sel]
1413 COM_S_DWORD_REG ecx
1414
1415 COM_S_PRINT ' es='
1416 movzx ecx, word [ebx + CPUMCTXCORE.es.Sel]
1417 COM_S_DWORD_REG ecx
1418
1419 COM_S_PRINT ' fs='
1420 movzx ecx, word [ebx + CPUMCTXCORE.fs.Sel]
1421 COM_S_DWORD_REG ecx
1422
1423 COM_S_PRINT ' gs='
1424 movzx ecx, word [ebx + CPUMCTXCORE.gs.Sel]
1425 COM_S_DWORD_REG ecx
1426
1427
1428 COM_S_PRINT 10,13,'eax='
1429 mov ecx, [ebx + CPUMCTXCORE.eax]
1430 COM_S_DWORD_REG ecx
1431
1432 COM_S_PRINT ' ebx='
1433 mov ecx, [ebx + CPUMCTXCORE.ebx]
1434 COM_S_DWORD_REG ecx
1435
1436 COM_S_PRINT ' ecx='
1437 mov ecx, [ebx + CPUMCTXCORE.ecx]
1438 COM_S_DWORD_REG ecx
1439
1440 COM_S_PRINT ' edx='
1441 mov ecx, [ebx + CPUMCTXCORE.edx]
1442 COM_S_DWORD_REG ecx
1443
1444
1445 COM_S_PRINT 10,13,'esi='
1446 mov ecx, [ebx + CPUMCTXCORE.esi]
1447 COM_S_DWORD_REG ecx
1448
1449 COM_S_PRINT ' edi='
1450 mov ecx, [ebx + CPUMCTXCORE.edi]
1451 COM_S_DWORD_REG ecx
1452
1453 COM_S_PRINT ' ebp='
1454 mov ecx, [ebx + CPUMCTXCORE.ebp]
1455 COM_S_DWORD_REG ecx
1456
1457
1458 COM_S_NEWLINE
1459
1460tddrf_ret:
1461 add esp, byte 8
1462 ret
1463
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette