VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMRZ/CPUMRZA.asm@ 76397

Last change on this file since 76397 was 69111, checked in by vboxsync, 7 years ago

(C) year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1 ; $Id: CPUMRZA.asm 69111 2017-10-17 14:26:02Z vboxsync $
2;; @file
3; CPUM - Raw-mode and Ring-0 Context Assembly Routines.
4;
5
6;
7; Copyright (C) 2006-2017 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;*******************************************************************************
20;* Header Files *
21;*******************************************************************************
22%define RT_ASM_WITH_SEH64
23%include "VBox/asmdefs.mac"
24%include "CPUMInternal.mac"
25%include "iprt/x86.mac"
26%include "VBox/vmm/cpum.mac"
27%include "VBox/err.mac"
28
29
30
31BEGINCODE
32
33
34;;
35; Saves the host FPU/SSE/AVX state.
36;
37; Will return with CR0.EM and CR0.TS cleared! This is the normal state in
38; ring-0, whereas in raw-mode the caller will probably set VMCPU_FF_CPUM to
39; re-evaluate the situation before executing more guest code.
40;
41; @returns VINF_SUCCESS (0) or VINF_CPUM_HOST_CR0_MODIFIED. (EAX)
42; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
43;
44align 16
45BEGINPROC cpumRZSaveHostFPUState
46 push xBP
47 SEH64_PUSH_xBP
48 mov xBP, xSP
49 SEH64_SET_FRAME_xBP 0
50SEH64_END_PROLOGUE
51
52 ;
53 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
54 ;
55%ifdef RT_ARCH_AMD64
56 %ifdef ASM_CALL64_MSC
57 mov r11, rcx
58 %else
59 mov r11, rdi
60 %endif
61 %define pCpumCpu r11
62 %define pXState r10
63%else
64 push ebx
65 push esi
66 mov ebx, dword [ebp + 8]
67 %define pCpumCpu ebx
68 %define pXState esi
69%endif
70
71 pushf ; The darwin kernel can get upset or upset things if an
72 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
73
74 ;
75 ; We may have to update CR0, indirectly or directly. We must report any
76 ; changes to the VT-x code.
77 ;
78 CPUMRZ_TOUCH_FPU_CLEAR_CR0_FPU_TRAPS_SET_RC xCX, xAX, pCpumCpu ; xCX is the return value (xAX scratch)
79
80 ;
81 ; Save the host state (xsave/fxsave will cause thread FPU state to be
82 ; loaded on systems where we are allowed to use it in ring-0.
83 ;
84 CPUMR0_SAVE_HOST
85
86 or dword [pCpumCpu + CPUMCPU.fUseFlags], (CPUM_USED_FPU_HOST | CPUM_USED_FPU_SINCE_REM) ; Latter is not necessarily true, but normally yes.
87 popf
88
89 mov eax, ecx ; The return value from above.
90%ifdef RT_ARCH_X86
91 pop esi
92 pop ebx
93%endif
94 leave
95 ret
96%undef pCpumCpu
97%undef pXState
98ENDPROC cpumRZSaveHostFPUState
99
100
101;;
102; Saves the guest FPU/SSE/AVX state.
103;
104; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
105; @param fLeaveFpuAccessible x86:[ebp+c] gcc:sil msc:dl Whether to restore CR0 and XCR0 on
106; the way out. Only really applicable to RC.
107;
108; @remarks 64-bit Windows drivers shouldn't use AVX registers without saving+loading:
109; https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
110; However the compiler docs have different idea:
111; https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
112; We'll go with the former for now.
113;
114align 16
115BEGINPROC cpumRZSaveGuestFpuState
116 push xBP
117 SEH64_PUSH_xBP
118 mov xBP, xSP
119 SEH64_SET_FRAME_xBP 0
120SEH64_END_PROLOGUE
121
122 ;
123 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
124 ;
125%ifdef RT_ARCH_AMD64
126 %ifdef ASM_CALL64_MSC
127 mov r11, rcx
128 %else
129 mov r11, rdi
130 %endif
131 %define pCpumCpu r11
132 %define pXState r10
133%else
134 push ebx
135 push esi
136 mov ebx, dword [ebp + 8]
137 %define pCpumCpu ebx
138 %define pXState esi
139%endif
140 pushf ; The darwin kernel can get upset or upset things if an
141 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
142
143 %ifdef IN_RC
144 mov ecx, cr0 ; ecx = saved cr0
145 test ecx, X86_CR0_TS | X86_CR0_EM
146 jz .skip_cr0_write
147 mov eax, ecx
148 and eax, ~(X86_CR0_TS | X86_CR0_EM)
149 mov cr0, eax
150.skip_cr0_write:
151 %endif
152
153 %ifndef VBOX_WITH_KERNEL_USING_XMM
154 CPUMR0_SAVE_GUEST
155 %else
156 ;
157 ; The XMM0..XMM15 registers have been saved already. We exploit the
158 ; host state here to temporarly save the non-volatile XMM registers,
159 ; so we can load the guest ones while saving. This is safe.
160 ;
161
162 ; Save caller's XMM registers.
163 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
164 movdqa [pXState + X86FXSTATE.xmm6 ], xmm6
165 movdqa [pXState + X86FXSTATE.xmm7 ], xmm7
166 movdqa [pXState + X86FXSTATE.xmm8 ], xmm8
167 movdqa [pXState + X86FXSTATE.xmm9 ], xmm9
168 movdqa [pXState + X86FXSTATE.xmm10], xmm10
169 movdqa [pXState + X86FXSTATE.xmm11], xmm11
170 movdqa [pXState + X86FXSTATE.xmm12], xmm12
171 movdqa [pXState + X86FXSTATE.xmm13], xmm13
172 movdqa [pXState + X86FXSTATE.xmm14], xmm14
173 movdqa [pXState + X86FXSTATE.xmm15], xmm15
174 stmxcsr [pXState + X86FXSTATE.MXCSR]
175
176 ; Load the guest XMM register values we already saved in HMR0VMXStartVMWrapXMM.
177 mov pXState, [pCpumCpu + CPUMCPU.Guest.pXStateR0]
178 movdqa xmm0, [pXState + X86FXSTATE.xmm0]
179 movdqa xmm1, [pXState + X86FXSTATE.xmm1]
180 movdqa xmm2, [pXState + X86FXSTATE.xmm2]
181 movdqa xmm3, [pXState + X86FXSTATE.xmm3]
182 movdqa xmm4, [pXState + X86FXSTATE.xmm4]
183 movdqa xmm5, [pXState + X86FXSTATE.xmm5]
184 movdqa xmm6, [pXState + X86FXSTATE.xmm6]
185 movdqa xmm7, [pXState + X86FXSTATE.xmm7]
186 movdqa xmm8, [pXState + X86FXSTATE.xmm8]
187 movdqa xmm9, [pXState + X86FXSTATE.xmm9]
188 movdqa xmm10, [pXState + X86FXSTATE.xmm10]
189 movdqa xmm11, [pXState + X86FXSTATE.xmm11]
190 movdqa xmm12, [pXState + X86FXSTATE.xmm12]
191 movdqa xmm13, [pXState + X86FXSTATE.xmm13]
192 movdqa xmm14, [pXState + X86FXSTATE.xmm14]
193 movdqa xmm15, [pXState + X86FXSTATE.xmm15]
194 ldmxcsr [pXState + X86FXSTATE.MXCSR]
195
196 CPUMR0_SAVE_GUEST
197
198 ; Restore caller's XMM registers.
199 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
200 movdqa xmm6, [pXState + X86FXSTATE.xmm6 ]
201 movdqa xmm7, [pXState + X86FXSTATE.xmm7 ]
202 movdqa xmm8, [pXState + X86FXSTATE.xmm8 ]
203 movdqa xmm9, [pXState + X86FXSTATE.xmm9 ]
204 movdqa xmm10, [pXState + X86FXSTATE.xmm10]
205 movdqa xmm11, [pXState + X86FXSTATE.xmm11]
206 movdqa xmm12, [pXState + X86FXSTATE.xmm12]
207 movdqa xmm13, [pXState + X86FXSTATE.xmm13]
208 movdqa xmm14, [pXState + X86FXSTATE.xmm14]
209 movdqa xmm15, [pXState + X86FXSTATE.xmm15]
210 ldmxcsr [pXState + X86FXSTATE.MXCSR]
211
212 %endif
213
214 and dword [pCpumCpu + CPUMCPU.fUseFlags], ~CPUM_USED_FPU_GUEST
215 %ifdef IN_RC
216 test byte [ebp + 0ch], 1 ; fLeaveFpuAccessible
217 jz .no_cr0_restore
218 CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET ecx
219.no_cr0_restore:
220 %endif
221 popf
222%ifdef RT_ARCH_X86
223 pop esi
224 pop ebx
225%endif
226 leave
227 ret
228%undef pCpumCpu
229%undef pXState
230ENDPROC cpumRZSaveGuestFpuState
231
232
233;;
234; Saves the guest XMM0..15 registers and MXCSR.
235;
236; The purpose is to actualize the register state for read-only use, so CR0 is
237; restored in raw-mode context (so, the FPU/SSE/AVX CPU features can be
238; inaccessible upon return).
239;
240; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
241;
242align 16
243BEGINPROC cpumRZSaveGuestSseRegisters
244 push xBP
245 SEH64_PUSH_xBP
246 mov xBP, xSP
247 SEH64_SET_FRAME_xBP 0
248SEH64_END_PROLOGUE
249
250%ifndef VBOX_WITH_KERNEL_USING_XMM
251 ;
252 ; Load xCX with the guest pXStateR0.
253 ;
254 %ifdef ASM_CALL64_GCC
255 mov xCX, rdi
256 %elifdef RT_ARCH_X86
257 mov xCX, dword [ebp + 8]
258 %endif
259 %ifdef IN_RING0
260 mov xCX, [xCX + CPUMCPU.Guest.pXStateR0]
261 %elifdef IN_RC
262 mov xCX, [xCX + CPUMCPU.Guest.pXStateRC]
263 %else
264 %error "Invalid context!"
265 %endif
266
267 %ifdef IN_RC
268 ; Temporarily grant access to the SSE state. xDX must be preserved until CR0 is restored!
269 mov edx, cr0
270 test edx, X86_CR0_TS | X86_CR0_EM
271 jz .skip_cr0_write
272 mov eax, edx
273 and eax, ~(X86_CR0_TS | X86_CR0_EM)
274 mov cr0, eax
275.skip_cr0_write:
276 %endif
277
278 ;
279 ; Do the job.
280 ;
281 stmxcsr [xCX + X86FXSTATE.MXCSR]
282 movdqa [xCX + X86FXSTATE.xmm0 ], xmm0
283 movdqa [xCX + X86FXSTATE.xmm1 ], xmm1
284 movdqa [xCX + X86FXSTATE.xmm2 ], xmm2
285 movdqa [xCX + X86FXSTATE.xmm3 ], xmm3
286 movdqa [xCX + X86FXSTATE.xmm4 ], xmm4
287 movdqa [xCX + X86FXSTATE.xmm5 ], xmm5
288 movdqa [xCX + X86FXSTATE.xmm6 ], xmm6
289 movdqa [xCX + X86FXSTATE.xmm7 ], xmm7
290 %if ARCH_BITS == 64
291 movdqa [xCX + X86FXSTATE.xmm8 ], xmm8
292 movdqa [xCX + X86FXSTATE.xmm9 ], xmm9
293 movdqa [xCX + X86FXSTATE.xmm10], xmm10
294 movdqa [xCX + X86FXSTATE.xmm11], xmm11
295 movdqa [xCX + X86FXSTATE.xmm12], xmm12
296 movdqa [xCX + X86FXSTATE.xmm13], xmm13
297 movdqa [xCX + X86FXSTATE.xmm14], xmm14
298 movdqa [xCX + X86FXSTATE.xmm15], xmm15
299 %endif
300
301 %ifdef IN_RC
302 CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET edx ; Restore CR0 if we changed it above.
303 %endif
304
305%endif ; !VBOX_WITH_KERNEL_USING_XMM
306
307 leave
308 ret
309ENDPROC cpumRZSaveGuestSseRegisters
310
311;;
312; Saves the guest YMM0..15 registers.
313;
314; The purpose is to actualize the register state for read-only use, so CR0 is
315; restored in raw-mode context (so, the FPU/SSE/AVX CPU features can be
316; inaccessible upon return).
317;
318; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
319;
320align 16
321BEGINPROC cpumRZSaveGuestAvxRegisters
322 push xBP
323 SEH64_PUSH_xBP
324 mov xBP, xSP
325 SEH64_SET_FRAME_xBP 0
326%ifdef IN_RC
327 push xBX
328%endif
329SEH64_END_PROLOGUE
330
331 ;
332 ; Load xCX with the guest pXStateR0.
333 ;
334%ifdef ASM_CALL64_GCC
335 mov xCX, rdi
336%elifdef RT_ARCH_X86
337 mov xCX, dword [ebp + 8]
338%endif
339%ifdef IN_RING0
340 mov xCX, [xCX + CPUMCPU.Guest.pXStateR0]
341%elifdef IN_RC
342 mov xCX, [xCX + CPUMCPU.Guest.pXStateRC]
343%else
344 %error "Invalid context!"
345%endif
346
347%ifdef IN_RC
348 ; Temporarily grant access to the SSE state. xBX must be preserved until CR0 is restored!
349 mov ebx, cr0
350 test ebx, X86_CR0_TS | X86_CR0_EM
351 jz .skip_cr0_write
352 mov eax, ebx
353 and eax, ~(X86_CR0_TS | X86_CR0_EM)
354 mov cr0, eax
355.skip_cr0_write:
356%endif
357
358 ;
359 ; Use XSAVE to do the job.
360 ;
361 ; Drivers shouldn't use AVX registers without saving+loading:
362 ; https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
363 ; However the compiler docs have different idea:
364 ; https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
365 ; We'll go with the former for now.
366 ;
367%ifdef VBOX_WITH_KERNEL_USING_XMM
368 mov eax, XSAVE_C_YMM
369%else
370 mov eax, XSAVE_C_YMM | XSAVE_C_SSE ; The SSE component includes MXCSR.
371%endif
372 xor edx, edx
373%if ARCH_BITS == 64
374 o64 xsave [xCX]
375%else
376 xsave [xCX]
377%endif
378
379%ifdef IN_RC
380 CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET ebx ; Restore CR0 if we changed it above.
381 pop xBX
382%endif
383 leave
384 ret
385ENDPROC cpumRZSaveGuestAvxRegisters
386
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use