VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/HWACCMR0A.asm@ 2747

Last change on this file since 2747 was 2747, checked in by vboxsync, 18 years ago

Sigh

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.3 KB
Line 
1; $Id: HWACCMR0A.asm 2747 2007-05-21 15:42:33Z vboxsync $
2;; @file
3; VMXM - R0 vmx helpers
4;
5
6;
7; Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13; in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14; distribution. VirtualBox OSE is distributed in the hope that it will
15; be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17; If you received this file as part of a commercial VirtualBox
18; distribution, then only the terms of your commercial VirtualBox
19; license agreement apply instead of the previous paragraph.
20;
21
22;*******************************************************************************
23;* Header Files *
24;*******************************************************************************
25%include "VBox/asmdefs.mac"
26%include "VBox/err.mac"
27%include "VBox/hwacc_vmx.mac"
28%include "VBox/cpum.mac"
29%include "VBox/x86.mac"
30
31%ifdef __OS2__ ;; @todo build cvs nasm like on OS X.
32 %macro vmwrite 2,
33 int3
34 %endmacro
35 %define vmlaunch int3
36 %define vmresume int3
37%endif
38
39
40;; @def MYPUSHAD
41; Macro generating an equivalent to pushad
42
43;; @def MYPOPAD
44; Macro generating an equivalent to popad
45
46;; @def MYPUSHSEGS
47; Macro saving all segment registers on the stack.
48; @param 1 full width register name
49; @param 2 16-bit regsiter name for \a 1.
50
51;; @def MYPOPSEGS
52; Macro restoring all segment registers on the stack
53; @param 1 full width register name
54; @param 2 16-bit regsiter name for \a 1.
55
56%ifdef __AMD64__
57 %ifdef ASM_CALL64_GCC
58 %macro MYPUSHAD 0
59 push r15
60 push r14
61 push r13
62 push r12
63 push rbx
64 %endmacro
65 %macro MYPOPAD 0
66 pop rbx
67 pop r12
68 pop r13
69 pop r14
70 pop r15
71 %endmacro
72
73 %else ; ASM_CALL64_MSC
74 %macro MYPUSHAD 0
75 push r15
76 push r14
77 push r13
78 push r12
79 push rbx
80 push rsi
81 push rdi
82 %endmacro
83 %macro MYPOPAD 0
84 pop rdi
85 pop rsi
86 pop rbx
87 pop r12
88 pop r13
89 pop r14
90 pop r15
91 %endmacro
92 %endif
93 ;; @todo check ds,es saving/restoring on AMD64
94 %macro MYPUSHSEGS 2
95 push gs
96 push fs
97 mov %2, es
98 push %1
99 mov %2, ds
100 push %1
101 %endmacro
102 %macro MYPOPSEGS 2
103 pop %1
104 mov ds, %2
105 pop %1
106 mov es, %2
107 pop fs
108 pop gs
109 %endmacro
110
111%else ; __X86__
112 %macro MYPUSHAD 0
113 pushad
114 %endmacro
115 %macro MYPOPAD 0
116 popad
117 %endmacro
118
119 %macro MYPUSHSEGS 2
120 push ds
121 push es
122 push fs
123 push gs
124 %endmacro
125 %macro MYPOPSEGS 2
126 pop gs
127 pop fs
128 pop es
129 pop ds
130 %endmacro
131%endif
132
133
134BEGINCODE
135
136;/**
137; * Prepares for and executes VMLAUNCH
138; *
139; * @note identical to VMXResumeVM, except for the vmlaunch/vmresume opcode
140; *
141; * @returns VBox status code
142; * @param pCtx Guest context
143; */
144BEGINPROC VMXStartVM
145 push xBP
146 mov xBP, xSP
147
148 ;/* First we have to save some final CPU context registers. */
149%ifdef __AMD64__
150 mov rax, qword .vmlaunch_done
151 push rax
152%else
153 push .vmlaunch_done
154%endif
155 mov eax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
156 vmwrite xAX, [xSP]
157 ;/* @todo assumes success... */
158 add xSP, xS
159
160 ;/* Manual save and restore:
161 ; * - General purpose registers except RIP, RSP
162 ; *
163 ; * Trashed:
164 ; * - CR2 (we don't care)
165 ; * - LDTR (reset to 0)
166 ; * - DRx (presumably not changed at all)
167 ; * - DR7 (reset to 0x400)
168 ; * - EFLAGS (reset to BIT(1); not relevant)
169 ; *
170 ; */
171
172 ;/* Save all general purpose host registers. */
173 MYPUSHAD
174
175 ;/* Save segment registers */
176 MYPUSHSEGS xAX, ax
177
178 ;/* Save the Guest CPU context pointer. */
179%ifdef __AMD64__
180 %ifdef ASM_CALL64_GCC
181 mov rsi, rdi ; pCtx
182 %else
183 mov rsi, rcx ; pCtx
184 %endif
185%else
186 mov esi, [ebp + 8] ; pCtx
187%endif
188 push xSI
189
190 ; Save LDTR
191 xor eax, eax
192 sldt ax
193 push xAX
194
195 ; Restore CR2
196 mov ebx, [xSI + CPUMCTX.cr2]
197 mov cr2, xBX
198
199 mov eax, VMX_VMCS_HOST_RSP
200 vmwrite xAX, xSP
201 ;/* @todo assumes success... */
202 ;/* Don't mess with ESP anymore!! */
203
204 ;/* Restore Guest's general purpose registers. */
205 mov eax, [xSI + CPUMCTX.eax]
206 mov ebx, [xSI + CPUMCTX.ebx]
207 mov ecx, [xSI + CPUMCTX.ecx]
208 mov edx, [xSI + CPUMCTX.edx]
209 mov edi, [xSI + CPUMCTX.edi]
210 mov ebp, [xSI + CPUMCTX.ebp]
211 mov esi, [xSI + CPUMCTX.esi]
212
213 vmlaunch
214 jmp .vmlaunch_done; ;/* here if vmlaunch detected a failure. */
215
216ALIGNCODE(16)
217.vmlaunch_done:
218 jnc .vmxstart_good
219
220 pop xAX ; saved LDTR
221 lldt ax
222
223 add xSP, xS ; pCtx
224
225 ; Restore segment registers
226 MYPOPSEGS xAX, ax
227
228 ;/* Restore all general purpose host registers. */
229 MYPOPAD
230 mov eax, VERR_VMX_INVALID_VMXON_PTR
231 jmp .vmstart_end
232
233.vmxstart_good:
234 jnz .vmxstart_success
235
236 pop xAX ; saved LDTR
237 lldt ax
238
239 add xSP, xS ; pCtx
240
241 ; Restore segment registers
242 MYPOPSEGS xAX, ax
243
244 ; Restore all general purpose host registers.
245 MYPOPAD
246 mov eax, VERR_VMX_UNABLE_TO_START_VM
247 jmp .vmstart_end
248
249.vmxstart_success:
250 push xDI
251 mov xDI, [xSP + xS * 2] ;/* pCtx */
252
253 mov [ss:xDI + CPUMCTX.eax], eax
254 mov [ss:xDI + CPUMCTX.ebx], ebx
255 mov [ss:xDI + CPUMCTX.ecx], ecx
256 mov [ss:xDI + CPUMCTX.edx], edx
257 mov [ss:xDI + CPUMCTX.esi], esi
258 mov [ss:xDI + CPUMCTX.ebp], ebp
259%ifdef __AMD64__
260 pop xAX ; the guest edi we pushed above
261 mov dword [ss:xDI + CPUMCTX.edi], eax
262%else
263 pop dword [ss:xDI + CPUMCTX.edi] ; the guest edi we pushed above
264%endif
265
266 pop xAX ; saved LDTR
267 lldt ax
268
269 add xSP, xS ; pCtx
270
271 ; Restore segment registers
272 MYPOPSEGS xAX, ax
273
274 ; Restore general purpose registers
275 MYPOPAD
276
277 mov eax, VINF_SUCCESS
278
279.vmstart_end:
280 pop xBP
281 ret
282ENDPROC VMXStartVM
283
284
285;/**
286; * Prepares for and executes VMRESUME
287; *
288; * @note identical to VMXStartVM, except for the vmlaunch/vmresume opcode
289; *
290; * @returns VBox status code
291; * @param pCtx Guest context
292; */
293BEGINPROC VMXResumeVM
294 push xBP
295 mov xBP, xSP
296
297 ;/* First we have to save some final CPU context registers. */
298%ifdef __AMD64__
299 mov rax, qword vmresume_done
300 push rax
301%else
302 push vmresume_done
303%endif
304 mov eax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
305 vmwrite xAX, [xSP]
306 ;/* @todo assumes success... */
307 add xSP, xS
308
309 ;/* Manual save and restore:
310 ; * - General purpose registers except RIP, RSP
311 ; *
312 ; * Trashed:
313 ; * - CR2 (we don't care)
314 ; * - LDTR (reset to 0)
315 ; * - DRx (presumably not changed at all)
316 ; * - DR7 (reset to 0x400)
317 ; * - EFLAGS (reset to BIT(1); not relevant)
318 ; *
319 ; */
320
321 ;/* Save all general purpose host registers. */
322 MYPUSHAD
323
324 ;/* Save segment registers */
325 MYPUSHSEGS xAX, ax
326
327 ;/* Save the Guest CPU context pointer. */
328%ifdef __AMD64__
329 %ifdef ASM_CALL64_GCC
330 mov rsi, rdi ; pCtx
331 %else
332 mov rsi, rcx ; pCtx
333 %endif
334%else
335 mov esi, [ebp + 8] ; pCtx
336%endif
337 push xSI
338
339 ; Save LDTR
340 xor eax, eax
341 sldt ax
342 push xAX
343
344 ; Restore CR2
345 mov xBX, [xSI + CPUMCTX.cr2]
346 mov cr2, xBX
347
348 mov eax, VMX_VMCS_HOST_RSP
349 vmwrite xAX, xSP
350 ;/* @todo assumes success... */
351 ;/* Don't mess with ESP anymore!! */
352
353 ;/* Restore Guest's general purpose registers. */
354 mov eax, [xSI + CPUMCTX.eax]
355 mov ebx, [xSI + CPUMCTX.ebx]
356 mov ecx, [xSI + CPUMCTX.ecx]
357 mov edx, [xSI + CPUMCTX.edx]
358 mov edi, [xSI + CPUMCTX.edi]
359 mov ebp, [xSI + CPUMCTX.ebp]
360 mov esi, [xSI + CPUMCTX.esi]
361
362 vmresume
363 jmp vmresume_done; ;/* here if vmresume detected a failure. */
364
365ALIGNCODE(16)
366vmresume_done:
367 jnc vmresume_good
368
369 pop xAX ; saved LDTR
370 lldt ax
371
372 add xSP, xS ; pCtx
373
374 ; Restore segment registers
375 MYPOPSEGS xAX, ax
376
377 ; Restore all general purpose host registers.
378 MYPOPAD
379 mov eax, VERR_VMX_INVALID_VMXON_PTR
380 jmp vmresume_end
381
382vmresume_good:
383 jnz vmresume_success
384
385 pop xAX ; saved LDTR
386 lldt ax
387
388 add xSP, xS ; pCtx
389
390 ; Restore segment registers
391 MYPOPSEGS xAX, ax
392
393 ; Restore all general purpose host registers.
394 MYPOPAD
395 mov eax, VERR_VMX_UNABLE_TO_RESUME_VM
396 jmp vmresume_end
397
398vmresume_success:
399 push xDI
400 mov xDI, [xSP + xS * 2] ; pCtx
401
402 mov [ss:xDI + CPUMCTX.eax], eax
403 mov [ss:xDI + CPUMCTX.ebx], ebx
404 mov [ss:xDI + CPUMCTX.ecx], ecx
405 mov [ss:xDI + CPUMCTX.edx], edx
406 mov [ss:xDI + CPUMCTX.esi], esi
407 mov [ss:xDI + CPUMCTX.ebp], ebp
408%ifdef __AMD64__
409 pop xAX ; the guest edi we pushed above
410 mov dword [ss:xDI + CPUMCTX.edi], eax
411%else
412 pop dword [ss:xDI + CPUMCTX.edi] ; the guest edi we pushed above
413%endif
414
415 pop xAX ; saved LDTR
416 lldt ax
417
418 add xSP, xS ; pCtx
419
420 ; Restore segment registers
421 MYPOPSEGS xAX, ax
422
423 ; Restore general purpose registers
424 MYPOPAD
425
426 mov eax, VINF_SUCCESS
427
428vmresume_end:
429 pop xBP
430 ret
431ENDPROC VMXResumeVM
432
433
434%ifdef __AMD64__
435;/**
436; * Executes VMWRITE
437; *
438; * @returns VBox status code
439; * @param idxField x86: [ebp + 08h] msc: rcx gcc: edi VMCS index
440; * @param pData x86: [ebp + 0ch] msc: rdx gcc: rsi VM field value
441; */
442BEGINPROC VMXWriteVMCS64
443 xor rax, rax
444%ifdef ASM_CALL64_GCC
445 and rdi, 0ffffffffh
446 vmwrite rdi, rsi
447%else
448 and rcx, 0ffffffffh
449 vmwrite rcx, rdx
450%endif
451 jnc .valid_vmcs
452 mov eax, VERR_VMX_INVALID_VMCS_PTR
453 ret
454.valid_vmcs:
455 jnz .the_end
456 mov eax, VERR_VMX_INVALID_VMCS_FIELD
457.the_end:
458 ret
459ENDPROC VMXWriteVMCS64
460
461;/**
462; * Executes VMREAD
463; *
464; * @returns VBox status code
465; * @param idxField VMCS index
466; * @param pData Ptr to store VM field value
467; */
468;DECLASM(int) VMXReadVMCS64(uint32_t idxField, uint64_t *pData);
469BEGINPROC VMXReadVMCS64
470 xor rax, rax
471%ifdef ASM_CALL64_GCC
472 and rdi, 0ffffffffh
473 vmread [rsi], rdi
474%else
475 and rcx, 0ffffffffh
476 vmread [rdx], rcx
477%endif
478 jnc .valid_vmcs
479 mov eax, VERR_VMX_INVALID_VMCS_PTR
480 ret
481.valid_vmcs:
482 jnz .the_end
483 mov eax, VERR_VMX_INVALID_VMCS_FIELD
484.the_end:
485 ret
486ENDPROC VMXReadVMCS64
487
488
489;/**
490; * Executes VMXON
491; *
492; * @returns VBox status code
493; * @param HCPhysVMXOn Physical address of VMXON structure
494; */
495;DECLASM(int) VMXEnable(RTHCPHYS HCPhysVMXOn);
496BEGINPROC VMXEnable
497%ifdef __AMD64__
498 xor rax, rax
499 %ifdef ASM_CALL64_GCC
500 push rdi
501 %else
502 push rcx
503 %endif
504 vmxon [rsp]
505%else
506 xor eax, eax
507 vmxon [esp + 4]
508%endif
509 jnc .good
510 mov eax, VERR_VMX_INVALID_VMXON_PTR
511 jmp .the_end
512
513.good:
514 jnz .the_end
515 mov eax, VERR_VMX_GENERIC
516
517.the_end:
518%ifdef __AMD64__
519 add rsp, 8
520%endif
521 ret
522ENDPROC VMXEnable
523
524
525;/**
526; * Executes VMXOFF
527; */
528;DECLASM(void) VMXDisable(void);
529BEGINPROC VMXDisable
530 vmxoff
531 ret
532ENDPROC VMXDisable
533
534
535;/**
536; * Executes VMCLEAR
537; *
538; * @returns VBox status code
539; * @param HCPhysVMCS Physical address of VM control structure
540; */
541;DECLASM(int) VMXClearVMCS(RTHCPHYS HCPhysVMCS);
542BEGINPROC VMXClearVMCS
543%ifdef __AMD64__
544 xor rax, rax
545 %ifdef ASM_CALL64_GCC
546 push rdi
547 %else
548 push rcx
549 %endif
550 vmclear [rsp]
551%else
552 xor eax, eax
553 vmclear [esp + 4]
554%endif
555 jnc .the_end
556 mov eax, VERR_VMX_INVALID_VMCS_PTR
557.the_end:
558%ifdef __AMD64__
559 add rsp, 8
560%endif
561 ret
562ENDPROC VMXClearVMCS
563
564
565;/**
566; * Executes VMPTRLD
567; *
568; * @returns VBox status code
569; * @param HCPhysVMCS Physical address of VMCS structure
570; */
571;DECLASM(int) VMXActivateVMCS(RTHCPHYS HCPhysVMCS);
572BEGINPROC VMXActivateVMCS
573%ifdef __AMD64__
574 xor rax, rax
575 %ifdef ASM_CALL64_GCC
576 push rdi
577 %else
578 push rcx
579 %endif
580 vmptrld [rsp]
581%else
582 xor eax, eax
583 vmptrld [esp + 4]
584%endif
585 jnc .the_end
586 mov eax, VERR_VMX_INVALID_VMCS_PTR
587.the_end:
588%ifdef __AMD64__
589 add rsp, 8
590%endif
591 ret
592ENDPROC VMXActivateVMCS
593
594%endif ; __AMD64__
595
596
597;/**
598; * Prepares for and executes VMRUN
599; *
600; * @returns VBox status code
601; * @param HCPhysVMCB Physical address of host VMCB
602; * @param HCPhysVMCB Physical address of guest VMCB
603; * @param pCtx Guest context
604; */
605BEGINPROC SVMVMRun
606%ifdef __AMD64__ ; fake a cdecl stack frame - I'm lazy, sosume.
607 %ifdef ASM_CALL64_GCC
608 push rdx
609 push rsi
610 push rdi
611 %else
612 push r8
613 push rdx
614 push rcx
615 %endif
616 push 0
617%endif
618 push xBP
619 mov xBP, xSP
620
621 ;/* Manual save and restore:
622 ; * - General purpose registers except RIP, RSP, RAX
623 ; *
624 ; * Trashed:
625 ; * - CR2 (we don't care)
626 ; * - LDTR (reset to 0)
627 ; * - DRx (presumably not changed at all)
628 ; * - DR7 (reset to 0x400)
629 ; */
630
631 ;/* Save all general purpose host registers. */
632 MYPUSHAD
633
634 ;/* Save the Guest CPU context pointer. */
635 mov xSI, [xBP + xS*2 + RTHCPHYS_CB*2] ; pCtx
636 push xSI ; push for saving the state at the end
637
638 ; Restore CR2
639 mov ebx, [xSI + CPUMCTX.cr2]
640 mov cr2, xBX
641
642 ; save host fs, gs, sysenter msr etc
643 mov xAX, [xBP + xS*2] ; pVMCBHostPhys (64 bits physical address; x86: take low dword only)
644 push xAX ; save for the vmload after vmrun
645 DB 0x0F, 0x01, 0xDB ; VMSAVE
646
647 ; setup eax for VMLOAD
648 mov xAX, [xBP + xS*2 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address; take low dword only)
649
650 ;/* Restore Guest's general purpose registers. */
651 ;/* EAX is loaded from the VMCB by VMRUN */
652 mov ebx, [xSI + CPUMCTX.ebx]
653 mov ecx, [xSI + CPUMCTX.ecx]
654 mov edx, [xSI + CPUMCTX.edx]
655 mov edi, [xSI + CPUMCTX.edi]
656 mov ebp, [xSI + CPUMCTX.ebp]
657 mov esi, [xSI + CPUMCTX.esi]
658
659 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
660 DB 0x0f, 0x01, 0xDD ; CLGI
661 sti
662
663 ; load guest fs, gs, sysenter msr etc
664 DB 0x0f, 0x01, 0xDA ; VMLOAD
665 ; run the VM
666 DB 0x0F, 0x01, 0xD8 ; VMRUN
667
668 ;/* EAX is in the VMCB already; we can use it here. */
669
670 ; save guest fs, gs, sysenter msr etc
671 DB 0x0F, 0x01, 0xDB ; VMSAVE
672
673 ; load host fs, gs, sysenter msr etc
674 pop xAX ; pushed above
675 DB 0x0F, 0x01, 0xDA ; VMLOAD
676
677 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
678 cli
679 DB 0x0f, 0x01, 0xDC ; STGI
680
681 pop xAX ; pCtx
682
683 mov [ss:xAX + CPUMCTX.ebx], ebx
684 mov [ss:xAX + CPUMCTX.ecx], ecx
685 mov [ss:xAX + CPUMCTX.edx], edx
686 mov [ss:xAX + CPUMCTX.esi], esi
687 mov [ss:xAX + CPUMCTX.edi], edi
688 mov [ss:xAX + CPUMCTX.ebp], ebp
689
690 ; Restore general purpose registers
691 MYPOPAD
692
693 mov eax, VINF_SUCCESS
694
695 pop xBP
696%ifdef __AMD64__
697 add xSP, 4*xS
698%endif
699 ret
700ENDPROC SVMVMRun
701
702%ifdef __AMD64__
703%ifdef __WIN__
704
705;;
706; Executes INVLPGA
707;
708; @param pPageGC msc:ecx gcc:edi x86:[esp+04] Virtual page to invalidate
709; @param uASID msc:edx gcc:esi x86:[esp+08] Tagged TLB id
710;
711;DECLASM(void) SVMInvlpgA(RTGCPTR pPageGC, uint32_t uASID);
712BEGINPROC SVMInvlpgA
713%ifdef __AMD64__
714 %ifdef ASM_CALL64_GCC
715 mov eax, edi ;; @todo 64-bit guest.
716 mov ecx, esi
717 %else
718 mov eax, ecx ;; @todo 64-bit guest.
719 mov ecx, edx
720 %endif
721 invlpga rax, ecx
722%else
723 mov eax, [esp + 4]
724 mov ecx, [esp + 8]
725 invlpga eax, ecx
726%endif
727 ret
728ENDPROC SVMInvlpgA
729%endif
730%endif
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