VirtualBox

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

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