~ubuntu-branches/ubuntu/gutsy/virtualbox-ose/gutsy

« back to all changes in this revision

Viewing changes to src/VBox/VMM/VMMGC/TRPMGCHandlersA.asm

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-09-08 16:44:58 UTC
  • Revision ID: james.westby@ubuntu.com-20070908164458-wao29470vqtr8ksy
Tags: upstream-1.5.0-dfsg2
ImportĀ upstreamĀ versionĀ 1.5.0-dfsg2

Show diffs side-by-side

added added

removed removed

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