VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId-armv8.cpp@ 108404

最後變更 在這個檔案從108404是 108404,由 vboxsync 提交於 2 週 前

VMM/NEMR3Native-win-armv8.cpp: Need to call WHvResumePartitionTime() to get time ticking despite the docs claiming that it is resumed as soon as vCPU starts executing. Also suspend time already when querying the guest CPU tick counter, bugref:10392

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 77.4 KB
 
1/* $Id: CPUMR3CpuId-armv8.cpp 108404 2025-02-27 09:41:50Z vboxsync $ */
2/** @file
3 * CPUM - CPU ID part for ARMv8 hypervisor.
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.alldomusa.eu.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#define CPUM_WITH_NONCONST_HOST_FEATURES /* required for initializing parts of the g_CpumHostFeatures structure here. */
34#include <VBox/vmm/cpum.h>
35#include <VBox/vmm/dbgf.h>
36#include <VBox/vmm/nem.h>
37#include <VBox/vmm/ssm.h>
38#include "CPUMInternal-armv8.h"
39#include <VBox/vmm/vmcc.h>
40
41#include <VBox/err.h>
42#include <iprt/ctype.h>
43#include <iprt/mem.h>
44#include <iprt/string.h>
45
46
47/*********************************************************************************************************************************
48* Defined Constants And Macros *
49*********************************************************************************************************************************/
50
51/*
52 *
53 * Init related code.
54 * Init related code.
55 * Init related code.
56 *
57 *
58 */
59
60/** @name Instruction Set Extension Options
61 * @{ */
62/** Configuration option type (extended boolean, really). */
63typedef uint8_t CPUMISAEXTCFG;
64/** Always disable the extension. */
65#define CPUMISAEXTCFG_DISABLED false
66/** Enable the extension if it's supported by the host CPU. */
67#define CPUMISAEXTCFG_ENABLED_SUPPORTED true
68/** Enable the extension if it's supported by the host CPU, but don't let
69 * the portable CPUID feature disable it. */
70#define CPUMISAEXTCFG_ENABLED_PORTABLE UINT8_C(127)
71/** Always enable the extension. */
72#define CPUMISAEXTCFG_ENABLED_ALWAYS UINT8_C(255)
73/** @} */
74
75/**
76 * CPUID Configuration (from CFGM).
77 *
78 * @remarks The members aren't document since we would only be duplicating the
79 * \@cfgm entries in cpumR3CpuIdReadConfig.
80 */
81typedef struct CPUMCPUIDCONFIG
82{
83 CPUMISAEXTCFG enmAes;
84 CPUMISAEXTCFG enmPmull;
85 CPUMISAEXTCFG enmSha1;
86 CPUMISAEXTCFG enmSha256;
87 CPUMISAEXTCFG enmSha512;
88 CPUMISAEXTCFG enmCrc32;
89 CPUMISAEXTCFG enmSha3;
90
91 char szCpuName[128];
92} CPUMCPUIDCONFIG;
93/** Pointer to CPUID config (from CFGM). */
94typedef CPUMCPUIDCONFIG *PCPUMCPUIDCONFIG;
95
96
97/**
98 * Sanitizes and adjust the CPUID leaves.
99 *
100 * Drop features that aren't virtualized (or virtualizable). Adjust information
101 * and capabilities to fit the virtualized hardware. Remove information the
102 * guest shouldn't have (because it's wrong in the virtual world or because it
103 * gives away host details) or that we don't have documentation for and no idea
104 * what means.
105 *
106 * @returns VBox status code.
107 * @param pVM The cross context VM structure (for cCpus).
108 * @param pCpum The CPUM instance data.
109 * @param pConfig The CPUID configuration we've read from CFGM.
110 */
111static int cpumR3CpuIdSanitize(PVM pVM, PCPUM pCpum, PCPUMCPUIDCONFIG pConfig)
112{
113#define PORTABLE_CLEAR_BITS_WHEN(Lvl, a_pLeafReg, FeatNm, fMask, uValue) \
114 if ( pCpum->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fMask)) == (uValue) ) \
115 { \
116 LogRel(("PortableCpuId: " #a_pLeafReg "[" #FeatNm "]: %#x -> 0\n", (a_pLeafReg) & (fMask))); \
117 (a_pLeafReg) &= ~(uint32_t)(fMask); \
118 }
119#define PORTABLE_DISABLE_FEATURE_BIT(Lvl, a_pLeafReg, FeatNm, fBitMask) \
120 if ( pCpum->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fBitMask)) ) \
121 { \
122 LogRel(("PortableCpuId: " #a_pLeafReg "[" #FeatNm "]: 1 -> 0\n")); \
123 (a_pLeafReg) &= ~(uint32_t)(fBitMask); \
124 }
125#define PORTABLE_DISABLE_FEATURE_BIT_CFG(Lvl, a_IdReg, a_FeatNm, a_IdRegValCheck, enmConfig, a_IdRegValNotSup) \
126 if ( pCpum->u8PortableCpuIdLevel >= (Lvl) \
127 && (RT_BF_GET(a_IdReg, a_FeatNm) >= a_IdRegValCheck) \
128 && (enmConfig) != CPUMISAEXTCFG_ENABLED_PORTABLE ) \
129 { \
130 LogRel(("PortableCpuId: [" #a_FeatNm "]: 1 -> 0\n")); \
131 (a_IdReg) = RT_BF_SET(a_IdReg, a_FeatNm, a_IdRegValNotSup); \
132 }
133 //Assert(pCpum->GuestFeatures.enmCpuVendor != CPUMCPUVENDOR_INVALID);
134
135 /* The CPUID entries we start with here isn't necessarily the ones of the host, so we
136 must consult HostFeatures when processing CPUMISAEXTCFG variables. */
137 PCCPUMFEATURES pHstFeat = &pCpum->HostFeatures.s;
138#define PASSTHRU_FEATURE(a_IdReg, enmConfig, fHostFeature, a_IdRegNm, a_IdRegValSup, a_IdRegValNotSup) \
139 (a_IdReg) = ((enmConfig) && ((enmConfig) == CPUMISAEXTCFG_ENABLED_ALWAYS || (fHostFeature)) \
140 ? RT_BF_SET(a_IdReg, a_IdRegNm, a_IdRegValSup) \
141 : RT_BF_SET(a_IdReg, a_IdRegNm, a_IdRegValNotSup))
142
143 /* ID_AA64ISAR0_EL1 */
144 uint64_t u64ValTmp = 0;
145 uint64_t u64IdReg = pVM->cpum.s.GuestIdRegs.u64RegIdAa64Isar0El1;
146
147 PASSTHRU_FEATURE(u64IdReg, pConfig->enmAes, pHstFeat->fAes, ARMV8_ID_AA64ISAR0_EL1_AES, ARMV8_ID_AA64ISAR0_EL1_AES_SUPPORTED, ARMV8_ID_AA64ISAR0_EL1_AES_NOT_IMPL);
148 u64ValTmp = RT_BF_GET(u64IdReg, ARMV8_ID_AA64ISAR0_EL1_AES) == ARMV8_ID_AA64ISAR0_EL1_AES_SUPPORTED ? ARMV8_ID_AA64ISAR0_EL1_AES_SUPPORTED : ARMV8_ID_AA64ISAR0_EL1_AES_NOT_IMPL;
149 PASSTHRU_FEATURE(u64IdReg, pConfig->enmPmull, pHstFeat->fPmull, ARMV8_ID_AA64ISAR0_EL1_AES, ARMV8_ID_AA64ISAR0_EL1_AES_SUPPORTED_PMULL, u64ValTmp);
150 PASSTHRU_FEATURE(u64IdReg, pConfig->enmSha1, pHstFeat->fSha1, ARMV8_ID_AA64ISAR0_EL1_SHA1, ARMV8_ID_AA64ISAR0_EL1_SHA1_SUPPORTED, ARMV8_ID_AA64ISAR0_EL1_SHA1_NOT_IMPL);
151 PASSTHRU_FEATURE(u64IdReg, pConfig->enmSha256, pHstFeat->fSha256, ARMV8_ID_AA64ISAR0_EL1_SHA2, ARMV8_ID_AA64ISAR0_EL1_SHA2_SUPPORTED_SHA256, ARMV8_ID_AA64ISAR0_EL1_SHA2_NOT_IMPL);
152 u64ValTmp = RT_BF_GET(u64IdReg, ARMV8_ID_AA64ISAR0_EL1_SHA2) == ARMV8_ID_AA64ISAR0_EL1_SHA2_SUPPORTED_SHA256 ? ARMV8_ID_AA64ISAR0_EL1_SHA2_SUPPORTED_SHA256 : ARMV8_ID_AA64ISAR0_EL1_SHA2_NOT_IMPL;
153 PASSTHRU_FEATURE(u64IdReg, pConfig->enmSha512, pHstFeat->fSha512, ARMV8_ID_AA64ISAR0_EL1_SHA2, ARMV8_ID_AA64ISAR0_EL1_SHA2_SUPPORTED_SHA256_SHA512, u64ValTmp);
154 PASSTHRU_FEATURE(u64IdReg, pConfig->enmCrc32, pHstFeat->fCrc32, ARMV8_ID_AA64ISAR0_EL1_CRC32, ARMV8_ID_AA64ISAR0_EL1_CRC32_SUPPORTED, ARMV8_ID_AA64ISAR0_EL1_CRC32_NOT_IMPL);
155 PASSTHRU_FEATURE(u64IdReg, pConfig->enmSha3, pHstFeat->fSha3, ARMV8_ID_AA64ISAR0_EL1_SHA3, ARMV8_ID_AA64ISAR0_EL1_SHA3_SUPPORTED, ARMV8_ID_AA64ISAR0_EL1_SHA3_NOT_IMPL);
156
157 if (pCpum->u8PortableCpuIdLevel > 0)
158 {
159 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_AES, ARMV8_ID_AA64ISAR0_EL1_AES_SUPPORTED, pConfig->enmAes, ARMV8_ID_AA64ISAR0_EL1_AES_NOT_IMPL);
160 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_AES, ARMV8_ID_AA64ISAR0_EL1_AES_SUPPORTED_PMULL, pConfig->enmPmull, ARMV8_ID_AA64ISAR0_EL1_AES_NOT_IMPL);
161 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_SHA1, ARMV8_ID_AA64ISAR0_EL1_SHA1_SUPPORTED, pConfig->enmSha1, ARMV8_ID_AA64ISAR0_EL1_SHA1_NOT_IMPL);
162 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_SHA2, ARMV8_ID_AA64ISAR0_EL1_SHA2_SUPPORTED_SHA256, pConfig->enmSha256, ARMV8_ID_AA64ISAR0_EL1_SHA2_NOT_IMPL);
163 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_SHA2, ARMV8_ID_AA64ISAR0_EL1_SHA2_SUPPORTED_SHA256_SHA512, pConfig->enmSha512, ARMV8_ID_AA64ISAR0_EL1_SHA2_NOT_IMPL);
164 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_CRC32, ARMV8_ID_AA64ISAR0_EL1_CRC32_SUPPORTED, pConfig->enmCrc32, ARMV8_ID_AA64ISAR0_EL1_CRC32_NOT_IMPL);
165 PORTABLE_DISABLE_FEATURE_BIT_CFG(1, u64IdReg, ARMV8_ID_AA64ISAR0_EL1_SHA3, ARMV8_ID_AA64ISAR0_EL1_SHA3_SUPPORTED, pConfig->enmSha3, ARMV8_ID_AA64ISAR0_EL1_SHA3_NOT_IMPL);
166 }
167
168 /* Write ID_AA64ISAR0_EL1 register back. */
169 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Isar0El1 = u64IdReg;
170
171
172 u64IdReg = pVM->cpum.s.GuestIdRegs.u64RegIdAa64Dfr0El1;
173 PORTABLE_DISABLE_FEATURE_BIT_CFG(0, u64IdReg, ARMV8_ID_AA64DFR0_EL1_PMUVER, ARMV8_ID_AA64DFR0_EL1_PMUVER_SUPPORTED_V3, CPUMISAEXTCFG_DISABLED , ARMV8_ID_AA64DFR0_EL1_PMUVER_NOT_IMPL);
174
175 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Dfr0El1 = u64IdReg;
176
177 /** @todo Other ID and feature registers. */
178
179 return VINF_SUCCESS;
180#undef PORTABLE_DISABLE_FEATURE_BIT
181#undef PORTABLE_CLEAR_BITS_WHEN
182}
183
184
185/**
186 * Reads a value in /CPUM/IsaExts/ node.
187 *
188 * @returns VBox status code (error message raised).
189 * @param pVM The cross context VM structure. (For errors.)
190 * @param pIsaExts The /CPUM/IsaExts node (can be NULL).
191 * @param pszValueName The value / extension name.
192 * @param penmValue Where to return the choice.
193 * @param enmDefault The default choice.
194 */
195static int cpumR3CpuIdReadIsaExtCfg(PVM pVM, PCFGMNODE pIsaExts, const char *pszValueName,
196 CPUMISAEXTCFG *penmValue, CPUMISAEXTCFG enmDefault)
197{
198 /*
199 * Try integer encoding first.
200 */
201 uint64_t uValue;
202 int rc = CFGMR3QueryInteger(pIsaExts, pszValueName, &uValue);
203 if (RT_SUCCESS(rc))
204 switch (uValue)
205 {
206 case 0: *penmValue = CPUMISAEXTCFG_DISABLED; break;
207 case 1: *penmValue = CPUMISAEXTCFG_ENABLED_SUPPORTED; break;
208 case 2: *penmValue = CPUMISAEXTCFG_ENABLED_ALWAYS; break;
209 case 9: *penmValue = CPUMISAEXTCFG_ENABLED_PORTABLE; break;
210 default:
211 return VMSetError(pVM, VERR_CPUM_INVALID_CONFIG_VALUE, RT_SRC_POS,
212 "Invalid config value for '/CPUM/IsaExts/%s': %llu (expected 0/'disabled', 1/'enabled', 2/'portable', or 9/'forced')",
213 pszValueName, uValue);
214 }
215 /*
216 * If missing, use default.
217 */
218 else if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
219 *penmValue = enmDefault;
220 else
221 {
222 if (rc == VERR_CFGM_NOT_INTEGER)
223 {
224 /*
225 * Not an integer, try read it as a string.
226 */
227 char szValue[32];
228 rc = CFGMR3QueryString(pIsaExts, pszValueName, szValue, sizeof(szValue));
229 if (RT_SUCCESS(rc))
230 {
231 RTStrToLower(szValue);
232 size_t cchValue = strlen(szValue);
233#define EQ(a_str) (cchValue == sizeof(a_str) - 1U && memcmp(szValue, a_str, sizeof(a_str) - 1))
234 if ( EQ("disabled") || EQ("disable") || EQ("off") || EQ("no"))
235 *penmValue = CPUMISAEXTCFG_DISABLED;
236 else if (EQ("enabled") || EQ("enable") || EQ("on") || EQ("yes"))
237 *penmValue = CPUMISAEXTCFG_ENABLED_SUPPORTED;
238 else if (EQ("forced") || EQ("force") || EQ("always"))
239 *penmValue = CPUMISAEXTCFG_ENABLED_ALWAYS;
240 else if (EQ("portable"))
241 *penmValue = CPUMISAEXTCFG_ENABLED_PORTABLE;
242 else if (EQ("default") || EQ("def"))
243 *penmValue = enmDefault;
244 else
245 return VMSetError(pVM, VERR_CPUM_INVALID_CONFIG_VALUE, RT_SRC_POS,
246 "Invalid config value for '/CPUM/IsaExts/%s': '%s' (expected 0/'disabled', 1/'enabled', 2/'portable', or 9/'forced')",
247 pszValueName, uValue);
248#undef EQ
249 }
250 }
251 if (RT_FAILURE(rc))
252 return VMSetError(pVM, rc, RT_SRC_POS, "Error reading config value '/CPUM/IsaExts/%s': %Rrc", pszValueName, rc);
253 }
254 return VINF_SUCCESS;
255}
256
257
258#if 0
259/**
260 * Reads a value in /CPUM/IsaExts/ node, forcing it to DISABLED if wanted.
261 *
262 * @returns VBox status code (error message raised).
263 * @param pVM The cross context VM structure. (For errors.)
264 * @param pIsaExts The /CPUM/IsaExts node (can be NULL).
265 * @param pszValueName The value / extension name.
266 * @param penmValue Where to return the choice.
267 * @param enmDefault The default choice.
268 * @param fAllowed Allowed choice. Applied both to the result and to
269 * the default value.
270 */
271static int cpumR3CpuIdReadIsaExtCfgEx(PVM pVM, PCFGMNODE pIsaExts, const char *pszValueName,
272 CPUMISAEXTCFG *penmValue, CPUMISAEXTCFG enmDefault, bool fAllowed)
273{
274 int rc;
275 if (fAllowed)
276 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, pszValueName, penmValue, enmDefault);
277 else
278 {
279 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, pszValueName, penmValue, false /*enmDefault*/);
280 if (RT_SUCCESS(rc) && *penmValue == CPUMISAEXTCFG_ENABLED_ALWAYS)
281 LogRel(("CPUM: Ignoring forced '%s'\n", pszValueName));
282 *penmValue = CPUMISAEXTCFG_DISABLED;
283 }
284 return rc;
285}
286#endif
287
288static int cpumR3CpuIdReadConfig(PVM pVM, PCPUMCPUIDCONFIG pConfig, PCFGMNODE pCpumCfg)
289{
290 /** @cfgm{/CPUM/PortableCpuIdLevel, 8-bit, 0, 3, 0}
291 * When non-zero CPUID features that could cause portability issues will be
292 * stripped. The higher the value the more features gets stripped. Higher
293 * values should only be used when older CPUs are involved since it may
294 * harm performance and maybe also cause problems with specific guests. */
295 int rc = CFGMR3QueryU8Def(pCpumCfg, "PortableCpuIdLevel", &pVM->cpum.s.u8PortableCpuIdLevel, 0);
296 AssertLogRelRCReturn(rc, rc);
297
298 /** @cfgm{/CPUM/GuestCpuName, string}
299 * The name of the CPU we're to emulate. The default is the host CPU.
300 * Note! CPUs other than "host" one is currently unsupported. */
301 rc = CFGMR3QueryStringDef(pCpumCfg, "GuestCpuName", pConfig->szCpuName, sizeof(pConfig->szCpuName), "host");
302 AssertLogRelRCReturn(rc, rc);
303
304 /*
305 * Instruction Set Architecture (ISA) Extensions.
306 */
307 PCFGMNODE pIsaExts = CFGMR3GetChild(pCpumCfg, "IsaExts");
308 if (pIsaExts)
309 {
310 rc = CFGMR3ValidateConfig(pIsaExts, "/CPUM/IsaExts/",
311 "AES"
312 "|PMULL"
313 "|SHA1"
314 "|SHA256"
315 "|SHA512"
316 "|CRC32"
317 "|SHA3"
318 , "" /*pszValidNodes*/, "CPUM" /*pszWho*/, 0 /*uInstance*/);
319 if (RT_FAILURE(rc))
320 return rc;
321 }
322
323 /** @cfgm{/CPUM/IsaExts/AES, boolean, depends}
324 * Expose FEAT_AES instruction set extension to the guest.
325 */
326 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "AES", &pConfig->enmAes, true /*enmDefault*/);
327 AssertLogRelRCReturn(rc, rc);
328
329 /** @cfgm{/CPUM/IsaExts/AES, boolean, depends}
330 * Expose FEAT_AES and FEAT_PMULL instruction set extension to the guest.
331 */
332 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "PMULL", &pConfig->enmPmull, true /*enmDefault*/);
333 AssertLogRelRCReturn(rc, rc);
334
335 /** @cfgm{/CPUM/IsaExts/SHA1, boolean, depends}
336 * Expose FEAT_SHA1 instruction set extension to the guest.
337 */
338 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "SHA1", &pConfig->enmSha1, true /*enmDefault*/);
339 AssertLogRelRCReturn(rc, rc);
340
341 /** @cfgm{/CPUM/IsaExts/SHA256, boolean, depends}
342 * Expose FEAT_SHA256 instruction set extension to the guest.
343 */
344 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "SHA256", &pConfig->enmSha256, true /*enmDefault*/);
345 AssertLogRelRCReturn(rc, rc);
346
347 /** @cfgm{/CPUM/IsaExts/SHA512, boolean, depends}
348 * Expose FEAT_SHA256 and FEAT_SHA512 instruction set extension to the guest.
349 */
350 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "SHA512", &pConfig->enmSha512, true /*enmDefault*/);
351 AssertLogRelRCReturn(rc, rc);
352
353 /** @cfgm{/CPUM/IsaExts/CRC32, boolean, depends}
354 * Expose FEAT_CRC32 instruction set extension to the guest.
355 */
356 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "CRC32", &pConfig->enmCrc32, true /*enmDefault*/);
357 AssertLogRelRCReturn(rc, rc);
358
359 /** @cfgm{/CPUM/IsaExts/SHA3, boolean, depends}
360 * Expose FEAT_SHA3 instruction set extension to the guest.
361 */
362 rc = cpumR3CpuIdReadIsaExtCfg(pVM, pIsaExts, "SHA3", &pConfig->enmSha3, true /*enmDefault*/);
363 AssertLogRelRCReturn(rc, rc);
364
365 /** @todo Add more options for other extensions. */
366
367 return VINF_SUCCESS;
368}
369
370
371/**
372 * Populates the host and guest features by the given ID registers.
373 *
374 * @returns VBox status code.
375 * @param pVM The cross context VM structure.
376 * @param pIdRegs Pointer to the ID register struct.
377 *
378 * @note Unlike on x86 there is no cross platform usermode accessible way to get at the CPU features.
379 * On ARM there are some ID_AA64*_EL1 system registers accessible by EL1 and higher only so we have to
380 * rely on the host/NEM backend to query those and hand them to CPUM where they will be parsed and modified based
381 * on the VM config.
382 */
383VMMR3DECL(int) CPUMR3PopulateFeaturesByIdRegisters(PVM pVM, PCCPUMARMV8IDREGS pIdRegs)
384{
385 /* Set the host features from the given ID registers. */
386 int rc = cpumCpuIdExplodeFeaturesArmV8(pIdRegs, &g_CpumHostFeatures.s);
387 AssertRCReturn(rc, rc);
388
389 pVM->cpum.s.HostFeatures.s = g_CpumHostFeatures.s;
390 pVM->cpum.s.GuestFeatures.enmCpuVendor = pVM->cpum.s.HostFeatures.Common.enmCpuVendor;
391 pVM->cpum.s.HostIdRegs = *pIdRegs;
392 pVM->cpum.s.GuestIdRegs = *pIdRegs;
393
394 PCPUM pCpum = &pVM->cpum.s;
395 PCFGMNODE pCpumCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM");
396
397 /*
398 * Read the configuration.
399 */
400 CPUMCPUIDCONFIG Config;
401 RT_ZERO(Config);
402
403 rc = cpumR3CpuIdReadConfig(pVM, &Config, pCpumCfg);
404 AssertRCReturn(rc, rc);
405
406#if 0
407 /*
408 * Get the guest CPU data from the database and/or the host.
409 *
410 * The CPUID and MSRs are currently living on the regular heap to avoid
411 * fragmenting the hyper heap (and because there isn't/wasn't any realloc
412 * API for the hyper heap). This means special cleanup considerations.
413 */
414 rc = cpumR3DbGetCpuInfo(Config.szCpuName, &pCpum->GuestInfo);
415 if (RT_FAILURE(rc))
416 return rc == VERR_CPUM_DB_CPU_NOT_FOUND
417 ? VMSetError(pVM, rc, RT_SRC_POS,
418 "Info on guest CPU '%s' could not be found. Please, select a different CPU.", Config.szCpuName)
419 : rc;
420#endif
421
422 /*
423 * Pre-explode the CPUID info.
424 */
425 if (RT_SUCCESS(rc))
426 rc = cpumCpuIdExplodeFeaturesArmV8(pIdRegs, &pCpum->GuestFeatures);
427
428 /*
429 * Sanitize the cpuid information passed on to the guest.
430 */
431 if (RT_SUCCESS(rc))
432 rc = cpumR3CpuIdSanitize(pVM, pCpum, &Config);
433
434 return rc;
435}
436
437
438/**
439 * Queries the pointer to the VM wide ID registers exposing configured features to the guest.
440 *
441 * @returns VBox status code.
442 * @param pVM The cross context VM structure.
443 * @param ppIdRegs Where to store the pointer to the guest ID register struct.
444 */
445VMMR3_INT_DECL(int) CPUMR3QueryGuestIdRegs(PVM pVM, PCCPUMARMV8IDREGS *ppIdRegs)
446{
447 AssertPtrReturn(ppIdRegs, VERR_INVALID_POINTER);
448
449 *ppIdRegs = &pVM->cpum.s.GuestIdRegs;
450 return VINF_SUCCESS;
451}
452
453
454/*
455 *
456 *
457 * Saved state related code.
458 * Saved state related code.
459 * Saved state related code.
460 *
461 *
462 */
463/** Saved state field descriptors for CPUMARMV8IDREGS. */
464static const SSMFIELD g_aCpumArmV8IdRegsFields[] =
465{
466 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Pfr0El1),
467 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Pfr1El1),
468 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Dfr0El1),
469 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Dfr1El1),
470 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Afr0El1),
471 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Afr1El1),
472 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Isar0El1),
473 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Isar1El1),
474 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Isar2El1),
475 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Mmfr0El1),
476 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Mmfr1El1),
477 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegIdAa64Mmfr2El1),
478 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegClidrEl1),
479 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegCtrEl0),
480 SSMFIELD_ENTRY(CPUMARMV8IDREGS, u64RegDczidEl0),
481 SSMFIELD_ENTRY_TERM()
482};
483
484
485/**
486 * Called both in pass 0 and the final pass.
487 *
488 * @param pVM The cross context VM structure.
489 * @param pSSM The saved state handle.
490 */
491void cpumR3SaveCpuId(PVM pVM, PSSMHANDLE pSSM)
492{
493 /*
494 * Save all the CPU ID leaves.
495 */
496 SSMR3PutStructEx(pSSM, &pVM->cpum.s.GuestIdRegs, sizeof(pVM->cpum.s.GuestIdRegs), 0, g_aCpumArmV8IdRegsFields, NULL);
497}
498
499
500/**
501 * Loads the CPU ID leaves saved by pass 0, inner worker.
502 *
503 * @returns VBox status code.
504 * @param pVM The cross context VM structure.
505 * @param pSSM The saved state handle.
506 * @param uVersion The format version.
507 * @param pGuestIdRegs The guest ID register as loaded from the saved state.
508 */
509static int cpumR3LoadCpuIdInner(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, PCCPUMARMV8IDREGS pGuestIdRegs)
510{
511 /*
512 * This can be skipped.
513 */
514 bool fStrictCpuIdChecks;
515 CFGMR3QueryBoolDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM"), "StrictCpuIdChecks", &fStrictCpuIdChecks, true);
516
517 /*
518 * Define a bunch of macros for simplifying the santizing/checking code below.
519 */
520 /* For checking guest features. */
521#define CPUID_GST_FEATURE_RET(a_IdReg, a_Field) \
522 do { \
523 if (RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
524 { \
525 if (fStrictCpuIdChecks) \
526 return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS, \
527 N_(#a_Field " is not supported by the host but has already exposed to the guest")); \
528 LogRel(("CPUM: " #a_Field " is not supported by the host but has already been exposed to the guest\n")); \
529 } \
530 } while (0)
531#define CPUID_GST_FEATURE_RET_NOT_IMPL(a_IdReg, a_Field, a_NotImpl) \
532 do { \
533 if ( ( RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) != (a_NotImpl) \
534 && RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field) == (a_NotImpl)) \
535 || RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
536 { \
537 if (fStrictCpuIdChecks) \
538 return SSMR3SetLoadError(pSSM, VERR_SSM_LOAD_CPUID_MISMATCH, RT_SRC_POS, \
539 N_(#a_Field " is not supported by the host but has already exposed to the guest")); \
540 LogRel(("CPUM: " #a_Field " is not supported by the host but has already been exposed to the guest\n")); \
541 } \
542 } while (0)
543#define CPUID_GST_FEATURE_WRN(a_IdReg, a_Field) \
544 do { \
545 if (RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
546 LogRel(("CPUM: " #a_Field " is not supported by the host but has already been exposed to the guest\n")); \
547 } while (0)
548#define CPUID_GST_FEATURE_EMU(a_IdReg, a_Field) \
549 do { \
550 if (RT_BF_GET(pGuestIdRegs->a_IdReg, a_Field) > RT_BF_GET(pVM->cpum.s.GuestIdRegs.a_IdReg, a_Field)) \
551 LogRel(("CPUM: Warning - " #a_Field " is not supported by the host but has already been exposed to the guest. This may impact performance.\n")); \
552 } while (0)
553#define CPUID_GST_FEATURE_IGN(a_IdReg, a_Field) do { } while (0)
554
555 RT_NOREF(uVersion);
556 /*
557 * Verify that we can support the features already exposed to the guest on
558 * this host.
559 *
560 * Most of the features we're emulating requires intercepting instruction
561 * and doing it the slow way, so there is no need to warn when they aren't
562 * present in the host CPU. Thus we use IGN instead of EMU on these.
563 *
564 * Trailing comments:
565 * "EMU" - Possible to emulate, could be lots of work and very slow.
566 * "EMU?" - Can this be emulated?
567 */
568 /* ID_AA64ISAR0_EL1 */
569 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_AES);
570 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SHA1);
571 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SHA2);
572 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_CRC32);
573 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_ATOMIC);
574 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_TME);
575 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_RDM);
576 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SHA3);
577 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SM3);
578 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_SM4);
579 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_DP);
580 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_FHM);
581 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_TS);
582 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_TLB);
583 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar0El1, ARMV8_ID_AA64ISAR0_EL1_RNDR);
584
585 /* ID_AA64ISAR1_EL1 */
586 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_DPB);
587 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_APA);
588 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_API);
589 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_FJCVTZS);
590 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_LRCPC);
591 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_GPA);
592 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_GPI);
593 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_FRINTTS);
594 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_SB);
595 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_SPECRES);
596 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_BF16);
597 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_DGH);
598 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_I8MM);
599 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_XS);
600 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar1El1, ARMV8_ID_AA64ISAR1_EL1_LS64);
601
602 /* ID_AA64ISAR2_EL1 */
603 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_WFXT);
604 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_RPRES);
605 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_GPA3);
606 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_APA3);
607 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_MOPS);
608 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_BC);
609 CPUID_GST_FEATURE_RET(u64RegIdAa64Isar2El1, ARMV8_ID_AA64ISAR2_EL1_PACFRAC);
610
611 /* ID_AA64PFR0_EL1 */
612 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_EL0);
613 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_EL1);
614 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_EL2);
615 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_EL3);
616 CPUID_GST_FEATURE_RET_NOT_IMPL(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_FP, ARMV8_ID_AA64PFR0_EL1_FP_NOT_IMPL); /* Special not implemented value. */
617 CPUID_GST_FEATURE_RET_NOT_IMPL(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_ADVSIMD, ARMV8_ID_AA64PFR0_EL1_ADVSIMD_NOT_IMPL); /* Special not implemented value. */
618 CPUID_GST_FEATURE_IGN(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_GIC);
619 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_RAS);
620 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_SVE);
621 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_SEL2);
622 /** @todo MPAM */
623 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_AMU);
624 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_DIT);
625 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_RME);
626 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_CSV2);
627 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr0El1, ARMV8_ID_AA64PFR0_EL1_CSV3);
628
629 /* ID_AA64PFR1_EL1 */
630 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_BT);
631 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_SSBS);
632 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_MTE);
633 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_RASFRAC);
634 /** @todo MPAM. */
635 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_SME);
636 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_RNDRTRAP);
637 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_CSV2FRAC);
638 CPUID_GST_FEATURE_RET(u64RegIdAa64Pfr1El1, ARMV8_ID_AA64PFR1_EL1_NMI);
639
640 /* ID_AA64MMFR0_EL1 */
641 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_PARANGE);
642 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_ASIDBITS);
643 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_BIGEND);
644 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_SNSMEM);
645 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_BIGENDEL0);
646 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_TGRAN16);
647 CPUID_GST_FEATURE_RET_NOT_IMPL(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_TGRAN64, ARMV8_ID_AA64MMFR0_EL1_TGRAN64_NOT_IMPL);
648 CPUID_GST_FEATURE_RET_NOT_IMPL(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_TGRAN4, ARMV8_ID_AA64MMFR0_EL1_TGRAN4_NOT_IMPL);
649 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_TGRAN16_2);
650 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_TGRAN64_2);
651 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_TGRAN4_2);
652 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_EXS);
653 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_FGT);
654 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr0El1, ARMV8_ID_AA64MMFR0_EL1_ECV);
655
656 /* ID_AA64MMFR1_EL1 */
657 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_HAFDBS);
658 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_VMIDBITS);
659 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_VHE);
660 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_HPDS);
661 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_LO);
662 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_PAN);
663 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_SPECSEI);
664 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_XNX);
665 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_TWED);
666 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_ETS);
667 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_HCX);
668 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_AFP);
669 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_NTLBPA);
670 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_TIDCP1);
671 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr1El1, ARMV8_ID_AA64MMFR1_EL1_CMOW);
672
673 /* ID_AA64MMFR2_EL1 */
674 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_CNP);
675 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_UAO);
676 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_LSM);
677 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_IESB);
678 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_VARANGE);
679 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_CCIDX);
680 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_CNP);
681 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_NV);
682 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_ST);
683 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_AT);
684 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_IDS);
685 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_FWB);
686 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_TTL);
687 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_BBM);
688 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_EVT);
689 CPUID_GST_FEATURE_RET(u64RegIdAa64Mmfr2El1, ARMV8_ID_AA64MMFR2_EL1_E0PD);
690
691 /* ID_AA64DFR0_EL1 */
692 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_DEBUGVER);
693 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_TRACEVER);
694 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_PMUVER);
695 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_BRPS);
696 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_WRPS);
697 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_CTXCMPS);
698 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_PMSVER);
699 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_DOUBLELOCK);
700 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_TRACEFILT);
701 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_TRACEBUFFER);
702 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_MTPMU);
703 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_BRBE);
704 CPUID_GST_FEATURE_RET(u64RegIdAa64Dfr0El1, ARMV8_ID_AA64DFR0_EL1_HPMN0);
705
706#undef CPUID_GST_FEATURE_RET
707#undef CPUID_GST_FEATURE_RET_NOT_IMPL
708#undef CPUID_GST_FEATURE_WRN
709#undef CPUID_GST_FEATURE_EMU
710#undef CPUID_GST_FEATURE_IGN
711
712 /*
713 * We're good, commit the CPU ID registers.
714 */
715 pVM->cpum.s.GuestIdRegs = *pGuestIdRegs;
716 return VINF_SUCCESS;
717}
718
719
720/**
721 * Loads the CPU ID leaves saved by pass 0, ARMv8 targets.
722 *
723 * @returns VBox status code.
724 * @param pVM The cross context VM structure.
725 * @param pSSM The saved state handle.
726 * @param uVersion The format version.
727 */
728int cpumR3LoadCpuIdArmV8(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
729{
730 CPUMARMV8IDREGS GuestIdRegs;
731 int rc = SSMR3GetStructEx(pSSM, &GuestIdRegs, sizeof(GuestIdRegs), 0, g_aCpumArmV8IdRegsFields, NULL);
732 AssertRCReturn(rc, rc);
733
734 return cpumR3LoadCpuIdInner(pVM, pSSM, uVersion, &GuestIdRegs);
735}
736
737
738/*
739 *
740 *
741 * CPUID Info Handler.
742 * CPUID Info Handler.
743 * CPUID Info Handler.
744 *
745 *
746 */
747
748/** CLIDR_EL1 field descriptions. */
749static DBGFREGSUBFIELD const g_aClidrEl1Fields[] =
750{
751 DBGFREGSUBFIELD_RO("Ctype1\0" "Cache 1 type field", 0, 3, 0),
752 DBGFREGSUBFIELD_RO("Ctype2\0" "Cache 2 type field", 3, 3, 0),
753 DBGFREGSUBFIELD_RO("Ctype3\0" "Cache 3 type field", 6, 3, 0),
754 DBGFREGSUBFIELD_RO("Ctype4\0" "Cache 4 type field", 9, 3, 0),
755 DBGFREGSUBFIELD_RO("Ctype5\0" "Cache 5 type field", 12, 3, 0),
756 DBGFREGSUBFIELD_RO("Ctype6\0" "Cache 6 type field", 15, 3, 0),
757 DBGFREGSUBFIELD_RO("Ctype7\0" "Cache 7 type field", 18, 3, 0),
758 DBGFREGSUBFIELD_RO("LoUIS\0" "Level of Unification Inner Shareable", 21, 3, 0),
759 DBGFREGSUBFIELD_RO("LoC\0" "Level of Coherence for the cache hierarchy", 24, 3, 0),
760 DBGFREGSUBFIELD_RO("LoUU\0" "Level of Unification Uniprocessor", 27, 3, 0),
761 DBGFREGSUBFIELD_RO("ICB\0" "Inner cache boundary", 30, 3, 0),
762 DBGFREGSUBFIELD_RO("Ttype1\0" "Cache 1 - Tag cache type", 33, 2, 0),
763 DBGFREGSUBFIELD_RO("Ttype2\0" "Cache 2 - Tag cache type", 35, 2, 0),
764 DBGFREGSUBFIELD_RO("Ttype3\0" "Cache 3 - Tag cache type", 37, 2, 0),
765 DBGFREGSUBFIELD_RO("Ttype4\0" "Cache 4 - Tag cache type", 39, 2, 0),
766 DBGFREGSUBFIELD_RO("Ttype5\0" "Cache 5 - Tag cache type", 41, 2, 0),
767 DBGFREGSUBFIELD_RO("Ttype6\0" "Cache 6 - Tag cache type", 43, 2, 0),
768 DBGFREGSUBFIELD_RO("Ttype7\0" "Cache 7 - Tag cache type", 45, 2, 0),
769 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 47, 17, 0),
770 DBGFREGSUBFIELD_TERMINATOR()
771};
772
773
774/** ID_AA64PFR0_EL1 field descriptions. */
775static DBGFREGSUBFIELD const g_aIdAa64PfR0Fields[] =
776{
777 DBGFREGSUBFIELD_RO("EL0\0" "EL0 Exception level handling", 0, 4, 0),
778 DBGFREGSUBFIELD_RO("EL1\0" "EL1 Exception level handling", 4, 4, 0),
779 DBGFREGSUBFIELD_RO("EL2\0" "EL2 Exception level handling", 8, 4, 0),
780 DBGFREGSUBFIELD_RO("EL3\0" "EL3 Exception level handling", 12, 4, 0),
781 DBGFREGSUBFIELD_RO("FP\0" "Floating-point", 16, 4, 0),
782 DBGFREGSUBFIELD_RO("AdvSIMD\0" "Advanced SIMD", 20, 4, 0),
783 DBGFREGSUBFIELD_RO("GIC\0" "System register GIC CPU interface", 24, 4, 0),
784 DBGFREGSUBFIELD_RO("RAS\0" "RAS Extension version", 28, 4, 0),
785 DBGFREGSUBFIELD_RO("SVE\0" "Scalable Vector Extension", 32, 4, 0),
786 DBGFREGSUBFIELD_RO("SEL2\0" "Secure EL2", 36, 4, 0),
787 DBGFREGSUBFIELD_RO("MPAM\0" "MPAM Extension major version number", 40, 4, 0),
788 DBGFREGSUBFIELD_RO("AMU\0" "Activity Monitors Extension support", 44, 4, 0),
789 DBGFREGSUBFIELD_RO("DIT\0" "Data Independent Timing", 48, 4, 0),
790 DBGFREGSUBFIELD_RO("RME\0" "Realm Management Extension", 52, 4, 0),
791 DBGFREGSUBFIELD_RO("CSV2\0" "Speculative use of out of branch targets", 56, 4, 0),
792 DBGFREGSUBFIELD_RO("CSV3\0" "Speculative use of faulting data", 60, 4, 0),
793 DBGFREGSUBFIELD_TERMINATOR()
794};
795
796
797/** ID_AA64PFR1_EL1 field descriptions. */
798static DBGFREGSUBFIELD const g_aIdAa64PfR1Fields[] =
799{
800 DBGFREGSUBFIELD_RO("BT\0" "Branch Target Identification mechanism", 0, 4, 0),
801 DBGFREGSUBFIELD_RO("SSBS\0" "Speculative Store Bypassing controls", 4, 4, 0),
802 DBGFREGSUBFIELD_RO("MTE\0" "Memory Tagging Extension support", 8, 4, 0),
803 DBGFREGSUBFIELD_RO("RAS_frac\0" "RAS Extension fractional field", 12, 4, 0),
804 DBGFREGSUBFIELD_RO("MPAM_frac\0" "MPAM Extension minor version", 16, 4, 0),
805 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 20, 4, 0),
806 DBGFREGSUBFIELD_RO("SME\0" "Scalable Matrix Extension", 24, 4, 0),
807 DBGFREGSUBFIELD_RO("RNDR_trap\0" "Random Number trap to EL3", 28, 4, 0),
808 DBGFREGSUBFIELD_RO("CSV2_frac\0" "CSV2 fractional version field", 32, 4, 0),
809 DBGFREGSUBFIELD_RO("NMI\0" "Non-maskable Interrupt support", 36, 4, 0),
810 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 40, 4, 0),
811 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 44, 4, 0),
812 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 48, 4, 0),
813 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 52, 4, 0),
814 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 56, 4, 0),
815 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 60, 4, 0),
816 DBGFREGSUBFIELD_TERMINATOR()
817};
818
819
820/** ID_AA64ISAR0_EL1 field descriptions. */
821static DBGFREGSUBFIELD const g_aIdAa64IsaR0Fields[] =
822{
823 DBGFREGSUBFIELD_RO("AES\0" "AES instruction support in AArch64", 4, 4, 0),
824 DBGFREGSUBFIELD_RO("SHA1\0" "SHA1 instruction support in AArch64", 8, 4, 0),
825 DBGFREGSUBFIELD_RO("SHA2\0" "SHA256/512 instruction support in AArch64", 12, 4, 0),
826 DBGFREGSUBFIELD_RO("CRC32\0" "CRC32 instruction support in AArch64", 16, 4, 0),
827 DBGFREGSUBFIELD_RO("ATOMIC\0" "Atomic instruction support in AArch64", 20, 4, 0),
828 DBGFREGSUBFIELD_RO("TME\0" "TME instruction support in AArch64", 24, 4, 0),
829 DBGFREGSUBFIELD_RO("RDM\0" "SQRDMLAH/SQRDMLSH instruction support in AArch64", 28, 4, 0),
830 DBGFREGSUBFIELD_RO("SHA3\0" "SHA3 instruction support in AArch64", 32, 4, 0),
831 DBGFREGSUBFIELD_RO("SM3\0" "SM3 instruction support in AArch64", 36, 4, 0),
832 DBGFREGSUBFIELD_RO("SM4\0" "SM4 instruction support in AArch64", 40, 4, 0),
833 DBGFREGSUBFIELD_RO("DP\0" "Dot Product instruction support in AArch64", 44, 4, 0),
834 DBGFREGSUBFIELD_RO("FHM\0" "FMLAL/FMLSL instruction support in AArch64", 48, 4, 0),
835 DBGFREGSUBFIELD_RO("TS\0" "Flag manipulation instruction support in AArch64", 52, 4, 0),
836 DBGFREGSUBFIELD_RO("TLB\0" "TLB maintenance instruction support in AArch64", 56, 4, 0),
837 DBGFREGSUBFIELD_RO("RNDR\0" "Random number instruction support in AArch64", 60, 4, 0),
838 DBGFREGSUBFIELD_TERMINATOR()
839};
840
841
842/** ID_AA64ISAR1_EL1 field descriptions. */
843static DBGFREGSUBFIELD const g_aIdAa64IsaR1Fields[] =
844{
845 DBGFREGSUBFIELD_RO("DPB\0" "Data Persistance writeback support in AArch64", 0, 4, 0),
846 DBGFREGSUBFIELD_RO("APA\0" "QARMA5 PAuth support in AArch64", 4, 4, 0),
847 DBGFREGSUBFIELD_RO("API\0" "Impl defined PAuth support in AArch64", 8, 4, 0),
848 DBGFREGSUBFIELD_RO("JSCVT\0" "FJCVTZS instruction support in AArch64", 12, 4, 0),
849 DBGFREGSUBFIELD_RO("FCMA\0" "FCMLA/FCADD instruction support in AArch64", 16, 4, 0),
850 DBGFREGSUBFIELD_RO("LRCPC\0" "RCpc instruction support in AArch64", 20, 4, 0),
851 DBGFREGSUBFIELD_RO("GPA\0" "QARMA5 code authentication support in AArch64", 24, 4, 0),
852 DBGFREGSUBFIELD_RO("GPI\0" "Impl defined code authentication support in AArch64", 28, 4, 0),
853 DBGFREGSUBFIELD_RO("FRINTTS\0" "FRINT{32,64}{Z,X} instruction support in AArch64", 32, 4, 0),
854 DBGFREGSUBFIELD_RO("SB\0" "SB instruction support in AArch64", 36, 4, 0),
855 DBGFREGSUBFIELD_RO("SPECRES\0" "Prediction invalidation support in AArch64", 40, 4, 0),
856 DBGFREGSUBFIELD_RO("BF16\0" "BFloat16 support in AArch64", 44, 4, 0),
857 DBGFREGSUBFIELD_RO("DGH\0" "Data Gathering Hint support in AArch64", 48, 4, 0),
858 DBGFREGSUBFIELD_RO("I8MM\0" "Int8 matrix mul instruction support in AArch64", 52, 4, 0),
859 DBGFREGSUBFIELD_RO("XS\0" "XS attribute support in AArch64", 56, 4, 0),
860 DBGFREGSUBFIELD_RO("LS64\0" "LD64B and ST64B* instruction support in AArch64", 60, 4, 0),
861 DBGFREGSUBFIELD_TERMINATOR()
862};
863
864
865/** ID_AA64ISAR2_EL1 field descriptions. */
866static DBGFREGSUBFIELD const g_aIdAa64IsaR2Fields[] =
867{
868 DBGFREGSUBFIELD_RO("WFxT\0" "WFET/WFIT intruction support in AArch64", 0, 4, 0),
869 DBGFREGSUBFIELD_RO("RPRES\0" "Reciprocal 12 bit mantissa support in AArch64", 4, 4, 0),
870 DBGFREGSUBFIELD_RO("GPA3\0" "QARMA3 code authentication support in AArch64", 8, 4, 0),
871 DBGFREGSUBFIELD_RO("APA3\0" "QARMA3 PAuth support in AArch64", 12, 4, 0),
872 DBGFREGSUBFIELD_RO("MOPS\0" "Memory Copy and Set instruction support in AArch64", 16, 4, 0),
873 DBGFREGSUBFIELD_RO("BC\0" "BC instruction support in AArch64", 20, 4, 0),
874 DBGFREGSUBFIELD_RO("PAC_frac\0" "ConstPACField() returns TRUE", 24, 4, 0),
875 DBGFREGSUBFIELD_TERMINATOR()
876};
877
878
879/** ID_AA64MMFR0_EL1 field descriptions. */
880static DBGFREGSUBFIELD const g_aIdAa64MmfR0Fields[] =
881{
882 DBGFREGSUBFIELD_RO("PARange\0" "Physical address width", 0, 4, 0),
883 DBGFREGSUBFIELD_RO("ASIDBits\0" "Number of ASID bits", 4, 4, 0),
884 DBGFREGSUBFIELD_RO("BigEnd\0" "Mixed-endian configuration support", 8, 4, 0),
885 DBGFREGSUBFIELD_RO("SNSMem\0" "Secure and Non-secure memory distinction", 12, 4, 0),
886 DBGFREGSUBFIELD_RO("BigEndEL0\0" "Mixed-endian support in EL0 only", 16, 4, 0),
887 DBGFREGSUBFIELD_RO("TGran16\0" "16KiB memory granule size", 20, 4, 0),
888 DBGFREGSUBFIELD_RO("TGran64\0" "64KiB memory granule size", 24, 4, 0),
889 DBGFREGSUBFIELD_RO("TGran4\0" "4KiB memory granule size", 28, 4, 0),
890 DBGFREGSUBFIELD_RO("TGran16_2\0" "16KiB memory granule size at stage 2", 32, 4, 0),
891 DBGFREGSUBFIELD_RO("TGran64_2\0" "64KiB memory granule size at stage 2", 36, 4, 0),
892 DBGFREGSUBFIELD_RO("TGran4_2\0" "4KiB memory granule size at stage 2", 40, 4, 0),
893 DBGFREGSUBFIELD_RO("ExS\0" "Disabling context synchronizing exception", 44, 4, 0),
894 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 48, 4, 0),
895 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 52, 4, 0),
896 DBGFREGSUBFIELD_RO("FGT\0" "Fine-grained trap controls support", 56, 4, 0),
897 DBGFREGSUBFIELD_RO("ECV\0" "Enhanced Counter Virtualization support", 60, 4, 0),
898 DBGFREGSUBFIELD_TERMINATOR()
899};
900
901
902/** ID_AA64MMFR1_EL1 field descriptions. */
903static DBGFREGSUBFIELD const g_aIdAa64MmfR1Fields[] =
904{
905 DBGFREGSUBFIELD_RO("HAFDBS\0" "Hardware updates to Access/Dirty state", 0, 4, 0),
906 DBGFREGSUBFIELD_RO("VMIDBit\0" "Number of VMID bits", 4, 4, 0),
907 DBGFREGSUBFIELD_RO("VH\0" "Virtualization Host Extensions", 8, 4, 0),
908 DBGFREGSUBFIELD_RO("HPDS\0" "Hierarchical Permission Disables", 12, 4, 0),
909 DBGFREGSUBFIELD_RO("LO\0" "LORegions support", 16, 4, 0),
910 DBGFREGSUBFIELD_RO("PAN\0" "Privileged Access Never", 20, 4, 0),
911 DBGFREGSUBFIELD_RO("SpecSEI\0" "SError interrupt exception for speculative reads", 24, 4, 0),
912 DBGFREGSUBFIELD_RO("XNX\0" "Execute-never control support", 28, 4, 0),
913 DBGFREGSUBFIELD_RO("TWED\0" "Configurable delayed WFE trapping", 32, 4, 0),
914 DBGFREGSUBFIELD_RO("ETS\0" "Enhanced Translation Synchronization support", 36, 4, 0),
915 DBGFREGSUBFIELD_RO("HCX\0" "HCRX_EL2 support", 40, 4, 0),
916 DBGFREGSUBFIELD_RO("AFP\0" "FPCR.{AH,FIZ,NEP} support", 44, 4, 0),
917 DBGFREGSUBFIELD_RO("nTLBPA\0" "Caching of translation table walks", 48, 4, 0),
918 DBGFREGSUBFIELD_RO("TIDCP1\0" "FEAT_TIDCP1 support", 52, 4, 0),
919 DBGFREGSUBFIELD_RO("CMOW\0" "Cache maintenance instruction permission", 56, 4, 0),
920 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 60, 4, 0),
921 DBGFREGSUBFIELD_TERMINATOR()
922};
923
924
925/** ID_AA64MMFR2_EL1 field descriptions. */
926static DBGFREGSUBFIELD const g_aIdAa64MmfR2Fields[] =
927{
928 DBGFREGSUBFIELD_RO("CnP\0" "Common not Private translation support", 0, 4, 0),
929 DBGFREGSUBFIELD_RO("UAO\0" "User Access Override", 4, 4, 0),
930 DBGFREGSUBFIELD_RO("LSM\0" "LSMAOE/nTLSMD bit support", 8, 4, 0),
931 DBGFREGSUBFIELD_RO("IESB\0" "IESB bit support in SCTLR_ELx", 12, 4, 0),
932 DBGFREGSUBFIELD_RO("VARange\0" "Large virtual address space support", 16, 4, 0),
933 DBGFREGSUBFIELD_RO("CCIDX\0" "64-bit CCSIDR_EL1 format", 20, 4, 0),
934 DBGFREGSUBFIELD_RO("NV\0" "Nested Virtualization support", 24, 4, 0),
935 DBGFREGSUBFIELD_RO("ST\0" "Small translation table support", 28, 4, 0),
936 DBGFREGSUBFIELD_RO("AT\0" "Unaligned single-copy atomicity support", 32, 4, 0),
937 DBGFREGSUBFIELD_RO("IDS\0" "FEAT_IDST support", 36, 4, 0),
938 DBGFREGSUBFIELD_RO("FWB\0" "HCR_EL2.FWB support", 40, 4, 0),
939 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 44, 4, 0),
940 DBGFREGSUBFIELD_RO("TTL\0" "TTL field support in address operations", 48, 4, 0),
941 DBGFREGSUBFIELD_RO("BBM\0" "FEAT_BBM support", 52, 4, 0),
942 DBGFREGSUBFIELD_RO("EVT\0" "Enhanced Virtualization Traps support", 56, 4, 0),
943 DBGFREGSUBFIELD_RO("E0PD\0" "E0PD mechanism support", 60, 4, 0),
944 DBGFREGSUBFIELD_TERMINATOR()
945};
946
947
948/** ID_AA64DFR0_EL1 field descriptions. */
949static DBGFREGSUBFIELD const g_aIdAa64DfR0Fields[] =
950{
951 DBGFREGSUBFIELD_RO("DebugVer\0" "Debug architecture version", 0, 4, 0),
952 DBGFREGSUBFIELD_RO("TraceVer\0" "Trace support", 4, 4, 0),
953 DBGFREGSUBFIELD_RO("PMUVer\0" "Performance Monitors Extension version", 8, 4, 0),
954 DBGFREGSUBFIELD_RO("BRPs\0" "Number of breakpoints minus 1", 12, 4, 0),
955 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 16, 4, 0),
956 DBGFREGSUBFIELD_RO("WRPs\0" "Number of watchpoints minus 1", 20, 4, 0),
957 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 24, 4, 0),
958 DBGFREGSUBFIELD_RO("CTX_CMPs\0" "Number of context-aware breakpoints minus 1", 28, 4, 0),
959 DBGFREGSUBFIELD_RO("PMSVer\0" "Statistical Profiling Extension version", 32, 4, 0),
960 DBGFREGSUBFIELD_RO("DoubleLock\0" "OS Double Lock support", 36, 4, 0),
961 DBGFREGSUBFIELD_RO("TraceFilt\0" "Armv8.4 Self-hosted Trace Extension version", 40, 4, 0),
962 DBGFREGSUBFIELD_RO("TraceBuffer\0" "Trace Buffer Extension", 44, 4, 0),
963 DBGFREGSUBFIELD_RO("MTPMU\0" "Multi-threaded PMU extension", 48, 4, 0),
964 DBGFREGSUBFIELD_RO("BRBE\0" "Branch Record Buffer Extension", 52, 4, 0),
965 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 56, 4, 0),
966 DBGFREGSUBFIELD_RO("HPMN0\0" "Zero PMU event counters for guest", 60, 4, 0),
967 DBGFREGSUBFIELD_TERMINATOR()
968};
969
970
971/** ID_AA64DFR1_EL1 field descriptions. */
972static DBGFREGSUBFIELD const g_aIdAa64DfR1Fields[] =
973{
974 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 0, 4, 0),
975 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 4, 4, 0),
976 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 8, 4, 0),
977 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 12, 4, 0),
978 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 16, 4, 0),
979 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 20, 4, 0),
980 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 24, 4, 0),
981 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 28, 4, 0),
982 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 32, 4, 0),
983 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 36, 4, 0),
984 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 40, 4, 0),
985 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 44, 4, 0),
986 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 48, 4, 0),
987 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 52, 4, 0),
988 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 56, 4, 0),
989 DBGFREGSUBFIELD_RO("Res0\0" "Reserved", 60, 4, 0),
990 DBGFREGSUBFIELD_TERMINATOR()
991};
992
993
994/** ID_AA64AFR0_EL1 field descriptions. */
995static DBGFREGSUBFIELD const g_aIdAa64AfR0Fields[] =
996{
997 DBGFREGSUBFIELD_RO("ImpDef\0" "Implementation defined", 0, 32, 0),
998 DBGFREGSUBFIELD_TERMINATOR()
999};
1000
1001
1002/** ID_AA64AFR1_EL1 field descriptions. */
1003static DBGFREGSUBFIELD const g_aIdAa64AfR1Fields[] =
1004{
1005 DBGFREGSUBFIELD_RO("ImpDef\0" "Implementation defined", 0, 32, 0),
1006 DBGFREGSUBFIELD_TERMINATOR()
1007};
1008
1009
1010static void cpumR3CpuIdInfoMnemonicListU64(PCDBGFINFOHLP pHlp, uint64_t uVal, PCDBGFREGSUBFIELD pDesc,
1011 const char *pszLeadIn, uint32_t cchWidth)
1012{
1013 if (pszLeadIn)
1014 pHlp->pfnPrintf(pHlp, "%*s", cchWidth, pszLeadIn);
1015
1016 for (uint32_t iBit = 0; iBit < 64; iBit++)
1017 if (RT_BIT_64(iBit) & uVal)
1018 {
1019 while ( pDesc->pszName != NULL
1020 && iBit >= (uint32_t)pDesc->iFirstBit + pDesc->cBits)
1021 pDesc++;
1022 if ( pDesc->pszName != NULL
1023 && iBit - (uint32_t)pDesc->iFirstBit < (uint32_t)pDesc->cBits)
1024 {
1025 if (pDesc->cBits == 1)
1026 pHlp->pfnPrintf(pHlp, " %s", pDesc->pszName);
1027 else
1028 {
1029 uint64_t uFieldValue = uVal >> pDesc->iFirstBit;
1030 if (pDesc->cBits < 64)
1031 uFieldValue &= RT_BIT_64(pDesc->cBits) - UINT64_C(1);
1032 pHlp->pfnPrintf(pHlp, pDesc->cBits < 4 ? " %s=%llu" : " %s=%#llx", pDesc->pszName, uFieldValue);
1033 iBit = pDesc->iFirstBit + pDesc->cBits - 1;
1034 }
1035 }
1036 else
1037 pHlp->pfnPrintf(pHlp, " %u", iBit);
1038 }
1039 if (pszLeadIn)
1040 pHlp->pfnPrintf(pHlp, "\n");
1041}
1042
1043
1044static void cpumR3CpuIdInfoVerboseCompareListU64(PCDBGFINFOHLP pHlp, uint64_t uVal1, uint64_t uVal2, PCDBGFREGSUBFIELD pDesc,
1045 uint32_t cchWidth)
1046{
1047 uint32_t uCombined = uVal1 | uVal2;
1048 for (uint32_t iBit = 0; iBit < 64; iBit++)
1049 if ( (RT_BIT_64(iBit) & uCombined)
1050 || (iBit == pDesc->iFirstBit && pDesc->pszName) )
1051 {
1052 while ( pDesc->pszName != NULL
1053 && iBit >= (uint32_t)pDesc->iFirstBit + pDesc->cBits)
1054 pDesc++;
1055
1056 if ( pDesc->pszName != NULL
1057 && iBit - (uint32_t)pDesc->iFirstBit < (uint32_t)pDesc->cBits)
1058 {
1059 size_t cchMnemonic = strlen(pDesc->pszName);
1060 const char *pszDesc = pDesc->pszName + cchMnemonic + 1;
1061 size_t cchDesc = strlen(pszDesc);
1062 uint32_t uFieldValue1 = uVal1 >> pDesc->iFirstBit;
1063 uint32_t uFieldValue2 = uVal2 >> pDesc->iFirstBit;
1064 if (pDesc->cBits < 64)
1065 {
1066 uFieldValue1 &= RT_BIT_64(pDesc->cBits) - UINT64_C(1);
1067 uFieldValue2 &= RT_BIT_64(pDesc->cBits) - UINT64_C(1);
1068 }
1069
1070 pHlp->pfnPrintf(pHlp, pDesc->cBits < 5 ? " %s - %s%*s= %u (%u)\n" : " %s - %s%*s= %#x (%#x)\n",
1071 pDesc->pszName, pszDesc,
1072 cchMnemonic + 3 + cchDesc < cchWidth ? cchWidth - (cchMnemonic + 3 + cchDesc) : 1, "",
1073 uFieldValue1, uFieldValue2);
1074
1075 iBit = pDesc->iFirstBit + pDesc->cBits - 1U;
1076 pDesc++;
1077 }
1078 else
1079 pHlp->pfnPrintf(pHlp, " %2u - Reserved%*s= %u (%u)\n", iBit, 13 < cchWidth ? cchWidth - 13 : 1, "",
1080 RT_BOOL(uVal1 & RT_BIT_64(iBit)), RT_BOOL(uVal2 & RT_BIT_64(iBit)));
1081 }
1082}
1083
1084
1085/**
1086 * Produces a detailed summary of standard leaf 0x00000007.
1087 *
1088 * @param pHlp The info helper functions.
1089 * @param pszIdReg The ID register name.
1090 * @param u64IdRegHost The host value of the ID register.
1091 * @param u64IdRegGuest The guest value of the ID register.
1092 * @param pDesc The field descriptor.
1093 * @param fVerbose Whether to be very verbose or not.
1094 */
1095static void cpumR3CpuIdInfoIdRegDetails(PCDBGFINFOHLP pHlp, const char *pszIdReg, uint64_t u64IdRegHost, uint64_t u64IdRegGuest,
1096 PCDBGFREGSUBFIELD pDesc, bool fVerbose)
1097{
1098 pHlp->pfnPrintf(pHlp, "ID register %s: Host %#RX64 Guest %#RX64\n", pszIdReg, u64IdRegHost, u64IdRegGuest);
1099 if (fVerbose)
1100 {
1101 pHlp->pfnPrintf(pHlp, " Mnemonic - Description = guest (host)\n");
1102 cpumR3CpuIdInfoVerboseCompareListU64(pHlp, u64IdRegGuest, u64IdRegHost, pDesc, 56);
1103 }
1104 else
1105 cpumR3CpuIdInfoMnemonicListU64(pHlp, u64IdRegGuest, pDesc, "Features:", 36);
1106}
1107
1108
1109/**
1110 * Display the guest CpuId leaves.
1111 *
1112 * @param pVM The cross context VM structure.
1113 * @param pHlp The info helper functions.
1114 * @param pszArgs "terse", "default" or "verbose".
1115 */
1116DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
1117{
1118 /*
1119 * Parse the argument.
1120 */
1121 unsigned iVerbosity = 1;
1122 if (pszArgs)
1123 {
1124 pszArgs = RTStrStripL(pszArgs);
1125 if (!strcmp(pszArgs, "terse"))
1126 iVerbosity--;
1127 else if (!strcmp(pszArgs, "verbose"))
1128 iVerbosity++;
1129 }
1130
1131 /** @todo MIDR_EL1. */
1132
1133 cpumR3CpuIdInfoIdRegDetails(pHlp, "CLIDR_EL1",
1134 pVM->cpum.s.HostIdRegs.u64RegClidrEl1,
1135 pVM->cpum.s.GuestIdRegs.u64RegClidrEl1,
1136 g_aClidrEl1Fields, iVerbosity > 1);
1137
1138 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64PFR0_EL1",
1139 pVM->cpum.s.HostIdRegs.u64RegIdAa64Pfr0El1,
1140 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Pfr0El1,
1141 g_aIdAa64PfR0Fields, iVerbosity > 1);
1142
1143 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64PFR1_EL1",
1144 pVM->cpum.s.HostIdRegs.u64RegIdAa64Pfr1El1,
1145 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Pfr1El1,
1146 g_aIdAa64PfR1Fields, iVerbosity > 1);
1147
1148 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64ISAR0_EL1",
1149 pVM->cpum.s.HostIdRegs.u64RegIdAa64Isar0El1,
1150 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Isar0El1,
1151 g_aIdAa64IsaR0Fields, iVerbosity > 1);
1152
1153 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64ISAR1_EL1",
1154 pVM->cpum.s.HostIdRegs.u64RegIdAa64Isar1El1,
1155 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Isar1El1,
1156 g_aIdAa64IsaR1Fields, iVerbosity > 1);
1157
1158 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64ISAR2_EL1",
1159 pVM->cpum.s.HostIdRegs.u64RegIdAa64Isar2El1,
1160 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Isar2El1,
1161 g_aIdAa64IsaR2Fields, iVerbosity > 1);
1162
1163 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64MMFR0_EL1",
1164 pVM->cpum.s.HostIdRegs.u64RegIdAa64Mmfr0El1,
1165 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Mmfr0El1,
1166 g_aIdAa64MmfR0Fields, iVerbosity > 1);
1167
1168 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64MMFR1_EL1",
1169 pVM->cpum.s.HostIdRegs.u64RegIdAa64Mmfr1El1,
1170 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Mmfr1El1,
1171 g_aIdAa64MmfR1Fields, iVerbosity > 1);
1172
1173 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64MMFR2_EL1",
1174 pVM->cpum.s.HostIdRegs.u64RegIdAa64Mmfr2El1,
1175 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Mmfr2El1,
1176 g_aIdAa64MmfR2Fields, iVerbosity > 1);
1177
1178 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64DFR0_EL1",
1179 pVM->cpum.s.HostIdRegs.u64RegIdAa64Dfr0El1,
1180 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Dfr0El1,
1181 g_aIdAa64DfR0Fields, iVerbosity > 1);
1182
1183 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64DFR1_EL1",
1184 pVM->cpum.s.HostIdRegs.u64RegIdAa64Dfr1El1,
1185 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Dfr1El1,
1186 g_aIdAa64DfR1Fields, iVerbosity > 1);
1187
1188 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64AFR0_EL1",
1189 pVM->cpum.s.HostIdRegs.u64RegIdAa64Afr0El1,
1190 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Afr0El1,
1191 g_aIdAa64AfR0Fields, iVerbosity > 1);
1192
1193 cpumR3CpuIdInfoIdRegDetails(pHlp, "ID_AA64AFR1_EL1",
1194 pVM->cpum.s.HostIdRegs.u64RegIdAa64Afr1El1,
1195 pVM->cpum.s.GuestIdRegs.u64RegIdAa64Afr1El1,
1196 g_aIdAa64AfR1Fields, iVerbosity > 1);
1197}
1198
1199
1200/**
1201 * Display the guest CPU features.
1202 *
1203 * @param pVM The cross context VM structure.
1204 * @param pHlp The info helper functions.
1205 * @param pszArgs "default" or "verbose".
1206 */
1207DECLCALLBACK(void) cpumR3CpuFeatInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
1208{
1209 /*
1210 * Parse the argument.
1211 */
1212 bool fVerbose = false;
1213 if (pszArgs)
1214 {
1215 pszArgs = RTStrStripL(pszArgs);
1216 if (!strcmp(pszArgs, "verbose"))
1217 fVerbose = true;
1218 }
1219
1220 if (fVerbose)
1221 pHlp->pfnPrintf(pHlp, " Features = guest (host)\n");
1222 else
1223 pHlp->pfnPrintf(pHlp, " Features = guest\n");
1224
1225
1226#define LOG_CPU_FEATURE(a_FeatNm, a_Flag) \
1227 do { \
1228 if (fVerbose) \
1229 pHlp->pfnPrintf(pHlp, " %*s = %u (%u)\n", 41, #a_FeatNm, pVM->cpum.s.GuestFeatures.a_Flag, pVM->cpum.s.HostFeatures.s.a_Flag); \
1230 else \
1231 pHlp->pfnPrintf(pHlp, " %*s = %u\n", 41, #a_FeatNm, pVM->cpum.s.GuestFeatures.a_Flag); \
1232 } while (0)
1233
1234 /* Not really features. */
1235 LOG_CPU_FEATURE(FEAT_TGRAN4K, fTGran4K);
1236 LOG_CPU_FEATURE(FEAT_TGRAN16K, fTGran16K);
1237 LOG_CPU_FEATURE(FEAT_TGRAN64K, fTGran64K);
1238
1239 /* Offical ARM FEAT_* definitions start here. */
1240 LOG_CPU_FEATURE(FEAT_AdvSIMD, fAdvSimd);
1241 LOG_CPU_FEATURE(FEAT_AES, fAes);
1242 LOG_CPU_FEATURE(FEAT_PMULL, fPmull);
1243 LOG_CPU_FEATURE(FEAT_CP15DISABLE2, fCp15Disable2);
1244 LOG_CPU_FEATURE(FEAT_CSV2, fCsv2);
1245 LOG_CPU_FEATURE(FEAT_CSV2_1p1, fCsv21p1);
1246 LOG_CPU_FEATURE(FEAT_CSV2_1p2, fCsv21p2);
1247 LOG_CPU_FEATURE(FEAT_CSV3, fCsv3);
1248 LOG_CPU_FEATURE(FEAT_DGH, fDgh);
1249 LOG_CPU_FEATURE(FEAT_DOUBLELOCK, fDoubleLock);
1250 LOG_CPU_FEATURE(FEAT_ETS2, fEts2);
1251 LOG_CPU_FEATURE(FEAT_FP, fFp);
1252 LOG_CPU_FEATURE(FEAT_IVIPT, fIvipt);
1253 LOG_CPU_FEATURE(FEAT_PCSRv8, fPcsrV8);
1254 LOG_CPU_FEATURE(FEAT_SPECRES, fSpecres);
1255 LOG_CPU_FEATURE(FEAT_RAS, fRas);
1256 LOG_CPU_FEATURE(FEAT_SB, fSb);
1257 LOG_CPU_FEATURE(FEAT_SHA1, fSha1);
1258 LOG_CPU_FEATURE(FEAT_SHA256, fSha256);
1259 LOG_CPU_FEATURE(FEAT_SSBS, fSsbs);
1260 LOG_CPU_FEATURE(FEAT_SSBS2, fSsbs2);
1261 LOG_CPU_FEATURE(FEAT_CRC32, fCrc32);
1262 LOG_CPU_FEATURE(FEAT_nTLBPA, fNTlbpa);
1263 LOG_CPU_FEATURE(FEAT_Debugv8p1, fDebugV8p1);
1264 LOG_CPU_FEATURE(FEAT_HPDS, fHpds);
1265 LOG_CPU_FEATURE(FEAT_LOR, fLor);
1266 LOG_CPU_FEATURE(FEAT_LSE, fLse);
1267 LOG_CPU_FEATURE(FEAT_PAN, fPan);
1268 LOG_CPU_FEATURE(FEAT_PMUv3p1, fPmuV3p1);
1269 LOG_CPU_FEATURE(FEAT_RDM, fRdm);
1270 LOG_CPU_FEATURE(FEAT_HAFDBS, fHafdbs);
1271 LOG_CPU_FEATURE(FEAT_VHE, fVhe);
1272 LOG_CPU_FEATURE(FEAT_VMID16, fVmid16);
1273 LOG_CPU_FEATURE(FEAT_AA32BF16, fAa32Bf16);
1274 LOG_CPU_FEATURE(FEAT_AA32HPD, fAa32Hpd);
1275 LOG_CPU_FEATURE(FEAT_AA32I8MM, fAa32I8mm);
1276 LOG_CPU_FEATURE(FEAT_PAN2, fPan2);
1277 LOG_CPU_FEATURE(FEAT_BF16, fBf16);
1278 LOG_CPU_FEATURE(FEAT_DPB2, fDpb2);
1279 LOG_CPU_FEATURE(FEAT_DPB, fDpb);
1280 LOG_CPU_FEATURE(FEAT_Debugv8p2, fDebugV8p2);
1281 LOG_CPU_FEATURE(FEAT_DotProd, fDotProd);
1282 LOG_CPU_FEATURE(FEAT_EVT, fEvt);
1283 LOG_CPU_FEATURE(FEAT_F32MM, fF32mm);
1284 LOG_CPU_FEATURE(FEAT_F64MM, fF64mm);
1285 LOG_CPU_FEATURE(FEAT_FHM, fFhm);
1286 LOG_CPU_FEATURE(FEAT_FP16, fFp16);
1287 LOG_CPU_FEATURE(FEAT_I8MM, fI8mm);
1288 LOG_CPU_FEATURE(FEAT_IESB, fIesb);
1289 LOG_CPU_FEATURE(FEAT_LPA, fLpa);
1290 LOG_CPU_FEATURE(FEAT_LSMAOC, fLsmaoc);
1291 LOG_CPU_FEATURE(FEAT_LVA, fLva);
1292 LOG_CPU_FEATURE(FEAT_MPAM, fMpam);
1293 LOG_CPU_FEATURE(FEAT_PCSRv8p2, fPcsrV8p2);
1294 LOG_CPU_FEATURE(FEAT_SHA3, fSha3);
1295 LOG_CPU_FEATURE(FEAT_SHA512, fSha512);
1296 LOG_CPU_FEATURE(FEAT_SM3, fSm3);
1297 LOG_CPU_FEATURE(FEAT_SM4, fSm4);
1298 LOG_CPU_FEATURE(FEAT_SPE, fSpe);
1299 LOG_CPU_FEATURE(FEAT_SVE, fSve);
1300 LOG_CPU_FEATURE(FEAT_TTCNP, fTtcnp);
1301 LOG_CPU_FEATURE(FEAT_HPDS2, fHpds2);
1302 LOG_CPU_FEATURE(FEAT_XNX, fXnx);
1303 LOG_CPU_FEATURE(FEAT_UAO, fUao);
1304 LOG_CPU_FEATURE(FEAT_VPIPT, fVpipt);
1305 LOG_CPU_FEATURE(FEAT_CCIDX, fCcidx);
1306 LOG_CPU_FEATURE(FEAT_FCMA, fFcma);
1307 LOG_CPU_FEATURE(FEAT_DoPD, fDopd);
1308 LOG_CPU_FEATURE(FEAT_EPAC, fEpac);
1309 LOG_CPU_FEATURE(FEAT_FPAC, fFpac);
1310 LOG_CPU_FEATURE(FEAT_FPACCOMBINE, fFpacCombine);
1311 LOG_CPU_FEATURE(FEAT_JSCVT, fJscvt);
1312 LOG_CPU_FEATURE(FEAT_LRCPC, fLrcpc);
1313 LOG_CPU_FEATURE(FEAT_NV, fNv);
1314 LOG_CPU_FEATURE(FEAT_PACQARMA5, fPacQarma5);
1315 LOG_CPU_FEATURE(FEAT_PACIMP, fPacImp);
1316 LOG_CPU_FEATURE(FEAT_PAuth, fPAuth);
1317 LOG_CPU_FEATURE(FEAT_PAuth2, fPAuth2);
1318 LOG_CPU_FEATURE(FEAT_SPEv1p1, fSpeV1p1);
1319 LOG_CPU_FEATURE(FEAT_AMUv1, fAmuV1);
1320 LOG_CPU_FEATURE(FEAT_CNTSC, fCntsc);
1321 LOG_CPU_FEATURE(FEAT_Debugv8p4, fDebugV8p4);
1322 LOG_CPU_FEATURE(FEAT_DoubleFault, fDoubleFault);
1323 LOG_CPU_FEATURE(FEAT_DIT, fDit);
1324 LOG_CPU_FEATURE(FEAT_FlagM, fFlagM);
1325 LOG_CPU_FEATURE(FEAT_IDST, fIdst);
1326 LOG_CPU_FEATURE(FEAT_LRCPC2, fLrcpc2);
1327 LOG_CPU_FEATURE(FEAT_LSE2, fLse2);
1328 LOG_CPU_FEATURE(FEAT_NV2, fNv2);
1329 LOG_CPU_FEATURE(FEAT_PMUv3p4, fPmuV3p4);
1330 LOG_CPU_FEATURE(FEAT_RASv1p1, fRasV1p1);
1331 LOG_CPU_FEATURE(FEAT_RASSAv1p1, fRassaV1p1);
1332 LOG_CPU_FEATURE(FEAT_S2FWB, fS2Fwb);
1333 LOG_CPU_FEATURE(FEAT_SEL2, fSecEl2);
1334 LOG_CPU_FEATURE(FEAT_TLBIOS, fTlbios);
1335 LOG_CPU_FEATURE(FEAT_TLBIRANGE, fTlbirange);
1336 LOG_CPU_FEATURE(FEAT_TRF, fTrf);
1337 LOG_CPU_FEATURE(FEAT_TTL, fTtl);
1338 LOG_CPU_FEATURE(FEAT_BBM, fBbm);
1339 LOG_CPU_FEATURE(FEAT_TTST, fTtst);
1340 LOG_CPU_FEATURE(FEAT_BTI, fBti);
1341 LOG_CPU_FEATURE(FEAT_FlagM2, fFlagM2);
1342 LOG_CPU_FEATURE(FEAT_ExS, fExs);
1343 LOG_CPU_FEATURE(FEAT_E0PD, fE0Pd);
1344 LOG_CPU_FEATURE(FEAT_FRINTTS, fFrintts);
1345 LOG_CPU_FEATURE(FEAT_GTG, fGtg);
1346 LOG_CPU_FEATURE(FEAT_MTE, fMte);
1347 LOG_CPU_FEATURE(FEAT_MTE2, fMte2);
1348 LOG_CPU_FEATURE(FEAT_PMUv3p5, fPmuV3p5);
1349 LOG_CPU_FEATURE(FEAT_RNG, fRng);
1350 LOG_CPU_FEATURE(FEAT_AMUv1p1, fAmuV1p1);
1351 LOG_CPU_FEATURE(FEAT_ECV, fEcv);
1352 LOG_CPU_FEATURE(FEAT_FGT, fFgt);
1353 LOG_CPU_FEATURE(FEAT_MPAMv0p1, fMpamV0p1);
1354 LOG_CPU_FEATURE(FEAT_MPAMv1p1, fMpamV1p1);
1355 LOG_CPU_FEATURE(FEAT_MTPMU, fMtPmu);
1356 LOG_CPU_FEATURE(FEAT_TWED, fTwed);
1357 LOG_CPU_FEATURE(FEAT_ETMv4, fEtmV4);
1358 LOG_CPU_FEATURE(FEAT_ETMv4p1, fEtmV4p1);
1359 LOG_CPU_FEATURE(FEAT_ETMv4p2, fEtmV4p2);
1360 LOG_CPU_FEATURE(FEAT_ETMv4p3, fEtmV4p3);
1361 LOG_CPU_FEATURE(FEAT_ETMv4p4, fEtmV4p4);
1362 LOG_CPU_FEATURE(FEAT_ETMv4p5, fEtmV4p5);
1363 LOG_CPU_FEATURE(FEAT_ETMv4p6, fEtmV4p6);
1364 LOG_CPU_FEATURE(FEAT_GICv3, fGicV3);
1365 LOG_CPU_FEATURE(FEAT_GICv3p1, fGicV3p1);
1366 LOG_CPU_FEATURE(FEAT_GICv3_TDIR, fGicV3Tdir);
1367 LOG_CPU_FEATURE(FEAT_GICv4, fGicV4);
1368 LOG_CPU_FEATURE(FEAT_GICv4p1, fGicV4p1);
1369 LOG_CPU_FEATURE(FEAT_PMUv3, fPmuV3);
1370 LOG_CPU_FEATURE(FEAT_ETE, fEte);
1371 LOG_CPU_FEATURE(FEAT_ETEv1p1, fEteV1p1);
1372 LOG_CPU_FEATURE(FEAT_ETEv1p2, fEteV1p2);
1373 LOG_CPU_FEATURE(FEAT_SVE2, fSve2);
1374 LOG_CPU_FEATURE(FEAT_SVE_AES, fSveAes);
1375 LOG_CPU_FEATURE(FEAT_SVE_PMULL128, fSvePmull128);
1376 LOG_CPU_FEATURE(FEAT_SVE_BitPerm, fSveBitPerm);
1377 LOG_CPU_FEATURE(FEAT_SVE_SHA3, fSveSha3);
1378 LOG_CPU_FEATURE(FEAT_SVE_SM4, fSveSm4);
1379 LOG_CPU_FEATURE(FEAT_TME, fTme);
1380 LOG_CPU_FEATURE(FEAT_TRBE, fTrbe);
1381 LOG_CPU_FEATURE(FEAT_SME, fSme);
1382
1383 LOG_CPU_FEATURE(FEAT_AFP, fAfp);
1384 LOG_CPU_FEATURE(FEAT_HCX, fHcx);
1385 LOG_CPU_FEATURE(FEAT_LPA2, fLpa2);
1386 LOG_CPU_FEATURE(FEAT_LS64, fLs64);
1387 LOG_CPU_FEATURE(FEAT_LS64_V, fLs64V);
1388 LOG_CPU_FEATURE(FEAT_LS64_ACCDATA, fLs64Accdata);
1389 LOG_CPU_FEATURE(FEAT_MTE3, fMte3);
1390 LOG_CPU_FEATURE(FEAT_PAN3, fPan3);
1391 LOG_CPU_FEATURE(FEAT_PMUv3p7, fPmuV3p7);
1392 LOG_CPU_FEATURE(FEAT_RPRES, fRpres);
1393 LOG_CPU_FEATURE(FEAT_RME, fRme);
1394 LOG_CPU_FEATURE(FEAT_SME_FA64, fSmeFA64);
1395 LOG_CPU_FEATURE(FEAT_SME_F64F64, fSmeF64F64);
1396 LOG_CPU_FEATURE(FEAT_SME_I16I64, fSmeI16I64);
1397 LOG_CPU_FEATURE(FEAT_SPEv1p2, fSpeV1p2);
1398 LOG_CPU_FEATURE(FEAT_EBF16, fEbf16);
1399 LOG_CPU_FEATURE(FEAT_WFxT, fWfxt);
1400 LOG_CPU_FEATURE(FEAT_XS, fXs);
1401 LOG_CPU_FEATURE(FEAT_BRBE, fBrbe);
1402
1403 LOG_CPU_FEATURE(FEAT_CMOW, fCmow);
1404 LOG_CPU_FEATURE(FEAT_CONSTPACFIELD, fConstPacField);
1405 LOG_CPU_FEATURE(FEAT_Debugv8p8, fDebugV8p8);
1406 LOG_CPU_FEATURE(FEAT_HBC, fHbc);
1407 LOG_CPU_FEATURE(FEAT_HPMN0, fHpmn0);
1408 LOG_CPU_FEATURE(FEAT_NMI, fNmi);
1409 LOG_CPU_FEATURE(FEAT_GICv3_NMI, fGicV3Nmi);
1410 LOG_CPU_FEATURE(FEAT_MOPS, fMops);
1411 LOG_CPU_FEATURE(FEAT_PACQARMA3, fPacQarma3);
1412 LOG_CPU_FEATURE(FEAT_PMUv3_TH, fPmuV3Th);
1413 LOG_CPU_FEATURE(FEAT_PMUv3p8, fPmuV3p8);
1414 LOG_CPU_FEATURE(FEAT_PMUv3_EXT64, fPmuV3Ext64);
1415 LOG_CPU_FEATURE(FEAT_PMUv3_EXT32, fPmuV3Ext32);
1416 LOG_CPU_FEATURE(FEAT_PMUv3_EXT, fPmuV3Ext);
1417 LOG_CPU_FEATURE(FEAT_RNG_TRAP, fRngTrap);
1418 LOG_CPU_FEATURE(FEAT_SPEv1p3, fSpeV1p3);
1419 LOG_CPU_FEATURE(FEAT_TIDCP1, fTidcp1);
1420 LOG_CPU_FEATURE(FEAT_BRBEv1p1, fBrbeV1p1);
1421
1422 LOG_CPU_FEATURE(FEAT_ABLE, fAble);
1423 LOG_CPU_FEATURE(FEAT_ADERR, fAderr);
1424 LOG_CPU_FEATURE(FEAT_AIE, fAie);
1425 LOG_CPU_FEATURE(FEAT_ANERR, fAnerr);
1426 LOG_CPU_FEATURE(FEAT_BWE, fBwe);
1427 LOG_CPU_FEATURE(FEAT_CLRBHB, fClrBhb);
1428 LOG_CPU_FEATURE(FEAT_CHK, fChk);
1429 LOG_CPU_FEATURE(FEAT_CSSC, fCssc);
1430 LOG_CPU_FEATURE(FEAT_CSV2_3, fCsv2v3);
1431 LOG_CPU_FEATURE(FEAT_D128, fD128);
1432 LOG_CPU_FEATURE(FEAT_Debugv8p9, fDebugV8p9);
1433 LOG_CPU_FEATURE(FEAT_DoubleFault2, fDoubleFault2);
1434 LOG_CPU_FEATURE(FEAT_EBEP, fEbep);
1435 LOG_CPU_FEATURE(FEAT_ECBHB, fEcBhb);
1436 LOG_CPU_FEATURE(FEAT_EDHSR, fEdhsr);
1437 LOG_CPU_FEATURE(FEAT_ETEv1p3, fEteV1p3);
1438 LOG_CPU_FEATURE(FEAT_FGT2, fFgt2);
1439 LOG_CPU_FEATURE(FEAT_GCS, fGcs);
1440 LOG_CPU_FEATURE(FEAT_HAFT, fHaft);
1441 LOG_CPU_FEATURE(FEAT_ITE, fIte);
1442 LOG_CPU_FEATURE(FEAT_LRCPC3, fLrcpc3);
1443 LOG_CPU_FEATURE(FEAT_LSE128, fLse128);
1444 LOG_CPU_FEATURE(FEAT_LVA3, fLva3);
1445 LOG_CPU_FEATURE(FEAT_MEC, fMec);
1446 LOG_CPU_FEATURE(FEAT_MTE4, fMte4);
1447 LOG_CPU_FEATURE(FEAT_MTE_CANONICAL_TAGS, fMteCanonicalTags);
1448 LOG_CPU_FEATURE(FEAT_MTE_TAGGED_FAR, fMteTaggedFar);
1449 LOG_CPU_FEATURE(FEAT_MTE_STORE_ONLY, fMteStoreOnly);
1450 LOG_CPU_FEATURE(FEAT_MTE_NO_ADDRESS_TAGS, fMteNoAddressTags);
1451 LOG_CPU_FEATURE(FEAT_MTE_ASYM_FAULT, fMteAsymFault);
1452 LOG_CPU_FEATURE(FEAT_MTE_ASYNC, fMteAsync);
1453 LOG_CPU_FEATURE(FEAT_MTE_PERM_S1, fMtePermS1);
1454 LOG_CPU_FEATURE(FEAT_PCSRv8p9, fPcsrV8p9);
1455 LOG_CPU_FEATURE(FEAT_S1PIE, fS1Pie);
1456 LOG_CPU_FEATURE(FEAT_S2PIE, fS2Pie);
1457 LOG_CPU_FEATURE(FEAT_S1POE, fS1Poe);
1458 LOG_CPU_FEATURE(FEAT_S2POE, fS2Poe);
1459 LOG_CPU_FEATURE(FEAT_PFAR, fPfar);
1460 LOG_CPU_FEATURE(FEAT_PMUv3p9, fPmuV3p9);
1461 LOG_CPU_FEATURE(FEAT_PMUv3_EDGE, fPmuV3Edge);
1462 LOG_CPU_FEATURE(FEAT_PMUv3_ICNTR, fPmuV3Icntr);
1463 LOG_CPU_FEATURE(FEAT_PMUv3_SS, fPmuV3Ss);
1464 LOG_CPU_FEATURE(FEAT_PRFMSLC, fPrfmSlc);
1465 LOG_CPU_FEATURE(FEAT_RASv2, fRasV2);
1466 LOG_CPU_FEATURE(FEAT_RASSAv2, fRasSaV2);
1467 LOG_CPU_FEATURE(FEAT_RPRFM, fRprfm);
1468 LOG_CPU_FEATURE(FEAT_SCTLR2, fSctlr2);
1469 LOG_CPU_FEATURE(FEAT_SEBEP, fSebep);
1470 LOG_CPU_FEATURE(FEAT_SME_F16F16, fSmeF16F16);
1471 LOG_CPU_FEATURE(FEAT_SME2, fSme2);
1472 LOG_CPU_FEATURE(FEAT_SME2p1, fSme2p1);
1473 LOG_CPU_FEATURE(FEAT_SPECRES2, fSpecres2);
1474 LOG_CPU_FEATURE(FEAT_SPMU, fSpmu);
1475 LOG_CPU_FEATURE(FEAT_SPEv1p4, fSpeV1p4);
1476 LOG_CPU_FEATURE(FEAT_SPE_CRR, fSpeCrr);
1477 LOG_CPU_FEATURE(FEAT_SPE_FDS, fSpeFds);
1478 LOG_CPU_FEATURE(FEAT_SVE2p1, fSve2p1);
1479 LOG_CPU_FEATURE(FEAT_SVE_B16B16, fSveB16B16);
1480 LOG_CPU_FEATURE(FEAT_SYSINSTR128, fSysInstr128);
1481 LOG_CPU_FEATURE(FEAT_SYSREG128, fSysReg128);
1482 LOG_CPU_FEATURE(FEAT_TCR2, fTcr2);
1483 LOG_CPU_FEATURE(FEAT_THE, fThe);
1484 LOG_CPU_FEATURE(FEAT_TRBE_EXT, fTrbeExt);
1485 LOG_CPU_FEATURE(FEAT_TRBE_MPAM, fTrbeMpam);
1486#undef LOG_CPU_FEATURE
1487}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette