VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/HWACCMR0Mixed.mac@ 39402

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

Save and restore the TSS limit on 64-bit hosts too.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.3 KB
Line 
1; $Id: HWACCMR0Mixed.mac 30414 2010-06-24 08:46:18Z vboxsync $
2;; @file
3; HWACCMR0Mixed.mac - Stuff that darwin needs to build two versions of.
4;
5; Included by HWACCMR0A.asm with RT_ARCH_AMD64 defined or or undefined.
6;
7
8;
9; Copyright (C) 2006-2007 Oracle Corporation
10;
11; This file is part of VirtualBox Open Source Edition (OSE), as
12; available from http://www.virtualbox.org. This file is free software;
13; you can redistribute it and/or modify it under the terms of the GNU
14; General Public License (GPL) as published by the Free Software
15; Foundation, in version 2 as it comes in the "COPYING" file of the
16; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18;
19
20
21;/**
22; * Prepares for and executes VMLAUNCH/VMRESUME (32 bits guest mode)
23; *
24; * @returns VBox status code
25; * @param fResume x86:[ebp+8], msc:rcx,gcc:rdi vmlauch/vmresume
26; * @param pCtx x86:[ebp+c], msc:rdx,gcc:rsi Guest context
27; * @param pCache x86:[esp+10],msc:r8, gcc:rdx VMCS cache
28; */
29ALIGNCODE(16)
30BEGINPROC MY_NAME(VMXR0StartVM32)
31 push xBP
32 mov xBP, xSP
33
34 pushf
35 cli
36
37 ;/* Save all general purpose host registers. */
38 MYPUSHAD
39
40 ;/* First we have to save some final CPU context registers. */
41 mov eax, VMX_VMCS_HOST_RIP
42%ifdef RT_ARCH_AMD64
43 lea r10, [.vmlaunch_done wrt rip]
44 vmwrite rax, r10
45%else
46 mov ecx, .vmlaunch_done
47 vmwrite eax, ecx
48%endif
49 ;/* Note: assumes success... */
50
51 ;/* Manual save and restore:
52 ; * - General purpose registers except RIP, RSP
53 ; *
54 ; * Trashed:
55 ; * - CR2 (we don't care)
56 ; * - LDTR (reset to 0)
57 ; * - DRx (presumably not changed at all)
58 ; * - DR7 (reset to 0x400)
59 ; * - EFLAGS (reset to RT_BIT(1); not relevant)
60 ; *
61 ; */
62
63 ;/* Save the Guest CPU context pointer. */
64%ifdef RT_ARCH_AMD64
65 %ifdef ASM_CALL64_GCC
66 ; fResume already in rdi
67 ; pCtx already in rsi
68 mov rbx, rdx ; pCache
69 %else
70 mov rdi, rcx ; fResume
71 mov rsi, rdx ; pCtx
72 mov rbx, r8 ; pCache
73 %endif
74%else
75 mov edi, [ebp + 8] ; fResume
76 mov esi, [ebp + 12] ; pCtx
77 mov ebx, [ebp + 16] ; pCache
78%endif
79
80 ;/* Save segment registers */
81 ; Note: MYPUSHSEGS trashes rdx & rcx, so we moved it here (msvc amd64 case)
82 MYPUSHSEGS xAX, ax
83
84%ifdef VMX_USE_CACHED_VMCS_ACCESSES
85 mov ecx, [xBX + VMCSCACHE.Write.cValidEntries]
86 cmp ecx, 0
87 je .no_cached_writes
88 mov edx, ecx
89 mov ecx, 0
90 jmp .cached_write
91
92ALIGN(16)
93.cached_write:
94 mov eax, [xBX + VMCSCACHE.Write.aField + xCX*4]
95 vmwrite xAX, [xBX + VMCSCACHE.Write.aFieldVal + xCX*8]
96 inc xCX
97 cmp xCX, xDX
98 jl .cached_write
99
100 mov dword [xBX + VMCSCACHE.Write.cValidEntries], 0
101.no_cached_writes:
102
103 ; Save the pCache pointer
104 push xBX
105%endif
106
107 ; Save the pCtx pointer
108 push xSI
109
110 ; Save LDTR
111 xor eax, eax
112 sldt ax
113 push xAX
114
115 ; The TR limit is reset to 0x67; restore it manually
116 str eax
117 push xAX
118
119 ; VMX only saves the base of the GDTR & IDTR and resets the limit to 0xffff; we must restore the limit correctly!
120 sub xSP, xS*2
121 sgdt [xSP]
122
123 sub xSP, xS*2
124 sidt [xSP]
125
126%ifdef VBOX_WITH_DR6_EXPERIMENT
127 ; Restore DR6 - experiment, not safe!
128 mov xBX, [xSI + CPUMCTX.dr6]
129 mov dr6, xBX
130%endif
131
132 ; Restore CR2
133 mov ebx, [xSI + CPUMCTX.cr2]
134 mov cr2, xBX
135
136 mov eax, VMX_VMCS_HOST_RSP
137 vmwrite xAX, xSP
138 ;/* Note: assumes success... */
139 ;/* Don't mess with ESP anymore!! */
140
141 ;/* Restore Guest's general purpose registers. */
142 mov eax, [xSI + CPUMCTX.eax]
143 mov ebx, [xSI + CPUMCTX.ebx]
144 mov ecx, [xSI + CPUMCTX.ecx]
145 mov edx, [xSI + CPUMCTX.edx]
146 mov ebp, [xSI + CPUMCTX.ebp]
147
148 ; resume or start?
149 cmp xDI, 0 ; fResume
150 je .vmlauch_lauch
151
152 ;/* Restore edi & esi. */
153 mov edi, [xSI + CPUMCTX.edi]
154 mov esi, [xSI + CPUMCTX.esi]
155
156 vmresume
157 jmp .vmlaunch_done; ;/* here if vmresume detected a failure. */
158
159.vmlauch_lauch:
160 ;/* Restore edi & esi. */
161 mov edi, [xSI + CPUMCTX.edi]
162 mov esi, [xSI + CPUMCTX.esi]
163
164 vmlaunch
165 jmp .vmlaunch_done; ;/* here if vmlaunch detected a failure. */
166
167ALIGNCODE(16) ;; @todo YASM BUG - this alignment is wrong on darwin, it's 1 byte off.
168.vmlaunch_done:
169 jc near .vmxstart_invalid_vmxon_ptr
170 jz near .vmxstart_start_failed
171
172 ; Restore base and limit of the IDTR & GDTR
173 lidt [xSP]
174 add xSP, xS*2
175 lgdt [xSP]
176 add xSP, xS*2
177
178 push xDI
179 mov xDI, [xSP + xS * 3] ; pCtx (*3 to skip the saved LDTR + TR)
180
181 mov [ss:xDI + CPUMCTX.eax], eax
182 mov [ss:xDI + CPUMCTX.ebx], ebx
183 mov [ss:xDI + CPUMCTX.ecx], ecx
184 mov [ss:xDI + CPUMCTX.edx], edx
185 mov [ss:xDI + CPUMCTX.esi], esi
186 mov [ss:xDI + CPUMCTX.ebp], ebp
187%ifdef RT_ARCH_AMD64
188 pop xAX ; the guest edi we pushed above
189 mov dword [ss:xDI + CPUMCTX.edi], eax
190%else
191 pop dword [ss:xDI + CPUMCTX.edi] ; the guest edi we pushed above
192%endif
193
194%ifdef VBOX_WITH_DR6_EXPERIMENT
195 ; Save DR6 - experiment, not safe!
196 mov xAX, dr6
197 mov [ss:xDI + CPUMCTX.dr6], xAX
198%endif
199
200 ; Restore TSS selector; must mark it as not busy before using ltr (!)
201 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
202 ; @todo get rid of sgdt
203 pop xBX ; saved TR
204 sub xSP, xS*2
205 sgdt [xSP]
206 mov xAX, xBX
207 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
208 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
209 and dword [ss:xAX + 4], ~0200h ; clear busy flag (2nd type2 bit)
210 ltr bx
211 add xSP, xS*2
212
213 pop xAX ; saved LDTR
214 lldt ax
215
216 add xSP, xS ; pCtx
217
218%ifdef VMX_USE_CACHED_VMCS_ACCESSES
219 pop xDX ; saved pCache
220
221 mov ecx, [ss:xDX + VMCSCACHE.Read.cValidEntries]
222 cmp ecx, 0 ; can't happen
223 je .no_cached_reads
224 jmp .cached_read
225
226ALIGN(16)
227.cached_read:
228 dec xCX
229 mov eax, [ss:xDX + VMCSCACHE.Read.aField + xCX*4]
230 vmread [ss:xDX + VMCSCACHE.Read.aFieldVal + xCX*8], xAX
231 cmp xCX, 0
232 jnz .cached_read
233.no_cached_reads:
234
235 ; Save CR2 for EPT
236 mov xAX, cr2
237 mov [ss:xDX + VMCSCACHE.cr2], xAX
238%endif
239
240 ; Restore segment registers
241 MYPOPSEGS xAX, ax
242
243 ; Restore general purpose registers
244 MYPOPAD
245
246 mov eax, VINF_SUCCESS
247
248.vmstart_end:
249 popf
250 pop xBP
251 ret
252
253
254.vmxstart_invalid_vmxon_ptr:
255 ; Restore base and limit of the IDTR & GDTR
256 lidt [xSP]
257 add xSP, xS*2
258 lgdt [xSP]
259 add xSP, xS*2
260
261 ; Restore TSS selector; must mark it as not busy before using ltr (!)
262 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
263 ; @todo get rid of sgdt
264 pop xBX ; saved TR
265 sub xSP, xS*2
266 sgdt [xSP]
267 mov xAX, xBX
268 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
269 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
270 and dword [ss:xAX + 4], ~0200h ; clear busy flag (2nd type2 bit)
271 ltr bx
272 add xSP, xS*2
273
274 pop xAX ; saved LDTR
275 lldt ax
276
277%ifdef VMX_USE_CACHED_VMCS_ACCESSES
278 add xSP, xS*2 ; pCtx + pCache
279%else
280 add xSP, xS ; pCtx
281%endif
282
283 ; Restore segment registers
284 MYPOPSEGS xAX, ax
285
286 ; Restore all general purpose host registers.
287 MYPOPAD
288 mov eax, VERR_VMX_INVALID_VMXON_PTR
289 jmp .vmstart_end
290
291.vmxstart_start_failed:
292 ; Restore base and limit of the IDTR & GDTR
293 lidt [xSP]
294 add xSP, xS*2
295 lgdt [xSP]
296 add xSP, xS*2
297
298 ; Restore TSS selector; must mark it as not busy before using ltr (!)
299 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
300 ; @todo get rid of sgdt
301 pop xBX ; saved TR
302 sub xSP, xS*2
303 sgdt [xSP]
304 mov xAX, xBX
305 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
306 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
307 and dword [ss:xAX + 4], ~0200h ; clear busy flag (2nd type2 bit)
308 ltr bx
309 add xSP, xS*2
310
311 pop xAX ; saved LDTR
312 lldt ax
313
314%ifdef VMX_USE_CACHED_VMCS_ACCESSES
315 add xSP, xS*2 ; pCtx + pCache
316%else
317 add xSP, xS ; pCtx
318%endif
319
320 ; Restore segment registers
321 MYPOPSEGS xAX, ax
322
323 ; Restore all general purpose host registers.
324 MYPOPAD
325 mov eax, VERR_VMX_UNABLE_TO_START_VM
326 jmp .vmstart_end
327
328ENDPROC MY_NAME(VMXR0StartVM32)
329
330%ifdef RT_ARCH_AMD64
331;/**
332; * Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
333; *
334; * @returns VBox status code
335; * @param fResume msc:rcx, gcc:rdi vmlauch/vmresume
336; * @param pCtx msc:rdx, gcc:rsi Guest context
337; * @param pCache msc:r8, gcc:rdx VMCS cache
338; */
339ALIGNCODE(16)
340BEGINPROC MY_NAME(VMXR0StartVM64)
341 push xBP
342 mov xBP, xSP
343
344 pushf
345 cli
346
347 ;/* Save all general purpose host registers. */
348 MYPUSHAD
349
350 ;/* First we have to save some final CPU context registers. */
351 lea r10, [.vmlaunch64_done wrt rip]
352 mov rax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
353 vmwrite rax, r10
354 ;/* Note: assumes success... */
355
356 ;/* Manual save and restore:
357 ; * - General purpose registers except RIP, RSP
358 ; *
359 ; * Trashed:
360 ; * - CR2 (we don't care)
361 ; * - LDTR (reset to 0)
362 ; * - DRx (presumably not changed at all)
363 ; * - DR7 (reset to 0x400)
364 ; * - EFLAGS (reset to RT_BIT(1); not relevant)
365 ; *
366 ; */
367
368 ;/* Save the Guest CPU context pointer. */
369%ifdef ASM_CALL64_GCC
370 ; fResume already in rdi
371 ; pCtx already in rsi
372 mov rbx, rdx ; pCache
373%else
374 mov rdi, rcx ; fResume
375 mov rsi, rdx ; pCtx
376 mov rbx, r8 ; pCache
377%endif
378
379 ;/* Save segment registers */
380 ; Note: MYPUSHSEGS trashes rdx & rcx, so we moved it here (msvc amd64 case)
381 MYPUSHSEGS xAX, ax
382
383%ifdef VMX_USE_CACHED_VMCS_ACCESSES
384 mov ecx, [xBX + VMCSCACHE.Write.cValidEntries]
385 cmp ecx, 0
386 je .no_cached_writes
387 mov edx, ecx
388 mov ecx, 0
389 jmp .cached_write
390
391ALIGN(16)
392.cached_write:
393 mov eax, [xBX + VMCSCACHE.Write.aField + xCX*4]
394 vmwrite xAX, [xBX + VMCSCACHE.Write.aFieldVal + xCX*8]
395 inc xCX
396 cmp xCX, xDX
397 jl .cached_write
398
399 mov dword [xBX + VMCSCACHE.Write.cValidEntries], 0
400.no_cached_writes:
401
402 ; Save the pCache pointer
403 push xBX
404%endif
405
406 ; Save the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs and restore the guest MSRs
407 ;; @todo use the automatic load feature for MSRs
408 LOADGUESTMSR MSR_K8_LSTAR, CPUMCTX.msrLSTAR
409%if 0 ; not supported on Intel CPUs
410 LOADGUESTMSR MSR_K8_CSTAR, CPUMCTX.msrCSTAR
411%endif
412 LOADGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
413 LOADGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
414 LOADGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
415
416 ; Save the pCtx pointer
417 push xSI
418
419 ; Save LDTR
420 xor eax, eax
421 sldt ax
422 push xAX
423
424 ; The TR limit is reset to 0x67; restore it manually
425 str eax
426 push xAX
427
428 ; VMX only saves the base of the GDTR & IDTR and resets the limit to 0xffff; we must restore the limit correctly!
429 sub xSP, xS*2
430 sgdt [xSP]
431
432 sub xSP, xS*2
433 sidt [xSP]
434
435%ifdef VBOX_WITH_DR6_EXPERIMENT
436 ; Restore DR6 - experiment, not safe!
437 mov xBX, [xSI + CPUMCTX.dr6]
438 mov dr6, xBX
439%endif
440
441 ; Restore CR2
442 mov rbx, qword [xSI + CPUMCTX.cr2]
443 mov cr2, rbx
444
445 mov eax, VMX_VMCS_HOST_RSP
446 vmwrite xAX, xSP
447 ;/* Note: assumes success... */
448 ;/* Don't mess with ESP anymore!! */
449
450 ;/* Restore Guest's general purpose registers. */
451 mov rax, qword [xSI + CPUMCTX.eax]
452 mov rbx, qword [xSI + CPUMCTX.ebx]
453 mov rcx, qword [xSI + CPUMCTX.ecx]
454 mov rdx, qword [xSI + CPUMCTX.edx]
455 mov rbp, qword [xSI + CPUMCTX.ebp]
456 mov r8, qword [xSI + CPUMCTX.r8]
457 mov r9, qword [xSI + CPUMCTX.r9]
458 mov r10, qword [xSI + CPUMCTX.r10]
459 mov r11, qword [xSI + CPUMCTX.r11]
460 mov r12, qword [xSI + CPUMCTX.r12]
461 mov r13, qword [xSI + CPUMCTX.r13]
462 mov r14, qword [xSI + CPUMCTX.r14]
463 mov r15, qword [xSI + CPUMCTX.r15]
464
465 ; resume or start?
466 cmp xDI, 0 ; fResume
467 je .vmlauch64_lauch
468
469 ;/* Restore edi & esi. */
470 mov rdi, qword [xSI + CPUMCTX.edi]
471 mov rsi, qword [xSI + CPUMCTX.esi]
472
473 vmresume
474 jmp .vmlaunch64_done; ;/* here if vmresume detected a failure. */
475
476.vmlauch64_lauch:
477 ;/* Restore rdi & rsi. */
478 mov rdi, qword [xSI + CPUMCTX.edi]
479 mov rsi, qword [xSI + CPUMCTX.esi]
480
481 vmlaunch
482 jmp .vmlaunch64_done; ;/* here if vmlaunch detected a failure. */
483
484ALIGNCODE(16)
485.vmlaunch64_done:
486 jc near .vmxstart64_invalid_vmxon_ptr
487 jz near .vmxstart64_start_failed
488
489 ; Restore base and limit of the IDTR & GDTR
490 lidt [xSP]
491 add xSP, xS*2
492 lgdt [xSP]
493 add xSP, xS*2
494
495 push xDI
496 mov xDI, [xSP + xS * 3] ; pCtx (*3 to skip the saved LDTR + TR)
497
498 mov qword [xDI + CPUMCTX.eax], rax
499 mov qword [xDI + CPUMCTX.ebx], rbx
500 mov qword [xDI + CPUMCTX.ecx], rcx
501 mov qword [xDI + CPUMCTX.edx], rdx
502 mov qword [xDI + CPUMCTX.esi], rsi
503 mov qword [xDI + CPUMCTX.ebp], rbp
504 mov qword [xDI + CPUMCTX.r8], r8
505 mov qword [xDI + CPUMCTX.r9], r9
506 mov qword [xDI + CPUMCTX.r10], r10
507 mov qword [xDI + CPUMCTX.r11], r11
508 mov qword [xDI + CPUMCTX.r12], r12
509 mov qword [xDI + CPUMCTX.r13], r13
510 mov qword [xDI + CPUMCTX.r14], r14
511 mov qword [xDI + CPUMCTX.r15], r15
512
513 pop xAX ; the guest edi we pushed above
514 mov qword [xDI + CPUMCTX.edi], rax
515
516%ifdef VBOX_WITH_DR6_EXPERIMENT
517 ; Save DR6 - experiment, not safe!
518 mov xAX, dr6
519 mov [xDI + CPUMCTX.dr6], xAX
520%endif
521
522 ; Restore TSS selector; must mark it as not busy before using ltr (!)
523 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
524 ; @todo get rid of sgdt
525 pop xBX ; saved TR
526 sub xSP, xS*2
527 sgdt [xSP]
528 mov xAX, xBX
529 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
530 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
531 and dword [xAX + 4], ~0200h ; clear busy flag (2nd type2 bit)
532 ltr bx
533 add xSP, xS*2
534
535 pop xAX ; saved LDTR
536 lldt ax
537
538 pop xSI ; pCtx (needed in rsi by the macros below)
539
540 ; Restore the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
541 ;; @todo use the automatic load feature for MSRs
542 LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
543 LOADHOSTMSREX MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
544 LOADHOSTMSREX MSR_K6_STAR, CPUMCTX.msrSTAR
545%if 0 ; not supported on Intel CPUs
546 LOADHOSTMSREX MSR_K8_CSTAR, CPUMCTX.msrCSTAR
547%endif
548 LOADHOSTMSREX MSR_K8_LSTAR, CPUMCTX.msrLSTAR
549
550%ifdef VMX_USE_CACHED_VMCS_ACCESSES
551 pop xDX ; saved pCache
552
553 mov ecx, [xDX + VMCSCACHE.Read.cValidEntries]
554 cmp ecx, 0 ; can't happen
555 je .no_cached_reads
556 jmp .cached_read
557
558ALIGN(16)
559.cached_read:
560 dec xCX
561 mov eax, [xDX + VMCSCACHE.Read.aField + xCX*4]
562 vmread [xDX + VMCSCACHE.Read.aFieldVal + xCX*8], xAX
563 cmp xCX, 0
564 jnz .cached_read
565.no_cached_reads:
566
567 ; Save CR2 for EPT
568 mov xAX, cr2
569 mov [xDX + VMCSCACHE.cr2], xAX
570%endif
571
572 ; Restore segment registers
573 MYPOPSEGS xAX, ax
574
575 ; Restore general purpose registers
576 MYPOPAD
577
578 mov eax, VINF_SUCCESS
579
580.vmstart64_end:
581 popf
582 pop xBP
583 ret
584
585
586.vmxstart64_invalid_vmxon_ptr:
587 ; Restore base and limit of the IDTR & GDTR
588 lidt [xSP]
589 add xSP, xS*2
590 lgdt [xSP]
591 add xSP, xS*2
592
593 ; Restore TSS selector; must mark it as not busy before using ltr (!)
594 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
595 ; @todo get rid of sgdt
596 pop xBX ; saved TR
597 sub xSP, xS*2
598 sgdt [xSP]
599 mov xAX, xBX
600 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
601 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
602 and dword [xAX + 4], ~0200h ; clear busy flag (2nd type2 bit)
603 ltr bx
604 add xSP, xS*2
605
606 pop xAX ; saved LDTR
607 lldt ax
608
609 pop xSI ; pCtx (needed in rsi by the macros below)
610
611 ; Restore the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
612 ;; @todo use the automatic load feature for MSRs
613 LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
614 LOADHOSTMSR MSR_K8_SF_MASK
615 LOADHOSTMSR MSR_K6_STAR
616%if 0 ; not supported on Intel CPUs
617 LOADHOSTMSR MSR_K8_CSTAR
618%endif
619 LOADHOSTMSR MSR_K8_LSTAR
620
621%ifdef VMX_USE_CACHED_VMCS_ACCESSES
622 add xSP, xS ; pCache
623%endif
624
625 ; Restore segment registers
626 MYPOPSEGS xAX, ax
627
628 ; Restore all general purpose host registers.
629 MYPOPAD
630 mov eax, VERR_VMX_INVALID_VMXON_PTR
631 jmp .vmstart64_end
632
633.vmxstart64_start_failed:
634 ; Restore base and limit of the IDTR & GDTR
635 lidt [xSP]
636 add xSP, xS*2
637 lgdt [xSP]
638 add xSP, xS*2
639
640 ; Restore TSS selector; must mark it as not busy before using ltr (!)
641 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
642 ; @todo get rid of sgdt
643 pop xBX ; saved TR
644 sub xSP, xS*2
645 sgdt [xSP]
646 mov xAX, xBX
647 and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
648 add xAX, [xSP + 2] ; eax <- GDTR.address + descriptor offset.
649 and dword [xAX + 4], ~0200h ; clear busy flag (2nd type2 bit)
650 ltr bx
651 add xSP, xS*2
652
653 pop xAX ; saved LDTR
654 lldt ax
655
656 pop xSI ; pCtx (needed in rsi by the macros below)
657
658 ; Restore the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
659 ;; @todo use the automatic load feature for MSRs
660 LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
661 LOADHOSTMSR MSR_K8_SF_MASK
662 LOADHOSTMSR MSR_K6_STAR
663%if 0 ; not supported on Intel CPUs
664 LOADHOSTMSR MSR_K8_CSTAR
665%endif
666 LOADHOSTMSR MSR_K8_LSTAR
667
668%ifdef VMX_USE_CACHED_VMCS_ACCESSES
669 add xSP, xS ; pCache
670%endif
671
672 ; Restore segment registers
673 MYPOPSEGS xAX, ax
674
675 ; Restore all general purpose host registers.
676 MYPOPAD
677 mov eax, VERR_VMX_UNABLE_TO_START_VM
678 jmp .vmstart64_end
679ENDPROC MY_NAME(VMXR0StartVM64)
680%endif ; RT_ARCH_AMD64
681
682
683;/**
684; * Prepares for and executes VMRUN (32 bits guests)
685; *
686; * @returns VBox status code
687; * @param HCPhysVMCB Physical address of host VMCB
688; * @param HCPhysVMCB Physical address of guest VMCB
689; * @param pCtx Guest context
690; */
691ALIGNCODE(16)
692BEGINPROC MY_NAME(SVMR0VMRun)
693%ifdef RT_ARCH_AMD64 ; fake a cdecl stack frame
694 %ifdef ASM_CALL64_GCC
695 push rdx
696 push rsi
697 push rdi
698 %else
699 push r8
700 push rdx
701 push rcx
702 %endif
703 push 0
704%endif
705 push xBP
706 mov xBP, xSP
707 pushf
708
709 ;/* Manual save and restore:
710 ; * - General purpose registers except RIP, RSP, RAX
711 ; *
712 ; * Trashed:
713 ; * - CR2 (we don't care)
714 ; * - LDTR (reset to 0)
715 ; * - DRx (presumably not changed at all)
716 ; * - DR7 (reset to 0x400)
717 ; */
718
719 ;/* Save all general purpose host registers. */
720 MYPUSHAD
721
722 ;/* Save the Guest CPU context pointer. */
723 mov xSI, [xBP + xS*2 + RTHCPHYS_CB*2] ; pCtx
724 push xSI ; push for saving the state at the end
725
726 ; save host fs, gs, sysenter msr etc
727 mov xAX, [xBP + xS*2] ; pVMCBHostPhys (64 bits physical address; x86: take low dword only)
728 push xAX ; save for the vmload after vmrun
729 vmsave
730
731 ; setup eax for VMLOAD
732 mov xAX, [xBP + xS*2 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address; take low dword only)
733
734 ;/* Restore Guest's general purpose registers. */
735 ;/* EAX is loaded from the VMCB by VMRUN */
736 mov ebx, [xSI + CPUMCTX.ebx]
737 mov ecx, [xSI + CPUMCTX.ecx]
738 mov edx, [xSI + CPUMCTX.edx]
739 mov edi, [xSI + CPUMCTX.edi]
740 mov ebp, [xSI + CPUMCTX.ebp]
741 mov esi, [xSI + CPUMCTX.esi]
742
743 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
744 clgi
745 sti
746
747 ; load guest fs, gs, sysenter msr etc
748 vmload
749 ; run the VM
750 vmrun
751
752 ;/* EAX is in the VMCB already; we can use it here. */
753
754 ; save guest fs, gs, sysenter msr etc
755 vmsave
756
757 ; load host fs, gs, sysenter msr etc
758 pop xAX ; pushed above
759 vmload
760
761 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
762 cli
763 stgi
764
765 pop xAX ; pCtx
766
767 mov [ss:xAX + CPUMCTX.ebx], ebx
768 mov [ss:xAX + CPUMCTX.ecx], ecx
769 mov [ss:xAX + CPUMCTX.edx], edx
770 mov [ss:xAX + CPUMCTX.esi], esi
771 mov [ss:xAX + CPUMCTX.edi], edi
772 mov [ss:xAX + CPUMCTX.ebp], ebp
773
774 ; Restore general purpose registers
775 MYPOPAD
776
777 mov eax, VINF_SUCCESS
778
779 popf
780 pop xBP
781%ifdef RT_ARCH_AMD64
782 add xSP, 4*xS
783%endif
784 ret
785ENDPROC MY_NAME(SVMR0VMRun)
786
787%ifdef RT_ARCH_AMD64
788;/**
789; * Prepares for and executes VMRUN (64 bits guests)
790; *
791; * @returns VBox status code
792; * @param HCPhysVMCB Physical address of host VMCB
793; * @param HCPhysVMCB Physical address of guest VMCB
794; * @param pCtx Guest context
795; */
796ALIGNCODE(16)
797BEGINPROC MY_NAME(SVMR0VMRun64)
798 ; fake a cdecl stack frame
799 %ifdef ASM_CALL64_GCC
800 push rdx
801 push rsi
802 push rdi
803 %else
804 push r8
805 push rdx
806 push rcx
807 %endif
808 push 0
809 push rbp
810 mov rbp, rsp
811 pushf
812
813 ;/* Manual save and restore:
814 ; * - General purpose registers except RIP, RSP, RAX
815 ; *
816 ; * Trashed:
817 ; * - CR2 (we don't care)
818 ; * - LDTR (reset to 0)
819 ; * - DRx (presumably not changed at all)
820 ; * - DR7 (reset to 0x400)
821 ; */
822
823 ;/* Save all general purpose host registers. */
824 MYPUSHAD
825
826 ;/* Save the Guest CPU context pointer. */
827 mov rsi, [rbp + xS*2 + RTHCPHYS_CB*2] ; pCtx
828 push rsi ; push for saving the state at the end
829
830 ; save host fs, gs, sysenter msr etc
831 mov rax, [rbp + xS*2] ; pVMCBHostPhys (64 bits physical address; x86: take low dword only)
832 push rax ; save for the vmload after vmrun
833 vmsave
834
835 ; setup eax for VMLOAD
836 mov rax, [rbp + xS*2 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address; take low dword only)
837
838 ;/* Restore Guest's general purpose registers. */
839 ;/* RAX is loaded from the VMCB by VMRUN */
840 mov rbx, qword [xSI + CPUMCTX.ebx]
841 mov rcx, qword [xSI + CPUMCTX.ecx]
842 mov rdx, qword [xSI + CPUMCTX.edx]
843 mov rdi, qword [xSI + CPUMCTX.edi]
844 mov rbp, qword [xSI + CPUMCTX.ebp]
845 mov r8, qword [xSI + CPUMCTX.r8]
846 mov r9, qword [xSI + CPUMCTX.r9]
847 mov r10, qword [xSI + CPUMCTX.r10]
848 mov r11, qword [xSI + CPUMCTX.r11]
849 mov r12, qword [xSI + CPUMCTX.r12]
850 mov r13, qword [xSI + CPUMCTX.r13]
851 mov r14, qword [xSI + CPUMCTX.r14]
852 mov r15, qword [xSI + CPUMCTX.r15]
853 mov rsi, qword [xSI + CPUMCTX.esi]
854
855 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
856 clgi
857 sti
858
859 ; load guest fs, gs, sysenter msr etc
860 vmload
861 ; run the VM
862 vmrun
863
864 ;/* RAX is in the VMCB already; we can use it here. */
865
866 ; save guest fs, gs, sysenter msr etc
867 vmsave
868
869 ; load host fs, gs, sysenter msr etc
870 pop rax ; pushed above
871 vmload
872
873 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
874 cli
875 stgi
876
877 pop rax ; pCtx
878
879 mov qword [rax + CPUMCTX.ebx], rbx
880 mov qword [rax + CPUMCTX.ecx], rcx
881 mov qword [rax + CPUMCTX.edx], rdx
882 mov qword [rax + CPUMCTX.esi], rsi
883 mov qword [rax + CPUMCTX.edi], rdi
884 mov qword [rax + CPUMCTX.ebp], rbp
885 mov qword [rax + CPUMCTX.r8], r8
886 mov qword [rax + CPUMCTX.r9], r9
887 mov qword [rax + CPUMCTX.r10], r10
888 mov qword [rax + CPUMCTX.r11], r11
889 mov qword [rax + CPUMCTX.r12], r12
890 mov qword [rax + CPUMCTX.r13], r13
891 mov qword [rax + CPUMCTX.r14], r14
892 mov qword [rax + CPUMCTX.r15], r15
893
894 ; Restore general purpose registers
895 MYPOPAD
896
897 mov eax, VINF_SUCCESS
898
899 popf
900 pop rbp
901 add rsp, 4*xS
902 ret
903ENDPROC MY_NAME(SVMR0VMRun64)
904%endif ; RT_ARCH_AMD64
905
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