VirtualBox

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

Last change on this file since 108822 was 108822, checked in by vboxsync, 2 weeks ago

VMM/CPUM: bugref:10877 Configure the ID_AA64PFR0_EL1 system register with the availability of the GIC CPU interface (required for EFI firmware).

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

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