VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/HMR0Mixed.mac@ 52934

Last change on this file since 52934 was 50428, checked in by vboxsync, 11 years ago

HMR0Mixed.mac: Windows experiment with delaying host IDTR.LIMIT restore again.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 21.0 KB
Line 
1; $Id: HMR0Mixed.mac 50428 2014-02-12 15:17:55Z vboxsync $
2;; @file
3; HM - Ring-0 Host 32/64, Guest 32/64 world-switch routines
4;
5; Darwin uses this to build two versions in the hybrid case.
6; Included by HMR0A.asm with RT_ARCH_AMD64 defined or undefined.
7;
8
9;
10; Copyright (C) 2006-2013 Oracle Corporation
11;
12; This file is part of VirtualBox Open Source Edition (OSE), as
13; available from http://www.virtualbox.org. This file is free software;
14; you can redistribute it and/or modify it under the terms of the GNU
15; General Public License (GPL) as published by the Free Software
16; Foundation, in version 2 as it comes in the "COPYING" file of the
17; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19;
20
21
22;;
23; Keep these macro definitions in this file as it gets included and compiled
24; with RT_ARCH_AMD64 once and RT_ARCH_X86 once.
25%undef VMX_SKIP_GDTR
26%undef VMX_SKIP_IDTR
27%undef VMX_SKIP_TR
28
29%ifdef RT_ARCH_AMD64
30 %define VMX_SKIP_GDTR
31 %ifdef RT_OS_DARWIN
32 ; Darwin (Mavericks) uses IDTR limit to store the CPU Id so we need to restore it always.
33 ; See @bugref{6875}.
34 %else
35 %define VMX_SKIP_IDTR
36 %endif
37 %define VMX_SKIP_TR
38%endif
39
40;; @def RESTORE_STATE_VM32
41; Macro restoring essential host state and updating guest state
42; for common host, 32-bit guest for VT-x.
43%macro RESTORE_STATE_VM32 0
44 ; Restore base and limit of the IDTR & GDTR.
45 %ifndef VMX_SKIP_IDTR
46 lidt [xSP]
47 add xSP, xCB * 2
48 %endif
49 %ifndef VMX_SKIP_GDTR
50 lgdt [xSP]
51 add xSP, xCB * 2
52 %endif
53
54 push xDI
55 %ifndef VMX_SKIP_TR
56 mov xDI, [xSP + xCB * 3] ; pCtx (*3 to skip the saved xDI, TR, LDTR).
57 %else
58 mov xDI, [xSP + xCB * 2] ; pCtx (*2 to skip the saved xDI, LDTR).
59 %endif
60
61 mov [ss:xDI + CPUMCTX.eax], eax
62 mov [ss:xDI + CPUMCTX.ebx], ebx
63 mov [ss:xDI + CPUMCTX.ecx], ecx
64 mov [ss:xDI + CPUMCTX.edx], edx
65 mov [ss:xDI + CPUMCTX.esi], esi
66 mov [ss:xDI + CPUMCTX.ebp], ebp
67 mov xAX, cr2
68 mov [ss:xDI + CPUMCTX.cr2], xAX
69
70 %ifdef RT_ARCH_AMD64
71 pop xAX ; The guest edi we pushed above.
72 mov dword [ss:xDI + CPUMCTX.edi], eax
73 %else
74 pop dword [ss:xDI + CPUMCTX.edi] ; The guest edi we pushed above.
75 %endif
76
77 %ifndef VMX_SKIP_TR
78 ; Restore TSS selector; must mark it as not busy before using ltr (!)
79 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
80 ; @todo get rid of sgdt
81 pop xBX ; Saved TR
82 sub xSP, xCB * 2
83 sgdt [xSP]
84 mov xAX, xBX
85 and eax, X86_SEL_MASK_OFF_RPL ; Mask away TI and RPL bits leaving only the descriptor offset.
86 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
87 and dword [ss:xAX + 4], ~RT_BIT(9) ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
88 ltr bx
89 add xSP, xCB * 2
90 %endif
91
92 pop xAX ; Saved LDTR
93 %ifdef RT_ARCH_AMD64
94 cmp eax, 0
95 je %%skip_ldt_write32
96 %endif
97 lldt ax
98
99%%skip_ldt_write32:
100 add xSP, xCB ; pCtx
101
102 %ifdef VMX_USE_CACHED_VMCS_ACCESSES
103 pop xDX ; Saved pCache
104
105 ; Note! If we get here as a result of invalid VMCS pointer, all the following
106 ; vmread's will fail (only eflags.cf=1 will be set) but that shouldn't cause any
107 ; trouble only just less efficient.
108 mov ecx, [ss:xDX + VMCSCACHE.Read.cValidEntries]
109 cmp ecx, 0 ; Can't happen
110 je %%no_cached_read32
111 jmp %%cached_read32
112
113ALIGN(16)
114%%cached_read32:
115 dec xCX
116 mov eax, [ss:xDX + VMCSCACHE.Read.aField + xCX * 4]
117 vmread [ss:xDX + VMCSCACHE.Read.aFieldVal + xCX * 8], xAX
118 cmp xCX, 0
119 jnz %%cached_read32
120%%no_cached_read32:
121 %endif
122
123 ; Restore segment registers.
124 MYPOPSEGS xAX, ax
125
126 ; Restore general purpose registers.
127 MYPOPAD
128%endmacro
129
130
131;/**
132; * Prepares for and executes VMLAUNCH/VMRESUME (32 bits guest mode)
133; *
134; * @returns VBox status code
135; * @param fResume x86:[ebp+8], msc:rcx,gcc:rdi Whether to use vmlauch/vmresume.
136; * @param pCtx x86:[ebp+c], msc:rdx,gcc:rsi Pointer to the guest-CPU context.
137; * @param pCache x86:[esp+10],msc:r8, gcc:rdx Pointer to the VMCS cache.
138; */
139ALIGNCODE(16)
140BEGINPROC MY_NAME(VMXR0StartVM32)
141 push xBP
142 mov xBP, xSP
143
144 pushf
145 cli
146
147 ; Save all general purpose host registers.
148 MYPUSHAD
149
150 ; First we have to save some final CPU context registers.
151 mov eax, VMX_VMCS_HOST_RIP
152%ifdef RT_ARCH_AMD64
153 lea r10, [.vmlaunch_done wrt rip]
154 vmwrite rax, r10
155%else
156 mov ecx, .vmlaunch_done
157 vmwrite eax, ecx
158%endif
159 ; Note: assumes success!
160
161 ; Save guest-CPU context pointer.
162%ifdef RT_ARCH_AMD64
163 %ifdef ASM_CALL64_GCC
164 ; fResume already in rdi
165 ; pCtx already in rsi
166 mov rbx, rdx ; pCache
167 %else
168 mov rdi, rcx ; fResume
169 mov rsi, rdx ; pCtx
170 mov rbx, r8 ; pCache
171 %endif
172%else
173 mov edi, [ebp + 8] ; fResume
174 mov esi, [ebp + 12] ; pCtx
175 mov ebx, [ebp + 16] ; pCache
176%endif
177
178 ; Save segment registers.
179 ; Note: MYPUSHSEGS trashes rdx & rcx, so we moved it here (msvc amd64 case).
180 MYPUSHSEGS xAX, ax
181
182%ifdef VMX_USE_CACHED_VMCS_ACCESSES
183 mov ecx, [xBX + VMCSCACHE.Write.cValidEntries]
184 cmp ecx, 0
185 je .no_cached_writes
186 mov edx, ecx
187 mov ecx, 0
188 jmp .cached_write
189
190ALIGN(16)
191.cached_write:
192 mov eax, [xBX + VMCSCACHE.Write.aField + xCX * 4]
193 vmwrite xAX, [xBX + VMCSCACHE.Write.aFieldVal + xCX * 8]
194 inc xCX
195 cmp xCX, xDX
196 jl .cached_write
197
198 mov dword [xBX + VMCSCACHE.Write.cValidEntries], 0
199.no_cached_writes:
200
201 ; Save the pCache pointer.
202 push xBX
203%endif
204
205 ; Save the pCtx pointer.
206 push xSI
207
208 ; Save host LDTR.
209 xor eax, eax
210 sldt ax
211 push xAX
212
213%ifndef VMX_SKIP_TR
214 ; The host TR limit is reset to 0x67; save & restore it manually.
215 str eax
216 push xAX
217%endif
218
219%ifndef VMX_SKIP_GDTR
220 ; VT-x only saves the base of the GDTR & IDTR and resets the limit to 0xffff; we must restore the limit correctly!
221 sub xSP, xCB * 2
222 sgdt [xSP]
223%endif
224%ifndef VMX_SKIP_IDTR
225 sub xSP, xCB * 2
226 sidt [xSP]
227%endif
228
229 ; Load CR2 if necessary (may be expensive as writing CR2 is a synchronizing instruction).
230 mov xBX, [xSI + CPUMCTX.cr2]
231 mov xDX, cr2
232 cmp xBX, xDX
233 je .skip_cr2_write32
234 mov cr2, xBX
235
236.skip_cr2_write32:
237 mov eax, VMX_VMCS_HOST_RSP
238 vmwrite xAX, xSP
239 ; Note: assumes success!
240 ; Don't mess with ESP anymore!!!
241
242 ; Load guest general purpose registers.
243 mov eax, [xSI + CPUMCTX.eax]
244 mov ebx, [xSI + CPUMCTX.ebx]
245 mov ecx, [xSI + CPUMCTX.ecx]
246 mov edx, [xSI + CPUMCTX.edx]
247 mov ebp, [xSI + CPUMCTX.ebp]
248
249 ; Resume or start VM?
250 cmp xDI, 0 ; fResume
251 je .vmlaunch_launch
252
253 ; Load guest edi & esi.
254 mov edi, [xSI + CPUMCTX.edi]
255 mov esi, [xSI + CPUMCTX.esi]
256
257 vmresume
258 jmp .vmlaunch_done; ; Here if vmresume detected a failure.
259
260.vmlaunch_launch:
261 ; Save guest edi & esi.
262 mov edi, [xSI + CPUMCTX.edi]
263 mov esi, [xSI + CPUMCTX.esi]
264
265 vmlaunch
266 jmp .vmlaunch_done; ; Here if vmlaunch detected a failure.
267
268ALIGNCODE(16) ;; @todo YASM BUG - this alignment is wrong on darwin, it's 1 byte off.
269.vmlaunch_done:
270 jc near .vmxstart_invalid_vmcs_ptr
271 jz near .vmxstart_start_failed
272
273 RESTORE_STATE_VM32
274 mov eax, VINF_SUCCESS
275
276.vmstart_end:
277 popf
278 pop xBP
279 ret
280
281.vmxstart_invalid_vmcs_ptr:
282 RESTORE_STATE_VM32
283 mov eax, VERR_VMX_INVALID_VMCS_PTR_TO_START_VM
284 jmp .vmstart_end
285
286.vmxstart_start_failed:
287 RESTORE_STATE_VM32
288 mov eax, VERR_VMX_UNABLE_TO_START_VM
289 jmp .vmstart_end
290
291ENDPROC MY_NAME(VMXR0StartVM32)
292
293
294%ifdef RT_ARCH_AMD64
295;; @def RESTORE_STATE_VM64
296; Macro restoring essential host state and updating guest state
297; for 64-bit host, 64-bit guest for VT-x.
298;
299%macro RESTORE_STATE_VM64 0
300 ; Restore base and limit of the IDTR & GDTR
301 %ifndef VMX_SKIP_IDTR
302 lidt [xSP]
303 add xSP, xCB * 2
304 %endif
305 %ifndef VMX_SKIP_GDTR
306 lgdt [xSP]
307 add xSP, xCB * 2
308 %endif
309
310 push xDI
311 %ifndef VMX_SKIP_TR
312 mov xDI, [xSP + xCB * 3] ; pCtx (*3 to skip the saved xDI, TR, LDTR)
313 %else
314 mov xDI, [xSP + xCB * 2] ; pCtx (*2 to skip the saved xDI, LDTR)
315 %endif
316
317 mov qword [xDI + CPUMCTX.eax], rax
318 mov qword [xDI + CPUMCTX.ebx], rbx
319 mov qword [xDI + CPUMCTX.ecx], rcx
320 mov qword [xDI + CPUMCTX.edx], rdx
321 mov qword [xDI + CPUMCTX.esi], rsi
322 mov qword [xDI + CPUMCTX.ebp], rbp
323 mov qword [xDI + CPUMCTX.r8], r8
324 mov qword [xDI + CPUMCTX.r9], r9
325 mov qword [xDI + CPUMCTX.r10], r10
326 mov qword [xDI + CPUMCTX.r11], r11
327 mov qword [xDI + CPUMCTX.r12], r12
328 mov qword [xDI + CPUMCTX.r13], r13
329 mov qword [xDI + CPUMCTX.r14], r14
330 mov qword [xDI + CPUMCTX.r15], r15
331 mov rax, cr2
332 mov qword [xDI + CPUMCTX.cr2], rax
333
334 pop xAX ; The guest rdi we pushed above
335 mov qword [xDI + CPUMCTX.edi], rax
336
337 %ifndef VMX_SKIP_TR
338 ; Restore TSS selector; must mark it as not busy before using ltr (!)
339 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p).
340 ; @todo get rid of sgdt
341 pop xBX ; Saved TR
342 sub xSP, xCB * 2
343 sgdt [xSP]
344 mov xAX, xBX
345 and eax, X86_SEL_MASK_OFF_RPL ; Mask away TI and RPL bits leaving only the descriptor offset.
346 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
347 and dword [xAX + 4], ~RT_BIT(9) ; Clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit).
348 ltr bx
349 add xSP, xCB * 2
350 %endif
351
352 pop xAX ; Saved LDTR
353 cmp eax, 0
354 je %%skip_ldt_write64
355 lldt ax
356
357%%skip_ldt_write64:
358 pop xSI ; pCtx (needed in rsi by the macros below)
359
360 %ifdef VMX_USE_CACHED_VMCS_ACCESSES
361 pop xDX ; Saved pCache
362
363 ; Note! If we get here as a result of invalid VMCS pointer, all the following
364 ; vmread's will fail (only eflags.cf=1 will be set) but that shouldn't cause any
365 ; trouble only just less efficient.
366 mov ecx, [xDX + VMCSCACHE.Read.cValidEntries]
367 cmp ecx, 0 ; Can't happen
368 je %%no_cached_read64
369 jmp %%cached_read64
370
371ALIGN(16)
372%%cached_read64:
373 dec xCX
374 mov eax, [xDX + VMCSCACHE.Read.aField + xCX * 4]
375 vmread [xDX + VMCSCACHE.Read.aFieldVal + xCX * 8], xAX
376 cmp xCX, 0
377 jnz %%cached_read64
378%%no_cached_read64:
379 %endif
380
381 ; Restore segment registers.
382 MYPOPSEGS xAX, ax
383
384 ; Restore general purpose registers.
385 MYPOPAD
386%endmacro
387
388
389;/**
390; * Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
391; *
392; * @returns VBox status code
393; * @param fResume msc:rcx, gcc:rdi Whether to use vmlauch/vmresume.
394; * @param pCtx msc:rdx, gcc:rsi Pointer to the guest-CPU context.
395; * @param pCache msc:r8, gcc:rdx Pointer to the VMCS cache.
396; */
397ALIGNCODE(16)
398BEGINPROC MY_NAME(VMXR0StartVM64)
399 push xBP
400 mov xBP, xSP
401
402 pushf
403 cli
404
405 ; Save all general purpose host registers.
406 MYPUSHAD
407
408 ; First we have to save some final CPU context registers.
409 lea r10, [.vmlaunch64_done wrt rip]
410 mov rax, VMX_VMCS_HOST_RIP ; Return address (too difficult to continue after VMLAUNCH?).
411 vmwrite rax, r10
412 ; Note: assumes success!
413
414 ; Save guest-CPU context pointer.
415%ifdef ASM_CALL64_GCC
416 ; fResume already in rdi
417 ; pCtx already in rsi
418 mov rbx, rdx ; pCache
419%else
420 mov rdi, rcx ; fResume
421 mov rsi, rdx ; pCtx
422 mov rbx, r8 ; pCache
423%endif
424
425 ; Save segment registers.
426 ; Note: MYPUSHSEGS trashes rdx & rcx, so we moved it here (msvc amd64 case).
427 MYPUSHSEGS xAX, ax
428
429%ifdef VMX_USE_CACHED_VMCS_ACCESSES
430 mov ecx, [xBX + VMCSCACHE.Write.cValidEntries]
431 cmp ecx, 0
432 je .no_cached_writes
433 mov edx, ecx
434 mov ecx, 0
435 jmp .cached_write
436
437ALIGN(16)
438.cached_write:
439 mov eax, [xBX + VMCSCACHE.Write.aField + xCX * 4]
440 vmwrite xAX, [xBX + VMCSCACHE.Write.aFieldVal + xCX * 8]
441 inc xCX
442 cmp xCX, xDX
443 jl .cached_write
444
445 mov dword [xBX + VMCSCACHE.Write.cValidEntries], 0
446.no_cached_writes:
447
448 ; Save the pCache pointer.
449 push xBX
450%endif
451
452 ; Save the pCtx pointer.
453 push xSI
454
455 ; Save host LDTR.
456 xor eax, eax
457 sldt ax
458 push xAX
459
460%ifndef VMX_SKIP_TR
461 ; The host TR limit is reset to 0x67; save & restore it manually.
462 str eax
463 push xAX
464%endif
465
466%ifndef VMX_SKIP_GDTR
467 ; VT-x only saves the base of the GDTR & IDTR and resets the limit to 0xffff; we must restore the limit correctly!
468 sub xSP, xCB * 2
469 sgdt [xSP]
470%endif
471%ifndef VMX_SKIP_IDTR
472 sub xSP, xCB * 2
473 sidt [xSP]
474%endif
475
476 ; Load CR2 if necessary (may be expensive as writing CR2 is a synchronizing instruction).
477 mov rbx, qword [xSI + CPUMCTX.cr2]
478 mov rdx, cr2
479 cmp rbx, rdx
480 je .skip_cr2_write
481 mov cr2, rbx
482
483.skip_cr2_write:
484 mov eax, VMX_VMCS_HOST_RSP
485 vmwrite xAX, xSP
486 ; Note: assumes success!
487 ; Don't mess with ESP anymore!!!
488
489 ; Load guest general purpose registers.
490 mov rax, qword [xSI + CPUMCTX.eax]
491 mov rbx, qword [xSI + CPUMCTX.ebx]
492 mov rcx, qword [xSI + CPUMCTX.ecx]
493 mov rdx, qword [xSI + CPUMCTX.edx]
494 mov rbp, qword [xSI + CPUMCTX.ebp]
495 mov r8, qword [xSI + CPUMCTX.r8]
496 mov r9, qword [xSI + CPUMCTX.r9]
497 mov r10, qword [xSI + CPUMCTX.r10]
498 mov r11, qword [xSI + CPUMCTX.r11]
499 mov r12, qword [xSI + CPUMCTX.r12]
500 mov r13, qword [xSI + CPUMCTX.r13]
501 mov r14, qword [xSI + CPUMCTX.r14]
502 mov r15, qword [xSI + CPUMCTX.r15]
503
504 ; Resume or start VM?
505 cmp xDI, 0 ; fResume
506 je .vmlaunch64_launch
507
508 ; Load guest rdi & rsi.
509 mov rdi, qword [xSI + CPUMCTX.edi]
510 mov rsi, qword [xSI + CPUMCTX.esi]
511
512 vmresume
513 jmp .vmlaunch64_done; ; Here if vmresume detected a failure.
514
515.vmlaunch64_launch:
516 ; Save guest rdi & rsi.
517 mov rdi, qword [xSI + CPUMCTX.edi]
518 mov rsi, qword [xSI + CPUMCTX.esi]
519
520 vmlaunch
521 jmp .vmlaunch64_done; ; Here if vmlaunch detected a failure.
522
523ALIGNCODE(16)
524.vmlaunch64_done:
525 jc near .vmxstart64_invalid_vmcs_ptr
526 jz near .vmxstart64_start_failed
527
528 RESTORE_STATE_VM64
529 mov eax, VINF_SUCCESS
530
531.vmstart64_end:
532 popf
533 pop xBP
534 ret
535
536.vmxstart64_invalid_vmcs_ptr:
537 RESTORE_STATE_VM64
538 mov eax, VERR_VMX_INVALID_VMCS_PTR_TO_START_VM
539 jmp .vmstart64_end
540
541.vmxstart64_start_failed:
542 RESTORE_STATE_VM64
543 mov eax, VERR_VMX_UNABLE_TO_START_VM
544 jmp .vmstart64_end
545ENDPROC MY_NAME(VMXR0StartVM64)
546%endif ; RT_ARCH_AMD64
547
548
549;/**
550; * Prepares for and executes VMRUN (32 bits guests)
551; *
552; * @returns VBox status code
553; * @param HCPhysVMCB Physical address of host VMCB.
554; * @param HCPhysVMCB Physical address of guest VMCB.
555; * @param pCtx Pointer to the guest CPU-context.
556; */
557ALIGNCODE(16)
558BEGINPROC MY_NAME(SVMR0VMRun)
559%ifdef RT_ARCH_AMD64 ; fake a cdecl stack frame
560 %ifdef ASM_CALL64_GCC
561 push rdx
562 push rsi
563 push rdi
564 %else
565 push r8
566 push rdx
567 push rcx
568 %endif
569 push 0
570%endif
571 push xBP
572 mov xBP, xSP
573 pushf
574
575 ; Save all general purpose host registers.
576 MYPUSHAD
577
578 ; Save guest CPU-context pointer.
579 mov xSI, [xBP + xCB * 2 + RTHCPHYS_CB * 2] ; pCtx
580 push xSI ; push for saving the state at the end
581
582 ; Save host fs, gs, sysenter msr etc.
583 mov xAX, [xBP + xCB * 2] ; pVMCBHostPhys (64 bits physical address; x86: take low dword only)
584 push xAX ; save for the vmload after vmrun
585 vmsave
586
587 ; Setup eax for VMLOAD.
588 mov xAX, [xBP + xCB * 2 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address; take low dword only)
589
590 ; Load guest general purpose registers.
591 ; eax is loaded from the VMCB by VMRUN.
592 mov ebx, [xSI + CPUMCTX.ebx]
593 mov ecx, [xSI + CPUMCTX.ecx]
594 mov edx, [xSI + CPUMCTX.edx]
595 mov edi, [xSI + CPUMCTX.edi]
596 mov ebp, [xSI + CPUMCTX.ebp]
597 mov esi, [xSI + CPUMCTX.esi]
598
599 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch.
600 clgi
601 sti
602
603 ; Load guest fs, gs, sysenter msr etc.
604 vmload
605 ; Run the VM.
606 vmrun
607
608 ; eax is in the VMCB already; we can use it here.
609
610 ; Save guest fs, gs, sysenter msr etc.
611 vmsave
612
613 ; Load host fs, gs, sysenter msr etc.
614 pop xAX ; Pushed above
615 vmload
616
617 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
618 cli
619 stgi
620
621 pop xAX ; pCtx
622
623 mov [ss:xAX + CPUMCTX.ebx], ebx
624 mov [ss:xAX + CPUMCTX.ecx], ecx
625 mov [ss:xAX + CPUMCTX.edx], edx
626 mov [ss:xAX + CPUMCTX.esi], esi
627 mov [ss:xAX + CPUMCTX.edi], edi
628 mov [ss:xAX + CPUMCTX.ebp], ebp
629
630 ; Restore host general purpose registers.
631 MYPOPAD
632
633 mov eax, VINF_SUCCESS
634
635 popf
636 pop xBP
637%ifdef RT_ARCH_AMD64
638 add xSP, 4*xCB
639%endif
640 ret
641ENDPROC MY_NAME(SVMR0VMRun)
642
643%ifdef RT_ARCH_AMD64
644;/**
645; * Prepares for and executes VMRUN (64 bits guests)
646; *
647; * @returns VBox status code
648; * @param HCPhysVMCB Physical address of host VMCB.
649; * @param HCPhysVMCB Physical address of guest VMCB.
650; * @param pCtx Pointer to the guest-CPU context.
651; */
652ALIGNCODE(16)
653BEGINPROC MY_NAME(SVMR0VMRun64)
654 ; Fake a cdecl stack frame
655 %ifdef ASM_CALL64_GCC
656 push rdx
657 push rsi
658 push rdi
659 %else
660 push r8
661 push rdx
662 push rcx
663 %endif
664 push 0
665 push rbp
666 mov rbp, rsp
667 pushf
668
669 ; Manual save and restore:
670 ; - General purpose registers except RIP, RSP, RAX
671 ;
672 ; Trashed:
673 ; - CR2 (we don't care)
674 ; - LDTR (reset to 0)
675 ; - DRx (presumably not changed at all)
676 ; - DR7 (reset to 0x400)
677 ;
678
679 ; Save all general purpose host registers.
680 MYPUSHAD
681
682 ; Save guest CPU-context pointer.
683 mov rsi, [rbp + xCB * 2 + RTHCPHYS_CB * 2] ; pCtx
684 push rsi ; push for saving the state at the end
685
686 ; Save host fs, gs, sysenter msr etc.
687 mov rax, [rbp + xCB * 2] ; pVMCBHostPhys (64 bits physical address; x86: take low dword only)
688 push rax ; Save for the vmload after vmrun
689 vmsave
690
691 ; Setup eax for VMLOAD.
692 mov rax, [rbp + xCB * 2 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address; take low dword only)
693
694 ; Load guest general purpose registers.
695 ; rax is loaded from the VMCB by VMRUN.
696 mov rbx, qword [xSI + CPUMCTX.ebx]
697 mov rcx, qword [xSI + CPUMCTX.ecx]
698 mov rdx, qword [xSI + CPUMCTX.edx]
699 mov rdi, qword [xSI + CPUMCTX.edi]
700 mov rbp, qword [xSI + CPUMCTX.ebp]
701 mov r8, qword [xSI + CPUMCTX.r8]
702 mov r9, qword [xSI + CPUMCTX.r9]
703 mov r10, qword [xSI + CPUMCTX.r10]
704 mov r11, qword [xSI + CPUMCTX.r11]
705 mov r12, qword [xSI + CPUMCTX.r12]
706 mov r13, qword [xSI + CPUMCTX.r13]
707 mov r14, qword [xSI + CPUMCTX.r14]
708 mov r15, qword [xSI + CPUMCTX.r15]
709 mov rsi, qword [xSI + CPUMCTX.esi]
710
711 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch.
712 clgi
713 sti
714
715 ; Load guest fs, gs, sysenter msr etc.
716 vmload
717 ; Run the VM.
718 vmrun
719
720 ; rax is in the VMCB already; we can use it here.
721
722 ; Save guest fs, gs, sysenter msr etc.
723 vmsave
724
725 ; Load host fs, gs, sysenter msr etc.
726 pop rax ; pushed above
727 vmload
728
729 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
730 cli
731 stgi
732
733 pop rax ; pCtx
734
735 mov qword [rax + CPUMCTX.ebx], rbx
736 mov qword [rax + CPUMCTX.ecx], rcx
737 mov qword [rax + CPUMCTX.edx], rdx
738 mov qword [rax + CPUMCTX.esi], rsi
739 mov qword [rax + CPUMCTX.edi], rdi
740 mov qword [rax + CPUMCTX.ebp], rbp
741 mov qword [rax + CPUMCTX.r8], r8
742 mov qword [rax + CPUMCTX.r9], r9
743 mov qword [rax + CPUMCTX.r10], r10
744 mov qword [rax + CPUMCTX.r11], r11
745 mov qword [rax + CPUMCTX.r12], r12
746 mov qword [rax + CPUMCTX.r13], r13
747 mov qword [rax + CPUMCTX.r14], r14
748 mov qword [rax + CPUMCTX.r15], r15
749
750 ; Restore host general purpose registers.
751 MYPOPAD
752
753 mov eax, VINF_SUCCESS
754
755 popf
756 pop rbp
757 add rsp, 4 * xCB
758 ret
759ENDPROC MY_NAME(SVMR0VMRun64)
760%endif ; RT_ARCH_AMD64
761
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