VirtualBox

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

Last change on this file since 77807 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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