VirtualBox

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

Last change on this file since 84044 was 82968, checked in by vboxsync, 4 years ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use