VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMSwitcher/AMD64andLegacy.mac@ 34986

Last change on this file since 34986 was 34986, checked in by vboxsync, 14 years ago

VMMSwitcher/AMD64andLegacy: restore the Local APIC NMI vectors _after_ we restored the host CS

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 36.7 KB
Line 
1; $Id: AMD64andLegacy.mac 34986 2010-12-13 10:38:20Z vboxsync $
2;; @file
3; VMM - World Switchers, template for AMD64 to PAE and 32-bit.
4;
5
6;
7; Copyright (C) 2006-2007 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;%define DEBUG_STUFF 1
19;%define STRICT_IF 1
20
21;*******************************************************************************
22;* Header Files *
23;*******************************************************************************
24%include "VBox/asmdefs.mac"
25%include "VBox/apic.mac"
26%include "VBox/x86.mac"
27%include "VBox/cpum.mac"
28%include "VBox/stam.mac"
29%include "VBox/vm.mac"
30%include "CPUMInternal.mac"
31%include "VMMSwitcher/VMMSwitcher.mac"
32
33
34;
35; Start the fixup records
36; We collect the fixups in the .data section as we go along
37; It is therefore VITAL that no-one is using the .data section
38; for anything else between 'Start' and 'End'.
39;
40BEGINDATA
41GLOBALNAME Fixups
42
43
44
45BEGINCODE
46GLOBALNAME Start
47
48%ifndef VBOX_WITH_HYBRID_32BIT_KERNEL
49BITS 64
50
51;;
52; The C interface.
53;
54; @param pVM GCC: rdi MSC:rcx The VM handle.
55;
56BEGINPROC vmmR0HostToGuest
57%ifdef DEBUG_STUFF
58 COM64_S_NEWLINE
59 COM64_S_CHAR '^'
60%endif
61 ;
62 ; The ordinary version of the code.
63 ;
64
65 %ifdef STRICT_IF
66 pushf
67 pop rax
68 test eax, X86_EFL_IF
69 jz .if_clear_in
70 mov eax, 0c0ffee00h
71 ret
72.if_clear_in:
73 %endif
74
75 ;
76 ; make r9 = pVM and rdx = pCpum.
77 ; rax, rcx and r8 are scratch here after.
78 %ifdef RT_OS_WINDOWS
79 mov r9, rcx
80 %else
81 mov r9, rdi
82 %endif
83 lea rdx, [r9 + VM.cpum]
84
85 %ifdef VBOX_WITH_STATISTICS
86 ;
87 ; Switcher stats.
88 ;
89 lea r8, [r9 + VM.StatSwitcherToGC]
90 STAM64_PROFILE_ADV_START r8
91 %endif
92
93 ;
94 ; Call worker (far return).
95 ;
96 mov eax, cs
97 push rax
98 call NAME(vmmR0HostToGuestAsm)
99
100 %ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
101 ; Unblock Local APIC NMI vectors
102 ; Do this here to ensure the host CS is already restored
103 mov ecx, [rdx + CPUM.fApicDisVectors]
104 mov r8, [rdx + CPUM.pvApicBase]
105 shr ecx, 1
106 jnc gth64_nolint0
107 and dword [r8 + APIC_REG_LVT_LINT0], ~APIC_REG_LVT_MASKED
108gth64_nolint0:
109 shr ecx, 1
110 jnc gth64_nolint1
111 and dword [r8 + APIC_REG_LVT_LINT1], ~APIC_REG_LVT_MASKED
112gth64_nolint1:
113 shr ecx, 1
114 jnc gth64_nopc
115 and dword [r8 + APIC_REG_LVT_PC], ~APIC_REG_LVT_MASKED
116gth64_nopc:
117 shr ecx, 1
118 jnc gth64_notherm
119 and dword [r8 + APIC_REG_LVT_THMR], ~APIC_REG_LVT_MASKED
120gth64_notherm:
121 %endif
122
123 %ifdef VBOX_WITH_STATISTICS
124 ;
125 ; Switcher stats.
126 ;
127 lea r8, [r9 + VM.StatSwitcherToGC]
128 STAM64_PROFILE_ADV_STOP r8
129 %endif
130
131 ret
132ENDPROC vmmR0HostToGuest
133
134
135%else ; VBOX_WITH_HYBRID_32BIT_KERNEL
136
137
138BITS 32
139
140;;
141; The C interface.
142;
143BEGINPROC vmmR0HostToGuest
144 %ifdef DEBUG_STUFF
145 COM32_S_NEWLINE
146 COM32_S_CHAR '^'
147 %endif
148
149 %ifdef VBOX_WITH_STATISTICS
150 ;
151 ; Switcher stats.
152 ;
153 FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToGC
154 mov edx, 0ffffffffh
155 STAM_PROFILE_ADV_START edx
156 %endif
157
158 ; Thunk to/from 64 bit when invoking the worker routine.
159 ;
160 FIXUP FIX_HC_VM_OFF, 1, VM.cpum
161 mov edx, 0ffffffffh
162
163 push 0
164 push cs
165 push 0
166 FIXUP FIX_HC_32BIT, 1, .vmmR0HostToGuestReturn - NAME(Start)
167 push 0ffffffffh
168
169 FIXUP FIX_HC_64BIT_CS, 1
170 push 0ffffh
171 FIXUP FIX_HC_32BIT, 1, NAME(vmmR0HostToGuestAsm) - NAME(Start)
172 push 0ffffffffh
173 retf
174.vmmR0HostToGuestReturn:
175
176 ;
177 ; This selector reloading is probably not necessary, but we do it anyway to be quite sure
178 ; the CPU has the right idea about the selectors.
179 ;
180 mov edx, ds
181 mov ds, edx
182 mov ecx, es
183 mov es, ecx
184 mov edx, ss
185 mov ss, edx
186
187 %ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
188 Missing implementation!
189 %endif
190
191
192 %ifdef VBOX_WITH_STATISTICS
193 ;
194 ; Switcher stats.
195 ;
196 FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToHC
197 mov edx, 0ffffffffh
198 STAM_PROFILE_ADV_STOP edx
199 %endif
200
201 ret
202ENDPROC vmmR0HostToGuest
203
204BITS 64
205%endif ;!VBOX_WITH_HYBRID_32BIT_KERNEL
206
207
208
209; *****************************************************************************
210; vmmR0HostToGuestAsm
211;
212; Phase one of the switch from host to guest context (host MMU context)
213;
214; INPUT:
215; - edx virtual address of CPUM structure (valid in host context)
216;
217; USES/DESTROYS:
218; - eax, ecx, edx, r8
219;
220; ASSUMPTION:
221; - current CS and DS selectors are wide open
222;
223; *****************************************************************************
224ALIGNCODE(16)
225BEGINPROC vmmR0HostToGuestAsm
226 ;; Store the offset from CPUM to CPUMCPU in r8
227 mov r8d, [rdx + CPUM.offCPUMCPU0]
228
229 ;;
230 ;; Save CPU host context
231 ;; Skip eax, edx and ecx as these are not preserved over calls.
232 ;;
233 ; general registers.
234 ; mov [rdx + r8 + CPUMCPU.Host.rax], rax - scratch
235 mov [rdx + r8 + CPUMCPU.Host.rbx], rbx
236 ; mov [rdx + r8 + CPUMCPU.Host.rcx], rcx - scratch
237 ; mov [rdx + r8 + CPUMCPU.Host.rdx], rdx - scratch
238 mov [rdx + r8 + CPUMCPU.Host.rdi], rdi
239 mov [rdx + r8 + CPUMCPU.Host.rsi], rsi
240 mov [rdx + r8 + CPUMCPU.Host.rsp], rsp
241 mov [rdx + r8 + CPUMCPU.Host.rbp], rbp
242 ; mov [rdx + r8 + CPUMCPU.Host.r8 ], r8 - scratch
243 ; mov [rdx + r8 + CPUMCPU.Host.r9 ], r9 - scratch
244 mov [rdx + r8 + CPUMCPU.Host.r10], r10
245 mov [rdx + r8 + CPUMCPU.Host.r11], r11
246 mov [rdx + r8 + CPUMCPU.Host.r12], r12
247 mov [rdx + r8 + CPUMCPU.Host.r13], r13
248 mov [rdx + r8 + CPUMCPU.Host.r14], r14
249 mov [rdx + r8 + CPUMCPU.Host.r15], r15
250 ; selectors.
251 mov [rdx + r8 + CPUMCPU.Host.ds], ds
252 mov [rdx + r8 + CPUMCPU.Host.es], es
253 mov [rdx + r8 + CPUMCPU.Host.fs], fs
254 mov [rdx + r8 + CPUMCPU.Host.gs], gs
255 mov [rdx + r8 + CPUMCPU.Host.ss], ss
256 ; MSRs
257 mov rbx, rdx
258 mov ecx, MSR_K8_FS_BASE
259 rdmsr
260 mov [rbx + r8 + CPUMCPU.Host.FSbase], eax
261 mov [rbx + r8 + CPUMCPU.Host.FSbase + 4], edx
262 mov ecx, MSR_K8_GS_BASE
263 rdmsr
264 mov [rbx + r8 + CPUMCPU.Host.GSbase], eax
265 mov [rbx + r8 + CPUMCPU.Host.GSbase + 4], edx
266 mov ecx, MSR_K6_EFER
267 rdmsr
268 mov [rbx + r8 + CPUMCPU.Host.efer], eax
269 mov [rbx + r8 + CPUMCPU.Host.efer + 4], edx
270 mov ecx, MSR_K6_EFER
271 mov rdx, rbx
272 ; special registers.
273 sldt [rdx + r8 + CPUMCPU.Host.ldtr]
274 sidt [rdx + r8 + CPUMCPU.Host.idtr]
275 sgdt [rdx + r8 + CPUMCPU.Host.gdtr]
276 str [rdx + r8 + CPUMCPU.Host.tr] ; yasm BUG, generates sldt. YASMCHECK!
277 ; flags
278 pushf
279 pop qword [rdx + r8 + CPUMCPU.Host.rflags]
280
281%ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
282 ; Block Local APIC NMI vectors
283 mov rbx, [rdx + CPUM.pvApicBase]
284 or rbx, rbx
285 jz htg_noapic
286 xor edi, edi
287 mov eax, [rbx + APIC_REG_LVT_LINT0]
288 mov ecx, eax
289 and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
290 cmp ecx, APIC_REG_LVT_MODE_NMI
291 jne htg_nolint0
292 or edi, 0x01
293 or eax, APIC_REG_LVT_MASKED
294 mov [rbx + APIC_REG_LVT_LINT0], eax
295 mov eax, [rbx + APIC_REG_LVT_LINT0] ; write completion
296htg_nolint0:
297 mov eax, [rbx + APIC_REG_LVT_LINT1]
298 mov ecx, eax
299 and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
300 cmp ecx, APIC_REG_LVT_MODE_NMI
301 jne htg_nolint1
302 or edi, 0x02
303 or eax, APIC_REG_LVT_MASKED
304 mov [rbx + APIC_REG_LVT_LINT1], eax
305 mov eax, [rbx + APIC_REG_LVT_LINT1] ; write completion
306htg_nolint1:
307 mov eax, [rbx + APIC_REG_LVT_PC]
308 mov ecx, eax
309 and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
310 cmp ecx, APIC_REG_LVT_MODE_NMI
311 jne htg_nopc
312 or edi, 0x04
313 or eax, APIC_REG_LVT_MASKED
314 mov [rbx + APIC_REG_LVT_PC], eax
315 mov eax, [rbx + APIC_REG_LVT_PC] ; write completion
316htg_nopc:
317 mov eax, [rbx + APIC_REG_VERSION]
318 shr eax, 16
319 cmp al, 5
320 jb htg_notherm
321 mov eax, [rbx + APIC_REG_LVT_THMR]
322 mov ecx, eax
323 and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
324 cmp ecx, APIC_REG_LVT_MODE_NMI
325 jne htg_notherm
326 or edi, 0x08
327 or eax, APIC_REG_LVT_MASKED
328 mov [rbx + APIC_REG_LVT_THMR], eax
329 mov eax, [rbx + APIC_REG_LVT_THMR] ; write completion
330htg_notherm:
331 mov [rdx + CPUM.fApicDisVectors], edi
332htg_noapic:
333%endif
334
335 FIXUP FIX_NO_SYSENTER_JMP, 0, htg_no_sysenter - NAME(Start) ; this will insert a jmp htg_no_sysenter if host doesn't use sysenter.
336 ; save MSR_IA32_SYSENTER_CS register.
337 mov rbx, rdx ; save edx
338 mov ecx, MSR_IA32_SYSENTER_CS
339 rdmsr ; edx:eax <- MSR[ecx]
340 mov [rbx + r8 + CPUMCPU.Host.SysEnter.cs], eax
341 mov [rbx + r8 + CPUMCPU.Host.SysEnter.cs + 4], edx
342 xor eax, eax ; load 0:0 to cause #GP upon sysenter
343 xor edx, edx
344 wrmsr
345 mov rdx, rbx ; restore edx
346 jmp short htg_no_sysenter
347
348ALIGNCODE(16)
349htg_no_sysenter:
350
351 ;; handle use flags.
352 mov esi, [rdx + r8 + CPUMCPU.fUseFlags] ; esi == use flags.
353 and esi, ~CPUM_USED_FPU ; Clear CPUM_USED_* flags. ;;@todo FPU check can be optimized to use cr0 flags!
354 mov [rdx + r8 + CPUMCPU.fUseFlags], esi
355
356 ; debug registers.
357 test esi, CPUM_USE_DEBUG_REGS | CPUM_USE_DEBUG_REGS_HOST
358 jz htg_debug_regs_no
359 jmp htg_debug_regs_save
360htg_debug_regs_no:
361 DEBUG_CHAR('a') ; trashes esi
362
363 ; control registers.
364 mov rax, cr0
365 mov [rdx + r8 + CPUMCPU.Host.cr0], rax
366 ;mov rax, cr2 ; assume host os don't stuff things in cr2. (safe)
367 ;mov [rdx + r8 + CPUMCPU.Host.cr2], rax
368 mov rax, cr3
369 mov [rdx + r8 + CPUMCPU.Host.cr3], rax
370 mov rax, cr4
371 mov [rdx + r8 + CPUMCPU.Host.cr4], rax
372
373 ;;
374 ;; Start switching to VMM context.
375 ;;
376
377 ;
378 ; Change CR0 and CR4 so we can correctly emulate FPU/MMX/SSE[23] exceptions
379 ; Also disable WP. (eax==cr4 now)
380 ; Note! X86_CR4_PSE and X86_CR4_PAE are important if the host thinks so :-)
381 ;
382 and rax, X86_CR4_MCE | X86_CR4_PSE | X86_CR4_PAE
383 mov ecx, [rdx + r8 + CPUMCPU.Guest.cr4]
384 DEBUG_CHAR('b') ; trashes esi
385 ;; @todo Switcher cleanup: Determine base CR4 during CPUMR0Init / VMMR3SelectSwitcher putting it
386 ; in CPUMCPU.Hyper.cr4 (which isn't currently being used). That should
387 ; simplify this operation a bit (and improve locality of the data).
388
389 ;
390 ; CR4.AndMask and CR4.OrMask are set in CPUMR3Init based on the presence of
391 ; FXSAVE support on the host CPU
392 ;
393 and ecx, [rdx + CPUM.CR4.AndMask]
394 or eax, ecx
395 or eax, [rdx + CPUM.CR4.OrMask]
396 mov cr4, rax
397 DEBUG_CHAR('c') ; trashes esi
398
399 mov eax, [rdx + r8 + CPUMCPU.Guest.cr0]
400 and eax, X86_CR0_EM
401 or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | X86_CR0_MP
402 mov cr0, rax
403 DEBUG_CHAR('0') ; trashes esi
404
405
406 ; Load new gdt so we can do far jump to guest code after cr3 reload.
407 lgdt [rdx + r8 + CPUMCPU.Hyper.gdtr]
408 DEBUG_CHAR('1') ; trashes esi
409
410 ; Store the hypervisor cr3 for later loading
411 mov ebp, [rdx + r8 + CPUMCPU.Hyper.cr3]
412
413 ;;
414 ;; Load Intermediate memory context.
415 ;;
416 FIXUP FIX_INTER_AMD64_CR3, 1
417 mov eax, 0ffffffffh
418 mov cr3, rax
419 DEBUG_CHAR('2') ; trashes esi
420
421 ;;
422 ;; 1. Switch to compatibility mode, placing ourselves in identity mapped code.
423 ;;
424 jmp far [NAME(fpIDEnterTarget) wrt rip]
425
426; 16:32 Pointer to IDEnterTarget.
427NAME(fpIDEnterTarget):
428 FIXUP FIX_ID_32BIT, 0, NAME(IDEnterTarget) - NAME(Start)
429dd 0
430 FIXUP FIX_HYPER_CS, 0
431dd 0
432
433
434;;
435; Detour for saving the host DR7 and DR6.
436; esi and rdx must be preserved.
437htg_debug_regs_save:
438DEBUG_S_CHAR('s');
439 mov rax, dr7 ; not sure, but if I read the docs right this will trap if GD is set. FIXME!!!
440 mov [rdx + r8 + CPUMCPU.Host.dr7], rax
441 xor eax, eax ; clear everything. (bit 12? is read as 1...)
442 mov dr7, rax
443 mov rax, dr6 ; just in case we save the state register too.
444 mov [rdx + r8 + CPUMCPU.Host.dr6], rax
445 ; save host DR0-3?
446 test esi, CPUM_USE_DEBUG_REGS
447 jz near htg_debug_regs_no
448DEBUG_S_CHAR('S');
449 mov rax, dr0
450 mov [rdx + r8 + CPUMCPU.Host.dr0], rax
451 mov rbx, dr1
452 mov [rdx + r8 + CPUMCPU.Host.dr1], rbx
453 mov rcx, dr2
454 mov [rdx + r8 + CPUMCPU.Host.dr2], rcx
455 mov rax, dr3
456 mov [rdx + r8 + CPUMCPU.Host.dr3], rax
457 jmp htg_debug_regs_no
458
459
460 ; We're now on an identity mapped pages! in 32-bit compatibility mode.
461BITS 32
462ALIGNCODE(16)
463GLOBALNAME IDEnterTarget
464 DEBUG_CHAR('3')
465
466 ; 2. Deactivate long mode by turning off paging.
467 mov ebx, cr0
468 and ebx, ~X86_CR0_PG
469 mov cr0, ebx
470 DEBUG_CHAR('4')
471
472 ; 3. Load intermediate page table.
473 FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
474 mov edx, 0ffffffffh
475 mov cr3, edx
476
477 ; 4. Disable long mode.
478 ; We also use the chance to disable syscall/sysret and fast fxsave/fxrstor.
479 mov ecx, MSR_K6_EFER
480 rdmsr
481 DEBUG_CHAR('5')
482 and eax, ~(MSR_K6_EFER_LME | MSR_K6_EFER_SCE | MSR_K6_EFER_FFXSR)
483 wrmsr
484 DEBUG_CHAR('6')
485
486%ifndef SWITCHER_TO_PAE
487 ; 4b. Disable PAE.
488 mov eax, cr4
489 and eax, ~X86_CR4_PAE
490 mov cr4, eax
491%else
492%endif
493
494 ; 5. Enable paging.
495 or ebx, X86_CR0_PG
496 mov cr0, ebx
497 jmp short just_a_jump
498just_a_jump:
499 DEBUG_CHAR('7')
500
501 ;;
502 ;; 6. Jump to guest code mapping of the code and load the Hypervisor CS.
503 ;;
504 FIXUP FIX_ID_2_GC_NEAR_REL, 1, NAME(JmpGCTarget) - NAME(Start)
505 jmp near NAME(JmpGCTarget)
506
507
508 ;;
509 ;; When we arrive at this label we're at the
510 ;; guest code mapping of the switching code.
511 ;;
512ALIGNCODE(16)
513GLOBALNAME JmpGCTarget
514 DEBUG_CHAR('-')
515;mov eax, 0ffff0000h
516;.delay_loop:
517;nop
518;dec eax
519;nop
520;jnz .delay_loop
521 ; load final cr3 and do far jump to load cs.
522 mov cr3, ebp ; ebp set above
523 DEBUG_CHAR('0')
524
525 ;;
526 ;; We're in VMM MMU context and VMM CS is loaded.
527 ;; Setup the rest of the VMM state.
528 ;;
529 ; Load selectors
530 DEBUG_CHAR('1')
531 FIXUP FIX_HYPER_DS, 1
532 mov eax, 0ffffh
533 mov ds, eax
534 mov es, eax
535 xor eax, eax
536 mov gs, eax
537 mov fs, eax
538 ; Load pCpum into EDX
539 FIXUP FIX_GC_CPUMCPU_OFF, 1, 0
540 mov edx, 0ffffffffh
541 ; Activate guest IDT
542 DEBUG_CHAR('2')
543 lidt [edx + CPUMCPU.Hyper.idtr]
544
545 ; Setup stack; use the lss_esp, ss pair for lss
546 DEBUG_CHAR('3')
547 mov eax, [edx + CPUMCPU.Hyper.esp]
548 mov [edx + CPUMCPU.Hyper.lss_esp], eax
549 lss esp, [edx + CPUMCPU.Hyper.lss_esp]
550
551 ; Restore TSS selector; must mark it as not busy before using ltr (!)
552 DEBUG_CHAR('4')
553 FIXUP FIX_GC_TSS_GDTE_DW2, 2
554 and dword [0ffffffffh], ~0200h ; clear busy flag (2nd type2 bit)
555 DEBUG_CHAR('5')
556 ltr word [edx + CPUMCPU.Hyper.tr]
557 DEBUG_CHAR('6')
558
559 ; Activate the ldt (now we can safely crash).
560 lldt [edx + CPUMCPU.Hyper.ldtr]
561 DEBUG_CHAR('7')
562
563 ;; use flags.
564 mov esi, [edx + CPUMCPU.fUseFlags]
565
566 ; debug registers
567 test esi, CPUM_USE_DEBUG_REGS
568 jz htg_debug_regs_guest_no
569 jmp htg_debug_regs_guest
570htg_debug_regs_guest_no:
571 DEBUG_CHAR('9')
572
573 ; General registers.
574 mov ebx, [edx + CPUMCPU.Hyper.ebx]
575 mov ebp, [edx + CPUMCPU.Hyper.ebp]
576 mov esi, [edx + CPUMCPU.Hyper.esi]
577 mov edi, [edx + CPUMCPU.Hyper.edi]
578 push dword [edx + CPUMCPU.Hyper.eflags]
579 popfd
580 DEBUG_CHAR('!')
581
582 ;;
583 ;; Return to the VMM code which either called the switcher or
584 ;; the code set up to run by HC.
585 ;;
586%ifdef DEBUG_STUFF
587 COM32_S_PRINT ';eip='
588 mov eax, [edx + CPUMCPU.Hyper.eip]
589 COM32_S_DWORD_REG eax
590 COM32_S_CHAR ';'
591%endif
592 mov eax, [edx + CPUMCPU.Hyper.eip]
593 ; callees expect CPUM ptr
594 CPUM_FROM_CPUMCPU(edx)
595
596%ifdef VBOX_WITH_STATISTICS
597 FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToGC
598 mov edx, 0ffffffffh
599 STAM32_PROFILE_ADV_STOP edx
600 FIXUP FIX_GC_CPUM_OFF, 1, 0
601 mov edx, 0ffffffffh
602%endif
603 jmp eax
604
605;;
606; Detour for saving host DR0-3 and loading hypervisor debug registers.
607; esi and edx must be preserved.
608htg_debug_regs_guest:
609 DEBUG_S_CHAR('D')
610 DEBUG_S_CHAR('R')
611 DEBUG_S_CHAR('x')
612 ; load hyper DR0-7
613 mov ebx, [edx + CPUMCPU.Hyper.dr]
614 mov dr0, ebx
615 mov ecx, [edx + CPUMCPU.Hyper.dr + 8*1]
616 mov dr1, ecx
617 mov eax, [edx + CPUMCPU.Hyper.dr + 8*2]
618 mov dr2, eax
619 mov ebx, [edx + CPUMCPU.Hyper.dr + 8*3]
620 mov dr3, ebx
621 ;mov eax, [edx + CPUMCPU.Hyper.dr + 8*6]
622 mov ecx, 0ffff0ff0h
623 mov dr6, ecx
624 mov eax, [edx + CPUMCPU.Hyper.dr + 8*7]
625 mov dr7, eax
626 jmp htg_debug_regs_guest_no
627
628ENDPROC vmmR0HostToGuestAsm
629
630
631;;
632; Trampoline for doing a call when starting the hyper visor execution.
633;
634; Push any arguments to the routine.
635; Push the argument frame size (cArg * 4).
636; Push the call target (_cdecl convention).
637; Push the address of this routine.
638;
639;
640ALIGNCODE(16)
641BEGINPROC vmmGCCallTrampoline
642%ifdef DEBUG_STUFF
643 COM32_S_CHAR 'c'
644 COM32_S_CHAR 't'
645 COM32_S_CHAR '!'
646%endif
647
648 ; call routine
649 pop eax ; call address
650 mov esi, edx ; save edx
651 pop edi ; argument count.
652%ifdef DEBUG_STUFF
653 COM32_S_PRINT ';eax='
654 COM32_S_DWORD_REG eax
655 COM32_S_CHAR ';'
656%endif
657 call eax ; do call
658 add esp, edi ; cleanup stack
659
660 ; return to the host context.
661 push byte 0 ; eip
662 mov edx, esi ; CPUM pointer
663
664%ifdef DEBUG_STUFF
665 COM32_S_CHAR '`'
666%endif
667 jmp NAME(VMMGCGuestToHostAsm) ; eax = returncode.
668ENDPROC vmmGCCallTrampoline
669
670
671
672;;
673; The C interface.
674;
675ALIGNCODE(16)
676BEGINPROC vmmGCGuestToHost
677%ifdef DEBUG_STUFF
678 push esi
679 COM_NEWLINE
680 DEBUG_CHAR('b')
681 DEBUG_CHAR('a')
682 DEBUG_CHAR('c')
683 DEBUG_CHAR('k')
684 DEBUG_CHAR('!')
685 COM_NEWLINE
686 pop esi
687%endif
688 mov eax, [esp + 4]
689 jmp NAME(VMMGCGuestToHostAsm)
690ENDPROC vmmGCGuestToHost
691
692
693;;
694; VMMGCGuestToHostAsmGuestCtx
695;
696; Switches from Guest Context to Host Context.
697; Of course it's only called from within the GC.
698;
699; @param eax Return code.
700; @param esp + 4 Pointer to CPUMCTXCORE.
701;
702; @remark ASSUMES interrupts disabled.
703;
704ALIGNCODE(16)
705BEGINPROC VMMGCGuestToHostAsmGuestCtx
706 DEBUG_CHAR('~')
707
708%ifdef VBOX_WITH_STATISTICS
709 FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
710 mov edx, 0ffffffffh
711 STAM32_PROFILE_ADV_STOP edx
712
713 FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
714 mov edx, 0ffffffffh
715 STAM32_PROFILE_ADV_START edx
716
717 FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
718 mov edx, 0ffffffffh
719 STAM32_PROFILE_ADV_START edx
720%endif
721
722 ;
723 ; Load the CPUMCPU pointer.
724 ;
725 FIXUP FIX_GC_CPUMCPU_OFF, 1, 0
726 mov edx, 0ffffffffh
727
728 ; Skip return address (assumes called!)
729 lea esp, [esp + 4]
730
731 ;
732 ; Guest Context (assumes esp now points to CPUMCTXCORE structure).
733 ;
734 ; general purpose registers
735 push eax ; save return code.
736 mov eax, [esp + 4 + CPUMCTXCORE.edi]
737 mov [edx + CPUMCPU.Guest.edi], eax
738 mov eax, [esp + 4 + CPUMCTXCORE.esi]
739 mov [edx + CPUMCPU.Guest.esi], eax
740 mov eax, [esp + 4 + CPUMCTXCORE.ebp]
741 mov [edx + CPUMCPU.Guest.ebp], eax
742 mov eax, [esp + 4 + CPUMCTXCORE.eax]
743 mov [edx + CPUMCPU.Guest.eax], eax
744 mov eax, [esp + 4 + CPUMCTXCORE.ebx]
745 mov [edx + CPUMCPU.Guest.ebx], eax
746 mov eax, [esp + 4 + CPUMCTXCORE.edx]
747 mov [edx + CPUMCPU.Guest.edx], eax
748 mov eax, [esp + 4 + CPUMCTXCORE.ecx]
749 mov [edx + CPUMCPU.Guest.ecx], eax
750 mov eax, [esp + 4 + CPUMCTXCORE.esp]
751 mov [edx + CPUMCPU.Guest.esp], eax
752 ; selectors
753 mov eax, [esp + 4 + CPUMCTXCORE.ss]
754 mov [edx + CPUMCPU.Guest.ss], eax
755 mov eax, [esp + 4 + CPUMCTXCORE.gs]
756 mov [edx + CPUMCPU.Guest.gs], eax
757 mov eax, [esp + 4 + CPUMCTXCORE.fs]
758 mov [edx + CPUMCPU.Guest.fs], eax
759 mov eax, [esp + 4 + CPUMCTXCORE.es]
760 mov [edx + CPUMCPU.Guest.es], eax
761 mov eax, [esp + 4 + CPUMCTXCORE.ds]
762 mov [edx + CPUMCPU.Guest.ds], eax
763 mov eax, [esp + 4 + CPUMCTXCORE.cs]
764 mov [edx + CPUMCPU.Guest.cs], eax
765 ; flags
766 mov eax, [esp + 4 + CPUMCTXCORE.eflags]
767 mov [edx + CPUMCPU.Guest.eflags], eax
768 ; eip
769 mov eax, [esp + 4 + CPUMCTXCORE.eip]
770 mov [edx + CPUMCPU.Guest.eip], eax
771 ; jump to common worker code.
772 pop eax ; restore return code.
773
774 add esp, CPUMCTXCORE_size ; skip CPUMCTXCORE structure
775
776 jmp vmmGCGuestToHostAsm_EIPDone
777ENDPROC VMMGCGuestToHostAsmGuestCtx
778
779
780;;
781; VMMGCGuestToHostAsmHyperCtx
782;
783; This is an alternative entry point which we'll be using
784; when the we have the hypervisor context and need to save
785; that before going to the host.
786;
787; This is typically useful when abandoning the hypervisor
788; because of a trap and want the trap state to be saved.
789;
790; @param eax Return code.
791; @param ecx Points to CPUMCTXCORE.
792; @uses eax,edx,ecx
793ALIGNCODE(16)
794BEGINPROC VMMGCGuestToHostAsmHyperCtx
795 DEBUG_CHAR('#')
796
797%ifdef VBOX_WITH_STATISTICS
798 FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
799 mov edx, 0ffffffffh
800 STAM32_PROFILE_ADV_STOP edx
801
802 FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
803 mov edx, 0ffffffffh
804 STAM32_PROFILE_ADV_START edx
805
806 FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
807 mov edx, 0ffffffffh
808 STAM32_PROFILE_ADV_START edx
809%endif
810
811 ;
812 ; Load the CPUM pointer.
813 ;
814 FIXUP FIX_GC_CPUMCPU_OFF, 1, 0
815 mov edx, 0ffffffffh
816
817 push eax ; save return code.
818 ; general purpose registers
819 mov eax, [ecx + CPUMCTXCORE.edi]
820 mov [edx + CPUMCPU.Hyper.edi], eax
821 mov eax, [ecx + CPUMCTXCORE.esi]
822 mov [edx + CPUMCPU.Hyper.esi], eax
823 mov eax, [ecx + CPUMCTXCORE.ebp]
824 mov [edx + CPUMCPU.Hyper.ebp], eax
825 mov eax, [ecx + CPUMCTXCORE.eax]
826 mov [edx + CPUMCPU.Hyper.eax], eax
827 mov eax, [ecx + CPUMCTXCORE.ebx]
828 mov [edx + CPUMCPU.Hyper.ebx], eax
829 mov eax, [ecx + CPUMCTXCORE.edx]
830 mov [edx + CPUMCPU.Hyper.edx], eax
831 mov eax, [ecx + CPUMCTXCORE.ecx]
832 mov [edx + CPUMCPU.Hyper.ecx], eax
833 mov eax, [ecx + CPUMCTXCORE.esp]
834 mov [edx + CPUMCPU.Hyper.esp], eax
835 ; selectors
836 mov eax, [ecx + CPUMCTXCORE.ss]
837 mov [edx + CPUMCPU.Hyper.ss], eax
838 mov eax, [ecx + CPUMCTXCORE.gs]
839 mov [edx + CPUMCPU.Hyper.gs], eax
840 mov eax, [ecx + CPUMCTXCORE.fs]
841 mov [edx + CPUMCPU.Hyper.fs], eax
842 mov eax, [ecx + CPUMCTXCORE.es]
843 mov [edx + CPUMCPU.Hyper.es], eax
844 mov eax, [ecx + CPUMCTXCORE.ds]
845 mov [edx + CPUMCPU.Hyper.ds], eax
846 mov eax, [ecx + CPUMCTXCORE.cs]
847 mov [edx + CPUMCPU.Hyper.cs], eax
848 ; flags
849 mov eax, [ecx + CPUMCTXCORE.eflags]
850 mov [edx + CPUMCPU.Hyper.eflags], eax
851 ; eip
852 mov eax, [ecx + CPUMCTXCORE.eip]
853 mov [edx + CPUMCPU.Hyper.eip], eax
854 ; jump to common worker code.
855 pop eax ; restore return code.
856 jmp vmmGCGuestToHostAsm_SkipHyperRegs
857
858ENDPROC VMMGCGuestToHostAsmHyperCtx
859
860
861;;
862; VMMGCGuestToHostAsm
863;
864; This is an alternative entry point which we'll be using
865; when the we have saved the guest state already or we haven't
866; been messing with the guest at all.
867;
868; @param eax Return code.
869; @uses eax, edx, ecx (or it may use them in the future)
870;
871ALIGNCODE(16)
872BEGINPROC VMMGCGuestToHostAsm
873 DEBUG_CHAR('%')
874
875%ifdef VBOX_WITH_STATISTICS
876 FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
877 mov edx, 0ffffffffh
878 STAM32_PROFILE_ADV_STOP edx
879
880 FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
881 mov edx, 0ffffffffh
882 STAM32_PROFILE_ADV_START edx
883
884 FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
885 mov edx, 0ffffffffh
886 STAM32_PROFILE_ADV_START edx
887%endif
888
889 ;
890 ; Load the CPUM pointer.
891 ;
892 FIXUP FIX_GC_CPUMCPU_OFF, 1, 0
893 mov edx, 0ffffffffh
894
895 pop dword [edx + CPUMCPU.Hyper.eip] ; call return from stack
896 jmp short vmmGCGuestToHostAsm_EIPDone
897
898ALIGNCODE(16)
899vmmGCGuestToHostAsm_EIPDone:
900 ; general registers which we care about.
901 mov dword [edx + CPUMCPU.Hyper.ebx], ebx
902 mov dword [edx + CPUMCPU.Hyper.esi], esi
903 mov dword [edx + CPUMCPU.Hyper.edi], edi
904 mov dword [edx + CPUMCPU.Hyper.ebp], ebp
905 mov dword [edx + CPUMCPU.Hyper.esp], esp
906
907 ; special registers which may change.
908vmmGCGuestToHostAsm_SkipHyperRegs:
909%ifdef STRICT_IF
910 pushf
911 pop ecx
912 test ecx, X86_EFL_IF
913 jz .if_clear_out
914 mov eax, 0c0ffee01h
915 cli
916.if_clear_out:
917%endif
918 ; str [edx + CPUMCPU.Hyper.tr] - double fault only, and it won't be right then either.
919 sldt [edx + CPUMCPU.Hyper.ldtr]
920
921 ; No need to save CRx here. They are set dynamically according to Guest/Host requirements.
922 ; FPU context is saved before restore of host saving (another) branch.
923
924
925 ;;
926 ;; Load Intermediate memory context.
927 ;;
928 mov edi, eax ; save return code in EDI (careful with COM_DWORD_REG from here on!)
929 FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
930 mov eax, 0ffffffffh
931 mov cr3, eax
932 DEBUG_CHAR('?')
933
934 ;; We're now in intermediate memory context!
935
936 ;;
937 ;; 0. Jump to identity mapped location
938 ;;
939 FIXUP FIX_GC_2_ID_NEAR_REL, 1, NAME(IDExitTarget) - NAME(Start)
940 jmp near NAME(IDExitTarget)
941
942 ; We're now on identity mapped pages!
943ALIGNCODE(16)
944GLOBALNAME IDExitTarget
945 DEBUG_CHAR('1')
946
947 ; 1. Disable paging.
948 mov ebx, cr0
949 and ebx, ~X86_CR0_PG
950 mov cr0, ebx
951 DEBUG_CHAR('2')
952
953 ; 2. Enable PAE.
954%ifdef SWITCHER_TO_PAE
955 ; - already enabled
956%else
957 mov ecx, cr4
958 or ecx, X86_CR4_PAE
959 mov cr4, ecx
960%endif
961
962 ; 3. Load long mode intermediate CR3.
963 FIXUP FIX_INTER_AMD64_CR3, 1
964 mov ecx, 0ffffffffh
965 mov cr3, ecx
966 DEBUG_CHAR('3')
967
968 ; 4. Enable long mode.
969 mov ebp, edx
970 mov ecx, MSR_K6_EFER
971 rdmsr
972 or eax, MSR_K6_EFER_LME
973 wrmsr
974 mov edx, ebp
975 DEBUG_CHAR('4')
976
977 ; 5. Enable paging.
978 or ebx, X86_CR0_PG
979 mov cr0, ebx
980 DEBUG_CHAR('5')
981
982 ; Jump from compatibility mode to 64-bit mode.
983 FIXUP FIX_ID_FAR32_TO_64BIT_MODE, 1, NAME(IDExit64Mode) - NAME(Start)
984 jmp 0ffffh:0fffffffeh
985
986 ;
987 ; We're in 64-bit mode (ds, ss, es, fs, gs are all bogus).
988 ; Move on to the HC mapping.
989 ;
990BITS 64
991ALIGNCODE(16)
992NAME(IDExit64Mode):
993 DEBUG_CHAR('6')
994 jmp [NAME(pHCExitTarget) wrt rip]
995
996; 64-bit jump target
997NAME(pHCExitTarget):
998FIXUP FIX_HC_64BIT, 0, NAME(HCExitTarget) - NAME(Start)
999dq 0ffffffffffffffffh
1000
1001; 64-bit pCpum address.
1002NAME(pCpumHC):
1003FIXUP FIX_HC_64BIT_CPUM, 0
1004dq 0ffffffffffffffffh
1005
1006 ;
1007 ; When we arrive here we're at the host context
1008 ; mapping of the switcher code.
1009 ;
1010ALIGNCODE(16)
1011GLOBALNAME HCExitTarget
1012 DEBUG_CHAR('9')
1013
1014 ; Clear high dword of the CPUMCPU pointer
1015 and rdx, 0ffffffffh
1016
1017 ; load final cr3
1018 mov rsi, [rdx + CPUMCPU.Host.cr3]
1019 mov cr3, rsi
1020 DEBUG_CHAR('@')
1021
1022 ;;
1023 ;; Restore Host context.
1024 ;;
1025 ; Load CPUM pointer into edx
1026 mov rdx, [NAME(pCpumHC) wrt rip]
1027 ; Load the CPUMCPU offset.
1028 mov r8d, [rdx + CPUM.offCPUMCPU0]
1029
1030 ; activate host gdt and idt
1031 lgdt [rdx + r8 + CPUMCPU.Host.gdtr]
1032 DEBUG_CHAR('0')
1033 lidt [rdx + r8 + CPUMCPU.Host.idtr]
1034 DEBUG_CHAR('1')
1035 ; Restore TSS selector; must mark it as not busy before using ltr (!)
1036%if 1 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
1037 movzx eax, word [rdx + r8 + CPUMCPU.Host.tr] ; eax <- TR
1038 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
1039 add rax, [rdx + r8 + CPUMCPU.Host.gdtr + 2] ; eax <- GDTR.address + descriptor offset.
1040 and dword [rax + 4], ~0200h ; clear busy flag (2nd type2 bit)
1041 ltr word [rdx + r8 + CPUMCPU.Host.tr]
1042%else
1043 movzx eax, word [rdx + r8 + CPUMCPU.Host.tr] ; eax <- TR
1044 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
1045 add rax, [rdx + r8 + CPUMCPU.Host.gdtr + 2] ; eax <- GDTR.address + descriptor offset.
1046 mov ecx, [rax + 4] ; ecx <- 2nd descriptor dword
1047 mov ebx, ecx ; save original value
1048 and ecx, ~0200h ; clear busy flag (2nd type2 bit)
1049 mov [rax + 4], ccx ; not using xchg here is paranoia..
1050 ltr word [rdx + r8 + CPUMCPU.Host.tr]
1051 xchg [rax + 4], ebx ; using xchg is paranoia too...
1052%endif
1053 ; activate ldt
1054 DEBUG_CHAR('2')
1055 lldt [rdx + r8 + CPUMCPU.Host.ldtr]
1056 ; Restore segment registers
1057 mov eax, [rdx + r8 + CPUMCPU.Host.ds]
1058 mov ds, eax
1059 mov eax, [rdx + r8 + CPUMCPU.Host.es]
1060 mov es, eax
1061 mov eax, [rdx + r8 + CPUMCPU.Host.fs]
1062 mov fs, eax
1063 mov eax, [rdx + r8 + CPUMCPU.Host.gs]
1064 mov gs, eax
1065 ; restore stack
1066 mov eax, [rdx + r8 + CPUMCPU.Host.ss]
1067 mov ss, eax
1068 mov rsp, [rdx + r8 + CPUMCPU.Host.rsp]
1069
1070 FIXUP FIX_NO_SYSENTER_JMP, 0, gth_sysenter_no - NAME(Start) ; this will insert a jmp gth_sysenter_no if host doesn't use sysenter.
1071 ; restore MSR_IA32_SYSENTER_CS register.
1072 mov rbx, rdx ; save edx
1073 mov ecx, MSR_IA32_SYSENTER_CS
1074 mov eax, [rbx + r8 + CPUMCPU.Host.SysEnter.cs]
1075 mov edx, [rbx + r8 + CPUMCPU.Host.SysEnter.cs + 4]
1076 wrmsr ; MSR[ecx] <- edx:eax
1077 mov rdx, rbx ; restore edx
1078 jmp short gth_sysenter_no
1079
1080ALIGNCODE(16)
1081gth_sysenter_no:
1082
1083 ;; @todo AMD syscall
1084
1085 ; Restore FPU if guest has used it.
1086 ; Using fxrstor should ensure that we're not causing unwanted exception on the host.
1087 mov esi, [rdx + r8 + CPUMCPU.fUseFlags] ; esi == use flags.
1088 test esi, CPUM_USED_FPU
1089 jz short gth_fpu_no
1090 mov rcx, cr0
1091 and rcx, ~(X86_CR0_TS | X86_CR0_EM)
1092 mov cr0, rcx
1093
1094 fxsave [rdx + r8 + CPUMCPU.Guest.fpu]
1095 fxrstor [rdx + r8 + CPUMCPU.Host.fpu]
1096 jmp short gth_fpu_no
1097
1098ALIGNCODE(16)
1099gth_fpu_no:
1100
1101 ; Control registers.
1102 ; Would've liked to have these higher up in case of crashes, but
1103 ; the fpu stuff must be done before we restore cr0.
1104 mov rcx, [rdx + r8 + CPUMCPU.Host.cr4]
1105 mov cr4, rcx
1106 mov rcx, [rdx + r8 + CPUMCPU.Host.cr0]
1107 mov cr0, rcx
1108 ;mov rcx, [rdx + r8 + CPUMCPU.Host.cr2] ; assumes this is waste of time.
1109 ;mov cr2, rcx
1110
1111 ; restore debug registers (if modified) (esi must still be fUseFlags!)
1112 ; (must be done after cr4 reload because of the debug extension.)
1113 test esi, CPUM_USE_DEBUG_REGS | CPUM_USE_DEBUG_REGS_HOST
1114 jz short gth_debug_regs_no
1115 jmp gth_debug_regs_restore
1116gth_debug_regs_no:
1117
1118 ; Restore MSRs
1119 mov rbx, rdx
1120 mov ecx, MSR_K8_FS_BASE
1121 mov eax, [rbx + r8 + CPUMCPU.Host.FSbase]
1122 mov edx, [rbx + r8 + CPUMCPU.Host.FSbase + 4]
1123 wrmsr
1124 mov ecx, MSR_K8_GS_BASE
1125 mov eax, [rbx + r8 + CPUMCPU.Host.GSbase]
1126 mov edx, [rbx + r8 + CPUMCPU.Host.GSbase + 4]
1127 wrmsr
1128 mov ecx, MSR_K6_EFER
1129 mov eax, [rbx + r8 + CPUMCPU.Host.efer]
1130 mov edx, [rbx + r8 + CPUMCPU.Host.efer + 4]
1131 wrmsr
1132 mov rdx, rbx
1133
1134 ; restore general registers.
1135 mov eax, edi ; restore return code. eax = return code !!
1136 ; mov rax, [rdx + r8 + CPUMCPU.Host.rax] - scratch + return code
1137 mov rbx, [rdx + r8 + CPUMCPU.Host.rbx]
1138 ; mov rcx, [rdx + r8 + CPUMCPU.Host.rcx] - scratch
1139 ; mov rdx, [rdx + r8 + CPUMCPU.Host.rdx] - scratch
1140 mov rdi, [rdx + r8 + CPUMCPU.Host.rdi]
1141 mov rsi, [rdx + r8 + CPUMCPU.Host.rsi]
1142 mov rsp, [rdx + r8 + CPUMCPU.Host.rsp]
1143 mov rbp, [rdx + r8 + CPUMCPU.Host.rbp]
1144 ; mov r8, [rdx + r8 + CPUMCPU.Host.r8 ] - scratch
1145 ; mov r9, [rdx + r8 + CPUMCPU.Host.r9 ] - scratch
1146 mov r10, [rdx + r8 + CPUMCPU.Host.r10]
1147 mov r11, [rdx + r8 + CPUMCPU.Host.r11]
1148 mov r12, [rdx + r8 + CPUMCPU.Host.r12]
1149 mov r13, [rdx + r8 + CPUMCPU.Host.r13]
1150 mov r14, [rdx + r8 + CPUMCPU.Host.r14]
1151 mov r15, [rdx + r8 + CPUMCPU.Host.r15]
1152
1153 ; finally restore flags. (probably not required)
1154 push qword [rdx + r8 + CPUMCPU.Host.rflags]
1155 popf
1156
1157
1158%ifdef DEBUG_STUFF
1159 COM64_S_CHAR '4'
1160%endif
1161 db 048h
1162 retf
1163
1164;;
1165; Detour for restoring the host debug registers.
1166; edx and edi must be preserved.
1167gth_debug_regs_restore:
1168 DEBUG_S_CHAR('d')
1169 xor eax, eax
1170 mov dr7, rax ; paranoia or not?
1171 test esi, CPUM_USE_DEBUG_REGS
1172 jz short gth_debug_regs_dr7
1173 DEBUG_S_CHAR('r')
1174 mov rax, [rdx + r8 + CPUMCPU.Host.dr0]
1175 mov dr0, rax
1176 mov rbx, [rdx + r8 + CPUMCPU.Host.dr1]
1177 mov dr1, rbx
1178 mov rcx, [rdx + r8 + CPUMCPU.Host.dr2]
1179 mov dr2, rcx
1180 mov rax, [rdx + r8 + CPUMCPU.Host.dr3]
1181 mov dr3, rax
1182gth_debug_regs_dr7:
1183 mov rbx, [rdx + r8 + CPUMCPU.Host.dr6]
1184 mov dr6, rbx
1185 mov rcx, [rdx + r8 + CPUMCPU.Host.dr7]
1186 mov dr7, rcx
1187 jmp gth_debug_regs_no
1188
1189ENDPROC VMMGCGuestToHostAsm
1190
1191
1192GLOBALNAME End
1193;
1194; The description string (in the text section).
1195;
1196NAME(Description):
1197 db SWITCHER_DESCRIPTION
1198 db 0
1199
1200extern NAME(Relocate)
1201
1202;
1203; End the fixup records.
1204;
1205BEGINDATA
1206 db FIX_THE_END ; final entry.
1207GLOBALNAME FixupsEnd
1208
1209;;
1210; The switcher definition structure.
1211ALIGNDATA(16)
1212GLOBALNAME Def
1213 istruc VMMSWITCHERDEF
1214 at VMMSWITCHERDEF.pvCode, RTCCPTR_DEF NAME(Start)
1215 at VMMSWITCHERDEF.pvFixups, RTCCPTR_DEF NAME(Fixups)
1216 at VMMSWITCHERDEF.pszDesc, RTCCPTR_DEF NAME(Description)
1217 at VMMSWITCHERDEF.pfnRelocate, RTCCPTR_DEF NAME(Relocate)
1218 at VMMSWITCHERDEF.enmType, dd SWITCHER_TYPE
1219 at VMMSWITCHERDEF.cbCode, dd NAME(End) - NAME(Start)
1220 at VMMSWITCHERDEF.offR0HostToGuest, dd NAME(vmmR0HostToGuest) - NAME(Start)
1221 at VMMSWITCHERDEF.offGCGuestToHost, dd NAME(vmmGCGuestToHost) - NAME(Start)
1222 at VMMSWITCHERDEF.offGCCallTrampoline, dd NAME(vmmGCCallTrampoline) - NAME(Start)
1223 at VMMSWITCHERDEF.offGCGuestToHostAsm, dd NAME(VMMGCGuestToHostAsm) - NAME(Start)
1224 at VMMSWITCHERDEF.offGCGuestToHostAsmHyperCtx, dd NAME(VMMGCGuestToHostAsmHyperCtx)- NAME(Start)
1225 at VMMSWITCHERDEF.offGCGuestToHostAsmGuestCtx, dd NAME(VMMGCGuestToHostAsmGuestCtx)- NAME(Start)
1226 ; disasm help
1227 at VMMSWITCHERDEF.offHCCode0, dd 0
1228 at VMMSWITCHERDEF.cbHCCode0, dd NAME(IDEnterTarget) - NAME(Start)
1229 at VMMSWITCHERDEF.offHCCode1, dd NAME(HCExitTarget) - NAME(Start)
1230 at VMMSWITCHERDEF.cbHCCode1, dd NAME(End) - NAME(HCExitTarget)
1231 at VMMSWITCHERDEF.offIDCode0, dd NAME(IDEnterTarget) - NAME(Start)
1232 at VMMSWITCHERDEF.cbIDCode0, dd NAME(JmpGCTarget) - NAME(IDEnterTarget)
1233 at VMMSWITCHERDEF.offIDCode1, dd NAME(IDExitTarget) - NAME(Start)
1234 at VMMSWITCHERDEF.cbIDCode1, dd NAME(HCExitTarget) - NAME(IDExitTarget)
1235 at VMMSWITCHERDEF.offGCCode, dd NAME(JmpGCTarget) - NAME(Start)
1236 at VMMSWITCHERDEF.cbGCCode, dd NAME(IDExitTarget) - NAME(JmpGCTarget)
1237
1238 iend
1239
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