VirtualBox

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

Last change on this file since 20543 was 15962, checked in by vboxsync, 16 years ago

Added debugging code (inactive) for tracking the state of the 32/64 switcher in crash dumps

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.0 KB
Line 
1; $Id: HWACCMGCA.asm 15962 2009-01-15 12:33:49Z vboxsync $
2;; @file
3; VMXM - GC vmx helpers
4;
5
6;
7; Copyright (C) 2006-2007 Sun Microsystems, Inc.
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; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18; Clara, CA 95054 USA or visit http://www.sun.com if you need
19; additional information or have any questions.
20;
21
22;*******************************************************************************
23;* Header Files *
24;*******************************************************************************
25%undef RT_ARCH_X86
26%define RT_ARCH_AMD64
27%include "VBox/asmdefs.mac"
28%include "VBox/err.mac"
29%include "VBox/hwacc_vmx.mac"
30%include "VBox/cpum.mac"
31%include "VBox/x86.mac"
32%include "../HWACCMInternal.mac"
33
34%ifdef RT_OS_OS2 ;; @todo fix OMF support in yasm and kick nasm out completely.
35 %macro vmwrite 2,
36 int3
37 %endmacro
38 %define vmlaunch int3
39 %define vmresume int3
40 %define vmsave int3
41 %define vmload int3
42 %define vmrun int3
43 %define clgi int3
44 %define stgi int3
45 %macro invlpga 2,
46 int3
47 %endmacro
48%endif
49
50;; @def MYPUSHSEGS
51; Macro saving all segment registers on the stack.
52; @param 1 full width register name
53
54;; @def MYPOPSEGS
55; Macro restoring all segment registers on the stack
56; @param 1 full width register name
57
58 ; Load the corresponding guest MSR (trashes rdx & rcx)
59 %macro LOADGUESTMSR 2
60 mov rcx, %1
61 mov edx, dword [rsi + %2 + 4]
62 mov eax, dword [rsi + %2]
63 wrmsr
64 %endmacro
65
66 ; Save a guest MSR (trashes rdx & rcx)
67 ; Only really useful for gs kernel base as that one can be changed behind our back (swapgs)
68 %macro SAVEGUESTMSR 2
69 mov rcx, %1
70 rdmsr
71 mov dword [rsi + %2], eax
72 mov dword [rsi + %2 + 4], edx
73 %endmacro
74
75 %macro MYPUSHSEGS 1
76 mov %1, es
77 push %1
78 mov %1, ds
79 push %1
80 %endmacro
81
82 %macro MYPOPSEGS 1
83 pop %1
84 mov ds, %1
85 pop %1
86 mov es, %1
87 %endmacro
88
89BEGINCODE
90BITS 64
91
92
93;/**
94; * Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
95; *
96; * @returns VBox status code
97; * @param pPageCpuPhys VMXON physical address [rsp+8]
98; * @param pVMCSPhys VMCS physical address [rsp+16]
99; * @param pCache VMCS cache [rsp+24]
100; * @param pCtx Guest context (rsi)
101; */
102BEGINPROC VMXGCStartVM64
103 push rbp
104 mov rbp, rsp
105
106 ; Make sure VT-x instructions are allowed
107 mov rax, cr4
108 or rax, X86_CR4_VMXE
109 mov cr4, rax
110
111 ;/* Enter VMX Root Mode */
112 vmxon [rbp + 8 + 8]
113 jnc .vmxon_success
114 mov rax, VERR_VMX_INVALID_VMXON_PTR
115 jmp .vmstart64_vmxon_failed
116
117.vmxon_success:
118 jnz .vmxon_success2
119 mov rax, VERR_VMX_GENERIC
120 jmp .vmstart64_vmxon_failed
121
122.vmxon_success2:
123 ; Activate the VMCS pointer
124 vmptrld [rbp + 16 + 8]
125 jnc .vmptrld_success
126 mov rax, VERR_VMX_INVALID_VMCS_PTR
127 jmp .vmstart64_vmxoff_end
128
129.vmptrld_success:
130 jnz .vmptrld_success2
131 mov rax, VERR_VMX_GENERIC
132 jmp .vmstart64_vmxoff_end
133
134.vmptrld_success2:
135
136 ; Save the VMCS pointer on the stack
137 push qword [rbp + 16 + 8];
138
139 ;/* Save segment registers */
140 MYPUSHSEGS rax
141
142%ifdef VMX_USE_CACHED_VMCS_ACCESSES
143 ; Flush the VMCS write cache first (before any other vmreads/vmwrites!)
144 mov rbx, [rbp + 24 + 8] ; pCache
145
146%ifdef VBOX_WITH_CRASHDUMP_MAGIC
147 mov qword [rbx + VMCSCACHE.uPos], 2
148%endif
149
150%ifdef DEBUG
151 mov rax, [rbp + 8 + 8] ; pPageCpuPhys
152 mov [rbx + VMCSCACHE.TestIn.pPageCpuPhys], rax
153 mov rax, [rbp + 16 + 8] ; pVMCSPhys
154 mov [rbx + VMCSCACHE.TestIn.pVMCSPhys], rax
155 mov [rbx + VMCSCACHE.TestIn.pCache], rbx
156 mov [rbx + VMCSCACHE.TestIn.pCtx], rsi
157%endif
158
159 mov ecx, [rbx + VMCSCACHE.Write.cValidEntries]
160 cmp ecx, 0
161 je .no_cached_writes
162 mov rdx, rcx
163 mov rcx, 0
164 jmp .cached_write
165
166ALIGN(16)
167.cached_write:
168 mov eax, [rbx + VMCSCACHE.Write.aField + rcx*4]
169 vmwrite rax, qword [rbx + VMCSCACHE.Write.aFieldVal + rcx*8]
170 inc rcx
171 cmp rcx, rdx
172 jl .cached_write
173
174 mov dword [rbx + VMCSCACHE.Write.cValidEntries], 0
175.no_cached_writes:
176
177%ifdef VBOX_WITH_CRASHDUMP_MAGIC
178 mov qword [rbx + VMCSCACHE.uPos], 3
179%endif
180 ; Save the pCache pointer
181 push xBX
182%endif
183
184 ; Save the host state that's relevant in the temporary 64 bits mode
185 mov rdx, cr0
186 mov eax, VMX_VMCS_HOST_CR0
187 vmwrite rax, rdx
188
189 mov rdx, cr3
190 mov eax, VMX_VMCS_HOST_CR3
191 vmwrite rax, rdx
192
193 mov rdx, cr4
194 mov eax, VMX_VMCS_HOST_CR4
195 vmwrite rax, rdx
196
197 mov rdx, cs
198 mov eax, VMX_VMCS_HOST_FIELD_CS
199 vmwrite rax, rdx
200
201 mov rdx, ss
202 mov eax, VMX_VMCS_HOST_FIELD_SS
203 vmwrite rax, rdx
204
205 sub rsp, 8*2
206 sgdt [rsp]
207 mov eax, VMX_VMCS_HOST_GDTR_BASE
208 vmwrite rax, [rsp+2]
209 add rsp, 8*2
210
211%ifdef VBOX_WITH_CRASHDUMP_MAGIC
212 mov qword [rbx + VMCSCACHE.uPos], 4
213%endif
214
215 ; hopefully we can ignore TR (we restore it anyway on the way back to 32 bits mode)
216
217 ;/* First we have to save some final CPU context registers. */
218 lea rdx, [.vmlaunch64_done wrt rip]
219 mov rax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
220 vmwrite rax, rdx
221 ;/* Note: assumes success... */
222
223 ;/* Manual save and restore:
224 ; * - General purpose registers except RIP, RSP
225 ; *
226 ; * Trashed:
227 ; * - CR2 (we don't care)
228 ; * - LDTR (reset to 0)
229 ; * - DRx (presumably not changed at all)
230 ; * - DR7 (reset to 0x400)
231 ; * - EFLAGS (reset to RT_BIT(1); not relevant)
232 ; *
233 ; */
234
235 ; Load the guest LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
236 ;; @todo use the automatic load feature for MSRs
237 LOADGUESTMSR MSR_K8_LSTAR, CPUMCTX.msrLSTAR
238%if 0 ; not supported on Intel CPUs
239 LOADGUESTMSR MSR_K8_CSTAR, CPUMCTX.msrCSTAR
240%endif
241 LOADGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
242 LOADGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
243 LOADGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
244
245%ifdef VBOX_WITH_CRASHDUMP_MAGIC
246 mov qword [rbx + VMCSCACHE.uPos], 5
247%endif
248
249 ; Save the pCtx pointer
250 push rsi
251
252 ; Restore CR2
253 mov rbx, qword [rsi + CPUMCTX.cr2]
254 mov cr2, rbx
255
256 mov eax, VMX_VMCS_HOST_RSP
257 vmwrite rax, rsp
258 ;/* Note: assumes success... */
259 ;/* Don't mess with ESP anymore!! */
260
261 ;/* Restore Guest's general purpose registers. */
262 mov rax, qword [rsi + CPUMCTX.eax]
263 mov rbx, qword [rsi + CPUMCTX.ebx]
264 mov rcx, qword [rsi + CPUMCTX.ecx]
265 mov rdx, qword [rsi + CPUMCTX.edx]
266 mov rbp, qword [rsi + CPUMCTX.ebp]
267 mov r8, qword [rsi + CPUMCTX.r8]
268 mov r9, qword [rsi + CPUMCTX.r9]
269 mov r10, qword [rsi + CPUMCTX.r10]
270 mov r11, qword [rsi + CPUMCTX.r11]
271 mov r12, qword [rsi + CPUMCTX.r12]
272 mov r13, qword [rsi + CPUMCTX.r13]
273 mov r14, qword [rsi + CPUMCTX.r14]
274 mov r15, qword [rsi + CPUMCTX.r15]
275
276 ;/* Restore rdi & rsi. */
277 mov rdi, qword [rsi + CPUMCTX.edi]
278 mov rsi, qword [rsi + CPUMCTX.esi]
279
280 vmlaunch
281 jmp .vmlaunch64_done; ;/* here if vmlaunch detected a failure. */
282
283ALIGNCODE(16)
284.vmlaunch64_done:
285 jc near .vmstart64_invalid_vmxon_ptr
286 jz near .vmstart64_start_failed
287
288 push rdi
289 mov rdi, [rsp + 8] ; pCtx
290
291 mov qword [rdi + CPUMCTX.eax], rax
292 mov qword [rdi + CPUMCTX.ebx], rbx
293 mov qword [rdi + CPUMCTX.ecx], rcx
294 mov qword [rdi + CPUMCTX.edx], rdx
295 mov qword [rdi + CPUMCTX.esi], rsi
296 mov qword [rdi + CPUMCTX.ebp], rbp
297 mov qword [rdi + CPUMCTX.r8], r8
298 mov qword [rdi + CPUMCTX.r9], r9
299 mov qword [rdi + CPUMCTX.r10], r10
300 mov qword [rdi + CPUMCTX.r11], r11
301 mov qword [rdi + CPUMCTX.r12], r12
302 mov qword [rdi + CPUMCTX.r13], r13
303 mov qword [rdi + CPUMCTX.r14], r14
304 mov qword [rdi + CPUMCTX.r15], r15
305
306 pop rax ; the guest edi we pushed above
307 mov qword [rdi + CPUMCTX.edi], rax
308
309 pop rsi ; pCtx (needed in rsi by the macros below)
310
311 ;; @todo use the automatic load feature for MSRs
312 SAVEGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
313
314%ifdef VMX_USE_CACHED_VMCS_ACCESSES
315 pop rdi ; saved pCache
316
317%ifdef VBOX_WITH_CRASHDUMP_MAGIC
318 mov dword [rdi + VMCSCACHE.uPos], 7
319%endif
320%ifdef DEBUG
321 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
322 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
323 mov rax, cr8
324 mov [rdi + VMCSCACHE.TestOut.cr8], rax
325%endif
326
327 mov ecx, [rdi + VMCSCACHE.Read.cValidEntries]
328 cmp ecx, 0 ; can't happen
329 je .no_cached_reads
330 jmp .cached_read
331
332ALIGN(16)
333.cached_read:
334 dec rcx
335 mov eax, [rdi + VMCSCACHE.Read.aField + rcx*4]
336 vmread qword [rdi + VMCSCACHE.Read.aFieldVal + rcx*8], rax
337 cmp rcx, 0
338 jnz .cached_read
339.no_cached_reads:
340
341 ; Save CR2 for EPT
342 mov rax, cr2
343 mov [rdi + VMCSCACHE.cr2], rax
344%ifdef VBOX_WITH_CRASHDUMP_MAGIC
345 mov dword [rdi + VMCSCACHE.uPos], 8
346%endif
347%endif
348
349 ; Restore segment registers
350 MYPOPSEGS rax
351
352 mov eax, VINF_SUCCESS
353
354%ifdef VBOX_WITH_CRASHDUMP_MAGIC
355 mov dword [rdi + VMCSCACHE.uPos], 9
356%endif
357.vmstart64_end:
358
359%ifdef VMX_USE_CACHED_VMCS_ACCESSES
360%ifdef DEBUG
361 mov rdx, [rsp] ; pVMCSPhys
362 mov [rdi + VMCSCACHE.TestOut.pVMCSPhys], rdx
363%endif
364%endif
365
366 ; Write back the data and disable the VMCS
367 vmclear qword [rsp] ;Pushed pVMCS
368 add rsp, 8
369
370.vmstart64_vmxoff_end:
371 ; Disable VMX root mode
372 vmxoff
373.vmstart64_vmxon_failed:
374%ifdef VMX_USE_CACHED_VMCS_ACCESSES
375%ifdef DEBUG
376 cmp eax, VINF_SUCCESS
377 jne .skip_flags_save
378
379 pushf
380 pop rdx
381 mov [rdi + VMCSCACHE.TestOut.eflags], rdx
382%ifdef VBOX_WITH_CRASHDUMP_MAGIC
383 mov dword [rdi + VMCSCACHE.uPos], 12
384%endif
385.skip_flags_save:
386%endif
387%endif
388 pop rbp
389 ret
390
391
392.vmstart64_invalid_vmxon_ptr:
393 pop rsi ; pCtx (needed in rsi by the macros below)
394
395%ifdef VMX_USE_CACHED_VMCS_ACCESSES
396 pop rdi ; pCache
397%ifdef VBOX_WITH_CRASHDUMP_MAGIC
398 mov dword [rdi + VMCSCACHE.uPos], 10
399%endif
400
401%ifdef DEBUG
402 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
403 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
404%endif
405
406%endif
407
408 ; Restore segment registers
409 MYPOPSEGS rax
410
411 ; Restore all general purpose host registers.
412 mov eax, VERR_VMX_INVALID_VMXON_PTR
413 jmp .vmstart64_end
414
415.vmstart64_start_failed:
416 pop rsi ; pCtx (needed in rsi by the macros below)
417
418%ifdef VMX_USE_CACHED_VMCS_ACCESSES
419 pop rdi ; pCache
420
421%ifdef DEBUG
422 mov [rdi + VMCSCACHE.TestOut.pCache], rdi
423 mov [rdi + VMCSCACHE.TestOut.pCtx], rsi
424%endif
425%ifdef VBOX_WITH_CRASHDUMP_MAGIC
426 mov dword [rdi + VMCSCACHE.uPos], 11
427%endif
428
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