VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/CPUMR0A.asm@ 61031

Last change on this file since 61031 was 61031, checked in by vboxsync, 9 years ago

Oops, committed too much!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 KB
Line 
1 ; $Id: CPUMR0A.asm 61031 2016-05-18 11:12:00Z vboxsync $
2;; @file
3; CPUM - Ring-0 Assembly Routines (supporting HM and IEM).
4;
5
6;
7; Copyright (C) 2006-2015 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%include "VBox/asmdefs.mac"
22%include "VBox/vmm/vm.mac"
23%include "VBox/err.mac"
24%include "VBox/vmm/stam.mac"
25%include "CPUMInternal.mac"
26%include "iprt/x86.mac"
27%include "VBox/vmm/cpum.mac"
28
29%ifdef IN_RING3
30 %error "The jump table doesn't link on leopard."
31%endif
32
33;*******************************************************************************
34;* Defined Constants And Macros *
35;*******************************************************************************
36;; The offset of the XMM registers in X86FXSTATE.
37; Use define because I'm too lazy to convert the struct.
38%define XMM_OFF_IN_X86FXSTATE 160
39%define IP_OFF_IN_X86FXSTATE 08h
40%define CS_OFF_IN_X86FXSTATE 0ch
41%define DS_OFF_IN_X86FXSTATE 14h
42
43;; For numeric expressions
44%ifdef RT_ARCH_AMD64
45 %define CPUMR0_IS_AMD64 1
46%else
47 %define CPUMR0_IS_AMD64 0
48%endif
49
50
51
52BEGINCODE
53
54%if 0 ; Currently not used anywhere.
55;;
56; Macro for FXSAVE/FXRSTOR leaky behaviour on AMD CPUs, see cpumR3CheckLeakyFpu().
57;
58; Cleans the FPU state, if necessary, before restoring the FPU.
59;
60; This macro ASSUMES CR0.TS is not set!
61;
62; @param xDX Pointer to CPUMCPU.
63; @uses xAX, EFLAGS
64;
65; Changes here should also be reflected in CPUMRCA.asm's copy!
66;
67%macro CLEANFPU 0
68 test dword [xDX + CPUMCPU.fUseFlags], CPUM_USE_FFXSR_LEAKY
69 jz .nothing_to_clean
70
71 xor eax, eax
72 fnstsw ax ; FSW -> AX.
73 test eax, RT_BIT(7) ; If FSW.ES (bit 7) is set, clear it to not cause FPU exceptions
74 ; while clearing & loading the FPU bits in 'clean_fpu' below.
75 jz .clean_fpu
76 fnclex
77
78.clean_fpu:
79 ffree st7 ; Clear FPU stack register(7)'s tag entry to prevent overflow if a wraparound occurs.
80 ; for the upcoming push (load)
81 fild dword [g_r32_Zero xWrtRIP] ; Explicit FPU load to overwrite FIP, FOP, FDP registers in the FPU.
82.nothing_to_clean:
83%endmacro
84%endif ; Unused.
85
86
87;;
88; Clears CR0.TS and CR0.EM if necessary, saving the previous result.
89;
90; This is used to avoid FPU exceptions when touching the FPU state.
91;
92; @param %1 Register to save the old CR0 in (pass to RESTORE_CR0).
93; @param %2 Temporary scratch register.
94; @uses EFLAGS, CR0
95;
96%macro SAVE_CR0_CLEAR_FPU_TRAPS 2
97 xor %1, %1
98 mov %2, cr0
99 test %2, X86_CR0_TS | X86_CR0_EM ; Make sure its safe to access the FPU state.
100 jz %%skip_cr0_write
101 mov %1, %2 ; Save old CR0
102 and %2, ~(X86_CR0_TS | X86_CR0_EM)
103 mov cr0, %2
104%%skip_cr0_write:
105%endmacro
106
107;;
108; Restore CR0.TS and CR0.EM state if SAVE_CR0_CLEAR_FPU_TRAPS change it.
109;
110; @param %1 The register that SAVE_CR0_CLEAR_FPU_TRAPS saved the old CR0 in.
111;
112%macro RESTORE_CR0 1
113 cmp %1, 0
114 je %%skip_cr0_restore
115 mov cr0, %1
116%%skip_cr0_restore:
117%endmacro
118
119
120;;
121; Saves the host state.
122;
123; @uses rax, rdx
124; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
125; @param pXState Define for the regsiter containing the extended state pointer.
126;
127%macro CPUMR0_SAVE_HOST 0
128 ;
129 ; Load a couple of registers we'll use later in all branches.
130 ;
131 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
132 mov eax, [pCpumCpu + CPUMCPU.Host.fXStateMask]
133
134 ;
135 ; XSAVE or FXSAVE?
136 ;
137 or eax, eax
138 jz %%host_fxsave
139
140 ; XSAVE
141 mov edx, [pCpumCpu + CPUMCPU.Host.fXStateMask + 4]
142%ifdef RT_ARCH_AMD64
143 o64 xsave [pXState]
144%else
145 xsave [pXState]
146%endif
147 jmp %%host_done
148
149 ; FXSAVE
150%%host_fxsave:
151%ifdef RT_ARCH_AMD64
152 o64 fxsave [pXState] ; Use explicit REX prefix. See @bugref{6398}.
153%else
154 fxsave [pXState]
155%endif
156
157%%host_done:
158%endmacro ; CPUMR0_SAVE_HOST
159
160
161;;
162; Loads the host state.
163;
164; @uses rax, rdx
165; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
166; @param pXState Define for the regsiter containing the extended state pointer.
167;
168%macro CPUMR0_LOAD_HOST 0
169 ;
170 ; Load a couple of registers we'll use later in all branches.
171 ;
172 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
173 mov eax, [pCpumCpu + CPUMCPU.Host.fXStateMask]
174
175 ;
176 ; XRSTOR or FXRSTOR?
177 ;
178 or eax, eax
179 jz %%host_fxrstor
180
181 ; XRSTOR
182 mov edx, [pCpumCpu + CPUMCPU.Host.fXStateMask + 4]
183%ifdef RT_ARCH_AMD64
184 o64 xrstor [pXState]
185%else
186 xrstor [pXState]
187%endif
188 jmp %%host_done
189
190 ; FXRSTOR
191%%host_fxrstor:
192%ifdef RT_ARCH_AMD64
193 o64 fxrstor [pXState] ; Use explicit REX prefix. See @bugref{6398}.
194%else
195 fxrstor [pXState]
196%endif
197
198%%host_done:
199%endmacro ; CPUMR0_LOAD_HOST
200
201
202
203;; Macro for FXSAVE for the guest FPU but tries to figure out whether to
204; save the 32-bit FPU state or 64-bit FPU state.
205;
206; @param %1 Pointer to CPUMCPU.
207; @param %2 Pointer to XState.
208; @param %3 Force AMD64
209; @uses xAX, xDX, EFLAGS, 20h of stack.
210;
211%macro SAVE_32_OR_64_FPU 3
212%if CPUMR0_IS_AMD64 || %3
213 ; Save the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
214 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USE_SUPPORTS_LONGMODE
215 jnz short %%save_long_mode_guest
216%endif
217 fxsave [pXState]
218%if CPUMR0_IS_AMD64 || %3
219 jmp %%save_done_32bit_cs_ds
220
221%%save_long_mode_guest:
222 o64 fxsave [pXState]
223
224 xor edx, edx
225 cmp dword [pXState + CS_OFF_IN_X86FXSTATE], 0
226 jne short %%save_done
227
228 sub rsp, 20h ; Only need 1ch bytes but keep stack aligned otherwise we #GP(0).
229 fnstenv [rsp]
230 movzx eax, word [rsp + 10h]
231 mov [pXState + CS_OFF_IN_X86FXSTATE], eax
232 movzx eax, word [rsp + 18h]
233 add rsp, 20h
234 mov [pXState + DS_OFF_IN_X86FXSTATE], eax
235%endif
236%%save_done_32bit_cs_ds:
237 mov edx, X86_FXSTATE_RSVD_32BIT_MAGIC
238%%save_done:
239 mov dword [pXState + X86_OFF_FXSTATE_RSVD], edx
240%endmacro ; SAVE_32_OR_64_FPU
241
242
243;;
244; Save the guest state.
245;
246; @uses rax, rdx
247; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
248; @param pXState Define for the regsiter containing the extended state pointer.
249;
250%macro CPUMR0_SAVE_GUEST 0
251 ;
252 ; Load a couple of registers we'll use later in all branches.
253 ;
254 mov pXState, [pCpumCpu + CPUMCPU.Guest.pXStateR0]
255 mov eax, [pCpumCpu + CPUMCPU.Guest.fXStateMask]
256
257 ;
258 ; XSAVE or FXSAVE?
259 ;
260 or eax, eax
261 jz %%guest_fxsave
262
263 ; XSAVE
264 mov edx, [pCpumCpu + CPUMCPU.Guest.fXStateMask + 4]
265%ifdef VBOX_WITH_KERNEL_USING_XMM
266 and eax, ~CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS ; Already saved in HMR0A.asm.
267%endif
268%ifdef RT_ARCH_AMD64
269 o64 xsave [pXState]
270%else
271 xsave [pXState]
272%endif
273 jmp %%guest_done
274
275 ; FXSAVE
276%%guest_fxsave:
277 SAVE_32_OR_64_FPU pCpumCpu, pXState, 0
278
279%%guest_done:
280%endmacro ; CPUMR0_SAVE_GUEST
281
282
283;;
284; Wrapper for selecting 32-bit or 64-bit FXRSTOR according to what SAVE_32_OR_64_FPU did.
285;
286; @param %1 Pointer to CPUMCPU.
287; @param %2 Pointer to XState.
288; @param %3 Force AMD64.
289; @uses xAX, xDX, EFLAGS
290;
291%macro RESTORE_32_OR_64_FPU 3
292%if CPUMR0_IS_AMD64 || %3
293 ; Restore the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
294 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USE_SUPPORTS_LONGMODE
295 jz %%restore_32bit_fpu
296 cmp dword [pXState + X86_OFF_FXSTATE_RSVD], X86_FXSTATE_RSVD_32BIT_MAGIC
297 jne short %%restore_64bit_fpu
298%%restore_32bit_fpu:
299%endif
300 fxrstor [pXState]
301%if CPUMR0_IS_AMD64 || %3
302 ; TODO: Restore XMM8-XMM15!
303 jmp short %%restore_fpu_done
304%%restore_64bit_fpu:
305 o64 fxrstor [pXState]
306%%restore_fpu_done:
307%endif
308%endmacro ; RESTORE_32_OR_64_FPU
309
310
311;;
312; Loads the guest state.
313;
314; @uses rax, rdx
315; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
316; @param pXState Define for the regsiter containing the extended state pointer.
317;
318%macro CPUMR0_LOAD_GUEST 0
319 ;
320 ; Load a couple of registers we'll use later in all branches.
321 ;
322 mov pXState, [pCpumCpu + CPUMCPU.Guest.pXStateR0]
323 mov eax, [pCpumCpu + CPUMCPU.Guest.fXStateMask]
324
325 ;
326 ; XRSTOR or FXRSTOR?
327 ;
328 or eax, eax
329 jz %%guest_fxrstor
330
331 ; XRSTOR
332 mov edx, [pCpumCpu + CPUMCPU.Guest.fXStateMask + 4]
333%ifdef VBOX_WITH_KERNEL_USING_XMM
334 and eax, ~CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS ; Will be loaded by HMR0A.asm.
335%endif
336%ifdef RT_ARCH_AMD64
337 o64 xrstor [pXState]
338%else
339 xrstor [pXState]
340%endif
341 jmp %%guest_done
342
343 ; FXRSTOR
344%%guest_fxrstor:
345 RESTORE_32_OR_64_FPU pCpumCpu, pXState, 0
346
347%%guest_done:
348%endmacro ; CPUMR0_LOAD_GUEST
349
350
351;;
352; Saves the host FPU/SSE/AVX state and restores the guest FPU/SSE/AVX state.
353;
354; @returns 0
355; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
356;
357align 16
358BEGINPROC cpumR0SaveHostRestoreGuestFPUState
359 ;
360 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
361 ;
362%ifdef RT_ARCH_AMD64
363 %ifdef RT_OS_WINDOWS
364 mov r11, rcx
365 %else
366 mov r11, rdi
367 %endif
368 %define pCpumCpu r11
369 %define pXState r10
370%else
371 push ebp
372 mov ebp, esp
373 push ebx
374 push esi
375 mov ebx, dword [ebp + 8]
376 %define pCpumCpu ebx
377 %define pXState esi
378%endif
379
380 pushf ; The darwin kernel can get upset or upset things if an
381 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
382
383 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
384
385 CPUMR0_SAVE_HOST
386 CPUMR0_LOAD_GUEST
387
388%ifdef VBOX_WITH_KERNEL_USING_XMM
389 ; Restore the non-volatile xmm registers. ASSUMING 64-bit host.
390 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
391 movdqa xmm6, [pXState + XMM_OFF_IN_X86FXSTATE + 060h]
392 movdqa xmm7, [pXState + XMM_OFF_IN_X86FXSTATE + 070h]
393 movdqa xmm8, [pXState + XMM_OFF_IN_X86FXSTATE + 080h]
394 movdqa xmm9, [pXState + XMM_OFF_IN_X86FXSTATE + 090h]
395 movdqa xmm10, [pXState + XMM_OFF_IN_X86FXSTATE + 0a0h]
396 movdqa xmm11, [pXState + XMM_OFF_IN_X86FXSTATE + 0b0h]
397 movdqa xmm12, [pXState + XMM_OFF_IN_X86FXSTATE + 0c0h]
398 movdqa xmm13, [pXState + XMM_OFF_IN_X86FXSTATE + 0d0h]
399 movdqa xmm14, [pXState + XMM_OFF_IN_X86FXSTATE + 0e0h]
400 movdqa xmm15, [pXState + XMM_OFF_IN_X86FXSTATE + 0f0h]
401%endif
402
403 RESTORE_CR0 xCX
404 or dword [pCpumCpu + CPUMCPU.fUseFlags], (CPUM_USED_FPU | CPUM_USED_FPU_SINCE_REM)
405 popf
406
407%ifdef RT_ARCH_X86
408 pop esi
409 pop ebx
410 leave
411%endif
412 xor eax, eax
413 ret
414ENDPROC cpumR0SaveHostRestoreGuestFPUState
415
416
417%ifndef RT_ARCH_AMD64
418 %ifdef VBOX_WITH_64_BITS_GUESTS
419;;
420; Saves the host FPU/SSE/AVX state.
421;
422; @returns VINF_SUCCESS (0) in EAX
423; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
424;
425align 16
426BEGINPROC cpumR0SaveHostFPUState
427 ;
428 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
429 ;
430 %ifdef RT_ARCH_AMD64
431 %ifdef RT_OS_WINDOWS
432 mov r11, rcx
433 %else
434 mov r11, rdi
435 %endif
436 %define pCpumCpu r11
437 %define pXState r10
438 %else
439 push ebp
440 mov ebp, esp
441 push ebx
442 push esi
443 mov ebx, dword [ebp + 8]
444 %define pCpumCpu ebx
445 %define pXState esi
446 %endif
447
448 pushf ; The darwin kernel can get upset or upset things if an
449 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
450 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
451
452 CPUMR0_SAVE_HOST
453
454 RESTORE_CR0 xCX
455 or dword [pCpumCpu + CPUMCPU.fUseFlags], (CPUM_USED_FPU | CPUM_USED_FPU_SINCE_REM)
456 popf
457
458 %ifdef RT_ARCH_X86
459 pop esi
460 pop ebx
461 leave
462 %endif
463 xor eax, eax
464 ret
465%undef pCpumCpu
466%undef pXState
467ENDPROC cpumR0SaveHostFPUState
468 %endif
469%endif
470
471
472;;
473; Saves the guest FPU/SSE/AVX state and restores the host FPU/SSE/AVX state.
474;
475; @returns VINF_SUCCESS (0) in eax.
476; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
477;
478align 16
479BEGINPROC cpumR0SaveGuestRestoreHostFPUState
480 ;
481 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
482 ;
483%ifdef RT_ARCH_AMD64
484 %ifdef RT_OS_WINDOWS
485 mov r11, rcx
486 %else
487 mov r11, rdi
488 %endif
489 %define pCpumCpu r11
490 %define pXState r10
491%else
492 push ebp
493 mov ebp, esp
494 push ebx
495 push esi
496 mov ebx, dword [ebp + 8]
497 %define pCpumCpu ebx
498 %define pXState esi
499%endif
500
501 ;
502 ; Only restore FPU if guest has used it.
503 ;
504 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USED_FPU
505 jz .fpu_not_used
506
507 pushf ; The darwin kernel can get upset or upset things if an
508 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
509 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
510
511 CPUMR0_SAVE_GUEST
512 CPUMR0_LOAD_HOST
513
514 RESTORE_CR0 xCX
515 and dword [pCpumCpu + CPUMCPU.fUseFlags], ~CPUM_USED_FPU
516 popf
517
518.fpu_not_used:
519%ifdef RT_ARCH_X86
520 pop esi
521 pop ebx
522 leave
523%endif
524 xor eax, eax
525 ret
526%undef pCpumCpu
527%undef pXState
528ENDPROC cpumR0SaveGuestRestoreHostFPUState
529
530
531;;
532; Restores the host's FPU/SSE/AVX state from pCpumCpu->Host.
533;
534; @returns 0
535; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
536;
537align 16
538BEGINPROC cpumR0RestoreHostFPUState
539 ;
540 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
541 ;
542%ifdef RT_ARCH_AMD64
543 %ifdef RT_OS_WINDOWS
544 mov r11, rcx
545 %else
546 mov r11, rdi
547 %endif
548 %define pCpumCpu r11
549 %define pXState r10
550%else
551 push ebp
552 mov ebp, esp
553 push ebx
554 push esi
555 mov ebx, dword [ebp + 8]
556 %define pCpumCpu ebx
557 %define pXState esi
558%endif
559
560 ;
561 ; Restore FPU if guest has used it.
562 ;
563 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USED_FPU
564 jz short .fpu_not_used
565
566 pushf ; The darwin kernel can get upset or upset things if an
567 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
568 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
569
570 CPUMR0_LOAD_HOST
571
572 RESTORE_CR0 xCX
573 and dword [pCpumCpu + CPUMCPU.fUseFlags], ~CPUM_USED_FPU
574 popf
575
576.fpu_not_used:
577%ifdef RT_ARCH_X86
578 pop esi
579 pop ebx
580 leave
581%endif
582 xor eax, eax
583 ret
584%undef pCpumCPu
585%undef pXState
586ENDPROC cpumR0RestoreHostFPUState
587
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