VirtualBox

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

Last change on this file since 101138 was 101121, checked in by vboxsync, 18 months ago

VMM/CPUM: Log host and guest features, bugref:10525

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