VirtualBox

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

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

VMM/CPUM,++: Made the HostFeatures match the host when targeting x86 guests on arm64 hosts. Merged and deduplicated code targeting x86 & amd64. jiraref:VBP-1470

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