VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMRC/HWACCMRCA.asm@ 42186

Last change on this file since 42186 was 37955, checked in by vboxsync, 13 years ago

Moved VBox/x86.h/mac to iprt/x86.h/mac.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 KB
Line 
1; $Id: HWACCMRCA.asm 37955 2011-07-14 12:23:02Z 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/vmm/hwacc_vmx.mac"
26%include "VBox/vmm/cpum.mac"
27%include "iprt/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 HCPhysCpuPage VMXON physical address [rsp+8]
94; * @param HCPhysVMCS 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] ; HCPhysCpuPage
148 mov [rbx + VMCSCACHE.TestIn.HCPhysCpuPage], rax
149 mov rax, [rbp + 16 + 8] ; HCPhysVMCS
150 mov [rbx + VMCSCACHE.TestIn.HCPhysVMCS], 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] ; HCPhysVMCS
364 mov [rdi + VMCSCACHE.TestOut.HCPhysVMCS], 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%endif
408
409 ; Restore segment registers
410 MYPOPSEGS rax
411
412 ; Restore all general purpose host registers.
413 mov eax, VERR_VMX_INVALID_VMXON_PTR
414 jmp .vmstart64_end
415
416.vmstart64_start_failed:
417 pop rsi ; pCtx (needed in rsi by the macros below)
418
419%ifdef VMX_USE_CACHED_VMCS_ACCESSES
420 pop rdi ; pCache
421
422 %ifdef DEBUG
423 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
424 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
425 %endif
426 %ifdef VBOX_WITH_CRASHDUMP_MAGIC
427 mov dword [rdi + VMCSCACHE.uPos], 11
428 %endif
429%endif
430
431 ; Restore segment registers
432 MYPOPSEGS rax
433
434 ; Restore all general purpose host registers.
435 mov eax, VERR_VMX_UNABLE_TO_START_VM
436 jmp .vmstart64_end
437ENDPROC VMXGCStartVM64
438
439
440;/**
441; * Prepares for and executes VMRUN (64 bits guests)
442; *
443; * @returns VBox status code
444; * @param HCPhysVMCB Physical address of host VMCB (rsp+8)
445; * @param HCPhysVMCB Physical address of guest VMCB (rsp+16)
446; * @param pCtx Guest context (rsi)
447; */
448BEGINPROC SVMGCVMRun64
449 push rbp
450 mov rbp, rsp
451 pushf
452
453 ;/* Manual save and restore:
454 ; * - General purpose registers except RIP, RSP, RAX
455 ; *
456 ; * Trashed:
457 ; * - CR2 (we don't care)
458 ; * - LDTR (reset to 0)
459 ; * - DRx (presumably not changed at all)
460 ; * - DR7 (reset to 0x400)
461 ; */
462
463 ;/* Save the Guest CPU context pointer. */
464 push rsi ; push for saving the state at the end
465
466 ; save host fs, gs, sysenter msr etc
467 mov rax, [rbp + 8 + 8] ; pVMCBHostPhys (64 bits physical address)
468 push rax ; save for the vmload after vmrun
469 vmsave
470
471 ; setup eax for VMLOAD
472 mov rax, [rbp + 8 + 8 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address)
473
474 ;/* Restore Guest's general purpose registers. */
475 ;/* RAX is loaded from the VMCB by VMRUN */
476 mov rbx, qword [rsi + CPUMCTX.ebx]
477 mov rcx, qword [rsi + CPUMCTX.ecx]
478 mov rdx, qword [rsi + CPUMCTX.edx]
479 mov rdi, qword [rsi + CPUMCTX.edi]
480 mov rbp, qword [rsi + CPUMCTX.ebp]
481 mov r8, qword [rsi + CPUMCTX.r8]
482 mov r9, qword [rsi + CPUMCTX.r9]
483 mov r10, qword [rsi + CPUMCTX.r10]
484 mov r11, qword [rsi + CPUMCTX.r11]
485 mov r12, qword [rsi + CPUMCTX.r12]
486 mov r13, qword [rsi + CPUMCTX.r13]
487 mov r14, qword [rsi + CPUMCTX.r14]
488 mov r15, qword [rsi + CPUMCTX.r15]
489 mov rsi, qword [rsi + CPUMCTX.esi]
490
491 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
492 clgi
493 sti
494
495 ; load guest fs, gs, sysenter msr etc
496 vmload
497 ; run the VM
498 vmrun
499
500 ;/* RAX is in the VMCB already; we can use it here. */
501
502 ; save guest fs, gs, sysenter msr etc
503 vmsave
504
505 ; load host fs, gs, sysenter msr etc
506 pop rax ; pushed above
507 vmload
508
509 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
510 cli
511 stgi
512
513 pop rax ; pCtx
514
515 mov qword [rax + CPUMCTX.ebx], rbx
516 mov qword [rax + CPUMCTX.ecx], rcx
517 mov qword [rax + CPUMCTX.edx], rdx
518 mov qword [rax + CPUMCTX.esi], rsi
519 mov qword [rax + CPUMCTX.edi], rdi
520 mov qword [rax + CPUMCTX.ebp], rbp
521 mov qword [rax + CPUMCTX.r8], r8
522 mov qword [rax + CPUMCTX.r9], r9
523 mov qword [rax + CPUMCTX.r10], r10
524 mov qword [rax + CPUMCTX.r11], r11
525 mov qword [rax + CPUMCTX.r12], r12
526 mov qword [rax + CPUMCTX.r13], r13
527 mov qword [rax + CPUMCTX.r14], r14
528 mov qword [rax + CPUMCTX.r15], r15
529
530 mov eax, VINF_SUCCESS
531
532 popf
533 pop rbp
534 ret
535ENDPROC SVMGCVMRun64
536
537;/**
538; * Saves the guest FPU context
539; *
540; * @returns VBox status code
541; * @param pCtx Guest context [rsi]
542; */
543BEGINPROC HWACCMSaveGuestFPU64
544 mov rax, cr0
545 mov rcx, rax ; save old CR0
546 and rax, ~(X86_CR0_TS | X86_CR0_EM)
547 mov cr0, rax
548
549 fxsave [rsi + CPUMCTX.fpu]
550
551 mov cr0, rcx ; and restore old CR0 again
552
553 mov eax, VINF_SUCCESS
554 ret
555ENDPROC HWACCMSaveGuestFPU64
556
557;/**
558; * Saves the guest debug context (DR0-3, DR6)
559; *
560; * @returns VBox status code
561; * @param pCtx Guest context [rsi]
562; */
563BEGINPROC HWACCMSaveGuestDebug64
564 mov rax, dr0
565 mov qword [rsi + CPUMCTX.dr + 0*8], rax
566 mov rax, dr1
567 mov qword [rsi + CPUMCTX.dr + 1*8], rax
568 mov rax, dr2
569 mov qword [rsi + CPUMCTX.dr + 2*8], rax
570 mov rax, dr3
571 mov qword [rsi + CPUMCTX.dr + 3*8], rax
572 mov rax, dr6
573 mov qword [rsi + CPUMCTX.dr + 6*8], rax
574 mov eax, VINF_SUCCESS
575 ret
576ENDPROC HWACCMSaveGuestDebug64
577
578;/**
579; * Dummy callback handler
580; *
581; * @returns VBox status code
582; * @param param1 Parameter 1 [rsp+8]
583; * @param param2 Parameter 2 [rsp+12]
584; * @param param3 Parameter 3 [rsp+16]
585; * @param param4 Parameter 4 [rsp+20]
586; * @param param5 Parameter 5 [rsp+24]
587; * @param pCtx Guest context [rsi]
588; */
589BEGINPROC HWACCMTestSwitcher64
590 mov eax, [rsp+8]
591 ret
592ENDPROC 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