VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/CPUMAllSysRegs-armv8.cpp@ 106476

Last change on this file since 106476 was 106476, checked in by vboxsync, 5 weeks ago

VMMArm: Skeleton of the PMU device emulation enough to make Windows/ARM boot as a guest and have it out of the NEM darwin backend, bugref:10778

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.1 KB
Line 
1/* $Id: CPUMAllSysRegs-armv8.cpp 106476 2024-10-18 12:57:36Z vboxsync $ */
2/** @file
3 * CPUM - ARMv8 CPU System Registers.
4 */
5
6/*
7 * Copyright (C) 2023-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 LOG_GROUP LOG_GROUP_CPUM
33#include <VBox/vmm/cpum.h>
34#include "CPUMInternal-armv8.h"
35#include <VBox/vmm/gic.h>
36#include <VBox/vmm/pmu.h>
37#include <VBox/vmm/vmcc.h>
38#include <VBox/err.h>
39
40#include <iprt/armv8.h>
41
42
43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46/**
47 * Validates the CPUMSYSREGRANGE::offCpumCpu value and declares a local variable
48 * pointing to it.
49 *
50 * ASSUMES sizeof(a_Type) is a power of two and that the member is aligned
51 * correctly.
52 */
53#define CPUM_SYSREG_ASSERT_CPUMCPU_OFFSET_RETURN(a_pVCpu, a_pRange, a_Type, a_VarName) \
54 AssertMsgReturn( (a_pRange)->offCpumCpu >= 8 \
55 && (a_pRange)->offCpumCpu < sizeof(CPUMCPU) \
56 && !((a_pRange)->offCpumCpu & (RT_MIN(sizeof(a_Type), 8) - 1)) \
57 , ("offCpumCpu=%#x %s\n", (a_pRange)->offCpumCpu, (a_pRange)->szName), \
58 VERR_CPUM_MSR_BAD_CPUMCPU_OFFSET); \
59 a_Type *a_VarName = (a_Type *)((uintptr_t)&(a_pVCpu)->cpum.s + (a_pRange)->offCpumCpu)
60
61
62/*********************************************************************************************************************************
63* Structures and Typedefs *
64*********************************************************************************************************************************/
65
66/**
67 * Implements reading one or more system registers.
68 *
69 * @returns VBox status code.
70 * @retval VINF_SUCCESS on success.
71 * @retval VINF_CPUM_R3_MSR_READ if the MSR read could not be serviced in the
72 * current context (raw-mode or ring-0).
73 * @retval VERR_CPUM_RAISE_GP_0 on failure (invalid system register).
74 *
75 * @param pVCpu The cross context virtual CPU structure.
76 * @param idSysReg The system register we're reading.
77 * @param pRange The system register range descriptor.
78 * @param puValue Where to return the value.
79 */
80typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNCPUMRDSYSREG,(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue));
81/** Pointer to a MRS worker for a specific system register or range of system registers. */
82typedef FNCPUMRDSYSREG *PFNCPUMRDSYSREG;
83
84
85/**
86 * Implements writing one or more system registers.
87 *
88 * @retval VINF_SUCCESS on success.
89 * @retval VINF_CPUM_R3_MSR_WRITE if the MSR write could not be serviced in the
90 * current context (raw-mode or ring-0).
91 * @retval VERR_CPUM_RAISE_GP_0 on failure.
92 *
93 * @param pVCpu The cross context virtual CPU structure.
94 * @param idSysReg The system register we're writing.
95 * @param pRange The system register range descriptor.
96 * @param uValue The value to set, ignored bits masked.
97 * @param uRawValue The raw value with the ignored bits not masked.
98 */
99typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNCPUMWRSYSREG,(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange,
100 uint64_t uValue, uint64_t uRawValue));
101/** Pointer to a MSR worker for a specific system register or range of system registers. */
102typedef FNCPUMWRSYSREG *PFNCPUMWRSYSREG;
103
104
105
106/*
107 * Generic functions.
108 * Generic functions.
109 * Generic functions.
110 */
111
112
113/** @callback_method_impl{FNCPUMRDSYSREG} */
114static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_FixedValue(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
115{
116 RT_NOREF_PV(pVCpu); RT_NOREF_PV(idSysReg);
117 *puValue = pRange->uValue;
118 return VINF_SUCCESS;
119}
120
121
122/** @callback_method_impl{FNCPUMWRSYSREG} */
123static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_IgnoreWrite(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
124{
125 RT_NOREF_PV(pVCpu); RT_NOREF_PV(idSysReg); RT_NOREF_PV(pRange); RT_NOREF_PV(uValue); RT_NOREF_PV(uRawValue);
126 Log(("CPUM: Ignoring MSR %#x (%s), %#llx\n", idSysReg, pRange->szName, uValue));
127 return VINF_SUCCESS;
128}
129
130
131/** @callback_method_impl{FNCPUMRDSYSREG} */
132static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_WriteOnly(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
133{
134 RT_NOREF_PV(pVCpu); RT_NOREF_PV(idSysReg); RT_NOREF_PV(pRange); RT_NOREF_PV(puValue);
135 return VERR_CPUM_RAISE_GP_0;
136}
137
138
139/** @callback_method_impl{FNCPUMWRSYSREG} */
140static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_ReadOnly(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
141{
142 RT_NOREF_PV(pVCpu); RT_NOREF_PV(idSysReg); RT_NOREF_PV(pRange); RT_NOREF_PV(uValue); RT_NOREF_PV(uRawValue);
143 Assert(pRange->fWrExcpMask == UINT64_MAX);
144 return VERR_CPUM_RAISE_GP_0;
145}
146
147
148
149/** @callback_method_impl{FNCPUMRDSYSREG} */
150static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_GicV3Icc(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
151{
152 RT_NOREF_PV(pRange);
153 return GICReadSysReg(pVCpu, idSysReg, puValue);
154}
155
156
157/** @callback_method_impl{FNCPUMWRSYSREG} */
158static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_GicV3Icc(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
159{
160 RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue);
161 return GICWriteSysReg(pVCpu, idSysReg, uValue);
162}
163
164
165
166/** @callback_method_impl{FNCPUMRDSYSREG} */
167static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_OslsrEl1(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
168{
169 RT_NOREF(idSysReg, pRange);
170 *puValue = pVCpu->cpum.s.Guest.fOsLck ? ARMV8_OSLSR_EL1_AARCH64_OSLK : 0;
171 return VINF_SUCCESS;
172}
173
174
175/** @callback_method_impl{FNCPUMWRSYSREG} */
176static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_OslarEl1(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
177{
178 RT_NOREF(idSysReg, pRange, uRawValue);
179 Assert(!(uValue & ~ARMV8_OSLAR_EL1_AARCH64_OSLK));
180 pVCpu->cpum.s.Guest.fOsLck = RT_BOOL(uValue);
181 return VINF_SUCCESS;
182}
183
184
185
186/** @callback_method_impl{FNCPUMRDSYSREG} */
187static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_Pmu(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
188{
189 RT_NOREF_PV(pRange);
190 return PMUReadSysReg(pVCpu, idSysReg, puValue);
191}
192
193
194/** @callback_method_impl{FNCPUMWRSYSREG} */
195static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_Pmu(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
196{
197 RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue);
198 return PMUWriteSysReg(pVCpu, idSysReg, uValue);
199}
200
201
202/**
203 * System register read function table.
204 */
205static const struct READSYSREGCLANG11WEIRDNOTHROW { PFNCPUMRDSYSREG pfnRdSysReg; } g_aCpumRdSysRegFns[kCpumSysRegRdFn_End] =
206{
207 { NULL }, /* Invalid */
208 { cpumSysRegRd_FixedValue },
209 { NULL }, /* Alias */
210 { cpumSysRegRd_WriteOnly },
211 { cpumSysRegRd_GicV3Icc },
212 { cpumSysRegRd_OslsrEl1 },
213 { cpumSysRegRd_Pmu }
214};
215
216
217/**
218 * System register write function table.
219 */
220static const struct WRITESYSREGCLANG11WEIRDNOTHROW { PFNCPUMWRSYSREG pfnWrSysReg; } g_aCpumWrSysRegFns[kCpumSysRegWrFn_End] =
221{
222 { NULL }, /* Invalid */
223 { cpumSysRegWr_IgnoreWrite },
224 { cpumSysRegWr_ReadOnly },
225 { NULL }, /* Alias */
226 { cpumSysRegWr_GicV3Icc },
227 { cpumSysRegWr_OslarEl1 },
228 { cpumSysRegWr_Pmu }
229};
230
231
232/**
233 * Looks up the range for the given system register.
234 *
235 * @returns Pointer to the range if found, NULL if not.
236 * @param pVM The cross context VM structure.
237 * @param idSysReg The system register to look up.
238 */
239# ifndef IN_RING3
240static
241# endif
242PCPUMSYSREGRANGE cpumLookupSysRegRange(PVM pVM, uint32_t idSysReg)
243{
244 /*
245 * Binary lookup.
246 */
247 uint32_t cRanges = RT_MIN(pVM->cpum.s.GuestInfo.cSysRegRanges, RT_ELEMENTS(pVM->cpum.s.GuestInfo.aSysRegRanges));
248 if (!cRanges)
249 return NULL;
250 PCPUMSYSREGRANGE paRanges = pVM->cpum.s.GuestInfo.aSysRegRanges;
251 for (;;)
252 {
253 uint32_t i = cRanges / 2;
254 if (idSysReg < paRanges[i].uFirst)
255 {
256 if (i == 0)
257 break;
258 cRanges = i;
259 }
260 else if (idSysReg > paRanges[i].uLast)
261 {
262 i++;
263 if (i >= cRanges)
264 break;
265 cRanges -= i;
266 paRanges = &paRanges[i];
267 }
268 else
269 {
270 if (paRanges[i].enmRdFn == kCpumSysRegRdFn_Alias)
271 return cpumLookupSysRegRange(pVM, paRanges[i].uValue);
272 return &paRanges[i];
273 }
274 }
275
276# ifdef VBOX_STRICT
277 /*
278 * Linear lookup to verify the above binary search.
279 */
280 uint32_t cLeft = RT_MIN(pVM->cpum.s.GuestInfo.cSysRegRanges, RT_ELEMENTS(pVM->cpum.s.GuestInfo.aSysRegRanges));
281 PCPUMSYSREGRANGE pCur = pVM->cpum.s.GuestInfo.aSysRegRanges;
282 while (cLeft-- > 0)
283 {
284 if (idSysReg >= pCur->uFirst && idSysReg <= pCur->uLast)
285 {
286 AssertFailed();
287 if (pCur->enmRdFn == kCpumSysRegRdFn_Alias)
288 return cpumLookupSysRegRange(pVM, pCur->uValue);
289 return pCur;
290 }
291 pCur++;
292 }
293# endif
294 return NULL;
295}
296
297
298/**
299 * Query a guest system register.
300 *
301 * The caller is responsible for checking privilege if the call is the result of
302 * a MRS instruction. We'll do the rest.
303 *
304 * @retval VINF_SUCCESS on success.
305 * @retval VINF_CPUM_R3_MSR_READ if the system register read could not be serviced in the
306 * current context (raw-mode or ring-0).
307 * @retval VERR_CPUM_RAISE_GP_0 on failure (invalid system register), the caller is
308 * expected to take the appropriate actions. @a *puValue is set to 0.
309 * @param pVCpu The cross context virtual CPU structure.
310 * @param idSysReg The system register.
311 * @param puValue Where to return the value.
312 *
313 * @remarks This will always return the right values, even when we're in the
314 * recompiler.
315 */
316VMMDECL(VBOXSTRICTRC) CPUMQueryGuestSysReg(PVMCPUCC pVCpu, uint32_t idSysReg, uint64_t *puValue)
317{
318 *puValue = 0;
319
320 VBOXSTRICTRC rcStrict;
321 PVM pVM = pVCpu->CTX_SUFF(pVM);
322 PCPUMSYSREGRANGE pRange = cpumLookupSysRegRange(pVM, idSysReg);
323 if (pRange)
324 {
325 CPUMSYSREGRDFN enmRdFn = (CPUMSYSREGRDFN)pRange->enmRdFn;
326 AssertReturn(enmRdFn > kCpumSysRegRdFn_Invalid && enmRdFn < kCpumSysRegRdFn_End, VERR_CPUM_IPE_1);
327
328 PFNCPUMRDSYSREG pfnRdSysReg = g_aCpumRdSysRegFns[enmRdFn].pfnRdSysReg;
329 AssertReturn(pfnRdSysReg, VERR_CPUM_IPE_2);
330
331 STAM_COUNTER_INC(&pRange->cReads);
332 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReads);
333
334 rcStrict = pfnRdSysReg(pVCpu, idSysReg, pRange, puValue);
335 if (rcStrict == VINF_SUCCESS)
336 Log2(("CPUM: MRS %#x (%s) -> %#llx\n", idSysReg, pRange->szName, *puValue));
337 else if (rcStrict == VERR_CPUM_RAISE_GP_0)
338 {
339 Log(("CPUM: MRS %#x (%s) -> #GP(0)\n", idSysReg, pRange->szName));
340 STAM_COUNTER_INC(&pRange->cExcp);
341 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReadsRaiseExcp);
342 }
343#ifndef IN_RING3
344 else if (rcStrict == VINF_CPUM_R3_MSR_READ)
345 Log(("CPUM: MRS %#x (%s) -> ring-3\n", idSysReg, pRange->szName));
346#endif
347 else
348 {
349 Log(("CPUM: MRS %#x (%s) -> rcStrict=%Rrc\n", idSysReg, pRange->szName, VBOXSTRICTRC_VAL(rcStrict)));
350 AssertMsgStmt(RT_FAILURE_NP(rcStrict), ("%Rrc idSysReg=%#x\n", VBOXSTRICTRC_VAL(rcStrict), idSysReg),
351 rcStrict = VERR_IPE_UNEXPECTED_INFO_STATUS);
352 Assert(rcStrict != VERR_EM_INTERPRETER);
353 }
354 }
355 else
356 {
357 Log(("CPUM: Unknown MRS %#x -> Ignore\n", idSysReg));
358 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReads);
359 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReadsUnknown);
360 *puValue = 0;
361 rcStrict = VINF_SUCCESS;
362 }
363 return rcStrict;
364}
365
366
367/**
368 * Writes to a guest system register.
369 *
370 * The caller is responsible for checking privilege if the call is the result of
371 * a MSR instruction. We'll do the rest.
372 *
373 * @retval VINF_SUCCESS on success.
374 * @retval VINF_CPUM_R3_MSR_WRITE if the system register write could not be serviced in the
375 * current context (raw-mode or ring-0).
376 * @retval VERR_CPUM_RAISE_GP_0 on failure, the caller is expected to take the
377 * appropriate actions.
378 *
379 * @param pVCpu The cross context virtual CPU structure.
380 * @param idSysReg The system register id.
381 * @param uValue The value to set.
382 *
383 * @remarks Everyone changing system register values, shall do it
384 * by calling this method. This makes sure we have current values and
385 * that we trigger all the right actions when something changes.
386 */
387VMMDECL(VBOXSTRICTRC) CPUMSetGuestSysReg(PVMCPUCC pVCpu, uint32_t idSysReg, uint64_t uValue)
388{
389 VBOXSTRICTRC rcStrict;
390 PVM pVM = pVCpu->CTX_SUFF(pVM);
391 PCPUMSYSREGRANGE pRange = cpumLookupSysRegRange(pVM, idSysReg);
392 if (pRange)
393 {
394 STAM_COUNTER_INC(&pRange->cWrites);
395 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWrites);
396
397 if (!(uValue & pRange->fWrExcpMask))
398 {
399 CPUMSYSREGWRFN enmWrFn = (CPUMSYSREGWRFN)pRange->enmWrFn;
400 AssertReturn(enmWrFn > kCpumSysRegWrFn_Invalid && enmWrFn < kCpumSysRegWrFn_End, VERR_CPUM_IPE_1);
401
402 PFNCPUMWRSYSREG pfnWrSysReg = g_aCpumWrSysRegFns[enmWrFn].pfnWrSysReg;
403 AssertReturn(pfnWrSysReg, VERR_CPUM_IPE_2);
404
405 uint64_t uValueAdjusted = uValue & ~pRange->fWrIgnMask;
406 if (uValueAdjusted != uValue)
407 {
408 STAM_COUNTER_INC(&pRange->cIgnoredBits);
409 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesToIgnoredBits);
410 }
411
412 rcStrict = pfnWrSysReg(pVCpu, idSysReg, pRange, uValueAdjusted, uValue);
413 if (rcStrict == VINF_SUCCESS)
414 Log2(("CPUM: MSR %#x (%s), %#llx [%#llx]\n", idSysReg, pRange->szName, uValueAdjusted, uValue));
415 else if (rcStrict == VERR_CPUM_RAISE_GP_0)
416 {
417 Log(("CPUM: MSR %#x (%s), %#llx [%#llx] -> #GP(0)\n", idSysReg, pRange->szName, uValueAdjusted, uValue));
418 STAM_COUNTER_INC(&pRange->cExcp);
419 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesRaiseExcp);
420 }
421#ifndef IN_RING3
422 else if (rcStrict == VINF_CPUM_R3_MSR_WRITE)
423 Log(("CPUM: MSR %#x (%s), %#llx [%#llx] -> ring-3\n", idSysReg, pRange->szName, uValueAdjusted, uValue));
424#endif
425 else
426 {
427 Log(("CPUM: MSR %#x (%s), %#llx [%#llx] -> rcStrict=%Rrc\n",
428 idSysReg, pRange->szName, uValueAdjusted, uValue, VBOXSTRICTRC_VAL(rcStrict)));
429 AssertMsgStmt(RT_FAILURE_NP(rcStrict), ("%Rrc idSysReg=%#x\n", VBOXSTRICTRC_VAL(rcStrict), idSysReg),
430 rcStrict = VERR_IPE_UNEXPECTED_INFO_STATUS);
431 Assert(rcStrict != VERR_EM_INTERPRETER);
432 }
433 }
434 else
435 {
436 Log(("CPUM: MSR %#x (%s), %#llx -> #GP(0) - invalid bits %#llx\n",
437 idSysReg, pRange->szName, uValue, uValue & pRange->fWrExcpMask));
438 STAM_COUNTER_INC(&pRange->cExcp);
439 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesRaiseExcp);
440 rcStrict = VERR_CPUM_RAISE_GP_0;
441 }
442 }
443 else
444 {
445 Log(("CPUM: Unknown MSR %#x, %#llx -> #GP(0)\n", idSysReg, uValue));
446 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWrites);
447 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesUnknown);
448 rcStrict = VERR_CPUM_RAISE_GP_0; /** @todo Better status code. */
449 }
450 return rcStrict;
451}
452
453
454#if defined(VBOX_STRICT) && defined(IN_RING3)
455/**
456 * Performs some checks on the static data related to MSRs.
457 *
458 * @returns VINF_SUCCESS on success, error on failure.
459 */
460DECLHIDDEN(int) cpumR3SysRegStrictInitChecks(void)
461{
462#define CPUM_ASSERT_RD_SYSREG_FN(a_Register) \
463 AssertReturn(g_aCpumRdSysRegFns[kCpumSysRegRdFn_##a_Register].pfnRdSysReg == cpumSysRegRd_##a_Register, VERR_CPUM_IPE_2);
464#define CPUM_ASSERT_WR_SYSREG_FN(a_Register) \
465 AssertReturn(g_aCpumWrSysRegFns[kCpumSysRegWrFn_##a_Register].pfnWrSysReg == cpumSysRegWr_##a_Register, VERR_CPUM_IPE_2);
466
467 AssertReturn(g_aCpumRdSysRegFns[kCpumSysRegRdFn_Invalid].pfnRdSysReg == NULL, VERR_CPUM_IPE_2);
468 CPUM_ASSERT_RD_SYSREG_FN(FixedValue);
469 CPUM_ASSERT_RD_SYSREG_FN(WriteOnly);
470 CPUM_ASSERT_RD_SYSREG_FN(GicV3Icc);
471 CPUM_ASSERT_RD_SYSREG_FN(OslsrEl1);
472
473 AssertReturn(g_aCpumWrSysRegFns[kCpumSysRegWrFn_Invalid].pfnWrSysReg == NULL, VERR_CPUM_IPE_2);
474 CPUM_ASSERT_WR_SYSREG_FN(IgnoreWrite);
475 CPUM_ASSERT_WR_SYSREG_FN(ReadOnly);
476 CPUM_ASSERT_WR_SYSREG_FN(GicV3Icc);
477 CPUM_ASSERT_WR_SYSREG_FN(OslarEl1);
478
479 return VINF_SUCCESS;
480}
481#endif /* VBOX_STRICT && IN_RING3 */
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