VirtualBox

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

Last change on this file since 107031 was 107031, checked in by vboxsync, 8 days ago

VMM/CPUM-armv8: Allow reading/writing the debug control/value registers through CPUMQueryGuestSysReg/CPUMSetGuestSysReg, bugreef:10393

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1/* $Id: CPUMAllSysRegs-armv8.cpp 107031 2024-11-18 15:00:29Z 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(CPUMCTX) \
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.Guest + (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/** @callback_method_impl{FNCPUMRDSYSREG} */
149static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_ReadCpumOff(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
150{
151 RT_NOREF(idSysReg);
152
153 CPUM_SYSREG_ASSERT_CPUMCPU_OFFSET_RETURN(pVCpu, pRange, CPUMCTXSYSREG, pSysReg);
154 *puValue = pSysReg->u64;
155 return VINF_SUCCESS;
156}
157
158
159/** @callback_method_impl{FNCPUMWRSYSREG} */
160static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_WriteCpumOff(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
161{
162 RT_NOREF(idSysReg, uRawValue);
163
164 CPUM_SYSREG_ASSERT_CPUMCPU_OFFSET_RETURN(pVCpu, pRange, CPUMCTXSYSREG, pSysReg);
165 pSysReg->u64 = uValue;
166 return VINF_SUCCESS;
167}
168
169
170/** @callback_method_impl{FNCPUMRDSYSREG} */
171static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_GicV3Icc(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
172{
173 RT_NOREF_PV(pRange);
174 return GICReadSysReg(pVCpu, idSysReg, puValue);
175}
176
177
178/** @callback_method_impl{FNCPUMWRSYSREG} */
179static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_GicV3Icc(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
180{
181 RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue);
182 return GICWriteSysReg(pVCpu, idSysReg, uValue);
183}
184
185
186
187/** @callback_method_impl{FNCPUMRDSYSREG} */
188static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_OslsrEl1(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
189{
190 RT_NOREF(idSysReg, pRange);
191 *puValue = pVCpu->cpum.s.Guest.fOsLck ? ARMV8_OSLSR_EL1_AARCH64_OSLK : 0;
192 return VINF_SUCCESS;
193}
194
195
196/** @callback_method_impl{FNCPUMWRSYSREG} */
197static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_OslarEl1(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
198{
199 RT_NOREF(idSysReg, pRange, uRawValue);
200 Assert(!(uValue & ~ARMV8_OSLAR_EL1_AARCH64_OSLK));
201 pVCpu->cpum.s.Guest.fOsLck = RT_BOOL(uValue);
202 return VINF_SUCCESS;
203}
204
205
206
207/** @callback_method_impl{FNCPUMRDSYSREG} */
208static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegRd_Pmu(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t *puValue)
209{
210 RT_NOREF_PV(pRange);
211 return PMUReadSysReg(pVCpu, idSysReg, puValue);
212}
213
214
215/** @callback_method_impl{FNCPUMWRSYSREG} */
216static DECLCALLBACK(VBOXSTRICTRC) cpumSysRegWr_Pmu(PVMCPUCC pVCpu, uint32_t idSysReg, PCCPUMSYSREGRANGE pRange, uint64_t uValue, uint64_t uRawValue)
217{
218 RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue);
219 return PMUWriteSysReg(pVCpu, idSysReg, uValue);
220}
221
222
223/**
224 * System register read function table.
225 */
226static const struct READSYSREGCLANG11WEIRDNOTHROW { PFNCPUMRDSYSREG pfnRdSysReg; } g_aCpumRdSysRegFns[kCpumSysRegRdFn_End] =
227{
228 { NULL }, /* Invalid */
229 { cpumSysRegRd_FixedValue },
230 { NULL }, /* Alias */
231 { cpumSysRegRd_WriteOnly },
232 { cpumSysRegRd_ReadCpumOff },
233 { cpumSysRegRd_GicV3Icc },
234 { cpumSysRegRd_OslsrEl1 },
235 { cpumSysRegRd_Pmu }
236};
237
238
239/**
240 * System register write function table.
241 */
242static const struct WRITESYSREGCLANG11WEIRDNOTHROW { PFNCPUMWRSYSREG pfnWrSysReg; } g_aCpumWrSysRegFns[kCpumSysRegWrFn_End] =
243{
244 { NULL }, /* Invalid */
245 { cpumSysRegWr_IgnoreWrite },
246 { cpumSysRegWr_ReadOnly },
247 { NULL }, /* Alias */
248 { cpumSysRegWr_WriteCpumOff },
249 { cpumSysRegWr_GicV3Icc },
250 { cpumSysRegWr_OslarEl1 },
251 { cpumSysRegWr_Pmu }
252};
253
254
255/**
256 * Looks up the range for the given system register.
257 *
258 * @returns Pointer to the range if found, NULL if not.
259 * @param pVM The cross context VM structure.
260 * @param idSysReg The system register to look up.
261 */
262# ifndef IN_RING3
263static
264# endif
265PCPUMSYSREGRANGE cpumLookupSysRegRange(PVM pVM, uint32_t idSysReg)
266{
267 /*
268 * Binary lookup.
269 */
270 uint32_t cRanges = RT_MIN(pVM->cpum.s.GuestInfo.cSysRegRanges, RT_ELEMENTS(pVM->cpum.s.GuestInfo.aSysRegRanges));
271 if (!cRanges)
272 return NULL;
273 PCPUMSYSREGRANGE paRanges = pVM->cpum.s.GuestInfo.aSysRegRanges;
274 for (;;)
275 {
276 uint32_t i = cRanges / 2;
277 if (idSysReg < paRanges[i].uFirst)
278 {
279 if (i == 0)
280 break;
281 cRanges = i;
282 }
283 else if (idSysReg > paRanges[i].uLast)
284 {
285 i++;
286 if (i >= cRanges)
287 break;
288 cRanges -= i;
289 paRanges = &paRanges[i];
290 }
291 else
292 {
293 if (paRanges[i].enmRdFn == kCpumSysRegRdFn_Alias)
294 return cpumLookupSysRegRange(pVM, paRanges[i].uValue);
295 return &paRanges[i];
296 }
297 }
298
299# ifdef VBOX_STRICT
300 /*
301 * Linear lookup to verify the above binary search.
302 */
303 uint32_t cLeft = RT_MIN(pVM->cpum.s.GuestInfo.cSysRegRanges, RT_ELEMENTS(pVM->cpum.s.GuestInfo.aSysRegRanges));
304 PCPUMSYSREGRANGE pCur = pVM->cpum.s.GuestInfo.aSysRegRanges;
305 while (cLeft-- > 0)
306 {
307 if (idSysReg >= pCur->uFirst && idSysReg <= pCur->uLast)
308 {
309 AssertFailed();
310 if (pCur->enmRdFn == kCpumSysRegRdFn_Alias)
311 return cpumLookupSysRegRange(pVM, pCur->uValue);
312 return pCur;
313 }
314 pCur++;
315 }
316# endif
317 return NULL;
318}
319
320
321/**
322 * Query a guest system register.
323 *
324 * The caller is responsible for checking privilege if the call is the result of
325 * a MRS instruction. We'll do the rest.
326 *
327 * @retval VINF_SUCCESS on success.
328 * @retval VINF_CPUM_R3_MSR_READ if the system register read could not be serviced in the
329 * current context (raw-mode or ring-0).
330 * @retval VERR_CPUM_RAISE_GP_0 on failure (invalid system register), the caller is
331 * expected to take the appropriate actions. @a *puValue is set to 0.
332 * @param pVCpu The cross context virtual CPU structure.
333 * @param idSysReg The system register.
334 * @param puValue Where to return the value.
335 *
336 * @remarks This will always return the right values, even when we're in the
337 * recompiler.
338 */
339VMMDECL(VBOXSTRICTRC) CPUMQueryGuestSysReg(PVMCPUCC pVCpu, uint32_t idSysReg, uint64_t *puValue)
340{
341 *puValue = 0;
342
343 VBOXSTRICTRC rcStrict;
344 PVM pVM = pVCpu->CTX_SUFF(pVM);
345 PCPUMSYSREGRANGE pRange = cpumLookupSysRegRange(pVM, idSysReg);
346 if (pRange)
347 {
348 CPUMSYSREGRDFN enmRdFn = (CPUMSYSREGRDFN)pRange->enmRdFn;
349 AssertReturn(enmRdFn > kCpumSysRegRdFn_Invalid && enmRdFn < kCpumSysRegRdFn_End, VERR_CPUM_IPE_1);
350
351 PFNCPUMRDSYSREG pfnRdSysReg = g_aCpumRdSysRegFns[enmRdFn].pfnRdSysReg;
352 AssertReturn(pfnRdSysReg, VERR_CPUM_IPE_2);
353
354 STAM_COUNTER_INC(&pRange->cReads);
355 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReads);
356
357 rcStrict = pfnRdSysReg(pVCpu, idSysReg, pRange, puValue);
358 if (rcStrict == VINF_SUCCESS)
359 Log2(("CPUM: MRS %#x (%s) -> %#llx\n", idSysReg, pRange->szName, *puValue));
360 else if (rcStrict == VERR_CPUM_RAISE_GP_0)
361 {
362 Log(("CPUM: MRS %#x (%s) -> #GP(0)\n", idSysReg, pRange->szName));
363 STAM_COUNTER_INC(&pRange->cExcp);
364 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReadsRaiseExcp);
365 }
366#ifndef IN_RING3
367 else if (rcStrict == VINF_CPUM_R3_MSR_READ)
368 Log(("CPUM: MRS %#x (%s) -> ring-3\n", idSysReg, pRange->szName));
369#endif
370 else
371 {
372 Log(("CPUM: MRS %#x (%s) -> rcStrict=%Rrc\n", idSysReg, pRange->szName, VBOXSTRICTRC_VAL(rcStrict)));
373 AssertMsgStmt(RT_FAILURE_NP(rcStrict), ("%Rrc idSysReg=%#x\n", VBOXSTRICTRC_VAL(rcStrict), idSysReg),
374 rcStrict = VERR_IPE_UNEXPECTED_INFO_STATUS);
375 Assert(rcStrict != VERR_EM_INTERPRETER);
376 }
377 }
378 else
379 {
380 Log(("CPUM: Unknown MRS %#x -> Ignore\n", idSysReg));
381 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReads);
382 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegReadsUnknown);
383 *puValue = 0;
384 rcStrict = VINF_SUCCESS;
385 }
386 return rcStrict;
387}
388
389
390/**
391 * Writes to a guest system register.
392 *
393 * The caller is responsible for checking privilege if the call is the result of
394 * a MSR instruction. We'll do the rest.
395 *
396 * @retval VINF_SUCCESS on success.
397 * @retval VINF_CPUM_R3_MSR_WRITE if the system register write could not be serviced in the
398 * current context (raw-mode or ring-0).
399 * @retval VERR_CPUM_RAISE_GP_0 on failure, the caller is expected to take the
400 * appropriate actions.
401 *
402 * @param pVCpu The cross context virtual CPU structure.
403 * @param idSysReg The system register id.
404 * @param uValue The value to set.
405 *
406 * @remarks Everyone changing system register values, shall do it
407 * by calling this method. This makes sure we have current values and
408 * that we trigger all the right actions when something changes.
409 */
410VMMDECL(VBOXSTRICTRC) CPUMSetGuestSysReg(PVMCPUCC pVCpu, uint32_t idSysReg, uint64_t uValue)
411{
412 VBOXSTRICTRC rcStrict;
413 PVM pVM = pVCpu->CTX_SUFF(pVM);
414 PCPUMSYSREGRANGE pRange = cpumLookupSysRegRange(pVM, idSysReg);
415 if (pRange)
416 {
417 STAM_COUNTER_INC(&pRange->cWrites);
418 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWrites);
419
420 if (!(uValue & pRange->fWrExcpMask))
421 {
422 CPUMSYSREGWRFN enmWrFn = (CPUMSYSREGWRFN)pRange->enmWrFn;
423 AssertReturn(enmWrFn > kCpumSysRegWrFn_Invalid && enmWrFn < kCpumSysRegWrFn_End, VERR_CPUM_IPE_1);
424
425 PFNCPUMWRSYSREG pfnWrSysReg = g_aCpumWrSysRegFns[enmWrFn].pfnWrSysReg;
426 AssertReturn(pfnWrSysReg, VERR_CPUM_IPE_2);
427
428 uint64_t uValueAdjusted = uValue & ~pRange->fWrIgnMask;
429 if (uValueAdjusted != uValue)
430 {
431 STAM_COUNTER_INC(&pRange->cIgnoredBits);
432 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesToIgnoredBits);
433 }
434
435 rcStrict = pfnWrSysReg(pVCpu, idSysReg, pRange, uValueAdjusted, uValue);
436 if (rcStrict == VINF_SUCCESS)
437 Log2(("CPUM: MSR %#x (%s), %#llx [%#llx]\n", idSysReg, pRange->szName, uValueAdjusted, uValue));
438 else if (rcStrict == VERR_CPUM_RAISE_GP_0)
439 {
440 Log(("CPUM: MSR %#x (%s), %#llx [%#llx] -> #GP(0)\n", idSysReg, pRange->szName, uValueAdjusted, uValue));
441 STAM_COUNTER_INC(&pRange->cExcp);
442 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesRaiseExcp);
443 }
444#ifndef IN_RING3
445 else if (rcStrict == VINF_CPUM_R3_MSR_WRITE)
446 Log(("CPUM: MSR %#x (%s), %#llx [%#llx] -> ring-3\n", idSysReg, pRange->szName, uValueAdjusted, uValue));
447#endif
448 else
449 {
450 Log(("CPUM: MSR %#x (%s), %#llx [%#llx] -> rcStrict=%Rrc\n",
451 idSysReg, pRange->szName, uValueAdjusted, uValue, VBOXSTRICTRC_VAL(rcStrict)));
452 AssertMsgStmt(RT_FAILURE_NP(rcStrict), ("%Rrc idSysReg=%#x\n", VBOXSTRICTRC_VAL(rcStrict), idSysReg),
453 rcStrict = VERR_IPE_UNEXPECTED_INFO_STATUS);
454 Assert(rcStrict != VERR_EM_INTERPRETER);
455 }
456 }
457 else
458 {
459 Log(("CPUM: MSR %#x (%s), %#llx -> #GP(0) - invalid bits %#llx\n",
460 idSysReg, pRange->szName, uValue, uValue & pRange->fWrExcpMask));
461 STAM_COUNTER_INC(&pRange->cExcp);
462 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesRaiseExcp);
463 rcStrict = VERR_CPUM_RAISE_GP_0;
464 }
465 }
466 else
467 {
468 Log(("CPUM: Unknown MSR %#x, %#llx -> #GP(0)\n", idSysReg, uValue));
469 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWrites);
470 STAM_REL_COUNTER_INC(&pVM->cpum.s.cSysRegWritesUnknown);
471 rcStrict = VERR_CPUM_RAISE_GP_0; /** @todo Better status code. */
472 }
473 return rcStrict;
474}
475
476
477#if defined(VBOX_STRICT) && defined(IN_RING3)
478/**
479 * Performs some checks on the static data related to MSRs.
480 *
481 * @returns VINF_SUCCESS on success, error on failure.
482 */
483DECLHIDDEN(int) cpumR3SysRegStrictInitChecks(void)
484{
485#define CPUM_ASSERT_RD_SYSREG_FN(a_Register) \
486 AssertReturn(g_aCpumRdSysRegFns[kCpumSysRegRdFn_##a_Register].pfnRdSysReg == cpumSysRegRd_##a_Register, VERR_CPUM_IPE_2);
487#define CPUM_ASSERT_WR_SYSREG_FN(a_Register) \
488 AssertReturn(g_aCpumWrSysRegFns[kCpumSysRegWrFn_##a_Register].pfnWrSysReg == cpumSysRegWr_##a_Register, VERR_CPUM_IPE_2);
489
490 AssertReturn(g_aCpumRdSysRegFns[kCpumSysRegRdFn_Invalid].pfnRdSysReg == NULL, VERR_CPUM_IPE_2);
491 CPUM_ASSERT_RD_SYSREG_FN(FixedValue);
492 CPUM_ASSERT_RD_SYSREG_FN(WriteOnly);
493 CPUM_ASSERT_RD_SYSREG_FN(ReadCpumOff);
494 CPUM_ASSERT_RD_SYSREG_FN(GicV3Icc);
495 CPUM_ASSERT_RD_SYSREG_FN(OslsrEl1);
496 CPUM_ASSERT_RD_SYSREG_FN(Pmu);
497
498 AssertReturn(g_aCpumWrSysRegFns[kCpumSysRegWrFn_Invalid].pfnWrSysReg == NULL, VERR_CPUM_IPE_2);
499 CPUM_ASSERT_WR_SYSREG_FN(IgnoreWrite);
500 CPUM_ASSERT_WR_SYSREG_FN(ReadOnly);
501 CPUM_ASSERT_WR_SYSREG_FN(WriteCpumOff);
502 CPUM_ASSERT_WR_SYSREG_FN(GicV3Icc);
503 CPUM_ASSERT_WR_SYSREG_FN(OslarEl1);
504 CPUM_ASSERT_WR_SYSREG_FN(Pmu);
505
506 return VINF_SUCCESS;
507}
508#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