VirtualBox

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

Last change on this file since 92386 was 91283, checked in by vboxsync, 3 years ago

VMM/CPUM: Moved the host's extended state (XState) from the hyper heap and into CPUMCTX. bugref:10093

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 KB
Line 
1 ; $Id: CPUMRZA.asm 91283 2021-09-16 13:58:36Z 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 lea pXState, [pCpumCpu + CPUMCPU.Host.XState]
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 lea pXState, [pCpumCpu + CPUMCPU.Guest.XState]
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 lea pXState, [pCpumCpu + CPUMCPU.Host.XState]
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 mov byte [pCpumCpu + CPUMCPU.Guest.fUsedFpuGuest], 0
214 %ifdef IN_RC
215 test byte [ebp + 0ch], 1 ; fLeaveFpuAccessible
216 jz .no_cr0_restore
217 CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET ecx
218.no_cr0_restore:
219 %endif
220 popf
221%ifdef RT_ARCH_X86
222 pop esi
223 pop ebx
224%endif
225 leave
226 ret
227%undef pCpumCpu
228%undef pXState
229ENDPROC cpumRZSaveGuestFpuState
230
231
232;;
233; Saves the guest XMM0..15 registers and MXCSR.
234;
235; The purpose is to actualize the register state for read-only use, so CR0 is
236; restored in raw-mode context (so, the FPU/SSE/AVX CPU features can be
237; inaccessible upon return).
238;
239; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
240;
241align 16
242BEGINPROC cpumRZSaveGuestSseRegisters
243 push xBP
244 SEH64_PUSH_xBP
245 mov xBP, xSP
246 SEH64_SET_FRAME_xBP 0
247SEH64_END_PROLOGUE
248
249%ifndef VBOX_WITH_KERNEL_USING_XMM
250 ;
251 ; Load xCX with the guest pXState.
252 ;
253 %ifdef ASM_CALL64_GCC
254 mov xCX, rdi
255 %elifdef RT_ARCH_X86
256 mov xCX, dword [ebp + 8]
257 %endif
258 lea xCX, [xCX + CPUMCPU.Guest.XState]
259
260 %ifdef IN_RC
261 ; Temporarily grant access to the SSE state. xDX must be preserved until CR0 is restored!
262 mov edx, cr0
263 test edx, X86_CR0_TS | X86_CR0_EM
264 jz .skip_cr0_write
265 mov eax, edx
266 and eax, ~(X86_CR0_TS | X86_CR0_EM)
267 mov cr0, eax
268.skip_cr0_write:
269 %endif
270
271 ;
272 ; Do the job.
273 ;
274 stmxcsr [xCX + X86FXSTATE.MXCSR]
275 movdqa [xCX + X86FXSTATE.xmm0 ], xmm0
276 movdqa [xCX + X86FXSTATE.xmm1 ], xmm1
277 movdqa [xCX + X86FXSTATE.xmm2 ], xmm2
278 movdqa [xCX + X86FXSTATE.xmm3 ], xmm3
279 movdqa [xCX + X86FXSTATE.xmm4 ], xmm4
280 movdqa [xCX + X86FXSTATE.xmm5 ], xmm5
281 movdqa [xCX + X86FXSTATE.xmm6 ], xmm6
282 movdqa [xCX + X86FXSTATE.xmm7 ], xmm7
283 %if ARCH_BITS == 64
284 movdqa [xCX + X86FXSTATE.xmm8 ], xmm8
285 movdqa [xCX + X86FXSTATE.xmm9 ], xmm9
286 movdqa [xCX + X86FXSTATE.xmm10], xmm10
287 movdqa [xCX + X86FXSTATE.xmm11], xmm11
288 movdqa [xCX + X86FXSTATE.xmm12], xmm12
289 movdqa [xCX + X86FXSTATE.xmm13], xmm13
290 movdqa [xCX + X86FXSTATE.xmm14], xmm14
291 movdqa [xCX + X86FXSTATE.xmm15], xmm15
292 %endif
293
294 %ifdef IN_RC
295 CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET edx ; Restore CR0 if we changed it above.
296 %endif
297
298%endif ; !VBOX_WITH_KERNEL_USING_XMM
299
300 leave
301 ret
302ENDPROC cpumRZSaveGuestSseRegisters
303
304;;
305; Saves the guest YMM0..15 registers.
306;
307; The purpose is to actualize the register state for read-only use, so CR0 is
308; restored in raw-mode context (so, the FPU/SSE/AVX CPU features can be
309; inaccessible upon return).
310;
311; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
312;
313align 16
314BEGINPROC cpumRZSaveGuestAvxRegisters
315 push xBP
316 SEH64_PUSH_xBP
317 mov xBP, xSP
318 SEH64_SET_FRAME_xBP 0
319%ifdef IN_RC
320 push xBX
321%endif
322SEH64_END_PROLOGUE
323
324 ;
325 ; Load xCX with the guest pXState.
326 ;
327%ifdef ASM_CALL64_GCC
328 mov xCX, rdi
329%elifdef RT_ARCH_X86
330 mov xCX, dword [ebp + 8]
331%endif
332 lea xCX, [xCX + CPUMCPU.Guest.XState]
333
334%ifdef IN_RC
335 ; Temporarily grant access to the SSE state. xBX must be preserved until CR0 is restored!
336 mov ebx, cr0
337 test ebx, X86_CR0_TS | X86_CR0_EM
338 jz .skip_cr0_write
339 mov eax, ebx
340 and eax, ~(X86_CR0_TS | X86_CR0_EM)
341 mov cr0, eax
342.skip_cr0_write:
343%endif
344
345 ;
346 ; Use XSAVE to do the job.
347 ;
348 ; Drivers shouldn't use AVX registers without saving+loading:
349 ; https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
350 ; However the compiler docs have different idea:
351 ; https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
352 ; We'll go with the former for now.
353 ;
354%ifdef VBOX_WITH_KERNEL_USING_XMM
355 mov eax, XSAVE_C_YMM
356%else
357 mov eax, XSAVE_C_YMM | XSAVE_C_SSE ; The SSE component includes MXCSR.
358%endif
359 xor edx, edx
360%if ARCH_BITS == 64
361 o64 xsave [xCX]
362%else
363 xsave [xCX]
364%endif
365
366%ifdef IN_RC
367 CPUMRZ_RESTORE_CR0_IF_TS_OR_EM_SET ebx ; Restore CR0 if we changed it above.
368 pop xBX
369%endif
370 leave
371 ret
372ENDPROC cpumRZSaveGuestAvxRegisters
373
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