VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGC/HWACCMGCA.asm@ 29698

Last change on this file since 29698 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 KB
Line 
1; $Id: HWACCMGCA.asm 28800 2010-04-27 08:22:32Z vboxsync $
2;; @file
3; VMXM - GC vmx helpers
4;
5
6;
7; Copyright (C) 2006-2007 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17
18;*******************************************************************************
19;* Header Files *
20;*******************************************************************************
21%undef RT_ARCH_X86
22%define RT_ARCH_AMD64
23%include "VBox/asmdefs.mac"
24%include "VBox/err.mac"
25%include "VBox/hwacc_vmx.mac"
26%include "VBox/cpum.mac"
27%include "VBox/x86.mac"
28%include "../HWACCMInternal.mac"
29
30%ifdef RT_OS_OS2 ;; @todo fix OMF support in yasm and kick nasm out completely.
31 %macro vmwrite 2,
32 int3
33 %endmacro
34 %define vmlaunch int3
35 %define vmresume int3
36 %define vmsave int3
37 %define vmload int3
38 %define vmrun int3
39 %define clgi int3
40 %define stgi int3
41 %macro invlpga 2,
42 int3
43 %endmacro
44%endif
45
46;; @def MYPUSHSEGS
47; Macro saving all segment registers on the stack.
48; @param 1 full width register name
49
50;; @def MYPOPSEGS
51; Macro restoring all segment registers on the stack
52; @param 1 full width register name
53
54 ; Load the corresponding guest MSR (trashes rdx & rcx)
55 %macro LOADGUESTMSR 2
56 mov rcx, %1
57 mov edx, dword [rsi + %2 + 4]
58 mov eax, dword [rsi + %2]
59 wrmsr
60 %endmacro
61
62 ; Save a guest MSR (trashes rdx & rcx)
63 ; Only really useful for gs kernel base as that one can be changed behind our back (swapgs)
64 %macro SAVEGUESTMSR 2
65 mov rcx, %1
66 rdmsr
67 mov dword [rsi + %2], eax
68 mov dword [rsi + %2 + 4], edx
69 %endmacro
70
71 %macro MYPUSHSEGS 1
72 mov %1, es
73 push %1
74 mov %1, ds
75 push %1
76 %endmacro
77
78 %macro MYPOPSEGS 1
79 pop %1
80 mov ds, %1
81 pop %1
82 mov es, %1
83 %endmacro
84
85BEGINCODE
86BITS 64
87
88
89;/**
90; * Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
91; *
92; * @returns VBox status code
93; * @param pPageCpuPhys VMXON physical address [rsp+8]
94; * @param pVMCSPhys VMCS physical address [rsp+16]
95; * @param pCache VMCS cache [rsp+24]
96; * @param pCtx Guest context (rsi)
97; */
98BEGINPROC VMXGCStartVM64
99 push rbp
100 mov rbp, rsp
101
102 ; Make sure VT-x instructions are allowed
103 mov rax, cr4
104 or rax, X86_CR4_VMXE
105 mov cr4, rax
106
107 ;/* Enter VMX Root Mode */
108 vmxon [rbp + 8 + 8]
109 jnc .vmxon_success
110 mov rax, VERR_VMX_INVALID_VMXON_PTR
111 jmp .vmstart64_vmxon_failed
112
113.vmxon_success:
114 jnz .vmxon_success2
115 mov rax, VERR_VMX_GENERIC
116 jmp .vmstart64_vmxon_failed
117
118.vmxon_success2:
119 ; Activate the VMCS pointer
120 vmptrld [rbp + 16 + 8]
121 jnc .vmptrld_success
122 mov rax, VERR_VMX_INVALID_VMCS_PTR
123 jmp .vmstart64_vmxoff_end
124
125.vmptrld_success:
126 jnz .vmptrld_success2
127 mov rax, VERR_VMX_GENERIC
128 jmp .vmstart64_vmxoff_end
129
130.vmptrld_success2:
131
132 ; Save the VMCS pointer on the stack
133 push qword [rbp + 16 + 8];
134
135 ;/* Save segment registers */
136 MYPUSHSEGS rax
137
138%ifdef VMX_USE_CACHED_VMCS_ACCESSES
139 ; Flush the VMCS write cache first (before any other vmreads/vmwrites!)
140 mov rbx, [rbp + 24 + 8] ; pCache
141
142%ifdef VBOX_WITH_CRASHDUMP_MAGIC
143 mov qword [rbx + VMCSCACHE.uPos], 2
144%endif
145
146%ifdef DEBUG
147 mov rax, [rbp + 8 + 8] ; pPageCpuPhys
148 mov [rbx + VMCSCACHE.TestIn.pPageCpuPhys], rax
149 mov rax, [rbp + 16 + 8] ; pVMCSPhys
150 mov [rbx + VMCSCACHE.TestIn.pVMCSPhys], rax
151 mov [rbx + VMCSCACHE.TestIn.pCache], rbx
152 mov [rbx + VMCSCACHE.TestIn.pCtx], rsi
153%endif
154
155 mov ecx, [rbx + VMCSCACHE.Write.cValidEntries]
156 cmp ecx, 0
157 je .no_cached_writes
158 mov rdx, rcx
159 mov rcx, 0
160 jmp .cached_write
161
162ALIGN(16)
163.cached_write:
164 mov eax, [rbx + VMCSCACHE.Write.aField + rcx*4]
165 vmwrite rax, qword [rbx + VMCSCACHE.Write.aFieldVal + rcx*8]
166 inc rcx
167 cmp rcx, rdx
168 jl .cached_write
169
170 mov dword [rbx + VMCSCACHE.Write.cValidEntries], 0
171.no_cached_writes:
172
173%ifdef VBOX_WITH_CRASHDUMP_MAGIC
174 mov qword [rbx + VMCSCACHE.uPos], 3
175%endif
176 ; Save the pCache pointer
177 push xBX
178%endif
179
180 ; Save the host state that's relevant in the temporary 64 bits mode
181 mov rdx, cr0
182 mov eax, VMX_VMCS_HOST_CR0
183 vmwrite rax, rdx
184
185 mov rdx, cr3
186 mov eax, VMX_VMCS_HOST_CR3
187 vmwrite rax, rdx
188
189 mov rdx, cr4
190 mov eax, VMX_VMCS_HOST_CR4
191 vmwrite rax, rdx
192
193 mov rdx, cs
194 mov eax, VMX_VMCS_HOST_FIELD_CS
195 vmwrite rax, rdx
196
197 mov rdx, ss
198 mov eax, VMX_VMCS_HOST_FIELD_SS
199 vmwrite rax, rdx
200
201 sub rsp, 8*2
202 sgdt [rsp]
203 mov eax, VMX_VMCS_HOST_GDTR_BASE
204 vmwrite rax, [rsp+2]
205 add rsp, 8*2
206
207%ifdef VBOX_WITH_CRASHDUMP_MAGIC
208 mov qword [rbx + VMCSCACHE.uPos], 4
209%endif
210
211 ; hopefully we can ignore TR (we restore it anyway on the way back to 32 bits mode)
212
213 ;/* First we have to save some final CPU context registers. */
214 lea rdx, [.vmlaunch64_done wrt rip]
215 mov rax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
216 vmwrite rax, rdx
217 ;/* Note: assumes success... */
218
219 ;/* Manual save and restore:
220 ; * - General purpose registers except RIP, RSP
221 ; *
222 ; * Trashed:
223 ; * - CR2 (we don't care)
224 ; * - LDTR (reset to 0)
225 ; * - DRx (presumably not changed at all)
226 ; * - DR7 (reset to 0x400)
227 ; * - EFLAGS (reset to RT_BIT(1); not relevant)
228 ; *
229 ; */
230
231 ; Load the guest LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
232 ;; @todo use the automatic load feature for MSRs
233 LOADGUESTMSR MSR_K8_LSTAR, CPUMCTX.msrLSTAR
234%if 0 ; not supported on Intel CPUs
235 LOADGUESTMSR MSR_K8_CSTAR, CPUMCTX.msrCSTAR
236%endif
237 LOADGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
238 LOADGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
239 LOADGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
240
241%ifdef VBOX_WITH_CRASHDUMP_MAGIC
242 mov qword [rbx + VMCSCACHE.uPos], 5
243%endif
244
245 ; Save the pCtx pointer
246 push rsi
247
248 ; Restore CR2
249 mov rbx, qword [rsi + CPUMCTX.cr2]
250 mov cr2, rbx
251
252 mov eax, VMX_VMCS_HOST_RSP
253 vmwrite rax, rsp
254 ;/* Note: assumes success... */
255 ;/* Don't mess with ESP anymore!! */
256
257 ;/* Restore Guest's general purpose registers. */
258 mov rax, qword [rsi + CPUMCTX.eax]
259 mov rbx, qword [rsi + CPUMCTX.ebx]
260 mov rcx, qword [rsi + CPUMCTX.ecx]
261 mov rdx, qword [rsi + CPUMCTX.edx]
262 mov rbp, qword [rsi + CPUMCTX.ebp]
263 mov r8, qword [rsi + CPUMCTX.r8]
264 mov r9, qword [rsi + CPUMCTX.r9]
265 mov r10, qword [rsi + CPUMCTX.r10]
266 mov r11, qword [rsi + CPUMCTX.r11]
267 mov r12, qword [rsi + CPUMCTX.r12]
268 mov r13, qword [rsi + CPUMCTX.r13]
269 mov r14, qword [rsi + CPUMCTX.r14]
270 mov r15, qword [rsi + CPUMCTX.r15]
271
272 ;/* Restore rdi & rsi. */
273 mov rdi, qword [rsi + CPUMCTX.edi]
274 mov rsi, qword [rsi + CPUMCTX.esi]
275
276 vmlaunch
277 jmp .vmlaunch64_done; ;/* here if vmlaunch detected a failure. */
278
279ALIGNCODE(16)
280.vmlaunch64_done:
281 jc near .vmstart64_invalid_vmxon_ptr
282 jz near .vmstart64_start_failed
283
284 push rdi
285 mov rdi, [rsp + 8] ; pCtx
286
287 mov qword [rdi + CPUMCTX.eax], rax
288 mov qword [rdi + CPUMCTX.ebx], rbx
289 mov qword [rdi + CPUMCTX.ecx], rcx
290 mov qword [rdi + CPUMCTX.edx], rdx
291 mov qword [rdi + CPUMCTX.esi], rsi
292 mov qword [rdi + CPUMCTX.ebp], rbp
293 mov qword [rdi + CPUMCTX.r8], r8
294 mov qword [rdi + CPUMCTX.r9], r9
295 mov qword [rdi + CPUMCTX.r10], r10
296 mov qword [rdi + CPUMCTX.r11], r11
297 mov qword [rdi + CPUMCTX.r12], r12
298 mov qword [rdi + CPUMCTX.r13], r13
299 mov qword [rdi + CPUMCTX.r14], r14
300 mov qword [rdi + CPUMCTX.r15], r15
301
302 pop rax ; the guest edi we pushed above
303 mov qword [rdi + CPUMCTX.edi], rax
304
305 pop rsi ; pCtx (needed in rsi by the macros below)
306
307 ;; @todo use the automatic load feature for MSRs
308 SAVEGUESTMSR MSR_K8_LSTAR, CPUMCTX.msrLSTAR
309%if 0 ; not supported on Intel CPUs
310 SAVEGUESTMSR MSR_K8_CSTAR, CPUMCTX.msrCSTAR
311%endif
312 SAVEGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
313 SAVEGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
314 SAVEGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
315
316%ifdef VMX_USE_CACHED_VMCS_ACCESSES
317 pop rdi ; saved pCache
318
319%ifdef VBOX_WITH_CRASHDUMP_MAGIC
320 mov dword [rdi + VMCSCACHE.uPos], 7
321%endif
322%ifdef DEBUG
323 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
324 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
325 mov rax, cr8
326 mov [rdi + VMCSCACHE.TestOut.cr8], rax
327%endif
328
329 mov ecx, [rdi + VMCSCACHE.Read.cValidEntries]
330 cmp ecx, 0 ; can't happen
331 je .no_cached_reads
332 jmp .cached_read
333
334ALIGN(16)
335.cached_read:
336 dec rcx
337 mov eax, [rdi + VMCSCACHE.Read.aField + rcx*4]
338 vmread qword [rdi + VMCSCACHE.Read.aFieldVal + rcx*8], rax
339 cmp rcx, 0
340 jnz .cached_read
341.no_cached_reads:
342
343 ; Save CR2 for EPT
344 mov rax, cr2
345 mov [rdi + VMCSCACHE.cr2], rax
346%ifdef VBOX_WITH_CRASHDUMP_MAGIC
347 mov dword [rdi + VMCSCACHE.uPos], 8
348%endif
349%endif
350
351 ; Restore segment registers
352 MYPOPSEGS rax
353
354 mov eax, VINF_SUCCESS
355
356%ifdef VBOX_WITH_CRASHDUMP_MAGIC
357 mov dword [rdi + VMCSCACHE.uPos], 9
358%endif
359.vmstart64_end:
360
361%ifdef VMX_USE_CACHED_VMCS_ACCESSES
362%ifdef DEBUG
363 mov rdx, [rsp] ; pVMCSPhys
364 mov [rdi + VMCSCACHE.TestOut.pVMCSPhys], rdx
365%endif
366%endif
367
368 ; Write back the data and disable the VMCS
369 vmclear qword [rsp] ;Pushed pVMCS
370 add rsp, 8
371
372.vmstart64_vmxoff_end:
373 ; Disable VMX root mode
374 vmxoff
375.vmstart64_vmxon_failed:
376%ifdef VMX_USE_CACHED_VMCS_ACCESSES
377%ifdef DEBUG
378 cmp eax, VINF_SUCCESS
379 jne .skip_flags_save
380
381 pushf
382 pop rdx
383 mov [rdi + VMCSCACHE.TestOut.eflags], rdx
384%ifdef VBOX_WITH_CRASHDUMP_MAGIC
385 mov dword [rdi + VMCSCACHE.uPos], 12
386%endif
387.skip_flags_save:
388%endif
389%endif
390 pop rbp
391 ret
392
393
394.vmstart64_invalid_vmxon_ptr:
395 pop rsi ; pCtx (needed in rsi by the macros below)
396
397%ifdef VMX_USE_CACHED_VMCS_ACCESSES
398 pop rdi ; pCache
399%ifdef VBOX_WITH_CRASHDUMP_MAGIC
400 mov dword [rdi + VMCSCACHE.uPos], 10
401%endif
402
403%ifdef DEBUG
404 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
405 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
406%endif
407
408%endif
409
410 ; Restore segment registers
411 MYPOPSEGS rax
412
413 ; Restore all general purpose host registers.
414 mov eax, VERR_VMX_INVALID_VMXON_PTR
415 jmp .vmstart64_end
416
417.vmstart64_start_failed:
418 pop rsi ; pCtx (needed in rsi by the macros below)
419
420%ifdef VMX_USE_CACHED_VMCS_ACCESSES
421 pop rdi ; pCache
422
423%ifdef DEBUG
424 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
425 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
426%endif
427%ifdef VBOX_WITH_CRASHDUMP_MAGIC
428 mov dword [rdi + VMCSCACHE.uPos], 11
429%endif
430
431%endif
432
433 ; Restore segment registers
434 MYPOPSEGS rax
435
436 ; Restore all general purpose host registers.
437 mov eax, VERR_VMX_UNABLE_TO_START_VM
438 jmp .vmstart64_end
439ENDPROC VMXGCStartVM64
440
441
442;/**
443; * Prepares for and executes VMRUN (64 bits guests)
444; *
445; * @returns VBox status code
446; * @param HCPhysVMCB Physical address of host VMCB (rsp+8)
447; * @param HCPhysVMCB Physical address of guest VMCB (rsp+16)
448; * @param pCtx Guest context (rsi)
449; */
450BEGINPROC SVMGCVMRun64
451 push rbp
452 mov rbp, rsp
453 pushf
454
455 ;/* Manual save and restore:
456 ; * - General purpose registers except RIP, RSP, RAX
457 ; *
458 ; * Trashed:
459 ; * - CR2 (we don't care)
460 ; * - LDTR (reset to 0)
461 ; * - DRx (presumably not changed at all)
462 ; * - DR7 (reset to 0x400)
463 ; */
464
465 ;/* Save the Guest CPU context pointer. */
466 push rsi ; push for saving the state at the end
467
468 ; save host fs, gs, sysenter msr etc
469 mov rax, [rbp + 8 + 8] ; pVMCBHostPhys (64 bits physical address)
470 push rax ; save for the vmload after vmrun
471 vmsave
472
473 ; setup eax for VMLOAD
474 mov rax, [rbp + 8 + 8 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address)
475
476 ;/* Restore Guest's general purpose registers. */
477 ;/* RAX is loaded from the VMCB by VMRUN */
478 mov rbx, qword [rsi + CPUMCTX.ebx]
479 mov rcx, qword [rsi + CPUMCTX.ecx]
480 mov rdx, qword [rsi + CPUMCTX.edx]
481 mov rdi, qword [rsi + CPUMCTX.edi]
482 mov rbp, qword [rsi + CPUMCTX.ebp]
483 mov r8, qword [rsi + CPUMCTX.r8]
484 mov r9, qword [rsi + CPUMCTX.r9]
485 mov r10, qword [rsi + CPUMCTX.r10]
486 mov r11, qword [rsi + CPUMCTX.r11]
487 mov r12, qword [rsi + CPUMCTX.r12]
488 mov r13, qword [rsi + CPUMCTX.r13]
489 mov r14, qword [rsi + CPUMCTX.r14]
490 mov r15, qword [rsi + CPUMCTX.r15]
491 mov rsi, qword [rsi + CPUMCTX.esi]
492
493 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
494 clgi
495 sti
496
497 ; load guest fs, gs, sysenter msr etc
498 vmload
499 ; run the VM
500 vmrun
501
502 ;/* RAX is in the VMCB already; we can use it here. */
503
504 ; save guest fs, gs, sysenter msr etc
505 vmsave
506
507 ; load host fs, gs, sysenter msr etc
508 pop rax ; pushed above
509 vmload
510
511 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
512 cli
513 stgi
514
515 pop rax ; pCtx
516
517 mov qword [rax + CPUMCTX.ebx], rbx
518 mov qword [rax + CPUMCTX.ecx], rcx
519 mov qword [rax + CPUMCTX.edx], rdx
520 mov qword [rax + CPUMCTX.esi], rsi
521 mov qword [rax + CPUMCTX.edi], rdi
522 mov qword [rax + CPUMCTX.ebp], rbp
523 mov qword [rax + CPUMCTX.r8], r8
524 mov qword [rax + CPUMCTX.r9], r9
525 mov qword [rax + CPUMCTX.r10], r10
526 mov qword [rax + CPUMCTX.r11], r11
527 mov qword [rax + CPUMCTX.r12], r12
528 mov qword [rax + CPUMCTX.r13], r13
529 mov qword [rax + CPUMCTX.r14], r14
530 mov qword [rax + CPUMCTX.r15], r15
531
532 mov eax, VINF_SUCCESS
533
534 popf
535 pop rbp
536 ret
537ENDPROC SVMGCVMRun64
538
539;/**
540; * Saves the guest FPU context
541; *
542; * @returns VBox status code
543; * @param pCtx Guest context [rsi]
544; */
545BEGINPROC HWACCMSaveGuestFPU64
546 mov rax, cr0
547 mov rcx, rax ; save old CR0
548 and rax, ~(X86_CR0_TS | X86_CR0_EM)
549 mov cr0, rax
550
551 fxsave [rsi + CPUMCTX.fpu]
552
553 mov cr0, rcx ; and restore old CR0 again
554
555 mov eax, VINF_SUCCESS
556 ret
557ENDPROC HWACCMSaveGuestFPU64
558
559;/**
560; * Saves the guest debug context (DR0-3, DR6)
561; *
562; * @returns VBox status code
563; * @param pCtx Guest context [rsi]
564; */
565BEGINPROC HWACCMSaveGuestDebug64
566 mov rax, dr0
567 mov qword [rsi + CPUMCTX.dr + 0*8], rax
568 mov rax, dr1
569 mov qword [rsi + CPUMCTX.dr + 1*8], rax
570 mov rax, dr2
571 mov qword [rsi + CPUMCTX.dr + 2*8], rax
572 mov rax, dr3
573 mov qword [rsi + CPUMCTX.dr + 3*8], rax
574 mov rax, dr6
575 mov qword [rsi + CPUMCTX.dr + 6*8], rax
576 mov eax, VINF_SUCCESS
577 ret
578ENDPROC HWACCMSaveGuestDebug64
579
580;/**
581; * Dummy callback handler
582; *
583; * @returns VBox status code
584; * @param param1 Parameter 1 [rsp+8]
585; * @param param2 Parameter 2 [rsp+12]
586; * @param param3 Parameter 3 [rsp+16]
587; * @param param4 Parameter 4 [rsp+20]
588; * @param param5 Parameter 5 [rsp+24]
589; * @param pCtx Guest context [rsi]
590; */
591BEGINPROC HWACCMTestSwitcher64
592 mov eax, [rsp+8]
593 ret
594ENDPROC HWACCMTestSwitcher64
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