VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMRC/HMRCA.asm@ 44876

Last change on this file since 44876 was 44771, checked in by vboxsync, 12 years ago

VMM/VMMR0: debug build burn fix II.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.9 KB
Line 
1; $Id: HMRCA.asm 44771 2013-02-20 17:45:39Z vboxsync $
2;; @file
3; VMXM - GC vmx helpers
4;
5
6;
7; Copyright (C) 2006-2012 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/hm_vmx.mac"
26%include "VBox/vmm/cpum.mac"
27%include "iprt/x86.mac"
28%include "HMInternal.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 LOADGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
235 LOADGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
236 LOADGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
237
238%ifdef VBOX_WITH_CRASHDUMP_MAGIC
239 mov qword [rbx + VMCSCACHE.uPos], 5
240%endif
241
242 ; Save the pCtx pointer
243 push rsi
244
245 ; Restore CR2
246 mov rbx, qword [rsi + CPUMCTX.cr2]
247 mov cr2, rbx
248
249 mov eax, VMX_VMCS_HOST_RSP
250 vmwrite rax, rsp
251 ;/* Note: assumes success... */
252 ;/* Don't mess with ESP anymore!! */
253
254 ;/* Restore Guest's general purpose registers. */
255 mov rax, qword [rsi + CPUMCTX.eax]
256 mov rbx, qword [rsi + CPUMCTX.ebx]
257 mov rcx, qword [rsi + CPUMCTX.ecx]
258 mov rdx, qword [rsi + CPUMCTX.edx]
259 mov rbp, qword [rsi + CPUMCTX.ebp]
260 mov r8, qword [rsi + CPUMCTX.r8]
261 mov r9, qword [rsi + CPUMCTX.r9]
262 mov r10, qword [rsi + CPUMCTX.r10]
263 mov r11, qword [rsi + CPUMCTX.r11]
264 mov r12, qword [rsi + CPUMCTX.r12]
265 mov r13, qword [rsi + CPUMCTX.r13]
266 mov r14, qword [rsi + CPUMCTX.r14]
267 mov r15, qword [rsi + CPUMCTX.r15]
268
269 ;/* Restore rdi & rsi. */
270 mov rdi, qword [rsi + CPUMCTX.edi]
271 mov rsi, qword [rsi + CPUMCTX.esi]
272
273 vmlaunch
274 jmp .vmlaunch64_done; ;/* here if vmlaunch detected a failure. */
275
276ALIGNCODE(16)
277.vmlaunch64_done:
278 jc near .vmstart64_invalid_vmxon_ptr
279 jz near .vmstart64_start_failed
280
281 push rdi
282 mov rdi, [rsp + 8] ; pCtx
283
284 mov qword [rdi + CPUMCTX.eax], rax
285 mov qword [rdi + CPUMCTX.ebx], rbx
286 mov qword [rdi + CPUMCTX.ecx], rcx
287 mov qword [rdi + CPUMCTX.edx], rdx
288 mov qword [rdi + CPUMCTX.esi], rsi
289 mov qword [rdi + CPUMCTX.ebp], rbp
290 mov qword [rdi + CPUMCTX.r8], r8
291 mov qword [rdi + CPUMCTX.r9], r9
292 mov qword [rdi + CPUMCTX.r10], r10
293 mov qword [rdi + CPUMCTX.r11], r11
294 mov qword [rdi + CPUMCTX.r12], r12
295 mov qword [rdi + CPUMCTX.r13], r13
296 mov qword [rdi + CPUMCTX.r14], r14
297 mov qword [rdi + CPUMCTX.r15], r15
298
299 pop rax ; the guest edi we pushed above
300 mov qword [rdi + CPUMCTX.edi], rax
301
302 pop rsi ; pCtx (needed in rsi by the macros below)
303
304 ;; @todo use the automatic load feature for MSRs
305 SAVEGUESTMSR MSR_K8_LSTAR, CPUMCTX.msrLSTAR
306 SAVEGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
307 SAVEGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
308 SAVEGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
309
310%ifdef VMX_USE_CACHED_VMCS_ACCESSES
311 pop rdi ; saved pCache
312
313 %ifdef VBOX_WITH_CRASHDUMP_MAGIC
314 mov dword [rdi + VMCSCACHE.uPos], 7
315 %endif
316 %ifdef DEBUG
317 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
318 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
319 mov rax, cr8
320 mov [rdi + VMCSCACHE.TestOut.cr8], rax
321 %endif
322
323 mov ecx, [rdi + VMCSCACHE.Read.cValidEntries]
324 cmp ecx, 0 ; can't happen
325 je .no_cached_reads
326 jmp .cached_read
327
328ALIGN(16)
329.cached_read:
330 dec rcx
331 mov eax, [rdi + VMCSCACHE.Read.aField + rcx*4]
332 vmread qword [rdi + VMCSCACHE.Read.aFieldVal + rcx*8], rax
333 cmp rcx, 0
334 jnz .cached_read
335.no_cached_reads:
336
337 ; Save CR2 for EPT
338 mov rax, cr2
339 mov [rdi + VMCSCACHE.cr2], rax
340 %ifdef VBOX_WITH_CRASHDUMP_MAGIC
341 mov dword [rdi + VMCSCACHE.uPos], 8
342 %endif
343%endif
344
345 ; Restore segment registers
346 MYPOPSEGS rax
347
348 mov eax, VINF_SUCCESS
349
350%ifdef VBOX_WITH_CRASHDUMP_MAGIC
351 mov dword [rdi + VMCSCACHE.uPos], 9
352%endif
353.vmstart64_end:
354
355%ifdef VMX_USE_CACHED_VMCS_ACCESSES
356 %ifdef DEBUG
357 mov rdx, [rsp] ; HCPhysVmcs
358 mov [rdi + VMCSCACHE.TestOut.HCPhysVmcs], rdx
359 %endif
360%endif
361
362 ; Write back the data and disable the VMCS
363 vmclear qword [rsp] ;Pushed pVMCS
364 add rsp, 8
365
366.vmstart64_vmxoff_end:
367 ; Disable VMX root mode
368 vmxoff
369.vmstart64_vmxon_failed:
370%ifdef VMX_USE_CACHED_VMCS_ACCESSES
371 %ifdef DEBUG
372 cmp eax, VINF_SUCCESS
373 jne .skip_flags_save
374
375 pushf
376 pop rdx
377 mov [rdi + VMCSCACHE.TestOut.eflags], rdx
378 %ifdef VBOX_WITH_CRASHDUMP_MAGIC
379 mov dword [rdi + VMCSCACHE.uPos], 12
380 %endif
381.skip_flags_save:
382 %endif
383%endif
384 pop rbp
385 ret
386
387
388.vmstart64_invalid_vmxon_ptr:
389 pop rsi ; pCtx (needed in rsi by the macros below)
390
391%ifdef VMX_USE_CACHED_VMCS_ACCESSES
392 pop rdi ; pCache
393 %ifdef VBOX_WITH_CRASHDUMP_MAGIC
394 mov dword [rdi + VMCSCACHE.uPos], 10
395 %endif
396
397 %ifdef DEBUG
398 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
399 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
400 %endif
401%endif
402
403 ; Restore segment registers
404 MYPOPSEGS rax
405
406 ; Restore all general purpose host registers.
407 mov eax, VERR_VMX_INVALID_VMXON_PTR
408 jmp .vmstart64_end
409
410.vmstart64_start_failed:
411 pop rsi ; pCtx (needed in rsi by the macros below)
412
413%ifdef VMX_USE_CACHED_VMCS_ACCESSES
414 pop rdi ; pCache
415
416 %ifdef DEBUG
417 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
418 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
419 %endif
420 %ifdef VBOX_WITH_CRASHDUMP_MAGIC
421 mov dword [rdi + VMCSCACHE.uPos], 11
422 %endif
423%endif
424
425 ; Restore segment registers
426 MYPOPSEGS rax
427
428 ; Restore all general purpose host registers.
429 mov eax, VERR_VMX_UNABLE_TO_START_VM
430 jmp .vmstart64_end
431ENDPROC VMXGCStartVM64
432
433
434;/**
435; * Prepares for and executes VMRUN (64 bits guests)
436; *
437; * @returns VBox status code
438; * @param HCPhysVMCB Physical address of host VMCB (rsp+8)
439; * @param HCPhysVMCB Physical address of guest VMCB (rsp+16)
440; * @param pCtx Guest context (rsi)
441; */
442BEGINPROC SVMGCVMRun64
443 push rbp
444 mov rbp, rsp
445 pushf
446
447 ;/* Manual save and restore:
448 ; * - General purpose registers except RIP, RSP, RAX
449 ; *
450 ; * Trashed:
451 ; * - CR2 (we don't care)
452 ; * - LDTR (reset to 0)
453 ; * - DRx (presumably not changed at all)
454 ; * - DR7 (reset to 0x400)
455 ; */
456
457 ;/* Save the Guest CPU context pointer. */
458 push rsi ; push for saving the state at the end
459
460 ; save host fs, gs, sysenter msr etc
461 mov rax, [rbp + 8 + 8] ; pVMCBHostPhys (64 bits physical address)
462 push rax ; save for the vmload after vmrun
463 vmsave
464
465 ; setup eax for VMLOAD
466 mov rax, [rbp + 8 + 8 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address)
467
468 ;/* Restore Guest's general purpose registers. */
469 ;/* RAX is loaded from the VMCB by VMRUN */
470 mov rbx, qword [rsi + CPUMCTX.ebx]
471 mov rcx, qword [rsi + CPUMCTX.ecx]
472 mov rdx, qword [rsi + CPUMCTX.edx]
473 mov rdi, qword [rsi + CPUMCTX.edi]
474 mov rbp, qword [rsi + CPUMCTX.ebp]
475 mov r8, qword [rsi + CPUMCTX.r8]
476 mov r9, qword [rsi + CPUMCTX.r9]
477 mov r10, qword [rsi + CPUMCTX.r10]
478 mov r11, qword [rsi + CPUMCTX.r11]
479 mov r12, qword [rsi + CPUMCTX.r12]
480 mov r13, qword [rsi + CPUMCTX.r13]
481 mov r14, qword [rsi + CPUMCTX.r14]
482 mov r15, qword [rsi + CPUMCTX.r15]
483 mov rsi, qword [rsi + CPUMCTX.esi]
484
485 ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
486 clgi
487 sti
488
489 ; load guest fs, gs, sysenter msr etc
490 vmload
491 ; run the VM
492 vmrun
493
494 ;/* RAX is in the VMCB already; we can use it here. */
495
496 ; save guest fs, gs, sysenter msr etc
497 vmsave
498
499 ; load host fs, gs, sysenter msr etc
500 pop rax ; pushed above
501 vmload
502
503 ; Set the global interrupt flag again, but execute cli to make sure IF=0.
504 cli
505 stgi
506
507 pop rax ; pCtx
508
509 mov qword [rax + CPUMCTX.ebx], rbx
510 mov qword [rax + CPUMCTX.ecx], rcx
511 mov qword [rax + CPUMCTX.edx], rdx
512 mov qword [rax + CPUMCTX.esi], rsi
513 mov qword [rax + CPUMCTX.edi], rdi
514 mov qword [rax + CPUMCTX.ebp], rbp
515 mov qword [rax + CPUMCTX.r8], r8
516 mov qword [rax + CPUMCTX.r9], r9
517 mov qword [rax + CPUMCTX.r10], r10
518 mov qword [rax + CPUMCTX.r11], r11
519 mov qword [rax + CPUMCTX.r12], r12
520 mov qword [rax + CPUMCTX.r13], r13
521 mov qword [rax + CPUMCTX.r14], r14
522 mov qword [rax + CPUMCTX.r15], r15
523
524 mov eax, VINF_SUCCESS
525
526 popf
527 pop rbp
528 ret
529ENDPROC SVMGCVMRun64
530
531;/**
532; * Saves the guest FPU context
533; *
534; * @returns VBox status code
535; * @param pCtx Guest context [rsi]
536; */
537BEGINPROC HMSaveGuestFPU64
538 mov rax, cr0
539 mov rcx, rax ; save old CR0
540 and rax, ~(X86_CR0_TS | X86_CR0_EM)
541 mov cr0, rax
542
543 fxsave [rsi + CPUMCTX.fpu]
544
545 mov cr0, rcx ; and restore old CR0 again
546
547 mov eax, VINF_SUCCESS
548 ret
549ENDPROC HMSaveGuestFPU64
550
551;/**
552; * Saves the guest debug context (DR0-3, DR6)
553; *
554; * @returns VBox status code
555; * @param pCtx Guest context [rsi]
556; */
557BEGINPROC HMSaveGuestDebug64
558 mov rax, dr0
559 mov qword [rsi + CPUMCTX.dr + 0*8], rax
560 mov rax, dr1
561 mov qword [rsi + CPUMCTX.dr + 1*8], rax
562 mov rax, dr2
563 mov qword [rsi + CPUMCTX.dr + 2*8], rax
564 mov rax, dr3
565 mov qword [rsi + CPUMCTX.dr + 3*8], rax
566 mov rax, dr6
567 mov qword [rsi + CPUMCTX.dr + 6*8], rax
568 mov eax, VINF_SUCCESS
569 ret
570ENDPROC HMSaveGuestDebug64
571
572;/**
573; * Dummy callback handler
574; *
575; * @returns VBox status code
576; * @param param1 Parameter 1 [rsp+8]
577; * @param param2 Parameter 2 [rsp+12]
578; * @param param3 Parameter 3 [rsp+16]
579; * @param param4 Parameter 4 [rsp+20]
580; * @param param5 Parameter 5 [rsp+24]
581; * @param pCtx Guest context [rsi]
582; */
583BEGINPROC HMTestSwitcher64
584 mov eax, [rsp+8]
585 ret
586ENDPROC HMTestSwitcher64
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