VirtualBox

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

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

VMM: Switcher and TRPM fixes wrt hypervisor traps and tstVMM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 46.5 KB
Line 
1; $Id: TRPMRCHandlersA.asm 41976 2012-07-01 14:16:40Z 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.pfnVMMRCToHostAsm]
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.pfnVMMRCToHostAsm]
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 edx, IMP(g_VM)
614%if 0
615 call [edx + VM.pfnVMMRCToHostAsm]
616%else
617 call [edx + VM.pfnVMMRCToHostAsmNoReturn]
618%endif
619 mov eax, VERR_TRPM_DONT_PANIC
620 jmp .rc_to_host
621
622 ;
623 ; Continue(/Resume/Restart/Whatever) hypervisor execution.
624 ; Don't reset the TRPM state. Caller takes care of that.
625 ;
626ALIGNCODE(16)
627.rc_continue:
628%ifdef DEBUG_STUFF
629 mov eax, [%$STK_ERRCD]
630 mov ecx, 'resH' ; indicate trap.
631 mov edx, [%$STK_VECTOR]
632 call trpmDbgDumpRegisterFrame
633%endif
634
635%ifdef VBOX_WITH_STATISTICS
636 mov edx, [%$STK_VECTOR]
637 imul edx, edx, byte STAMPROFILEADV_size ; assumes < 128
638 add edx, TRPM.aStatGCTraps
639 add edx, IMP(g_TRPM)
640 STAM_PROFILE_ADV_STOP edx
641%endif
642
643 ; restore
644 mov eax, [ebx + CPUMCTXCORE.eax]
645 mov [%$STK_SAVED_EAX], eax
646 mov ecx, [ebx + CPUMCTXCORE.ecx]
647 mov edx, [ebx + CPUMCTXCORE.edx]
648 mov eax, [ebx + CPUMCTXCORE.ebx]
649 mov [%$STK_SAVED_EBX], eax
650 mov ebp, [ebx + CPUMCTXCORE.ebp]
651 mov esi, [ebx + CPUMCTXCORE.esi]
652 mov edi, [ebx + CPUMCTXCORE.edi]
653
654 ; skipping esp & ss.
655
656 mov eax, [ebx + CPUMCTXCORE.eflags]
657 mov [%$STK_EFLAGS], eax
658 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
659 mov [%$STK_CS], eax
660 mov eax, [ebx + CPUMCTXCORE.eip]
661 mov [%$STK_EIP], eax
662
663 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
664 mov gs, ax
665
666 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
667 mov fs, ax
668
669 mov ax, [ebx + CPUMCTXCORE.es.Sel]
670 mov es, ax
671
672 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
673 mov ds, ax
674
675 ; finally restore our scratch register eax and ebx.
676 pop ebx
677 pop eax
678 add esp, 16 + 8 ; skip segregs, error code, and vector number.
679
680 iret
681
682
683 ;
684 ; Internal processing error - don't panic, start meditating!
685 ;
686.rc_abandon_ship:
687%ifdef DEBUG_STUFF
688 mov eax, [%$STK_ERRCD]
689 mov ecx, 'trpH' ; indicate trap.
690 mov edx, [%$STK_VECTOR]
691 call trpmDbgDumpRegisterFrame
692%endif
693
694.rc_do_not_panic:
695 mov edx, IMP(g_VM)
696 mov eax, VERR_TRPM_DONT_PANIC
697%if 0
698 call [edx + VM.pfnVMMRCToHostAsm]
699%else
700 call [edx + VM.pfnVMMRCToHostAsmNoReturn]
701%endif
702%ifdef DEBUG_STUFF
703 COM_S_PRINT 'bad!!!'
704%endif
705 jmp .rc_do_not_panic ; this shall never ever happen!
706%pop
707ENDPROC TRPMGCHandlerGeneric
708
709
710
711
712
713;;
714; We start by 256 push <vector no.> + jmp interruptworker
715;
716ALIGNCODE(16)
717BEGINPROC_EXPORTED TRPMGCHandlerInterupt
718 ; NASM has some nice features, here an example of a loop.
719%assign i 0
720%rep 256
721 db 06ah, i ; push imm8 - note that this is a signextended value.
722 jmp ti_GenericInterrupt
723 ALIGNCODE(8)
724%assign i i+1
725%endrep
726
727;;
728; Main interrupt handler for the guest context
729;
730; Stack:
731; 24 GS (V86 only)
732; 20 FS (V86 only)
733; 1C DS (V86 only)
734; 18 ES (V86 only)
735; 14 SS
736; 10 ESP
737; c EFLAGS
738; 8 CS
739; 4 EIP
740; ESP -> 0 Vector number (only use low byte!).
741;
742; @uses none
743ti_GenericInterrupt:
744 cld
745
746 ;
747 ; Save ds, es, fs, gs, eax and ebx so we have a context pointer (ebx) and
748 ; scratch (eax) register to work with. A sideeffect of using ebx is that
749 ; it's preserved accross cdecl calls.
750 ;
751 ; In order to safely access data, we need to load our flat DS & ES selector,
752 ; clear FS and GS (stale guest selector prevention), and clear make sure
753 ; that CR0.WP is cleared.
754 ;
755 push ds ; +14h
756 push es ; +10h
757 push fs ; +0ch
758 push gs ; +08h
759 push eax ; +04h
760 push ebx ; +00h
761%push StackFrame
762%define %$STK_SAVED_EBX esp
763%define %$STK_SAVED_EAX esp + 04h
764%define %$STK_SAVED_GS esp + 08h
765%define %$STK_SAVED_FS esp + 0ch
766%define %$STK_SAVED_ES esp + 10h
767%define %$STK_SAVED_DS esp + 14h
768%define %$ESPOFF 18h
769%define %$STK_VECTOR esp + 00h + %$ESPOFF
770%define %$STK_EIP esp + 04h + %$ESPOFF
771%define %$STK_CS esp + 08h + %$ESPOFF
772%define %$STK_EFLAGS esp + 0ch + %$ESPOFF
773%define %$STK_ESP esp + 10h + %$ESPOFF
774%define %$STK_SS esp + 14h + %$ESPOFF
775%define %$STK_V86_ES esp + 18h + %$ESPOFF
776%define %$STK_V86_DS esp + 1ch + %$ESPOFF
777%define %$STK_V86_FS esp + 20h + %$ESPOFF
778%define %$STK_V86_GS esp + 24h + %$ESPOFF
779
780 mov bx, ss ; load
781 mov ds, bx
782 mov es, bx
783
784 xor bx, bx ; load 0 into gs and fs.
785 mov gs, bx
786 mov fs, bx
787
788 mov eax, cr0 ;; @todo elimitate this read?
789 and eax, ~X86_CR0_WRITE_PROTECT
790 mov cr0, eax
791
792 mov ebx, IMP(g_trpmGuestCtxCore) ; Assume GC as the most common.
793 test byte [%$STK_CS], 3h ; check RPL of the cs selector
794 ;; @todo check this for conforming segments.
795 jnz .save_state
796 test dword [%$STK_EFLAGS], X86_EFL_VM ; If in V86, then guest.
797 jnz .save_state
798 mov ebx, IMP(g_trpmHyperCtxCore) ; It's raw-mode context, actually.
799
800 ;
801 ; Save the state.
802 ;
803 ; ASSUMPTION: If trap in hypervisor, we assume that we can read two dword
804 ; under the bottom of the stack. This is atm safe.
805 ;
806.save_state:
807 mov eax, [%$STK_SAVED_EAX]
808 mov [ebx + CPUMCTXCORE.eax], eax
809 mov [ebx + CPUMCTXCORE.ecx], ecx
810 mov [ebx + CPUMCTXCORE.edx], edx
811 mov eax, [%$STK_SAVED_EBX]
812 mov [ebx + CPUMCTXCORE.ebx], eax
813 mov [ebx + CPUMCTXCORE.esi], esi
814 mov [ebx + CPUMCTXCORE.edi], edi
815 mov [ebx + CPUMCTXCORE.ebp], ebp
816
817 mov eax, [%$STK_ESP]
818 mov [ebx + CPUMCTXCORE.esp], eax
819 mov cx, [%$STK_SS]
820 mov [ebx + CPUMCTXCORE.ss.Sel], cx
821
822 mov cx, [%$STK_CS]
823 mov [ebx + CPUMCTXCORE.cs.Sel], cx
824 mov eax, [%$STK_EIP]
825 mov [ebx + CPUMCTXCORE.eip], eax
826 mov eax, [%$STK_EFLAGS]
827 mov [ebx + CPUMCTXCORE.eflags], eax
828
829%if GC_ARCH_BITS == 64 ; zero out the high dwords - probably not necessary any more.
830 mov dword [ebx + CPUMCTXCORE.eax + 4], 0
831 mov dword [ebx + CPUMCTXCORE.ecx + 4], 0
832 mov dword [ebx + CPUMCTXCORE.edx + 4], 0
833 mov dword [ebx + CPUMCTXCORE.ebx + 4], 0
834 mov dword [ebx + CPUMCTXCORE.esi + 4], 0
835 mov dword [ebx + CPUMCTXCORE.edi + 4], 0
836 mov dword [ebx + CPUMCTXCORE.ebp + 4], 0
837 mov dword [ebx + CPUMCTXCORE.esp + 4], 0
838 mov dword [ebx + CPUMCTXCORE.eip + 4], 0
839%endif
840
841 test dword [%$STK_EFLAGS], X86_EFL_VM
842 jnz .save_V86_segregs
843
844 mov cx, [%$STK_SAVED_ES]
845 mov [ebx + CPUMCTXCORE.es.Sel], cx
846 mov cx, [%$STK_SAVED_DS]
847 mov [ebx + CPUMCTXCORE.ds.Sel], cx
848 mov cx, [%$STK_SAVED_FS]
849 mov [ebx + CPUMCTXCORE.fs.Sel], cx
850 mov cx, [%$STK_SAVED_GS]
851 mov [ebx + CPUMCTXCORE.gs.Sel], cx
852 jmp .done_saving
853
854 ;
855 ; The DS, ES, FS and GS registers are zeroed in V86 mode and their real
856 ; values are on the stack.
857 ;
858.save_V86_segregs:
859 mov cx, [%$STK_V86_ES]
860 mov [ebx + CPUMCTXCORE.es.Sel], cx
861 mov cx, [%$STK_V86_DS]
862 mov [ebx + CPUMCTXCORE.ds.Sel], cx
863 mov cx, [%$STK_V86_FS]
864 mov [ebx + CPUMCTXCORE.fs.Sel], cx
865 mov cx, [%$STK_V86_GS]
866 mov [ebx + CPUMCTXCORE.gs.Sel], cx
867
868.done_saving:
869
870 ;
871 ; Store the information about the active trap/interrupt.
872 ;
873 mov esi, IMP(g_TRPMCPU) ; esi = TRPMCPU until resume!
874 movzx edx, byte [%$STK_VECTOR]
875 mov [esi + TRPMCPU.uActiveVector], edx
876 mov dword [esi + TRPMCPU.uActiveErrorCode], 0
877 mov dword [esi + TRPMCPU.enmActiveType], TRPM_TRAP
878 mov dword [esi + TRPMCPU.uActiveCR2], edx
879%if GC_ARCH_BITS == 64 ; zero out the high dwords.
880 mov dword [esi + TRPMCPU.uActiveErrorCode + 4], 0
881 mov dword [esi + TRPMCPU.uActiveCR2 + 4], 0
882%endif
883
884%ifdef VBOX_WITH_STATISTICS
885 ;
886 ; Update statistics.
887 ;
888 mov edi, IMP(g_TRPM)
889 movzx edx, byte [%$STK_VECTOR] ; vector number
890 imul edx, edx, byte STAMCOUNTER_size
891 add edx, [edi + TRPM.paStatHostIrqRC]
892 STAM_COUNTER_INC edx
893%endif
894
895 ;
896 ; Check if we're in the raw-mode context (RC / hypervisor) when this happened.
897 ;
898 test dword [%$STK_EFLAGS], X86_EFL_VM
899 jnz short .gc_not_raw_mode_context
900
901 test byte [%$STK_CS], 3h ; check RPL of the cs selector
902 jz .rc_in_raw_mode_context
903
904 ;
905 ; Trap in guest code.
906 ;
907.gc_not_raw_mode_context:
908 and dword [ebx + CPUMCTXCORE.eflags], ~X86_EFL_RF ; Clear RF.
909 ; The guest shall not see this in it's state.
910%ifdef DEBUG_STUFF_INT
911 xor eax, eax
912 mov ecx, 'intG' ; indicate trap in GC.
913 movzx edx, byte [%$STK_VECTOR]
914 call trpmDbgDumpRegisterFrame
915%endif
916
917 ;
918 ; Switch back to the host and process it there.
919 ;
920 mov edx, IMP(g_VM)
921 mov eax, VINF_EM_RAW_INTERRUPT
922 call [edx + VM.pfnVMMRCToHostAsm]
923
924 ;
925 ; We've returned!
926 ;
927
928 ; Reset TRPM state
929 xor edx, edx
930 dec edx ; edx = 0ffffffffh
931 xchg [esi + TRPMCPU.uActiveVector], edx
932 mov [esi + TRPMCPU.uPrevVector], edx
933
934 ; enable WP
935 mov eax, cr0 ;; @todo try elimiate this read.
936 or eax, X86_CR0_WRITE_PROTECT
937 mov cr0, eax
938
939 ; restore guest state and start executing again.
940 mov eax, [ebx + CPUMCTXCORE.eax]
941 mov [%$STK_SAVED_EAX], eax
942 mov ecx, [ebx + CPUMCTXCORE.ecx]
943 mov edx, [ebx + CPUMCTXCORE.edx]
944 mov eax, [ebx + CPUMCTXCORE.ebx]
945 mov [%$STK_SAVED_EBX], eax
946 mov ebp, [ebx + CPUMCTXCORE.ebp]
947 mov esi, [ebx + CPUMCTXCORE.esi]
948 mov edi, [ebx + CPUMCTXCORE.edi]
949
950 mov eax, [ebx + CPUMCTXCORE.esp]
951 mov [%$STK_ESP], eax
952 mov eax, dword [ebx + CPUMCTXCORE.ss.Sel]
953 mov [%$STK_SS], eax
954 mov eax, [ebx + CPUMCTXCORE.eflags]
955 mov [%$STK_EFLAGS], eax
956 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
957 mov [%$STK_CS], eax
958 mov eax, [ebx + CPUMCTXCORE.eip]
959 mov [%$STK_EIP], eax
960
961 test dword [ebx + CPUMCTXCORE.eflags], X86_EFL_VM
962 jnz .gc_V86_return
963
964 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
965 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_GS
966 mov gs, ax
967
968 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
969 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_FS
970 mov fs, ax
971
972 mov ax, [ebx + CPUMCTXCORE.es.Sel]
973 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_ES
974 mov es, ax
975
976 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
977 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_MOV_DS
978 mov ds, ax
979
980 ; finally restore our scratch register eax and ebx.
981 pop ebx
982 pop eax
983 add esp, 16 + 4 ; skip segregs, and vector number.
984
985 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_IRET
986 iret
987
988ALIGNCODE(16)
989.gc_V86_return:
990 mov eax, dword [ebx + CPUMCTXCORE.es.Sel]
991 mov [%$STK_V86_ES], eax
992 mov eax, dword [ebx + CPUMCTXCORE.ds.Sel]
993 mov [%$STK_V86_DS], eax
994 mov eax, dword [ebx + CPUMCTXCORE.fs.Sel]
995 mov [%$STK_V86_FS], eax
996 mov eax, dword [ebx + CPUMCTXCORE.gs.Sel]
997 mov [%$STK_V86_GS], eax
998
999 ; finally restore our scratch register eax and ebx.
1000 pop ebx
1001 pop eax
1002 add esp, 16 + 4 ; skip segregs, and vector number.
1003
1004 TRPM_NP_GP_HANDLER NAME(trpmRCTrapInGeneric), TRPM_TRAP_IN_IRET | TRPM_TRAP_IN_V86
1005 iret
1006
1007 ; -+- Entry point -+-
1008 ;
1009 ; We're in hypervisor mode which means no guest context
1010 ; and special care to be taken to restore the hypervisor
1011 ; context correctly.
1012 ;
1013 ; ATM the only place this can happen is when entering a trap handler.
1014 ; We make ASSUMPTIONS about this in respects to the WP CR0 bit
1015 ;
1016ALIGNCODE(16)
1017.rc_in_raw_mode_context:
1018 ; fix ss:esp.
1019 lea ecx, [%$STK_ESP] ; calc esp at trap
1020 mov [ebx + CPUMCTXCORE.esp], ecx ; update esp in register frame
1021 mov [ebx + CPUMCTXCORE.ss.Sel], ss ; update ss in register frame
1022
1023%ifdef DEBUG_STUFF_INT
1024 xor eax, eax
1025 mov ecx, 'intH' ; indicate trap in RC.
1026 movzx edx, byte [%$STK_VECTOR]
1027 call trpmDbgDumpRegisterFrame
1028%endif
1029
1030 mov edx, IMP(g_VM)
1031 mov eax, VINF_EM_RAW_INTERRUPT_HYPER
1032%if 0
1033 call [edx + VM.pfnVMMRCToHostAsm]
1034%else
1035 call [edx + VM.pfnVMMRCToHostAsmNoReturn]
1036%endif
1037%ifdef DEBUG_STUFF_INT
1038 COM_S_CHAR '!'
1039%endif
1040
1041 ;
1042 ; We've returned!
1043 ; Continue(/Resume/Restart/Whatever) hypervisor execution.
1044 ;
1045
1046 ; Reset TRPM state - don't record this.
1047 ;mov esi, IMP(g_TRPMCPU)
1048 mov dword [esi + TRPMCPU.uActiveVector], 0ffffffffh
1049
1050 ;
1051 ; Restore the hypervisor context and return.
1052 ;
1053 mov eax, [ebx + CPUMCTXCORE.eax]
1054 mov [%$STK_SAVED_EAX], eax
1055 mov ecx, [ebx + CPUMCTXCORE.ecx]
1056 mov edx, [ebx + CPUMCTXCORE.edx]
1057 mov eax, [ebx + CPUMCTXCORE.ebx]
1058 mov [%$STK_SAVED_EBX], eax
1059 mov ebp, [ebx + CPUMCTXCORE.ebp]
1060 mov esi, [ebx + CPUMCTXCORE.esi]
1061 mov edi, [ebx + CPUMCTXCORE.edi]
1062
1063 ; skipping esp & ss.
1064
1065 mov eax, [ebx + CPUMCTXCORE.eflags]
1066 mov [%$STK_EFLAGS], eax
1067 mov eax, dword [ebx + CPUMCTXCORE.cs.Sel]
1068 mov [%$STK_CS], eax
1069 mov eax, [ebx + CPUMCTXCORE.eip]
1070 mov [%$STK_EIP], eax
1071
1072 mov ax, [ebx + CPUMCTXCORE.gs.Sel]
1073 mov gs, ax
1074
1075 mov ax, [ebx + CPUMCTXCORE.fs.Sel]
1076 mov fs, ax
1077
1078 mov ax, [ebx + CPUMCTXCORE.es.Sel]
1079 mov es, ax
1080
1081 mov ax, [ebx + CPUMCTXCORE.ds.Sel]
1082 mov ds, ax
1083
1084 ; finally restore our scratch register eax and ebx.
1085 pop ebx
1086 pop eax
1087 add esp, 16 + 4 ; skip segregs, and vector number.
1088
1089 iret
1090%pop
1091ENDPROC TRPMGCHandlerInterupt
1092
1093
1094
1095;;
1096; Trap handler for #MC
1097;
1098; This handler will forward the #MC to the host OS. Since this
1099; is generalized in the generic interrupt handler, we just disable
1100; interrupts and push vector number and jump to the generic code.
1101;
1102; Stack:
1103; 10 SS (only if ring transition.)
1104; c ESP (only if ring transition.)
1105; 8 EFLAGS
1106; 4 CS
1107; 0 EIP
1108;
1109; @uses none
1110;
1111ALIGNCODE(16)
1112BEGINPROC_EXPORTED TRPMGCHandlerTrap12
1113 push byte 12h
1114 jmp ti_GenericInterrupt
1115ENDPROC TRPMGCHandlerTrap12
1116
1117
1118
1119
1120;;
1121; Trap handler for double fault (#DF).
1122;
1123; This is a special trap handler executes in separate task with own TSS, with
1124; one of the intermediate memory contexts instead of the shadow context.
1125; The handler will unconditionally print an report to the comport configured
1126; for the COM_S_* macros before attempting to return to the host. If it it ends
1127; up double faulting more than 10 times, it will simply cause an triple fault
1128; to get us out of the mess.
1129;
1130; @param esp Half way down the hypervisor stack + the trap frame.
1131; @param ebp Half way down the hypervisor stack.
1132; @param eflags Interrupts disabled, nested flag is probably set (we don't care).
1133; @param ecx The address of the hypervisor TSS.
1134; @param edi Same as ecx.
1135; @param eax Same as ecx.
1136; @param edx Address of the VM structure.
1137; @param esi Same as edx.
1138; @param ebx Same as edx.
1139; @param ss Hypervisor DS.
1140; @param ds Hypervisor DS.
1141; @param es Hypervisor DS.
1142; @param fs 0
1143; @param gs 0
1144;
1145;
1146; @remark To be able to catch errors with WP turned off, it is required that the
1147; TSS GDT descriptor and the TSSes are writable (X86_PTE_RW). See SELM.cpp
1148; for how to enable this.
1149;
1150; @remark It is *not* safe to resume the VMM after a double fault. (At least not
1151; without clearing the busy flag of the TssTrap8 and fixing whatever cause it.)
1152;
1153ALIGNCODE(16)
1154BEGINPROC_EXPORTED TRPMGCHandlerTrap08
1155 ; be careful.
1156 cli
1157 cld
1158
1159 ;
1160 ; Disable write protection.
1161 ;
1162 mov eax, cr0
1163 and eax, ~X86_CR0_WRITE_PROTECT
1164 mov cr0, eax
1165
1166 ;
1167 ; Load Hypervisor DS and ES (get it from the SS) - paranoia, but the TSS could be overwritten.. :)
1168 ;
1169 mov eax, ss
1170 mov ds, eax
1171 mov es, eax
1172
1173 COM_S_PRINT 10,13,'*** Guru Meditation 00000008 - Double Fault! ***',10,13
1174
1175 COM_S_PRINT 'VM='
1176 COM_S_DWORD_REG edx
1177 COM_S_PRINT ' prevTSS='
1178 COM_S_DWORD_REG ecx
1179 COM_S_PRINT ' prevCR3='
1180 mov eax, [ecx + VBOXTSS.cr3]
1181 COM_S_DWORD_REG eax
1182 COM_S_PRINT ' prevLdtr='
1183 movzx eax, word [ecx + VBOXTSS.selLdt]
1184 COM_S_DWORD_REG eax
1185 COM_S_NEWLINE
1186
1187 ;
1188 ; Create CPUMCTXCORE structure.
1189 ;
1190 mov ebx, IMP(g_trpmHyperCtxCore) ; It's raw-mode context, actually.
1191
1192 mov eax, [ecx + VBOXTSS.eip]
1193 mov [ebx + CPUMCTXCORE.eip], eax
1194%if GC_ARCH_BITS == 64
1195 ; zero out the high dword
1196 mov dword [ebx + CPUMCTXCORE.eip + 4], 0
1197%endif
1198 mov eax, [ecx + VBOXTSS.eflags]
1199 mov [ebx + CPUMCTXCORE.eflags], eax
1200
1201 movzx eax, word [ecx + VBOXTSS.cs]
1202 mov dword [ebx + CPUMCTXCORE.cs.Sel], eax
1203 movzx eax, word [ecx + VBOXTSS.ds]
1204 mov dword [ebx + CPUMCTXCORE.ds.Sel], eax
1205 movzx eax, word [ecx + VBOXTSS.es]
1206 mov dword [ebx + CPUMCTXCORE.es.Sel], eax
1207 movzx eax, word [ecx + VBOXTSS.fs]
1208 mov dword [ebx + CPUMCTXCORE.fs.Sel], eax
1209 movzx eax, word [ecx + VBOXTSS.gs]
1210 mov dword [ebx + CPUMCTXCORE.gs.Sel], eax
1211 movzx eax, word [ecx + VBOXTSS.ss]
1212 mov [ebx + CPUMCTXCORE.ss.Sel], eax
1213 mov eax, [ecx + VBOXTSS.esp]
1214 mov [ebx + CPUMCTXCORE.esp], eax
1215%if GC_ARCH_BITS == 64
1216 ; zero out the high dword
1217 mov dword [ebx + CPUMCTXCORE.esp + 4], 0
1218%endif
1219 mov eax, [ecx + VBOXTSS.ecx]
1220 mov [ebx + CPUMCTXCORE.ecx], eax
1221 mov eax, [ecx + VBOXTSS.edx]
1222 mov [ebx + CPUMCTXCORE.edx], eax
1223 mov eax, [ecx + VBOXTSS.ebx]
1224 mov [ebx + CPUMCTXCORE.ebx], eax
1225 mov eax, [ecx + VBOXTSS.eax]
1226 mov [ebx + CPUMCTXCORE.eax], eax
1227 mov eax, [ecx + VBOXTSS.ebp]
1228 mov [ebx + CPUMCTXCORE.ebp], eax
1229 mov eax, [ecx + VBOXTSS.esi]
1230 mov [ebx + CPUMCTXCORE.esi], eax
1231 mov eax, [ecx + VBOXTSS.edi]
1232 mov [ebx + CPUMCTXCORE.edi], eax
1233
1234 ;
1235 ; Show regs
1236 ;
1237 mov eax, 0ffffffffh
1238 mov ecx, 'trpH' ; indicate trap.
1239 mov edx, 08h ; vector number
1240 call trpmDbgDumpRegisterFrame
1241
1242 ;
1243 ; Should we try go back?
1244 ;
1245 inc dword [df_Count]
1246 cmp dword [df_Count], byte 10
1247 jb df_to_host
1248 jmp df_tripple_fault
1249df_Count: dd 0
1250
1251 ;
1252 ; Try return to the host.
1253 ;
1254df_to_host:
1255 COM_S_PRINT 'Trying to return to host...',10,13
1256 mov edx, IMP(g_VM)
1257 mov eax, VERR_TRPM_PANIC
1258%if 0
1259 call [edx + VM.pfnVMMRCToHostAsm]
1260%else
1261 call [edx + VM.pfnVMMRCToHostAsmNoReturn]
1262%endif
1263 jmp short df_to_host
1264
1265 ;
1266 ; Perform a tripple fault.
1267 ;
1268df_tripple_fault:
1269 COM_S_PRINT 'Giving up - tripple faulting the machine...',10,13
1270 push byte 0
1271 push byte 0
1272 sidt [esp]
1273 mov word [esp], 0
1274 lidt [esp]
1275 xor eax, eax
1276 mov dword [eax], 0
1277 jmp df_tripple_fault
1278
1279ENDPROC TRPMGCHandlerTrap08
1280
1281
1282
1283
1284;;
1285; Internal procedure used to dump registers.
1286;
1287; @param ebx Pointer to CPUMCTXCORE.
1288; @param edx Vector number
1289; @param ecx 'trap' if trap, 'int' if interrupt.
1290; @param eax Error code if trap.
1291;
1292trpmDbgDumpRegisterFrame:
1293 sub esp, byte 8 ; working space for sidt/sgdt/etc
1294
1295; Init _must_ be done on host before crashing!
1296; push edx
1297; push eax
1298; COM_INIT
1299; pop eax
1300; pop edx
1301
1302 cmp ecx, 'trpH'
1303 je near tddrf_trpH
1304 cmp ecx, 'trpG'
1305 je near tddrf_trpG
1306 cmp ecx, 'intH'
1307 je near tddrf_intH
1308 cmp ecx, 'intG'
1309 je near tddrf_intG
1310 cmp ecx, 'resH'
1311 je near tddrf_resH
1312 COM_S_PRINT 10,13,'*** Bogus Dump Code '
1313 jmp tddrf_regs
1314
1315%if 1 ; the verbose version
1316
1317tddrf_intG:
1318 COM_S_PRINT 10,13,'*** Interrupt (Guest) '
1319 COM_S_DWORD_REG edx
1320 jmp tddrf_regs
1321
1322tddrf_intH:
1323 COM_S_PRINT 10,13,'*** Interrupt (Hypervisor) '
1324 COM_S_DWORD_REG edx
1325 jmp tddrf_regs
1326
1327tddrf_trpG:
1328 COM_S_PRINT 10,13,'*** Trap '
1329 jmp tddrf_trap_rest
1330
1331%else ; the short version
1332
1333tddrf_intG:
1334 COM_S_CHAR 'I'
1335 jmp tddrf_ret
1336
1337tddrf_intH:
1338 COM_S_CHAR 'i'
1339 jmp tddrf_ret
1340
1341tddrf_trpG:
1342 COM_S_CHAR 'T'
1343 jmp tddrf_ret
1344
1345%endif ; the short version
1346
1347tddrf_trpH:
1348 COM_S_PRINT 10,13,'*** Guru Meditation '
1349 jmp tddrf_trap_rest
1350
1351tddrf_resH:
1352 COM_S_PRINT 10,13,'*** Resuming Hypervisor Trap '
1353 jmp tddrf_trap_rest
1354
1355tddrf_trap_rest:
1356 COM_S_DWORD_REG edx
1357 COM_S_PRINT ' ErrorCode='
1358 COM_S_DWORD_REG eax
1359 COM_S_PRINT ' cr2='
1360 mov ecx, cr2
1361 COM_S_DWORD_REG ecx
1362
1363tddrf_regs:
1364 COM_S_PRINT ' ***',10,13,'cs:eip='
1365 movzx ecx, word [ebx + CPUMCTXCORE.cs.Sel]
1366 COM_S_DWORD_REG ecx
1367 COM_S_CHAR ':'
1368 mov ecx, [ebx + CPUMCTXCORE.eip]
1369 COM_S_DWORD_REG ecx
1370
1371 COM_S_PRINT ' ss:esp='
1372 movzx ecx, word [ebx + CPUMCTXCORE.ss.Sel]
1373 COM_S_DWORD_REG ecx
1374 COM_S_CHAR ':'
1375 mov ecx, [ebx + CPUMCTXCORE.esp]
1376 COM_S_DWORD_REG ecx
1377
1378
1379 sgdt [esp]
1380 COM_S_PRINT 10,13,' gdtr='
1381 movzx ecx, word [esp]
1382 COM_S_DWORD_REG ecx
1383 COM_S_CHAR ':'
1384 mov ecx, [esp + 2]
1385 COM_S_DWORD_REG ecx
1386
1387 sidt [esp]
1388 COM_S_PRINT ' idtr='
1389 movzx ecx, word [esp]
1390 COM_S_DWORD_REG ecx
1391 COM_S_CHAR ':'
1392 mov ecx, [esp + 2]
1393 COM_S_DWORD_REG ecx
1394
1395
1396 str [esp] ; yasm BUG! it generates sldt [esp] here! YASMCHECK!
1397 COM_S_PRINT 10,13,' tr='
1398 movzx ecx, word [esp]
1399 COM_S_DWORD_REG ecx
1400
1401 sldt [esp]
1402 COM_S_PRINT ' ldtr='
1403 movzx ecx, word [esp]
1404 COM_S_DWORD_REG ecx
1405
1406 COM_S_PRINT ' eflags='
1407 mov ecx, [ebx + CPUMCTXCORE.eflags]
1408 COM_S_DWORD_REG ecx
1409
1410
1411 COM_S_PRINT 10,13,'cr0='
1412 mov ecx, cr0
1413 COM_S_DWORD_REG ecx
1414
1415 COM_S_PRINT ' cr2='
1416 mov ecx, cr2
1417 COM_S_DWORD_REG ecx
1418
1419 COM_S_PRINT ' cr3='
1420 mov ecx, cr3
1421 COM_S_DWORD_REG ecx
1422 COM_S_PRINT ' cr4='
1423 mov ecx, cr4
1424 COM_S_DWORD_REG ecx
1425
1426
1427 COM_S_PRINT 10,13,' ds='
1428 movzx ecx, word [ebx + CPUMCTXCORE.ds.Sel]
1429 COM_S_DWORD_REG ecx
1430
1431 COM_S_PRINT ' es='
1432 movzx ecx, word [ebx + CPUMCTXCORE.es.Sel]
1433 COM_S_DWORD_REG ecx
1434
1435 COM_S_PRINT ' fs='
1436 movzx ecx, word [ebx + CPUMCTXCORE.fs.Sel]
1437 COM_S_DWORD_REG ecx
1438
1439 COM_S_PRINT ' gs='
1440 movzx ecx, word [ebx + CPUMCTXCORE.gs.Sel]
1441 COM_S_DWORD_REG ecx
1442
1443
1444 COM_S_PRINT 10,13,'eax='
1445 mov ecx, [ebx + CPUMCTXCORE.eax]
1446 COM_S_DWORD_REG ecx
1447
1448 COM_S_PRINT ' ebx='
1449 mov ecx, [ebx + CPUMCTXCORE.ebx]
1450 COM_S_DWORD_REG ecx
1451
1452 COM_S_PRINT ' ecx='
1453 mov ecx, [ebx + CPUMCTXCORE.ecx]
1454 COM_S_DWORD_REG ecx
1455
1456 COM_S_PRINT ' edx='
1457 mov ecx, [ebx + CPUMCTXCORE.edx]
1458 COM_S_DWORD_REG ecx
1459
1460
1461 COM_S_PRINT 10,13,'esi='
1462 mov ecx, [ebx + CPUMCTXCORE.esi]
1463 COM_S_DWORD_REG ecx
1464
1465 COM_S_PRINT ' edi='
1466 mov ecx, [ebx + CPUMCTXCORE.edi]
1467 COM_S_DWORD_REG ecx
1468
1469 COM_S_PRINT ' ebp='
1470 mov ecx, [ebx + CPUMCTXCORE.ebp]
1471 COM_S_DWORD_REG ecx
1472
1473
1474 COM_S_NEWLINE
1475
1476tddrf_ret:
1477 add esp, byte 8
1478 ret
1479
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