VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/CPUM-armv8.cpp@ 106360

Last change on this file since 106360 was 106061, checked in by vboxsync, 2 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 41.6 KB
Line 
1/* $Id: CPUM-armv8.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * CPUM - CPU Monitor / Manager (ARMv8 variant).
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/** @page pg_cpum CPUM - CPU Monitor / Manager
29 *
30 * The CPU Monitor / Manager keeps track of all the CPU registers.
31 * This is the ARMv8 variant which is doing much less than its x86/AMD6464
32 * counterpart due to the fact that we currently only support the NEM backends
33 * for running ARM guests. It might become complex iff we decide to implement our
34 * own hypervisor.
35 *
36 * @section sec_cpum_logging_armv8 Logging Level Assignments.
37 *
38 * Following log level assignments:
39 * - @todo
40 *
41 */
42
43
44/*********************************************************************************************************************************
45* Header Files *
46*********************************************************************************************************************************/
47#define LOG_GROUP LOG_GROUP_CPUM
48#define CPUM_WITH_NONCONST_HOST_FEATURES
49#include <VBox/vmm/cpum.h>
50#include <VBox/vmm/cpumdis.h>
51#include <VBox/vmm/pgm.h>
52#include <VBox/vmm/mm.h>
53#include <VBox/vmm/em.h>
54#include <VBox/vmm/iem.h>
55#include <VBox/vmm/dbgf.h>
56#include <VBox/vmm/ssm.h>
57#include "CPUMInternal-armv8.h"
58#include <VBox/vmm/vm.h>
59
60#include <VBox/param.h>
61#include <VBox/dis.h>
62#include <VBox/err.h>
63#include <VBox/log.h>
64#include <iprt/assert.h>
65#include <iprt/cpuset.h>
66#include <iprt/mem.h>
67#include <iprt/mp.h>
68#include <iprt/string.h>
69#include <iprt/armv8.h>
70
71
72/*********************************************************************************************************************************
73* Defined Constants And Macros *
74*********************************************************************************************************************************/
75
76/** Internal form used by the macros. */
77#ifdef VBOX_WITH_STATISTICS
78# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
79 { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName, \
80 { 0 }, { 0 }, { 0 }, { 0 } }
81#else
82# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
83 { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName }
84#endif
85
86/** Function handlers, extended version. */
87#define MFX(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
88 RINT(a_uMsr, a_uMsr, kCpumSysRegRdFn_##a_enmRdFnSuff, kCpumSysRegWrFn_##a_enmWrFnSuff, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
89/** Function handlers, read-only. */
90#define MFO(a_uMsr, a_szName, a_enmRdFnSuff) \
91 RINT(a_uMsr, a_uMsr, kCpumSysRegRdFn_##a_enmRdFnSuff, kCpumSysRegWrFn_ReadOnly, 0, 0, 0, UINT64_MAX, a_szName)
92/** Read-only fixed value, ignores all writes. */
93#define MVI(a_uMsr, a_szName, a_uValue) \
94 RINT(a_uMsr, a_uMsr, kCpumSysRegRdFn_FixedValue, kCpumSysRegWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
95
96
97/*********************************************************************************************************************************
98* Structures and Typedefs *
99*********************************************************************************************************************************/
100
101/**
102 * What kind of cpu info dump to perform.
103 */
104typedef enum CPUMDUMPTYPE
105{
106 CPUMDUMPTYPE_TERSE,
107 CPUMDUMPTYPE_DEFAULT,
108 CPUMDUMPTYPE_VERBOSE
109} CPUMDUMPTYPE;
110/** Pointer to a cpu info dump type. */
111typedef CPUMDUMPTYPE *PCPUMDUMPTYPE;
112
113
114/*********************************************************************************************************************************
115* Internal Functions *
116*********************************************************************************************************************************/
117static DECLCALLBACK(int) cpumR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
118static DECLCALLBACK(int) cpumR3SaveExec(PVM pVM, PSSMHANDLE pSSM);
119static DECLCALLBACK(int) cpumR3LoadPrep(PVM pVM, PSSMHANDLE pSSM);
120static DECLCALLBACK(int) cpumR3LoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
121static DECLCALLBACK(int) cpumR3LoadDone(PVM pVM, PSSMHANDLE pSSM);
122static DECLCALLBACK(void) cpumR3InfoAll(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
123static DECLCALLBACK(void) cpumR3InfoGuest(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
124static DECLCALLBACK(void) cpumR3InfoGuestInstr(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
125
126
127/*********************************************************************************************************************************
128* Global Variables *
129*********************************************************************************************************************************/
130#if defined(RT_ARCH_ARM64)
131/** Host CPU features. */
132DECL_HIDDEN_DATA(CPUHOSTFEATURES) g_CpumHostFeatures;
133#endif
134
135/**
136 * System register ranges.
137 */
138static CPUMSYSREGRANGE const g_aSysRegRanges[] =
139{
140 MFX(ARMV8_AARCH64_SYSREG_OSLAR_EL1, "OSLAR_EL1", WriteOnly, OslarEl1, 0, UINT64_C(0xfffffffffffffffe), UINT64_C(0xfffffffffffffffe)),
141 MFO(ARMV8_AARCH64_SYSREG_OSLSR_EL1, "OSLSR_EL1", OslsrEl1),
142 MVI(ARMV8_AARCH64_SYSREG_OSDLR_EL1, "OSDLR_EL1", 0)
143};
144
145
146/** Saved state field descriptors for CPUMCTX. */
147static const SSMFIELD g_aCpumCtxFields[] =
148{
149 SSMFIELD_ENTRY( CPUMCTX, aGRegs[0].x),
150 SSMFIELD_ENTRY( CPUMCTX, aGRegs[1].x),
151 SSMFIELD_ENTRY( CPUMCTX, aGRegs[2].x),
152 SSMFIELD_ENTRY( CPUMCTX, aGRegs[3].x),
153 SSMFIELD_ENTRY( CPUMCTX, aGRegs[4].x),
154 SSMFIELD_ENTRY( CPUMCTX, aGRegs[5].x),
155 SSMFIELD_ENTRY( CPUMCTX, aGRegs[6].x),
156 SSMFIELD_ENTRY( CPUMCTX, aGRegs[7].x),
157 SSMFIELD_ENTRY( CPUMCTX, aGRegs[8].x),
158 SSMFIELD_ENTRY( CPUMCTX, aGRegs[9].x),
159 SSMFIELD_ENTRY( CPUMCTX, aGRegs[10].x),
160 SSMFIELD_ENTRY( CPUMCTX, aGRegs[11].x),
161 SSMFIELD_ENTRY( CPUMCTX, aGRegs[12].x),
162 SSMFIELD_ENTRY( CPUMCTX, aGRegs[13].x),
163 SSMFIELD_ENTRY( CPUMCTX, aGRegs[14].x),
164 SSMFIELD_ENTRY( CPUMCTX, aGRegs[15].x),
165 SSMFIELD_ENTRY( CPUMCTX, aGRegs[16].x),
166 SSMFIELD_ENTRY( CPUMCTX, aGRegs[17].x),
167 SSMFIELD_ENTRY( CPUMCTX, aGRegs[18].x),
168 SSMFIELD_ENTRY( CPUMCTX, aGRegs[19].x),
169 SSMFIELD_ENTRY( CPUMCTX, aGRegs[20].x),
170 SSMFIELD_ENTRY( CPUMCTX, aGRegs[21].x),
171 SSMFIELD_ENTRY( CPUMCTX, aGRegs[22].x),
172 SSMFIELD_ENTRY( CPUMCTX, aGRegs[23].x),
173 SSMFIELD_ENTRY( CPUMCTX, aGRegs[24].x),
174 SSMFIELD_ENTRY( CPUMCTX, aGRegs[25].x),
175 SSMFIELD_ENTRY( CPUMCTX, aGRegs[26].x),
176 SSMFIELD_ENTRY( CPUMCTX, aGRegs[27].x),
177 SSMFIELD_ENTRY( CPUMCTX, aGRegs[28].x),
178 SSMFIELD_ENTRY( CPUMCTX, aGRegs[29].x),
179 SSMFIELD_ENTRY( CPUMCTX, aGRegs[30].x),
180 SSMFIELD_ENTRY( CPUMCTX, aVRegs[0].v),
181 SSMFIELD_ENTRY( CPUMCTX, aVRegs[1].v),
182 SSMFIELD_ENTRY( CPUMCTX, aVRegs[2].v),
183 SSMFIELD_ENTRY( CPUMCTX, aVRegs[3].v),
184 SSMFIELD_ENTRY( CPUMCTX, aVRegs[4].v),
185 SSMFIELD_ENTRY( CPUMCTX, aVRegs[5].v),
186 SSMFIELD_ENTRY( CPUMCTX, aVRegs[6].v),
187 SSMFIELD_ENTRY( CPUMCTX, aVRegs[7].v),
188 SSMFIELD_ENTRY( CPUMCTX, aVRegs[8].v),
189 SSMFIELD_ENTRY( CPUMCTX, aVRegs[9].v),
190 SSMFIELD_ENTRY( CPUMCTX, aVRegs[10].v),
191 SSMFIELD_ENTRY( CPUMCTX, aVRegs[11].v),
192 SSMFIELD_ENTRY( CPUMCTX, aVRegs[12].v),
193 SSMFIELD_ENTRY( CPUMCTX, aVRegs[13].v),
194 SSMFIELD_ENTRY( CPUMCTX, aVRegs[14].v),
195 SSMFIELD_ENTRY( CPUMCTX, aVRegs[15].v),
196 SSMFIELD_ENTRY( CPUMCTX, aVRegs[16].v),
197 SSMFIELD_ENTRY( CPUMCTX, aVRegs[17].v),
198 SSMFIELD_ENTRY( CPUMCTX, aVRegs[18].v),
199 SSMFIELD_ENTRY( CPUMCTX, aVRegs[19].v),
200 SSMFIELD_ENTRY( CPUMCTX, aVRegs[20].v),
201 SSMFIELD_ENTRY( CPUMCTX, aVRegs[21].v),
202 SSMFIELD_ENTRY( CPUMCTX, aVRegs[22].v),
203 SSMFIELD_ENTRY( CPUMCTX, aVRegs[23].v),
204 SSMFIELD_ENTRY( CPUMCTX, aVRegs[24].v),
205 SSMFIELD_ENTRY( CPUMCTX, aVRegs[25].v),
206 SSMFIELD_ENTRY( CPUMCTX, aVRegs[26].v),
207 SSMFIELD_ENTRY( CPUMCTX, aVRegs[27].v),
208 SSMFIELD_ENTRY( CPUMCTX, aVRegs[28].v),
209 SSMFIELD_ENTRY( CPUMCTX, aVRegs[29].v),
210 SSMFIELD_ENTRY( CPUMCTX, aVRegs[30].v),
211 SSMFIELD_ENTRY( CPUMCTX, aVRegs[31].v),
212 SSMFIELD_ENTRY( CPUMCTX, aSpReg[0].u64),
213 SSMFIELD_ENTRY( CPUMCTX, aSpReg[1].u64),
214 SSMFIELD_ENTRY( CPUMCTX, Pc.u64),
215 SSMFIELD_ENTRY( CPUMCTX, Spsr.u64),
216 SSMFIELD_ENTRY( CPUMCTX, Elr.u64),
217 SSMFIELD_ENTRY( CPUMCTX, Sctlr.u64),
218 SSMFIELD_ENTRY( CPUMCTX, Tcr.u64),
219 SSMFIELD_ENTRY( CPUMCTX, Ttbr0.u64),
220 SSMFIELD_ENTRY( CPUMCTX, Ttbr1.u64),
221 SSMFIELD_ENTRY( CPUMCTX, VBar.u64),
222 SSMFIELD_ENTRY( CPUMCTX, aBp[0].Ctrl.u64),
223 SSMFIELD_ENTRY( CPUMCTX, aBp[0].Value.u64),
224 SSMFIELD_ENTRY( CPUMCTX, aBp[1].Ctrl.u64),
225 SSMFIELD_ENTRY( CPUMCTX, aBp[1].Value.u64),
226 SSMFIELD_ENTRY( CPUMCTX, aBp[2].Ctrl.u64),
227 SSMFIELD_ENTRY( CPUMCTX, aBp[2].Value.u64),
228 SSMFIELD_ENTRY( CPUMCTX, aBp[3].Ctrl.u64),
229 SSMFIELD_ENTRY( CPUMCTX, aBp[3].Value.u64),
230 SSMFIELD_ENTRY( CPUMCTX, aBp[4].Ctrl.u64),
231 SSMFIELD_ENTRY( CPUMCTX, aBp[4].Value.u64),
232 SSMFIELD_ENTRY( CPUMCTX, aBp[5].Ctrl.u64),
233 SSMFIELD_ENTRY( CPUMCTX, aBp[5].Value.u64),
234 SSMFIELD_ENTRY( CPUMCTX, aBp[6].Ctrl.u64),
235 SSMFIELD_ENTRY( CPUMCTX, aBp[6].Value.u64),
236 SSMFIELD_ENTRY( CPUMCTX, aBp[7].Ctrl.u64),
237 SSMFIELD_ENTRY( CPUMCTX, aBp[7].Value.u64),
238 SSMFIELD_ENTRY( CPUMCTX, aBp[8].Ctrl.u64),
239 SSMFIELD_ENTRY( CPUMCTX, aBp[8].Value.u64),
240 SSMFIELD_ENTRY( CPUMCTX, aBp[9].Ctrl.u64),
241 SSMFIELD_ENTRY( CPUMCTX, aBp[9].Value.u64),
242 SSMFIELD_ENTRY( CPUMCTX, aBp[10].Ctrl.u64),
243 SSMFIELD_ENTRY( CPUMCTX, aBp[10].Value.u64),
244 SSMFIELD_ENTRY( CPUMCTX, aBp[11].Ctrl.u64),
245 SSMFIELD_ENTRY( CPUMCTX, aBp[11].Value.u64),
246 SSMFIELD_ENTRY( CPUMCTX, aBp[12].Ctrl.u64),
247 SSMFIELD_ENTRY( CPUMCTX, aBp[12].Value.u64),
248 SSMFIELD_ENTRY( CPUMCTX, aBp[13].Ctrl.u64),
249 SSMFIELD_ENTRY( CPUMCTX, aBp[13].Value.u64),
250 SSMFIELD_ENTRY( CPUMCTX, aBp[14].Ctrl.u64),
251 SSMFIELD_ENTRY( CPUMCTX, aBp[14].Value.u64),
252 SSMFIELD_ENTRY( CPUMCTX, aBp[15].Ctrl.u64),
253 SSMFIELD_ENTRY( CPUMCTX, aBp[15].Value.u64),
254 SSMFIELD_ENTRY( CPUMCTX, aWp[0].Ctrl.u64),
255 SSMFIELD_ENTRY( CPUMCTX, aWp[0].Value.u64),
256 SSMFIELD_ENTRY( CPUMCTX, aWp[1].Ctrl.u64),
257 SSMFIELD_ENTRY( CPUMCTX, aWp[1].Value.u64),
258 SSMFIELD_ENTRY( CPUMCTX, aWp[2].Ctrl.u64),
259 SSMFIELD_ENTRY( CPUMCTX, aWp[2].Value.u64),
260 SSMFIELD_ENTRY( CPUMCTX, aWp[3].Ctrl.u64),
261 SSMFIELD_ENTRY( CPUMCTX, aWp[3].Value.u64),
262 SSMFIELD_ENTRY( CPUMCTX, aWp[4].Ctrl.u64),
263 SSMFIELD_ENTRY( CPUMCTX, aWp[4].Value.u64),
264 SSMFIELD_ENTRY( CPUMCTX, aWp[5].Ctrl.u64),
265 SSMFIELD_ENTRY( CPUMCTX, aWp[5].Value.u64),
266 SSMFIELD_ENTRY( CPUMCTX, aWp[6].Ctrl.u64),
267 SSMFIELD_ENTRY( CPUMCTX, aWp[6].Value.u64),
268 SSMFIELD_ENTRY( CPUMCTX, aWp[7].Ctrl.u64),
269 SSMFIELD_ENTRY( CPUMCTX, aWp[7].Value.u64),
270 SSMFIELD_ENTRY( CPUMCTX, aWp[8].Ctrl.u64),
271 SSMFIELD_ENTRY( CPUMCTX, aWp[8].Value.u64),
272 SSMFIELD_ENTRY( CPUMCTX, aWp[9].Ctrl.u64),
273 SSMFIELD_ENTRY( CPUMCTX, aWp[9].Value.u64),
274 SSMFIELD_ENTRY( CPUMCTX, aWp[10].Ctrl.u64),
275 SSMFIELD_ENTRY( CPUMCTX, aWp[10].Value.u64),
276 SSMFIELD_ENTRY( CPUMCTX, aWp[11].Ctrl.u64),
277 SSMFIELD_ENTRY( CPUMCTX, aWp[11].Value.u64),
278 SSMFIELD_ENTRY( CPUMCTX, aWp[12].Ctrl.u64),
279 SSMFIELD_ENTRY( CPUMCTX, aWp[12].Value.u64),
280 SSMFIELD_ENTRY( CPUMCTX, aWp[13].Ctrl.u64),
281 SSMFIELD_ENTRY( CPUMCTX, aWp[13].Value.u64),
282 SSMFIELD_ENTRY( CPUMCTX, aWp[14].Ctrl.u64),
283 SSMFIELD_ENTRY( CPUMCTX, aWp[14].Value.u64),
284 SSMFIELD_ENTRY( CPUMCTX, aWp[15].Ctrl.u64),
285 SSMFIELD_ENTRY( CPUMCTX, aWp[15].Value.u64),
286 SSMFIELD_ENTRY( CPUMCTX, Mdscr.u64),
287 SSMFIELD_ENTRY( CPUMCTX, Apda.Low.u64),
288 SSMFIELD_ENTRY( CPUMCTX, Apda.High.u64),
289 SSMFIELD_ENTRY( CPUMCTX, Apdb.Low.u64),
290 SSMFIELD_ENTRY( CPUMCTX, Apdb.High.u64),
291 SSMFIELD_ENTRY( CPUMCTX, Apga.Low.u64),
292 SSMFIELD_ENTRY( CPUMCTX, Apga.High.u64),
293 SSMFIELD_ENTRY( CPUMCTX, Apia.Low.u64),
294 SSMFIELD_ENTRY( CPUMCTX, Apia.High.u64),
295 SSMFIELD_ENTRY( CPUMCTX, Apib.Low.u64),
296 SSMFIELD_ENTRY( CPUMCTX, Apib.High.u64),
297 SSMFIELD_ENTRY( CPUMCTX, Afsr0.u64),
298 SSMFIELD_ENTRY( CPUMCTX, Afsr1.u64),
299 SSMFIELD_ENTRY( CPUMCTX, Amair.u64),
300 SSMFIELD_ENTRY( CPUMCTX, CntKCtl.u64),
301 SSMFIELD_ENTRY( CPUMCTX, ContextIdr.u64),
302 SSMFIELD_ENTRY( CPUMCTX, Cpacr.u64),
303 SSMFIELD_ENTRY( CPUMCTX, Csselr.u64),
304 SSMFIELD_ENTRY( CPUMCTX, Esr.u64),
305 SSMFIELD_ENTRY( CPUMCTX, Far.u64),
306 SSMFIELD_ENTRY( CPUMCTX, Mair.u64),
307 SSMFIELD_ENTRY( CPUMCTX, Par.u64),
308 SSMFIELD_ENTRY( CPUMCTX, TpIdrRoEl0.u64),
309 SSMFIELD_ENTRY( CPUMCTX, aTpIdr[0].u64),
310 SSMFIELD_ENTRY( CPUMCTX, aTpIdr[1].u64),
311 SSMFIELD_ENTRY( CPUMCTX, MDccInt.u64),
312 SSMFIELD_ENTRY( CPUMCTX, fpcr),
313 SSMFIELD_ENTRY( CPUMCTX, fpsr),
314 SSMFIELD_ENTRY( CPUMCTX, fPState),
315 SSMFIELD_ENTRY( CPUMCTX, fOsLck),
316 SSMFIELD_ENTRY( CPUMCTX, CntvCtlEl0),
317 SSMFIELD_ENTRY( CPUMCTX, CntvCValEl0),
318 /** @name EL2 support:
319 * @{ */
320 SSMFIELD_ENTRY( CPUMCTX, CntHCtlEl2),
321 SSMFIELD_ENTRY( CPUMCTX, CntHpCtlEl2),
322 SSMFIELD_ENTRY( CPUMCTX, CntHpCValEl2),
323 SSMFIELD_ENTRY( CPUMCTX, CntHpTValEl2),
324 SSMFIELD_ENTRY( CPUMCTX, CntVOffEl2),
325 SSMFIELD_ENTRY( CPUMCTX, CptrEl2),
326 SSMFIELD_ENTRY( CPUMCTX, ElrEl2),
327 SSMFIELD_ENTRY( CPUMCTX, EsrEl2),
328 SSMFIELD_ENTRY( CPUMCTX, FarEl2),
329 SSMFIELD_ENTRY( CPUMCTX, HcrEl2),
330 SSMFIELD_ENTRY( CPUMCTX, HpFarEl2),
331 SSMFIELD_ENTRY( CPUMCTX, MairEl2),
332 SSMFIELD_ENTRY( CPUMCTX, MdcrEl2),
333 SSMFIELD_ENTRY( CPUMCTX, SctlrEl2),
334 SSMFIELD_ENTRY( CPUMCTX, SpsrEl2),
335 SSMFIELD_ENTRY( CPUMCTX, SpEl2),
336 SSMFIELD_ENTRY( CPUMCTX, TcrEl2),
337 SSMFIELD_ENTRY( CPUMCTX, TpidrEl2),
338 SSMFIELD_ENTRY( CPUMCTX, Ttbr0El2),
339 SSMFIELD_ENTRY( CPUMCTX, Ttbr1El2),
340 SSMFIELD_ENTRY( CPUMCTX, VBarEl2),
341 SSMFIELD_ENTRY( CPUMCTX, VMpidrEl2),
342 SSMFIELD_ENTRY( CPUMCTX, VPidrEl2),
343 SSMFIELD_ENTRY( CPUMCTX, VTcrEl2),
344 SSMFIELD_ENTRY( CPUMCTX, VTtbrEl2),
345 /** @} */
346
347 SSMFIELD_ENTRY_TERM()
348};
349
350
351/**
352 * Initializes the guest system register states.
353 *
354 * @returns VBox status code.
355 * @param pVM The cross context VM structure.
356 */
357static int cpumR3InitSysRegs(PVM pVM)
358{
359 for (uint32_t i = 0; i < RT_ELEMENTS(g_aSysRegRanges); i++)
360 {
361 int rc = CPUMR3SysRegRangesInsert(pVM, &g_aSysRegRanges[i]);
362 AssertLogRelRCReturn(rc, rc);
363 }
364
365 return VINF_SUCCESS;
366}
367
368
369/**
370 * Initializes the CPUM.
371 *
372 * @returns VBox status code.
373 * @param pVM The cross context VM structure.
374 */
375VMMR3DECL(int) CPUMR3Init(PVM pVM)
376{
377 LogFlow(("CPUMR3Init\n"));
378
379 /*
380 * Assert alignment, sizes and tables.
381 */
382 AssertCompileMemberAlignment(VM, cpum.s, 32);
383 AssertCompile(sizeof(pVM->cpum.s) <= sizeof(pVM->cpum.padding));
384 AssertCompileSizeAlignment(CPUMCTX, 64);
385 AssertCompileMemberAlignment(VM, cpum, 64);
386 AssertCompileMemberAlignment(VMCPU, cpum.s, 64);
387#ifdef VBOX_STRICT
388 int rc2 = cpumR3SysRegStrictInitChecks();
389 AssertRCReturn(rc2, rc2);
390#endif
391
392 pVM->cpum.s.GuestInfo.paSysRegRangesR3 = &pVM->cpum.s.GuestInfo.aSysRegRanges[0];
393 pVM->cpum.s.bResetEl = ARMV8_AARCH64_EL_1;
394
395 PCFGMNODE pCpumCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM");
396
397 /** @cfgm{/CPUM/ResetPcValue, string}
398 * Program counter value after a reset, sets the address of the first instruction to execute. */
399 int rc = CFGMR3QueryU64Def(pCpumCfg, "ResetPcValue", &pVM->cpum.s.u64ResetPc, 0);
400 AssertLogRelRCReturn(rc, rc);
401
402 /** @cfgm{/CPUM/NestedHWVirt, bool, false}
403 * Whether to expose the hardware virtualization (EL2) feature to the guest.
404 * The default is false, and when enabled requires a 64-bit CPU and a NEM backend
405 * supporting it.
406 */
407 bool fNestedHWVirt = false;
408 rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedHWVirt", &fNestedHWVirt, false);
409 AssertLogRelRCReturn(rc, rc);
410 if (fNestedHWVirt)
411 pVM->cpum.s.bResetEl = ARMV8_AARCH64_EL_2;
412
413 /*
414 * Register saved state data item.
415 */
416 rc = SSMR3RegisterInternal(pVM, "cpum", 1, CPUM_SAVED_STATE_VERSION, sizeof(CPUM),
417 NULL, cpumR3LiveExec, NULL,
418 NULL, cpumR3SaveExec, NULL,
419 cpumR3LoadPrep, cpumR3LoadExec, cpumR3LoadDone);
420 if (RT_FAILURE(rc))
421 return rc;
422
423 /*
424 * Register info handlers and registers with the debugger facility.
425 */
426 DBGFR3InfoRegisterInternalEx(pVM, "cpum", "Displays the all the cpu states.",
427 &cpumR3InfoAll, DBGFINFO_FLAGS_ALL_EMTS);
428 DBGFR3InfoRegisterInternalEx(pVM, "cpumguest", "Displays the guest cpu state.",
429 &cpumR3InfoGuest, DBGFINFO_FLAGS_ALL_EMTS);
430 DBGFR3InfoRegisterInternalEx(pVM, "cpumguestinstr", "Displays the current guest instruction.",
431 &cpumR3InfoGuestInstr, DBGFINFO_FLAGS_ALL_EMTS);
432 DBGFR3InfoRegisterInternal( pVM, "cpuid", "Displays the guest cpuid information.",
433 &cpumR3CpuIdInfo);
434 DBGFR3InfoRegisterInternal( pVM, "cpufeat", "Displays the guest features.",
435 &cpumR3CpuFeatInfo);
436
437 rc = cpumR3DbgInit(pVM);
438 if (RT_FAILURE(rc))
439 return rc;
440
441 /*
442 * Initialize the Guest system register states.
443 */
444 rc = cpumR3InitSysRegs(pVM);
445 if (RT_FAILURE(rc))
446 return rc;
447
448 /*
449 * Initialize the general guest CPU state.
450 */
451 CPUMR3Reset(pVM);
452
453 return VINF_SUCCESS;
454}
455
456
457/**
458 * Applies relocations to data and code managed by this
459 * component. This function will be called at init and
460 * whenever the VMM need to relocate it self inside the GC.
461 *
462 * The CPUM will update the addresses used by the switcher.
463 *
464 * @param pVM The cross context VM structure.
465 */
466VMMR3DECL(void) CPUMR3Relocate(PVM pVM)
467{
468 RT_NOREF(pVM);
469}
470
471
472/**
473 * Terminates the CPUM.
474 *
475 * Termination means cleaning up and freeing all resources,
476 * the VM it self is at this point powered off or suspended.
477 *
478 * @returns VBox status code.
479 * @param pVM The cross context VM structure.
480 */
481VMMR3DECL(int) CPUMR3Term(PVM pVM)
482{
483 RT_NOREF(pVM);
484 return VINF_SUCCESS;
485}
486
487
488/**
489 * Resets a virtual CPU.
490 *
491 * Used by CPUMR3Reset and CPU hot plugging.
492 *
493 * @param pVM The cross context VM structure.
494 * @param pVCpu The cross context virtual CPU structure of the CPU that is
495 * being reset. This may differ from the current EMT.
496 */
497VMMR3DECL(void) CPUMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
498{
499 RT_NOREF(pVM);
500
501 /** @todo anything different for VCPU > 0? */
502 PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
503
504 /*
505 * Initialize everything to ZERO first.
506 */
507 RT_BZERO(pCtx, sizeof(*pCtx));
508
509 /* Start in Supervisor mode. */
510 /** @todo Differentiate between Aarch64 and Aarch32 configuation. */
511 pCtx->fPState = ARMV8_SPSR_EL2_AARCH64_SET_EL(pVM->cpum.s.bResetEl)
512 | ARMV8_SPSR_EL2_AARCH64_SP
513 | ARMV8_SPSR_EL2_AARCH64_D
514 | ARMV8_SPSR_EL2_AARCH64_A
515 | ARMV8_SPSR_EL2_AARCH64_I
516 | ARMV8_SPSR_EL2_AARCH64_F;
517
518 pCtx->Pc.u64 = pVM->cpum.s.u64ResetPc;
519 /** @todo */
520}
521
522
523/**
524 * Resets the CPU.
525 *
526 * @param pVM The cross context VM structure.
527 */
528VMMR3DECL(void) CPUMR3Reset(PVM pVM)
529{
530 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
531 {
532 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
533 CPUMR3ResetCpu(pVM, pVCpu);
534 }
535}
536
537
538
539
540/**
541 * Pass 0 live exec callback.
542 *
543 * @returns VINF_SSM_DONT_CALL_AGAIN.
544 * @param pVM The cross context VM structure.
545 * @param pSSM The saved state handle.
546 * @param uPass The pass (0).
547 */
548static DECLCALLBACK(int) cpumR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
549{
550 AssertReturn(uPass == 0, VERR_SSM_UNEXPECTED_PASS);
551 cpumR3SaveCpuId(pVM, pSSM);
552 return VINF_SSM_DONT_CALL_AGAIN;
553}
554
555
556/**
557 * Execute state save operation.
558 *
559 * @returns VBox status code.
560 * @param pVM The cross context VM structure.
561 * @param pSSM SSM operation handle.
562 */
563static DECLCALLBACK(int) cpumR3SaveExec(PVM pVM, PSSMHANDLE pSSM)
564{
565 /*
566 * Save.
567 */
568 SSMR3PutU32(pSSM, pVM->cCpus);
569 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
570 {
571 PVMCPU const pVCpu = pVM->apCpusR3[idCpu];
572 PCPUMCTX const pGstCtx = &pVCpu->cpum.s.Guest;
573
574 SSMR3PutStructEx(pSSM, pGstCtx, sizeof(*pGstCtx), 0, g_aCpumCtxFields, NULL);
575
576 SSMR3PutU32(pSSM, pVCpu->cpum.s.fChanged);
577 }
578
579 cpumR3SaveCpuId(pVM, pSSM);
580 return VINF_SUCCESS;
581}
582
583
584/**
585 * @callback_method_impl{FNSSMINTLOADPREP}
586 */
587static DECLCALLBACK(int) cpumR3LoadPrep(PVM pVM, PSSMHANDLE pSSM)
588{
589 RT_NOREF(pSSM);
590 pVM->cpum.s.fPendingRestore = true;
591 return VINF_SUCCESS;
592}
593
594
595/**
596 * @callback_method_impl{FNSSMINTLOADEXEC}
597 */
598static DECLCALLBACK(int) cpumR3LoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
599{
600 /*
601 * Validate version.
602 */
603 if (uVersion != CPUM_SAVED_STATE_VERSION)
604 {
605 AssertMsgFailed(("cpumR3LoadExec: Invalid version uVersion=%d!\n", uVersion));
606 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
607 }
608
609 if (uPass == SSM_PASS_FINAL)
610 {
611 uint32_t cCpus;
612 int rc = SSMR3GetU32(pSSM, &cCpus); AssertRCReturn(rc, rc);
613 AssertLogRelMsgReturn(cCpus == pVM->cCpus, ("Mismatching CPU counts: saved: %u; configured: %u \n", cCpus, pVM->cCpus),
614 VERR_SSM_UNEXPECTED_DATA);
615
616 /*
617 * Do the per-CPU restoring.
618 */
619 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
620 {
621 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
622 PCPUMCTX pGstCtx = &pVCpu->cpum.s.Guest;
623
624 /*
625 * Restore the CPUMCTX structure.
626 */
627 rc = SSMR3GetStructEx(pSSM, pGstCtx, sizeof(*pGstCtx), 0, g_aCpumCtxFields, NULL);
628 AssertRCReturn(rc, rc);
629
630 /*
631 * Restore a couple of flags.
632 */
633 SSMR3GetU32(pSSM, &pVCpu->cpum.s.fChanged);
634 }
635 }
636
637 pVM->cpum.s.fPendingRestore = false;
638
639 /* Load CPUID and explode guest features. */
640 return cpumR3LoadCpuId(pVM, pSSM, uVersion);
641}
642
643
644/**
645 * @callback_method_impl{FNSSMINTLOADDONE}
646 */
647static DECLCALLBACK(int) cpumR3LoadDone(PVM pVM, PSSMHANDLE pSSM)
648{
649 if (RT_FAILURE(SSMR3HandleGetStatus(pSSM)))
650 return VINF_SUCCESS;
651
652 /* just check this since we can. */ /** @todo Add a SSM unit flag for indicating that it's mandatory during a restore. */
653 if (pVM->cpum.s.fPendingRestore)
654 {
655 LogRel(("CPUM: Missing state!\n"));
656 return VERR_INTERNAL_ERROR_2;
657 }
658
659 /** @todo */
660 return VINF_SUCCESS;
661}
662
663
664/**
665 * Checks if the CPUM state restore is still pending.
666 *
667 * @returns true / false.
668 * @param pVM The cross context VM structure.
669 */
670VMMDECL(bool) CPUMR3IsStateRestorePending(PVM pVM)
671{
672 return pVM->cpum.s.fPendingRestore;
673}
674
675
676/**
677 * Formats the PSTATE value into mnemonics.
678 *
679 * @param pszPState Where to write the mnemonics. (Assumes sufficient buffer space.)
680 * @param fPState The PSTATE value with both guest hardware and VBox
681 * internal bits included.
682 */
683static void cpumR3InfoFormatPState(char *pszPState, uint32_t fPState)
684{
685 /*
686 * Format the flags.
687 */
688 static const struct
689 {
690 const char *pszSet; const char *pszClear; uint32_t fFlag;
691 } s_aFlags[] =
692 {
693 { "SP", "nSP", ARMV8_SPSR_EL2_AARCH64_SP },
694 { "M4", "nM4", ARMV8_SPSR_EL2_AARCH64_M4 },
695 { "T", "nT", ARMV8_SPSR_EL2_AARCH64_T },
696 { "nF", "F", ARMV8_SPSR_EL2_AARCH64_F },
697 { "nI", "I", ARMV8_SPSR_EL2_AARCH64_I },
698 { "nA", "A", ARMV8_SPSR_EL2_AARCH64_A },
699 { "nD", "D", ARMV8_SPSR_EL2_AARCH64_D },
700 { "V", "nV", ARMV8_SPSR_EL2_AARCH64_V },
701 { "C", "nC", ARMV8_SPSR_EL2_AARCH64_C },
702 { "Z", "nZ", ARMV8_SPSR_EL2_AARCH64_Z },
703 { "N", "nN", ARMV8_SPSR_EL2_AARCH64_N },
704 };
705 char *psz = pszPState;
706 for (unsigned i = 0; i < RT_ELEMENTS(s_aFlags); i++)
707 {
708 const char *pszAdd = s_aFlags[i].fFlag & fPState ? s_aFlags[i].pszSet : s_aFlags[i].pszClear;
709 if (pszAdd)
710 {
711 strcpy(psz, pszAdd);
712 psz += strlen(pszAdd);
713 *psz++ = ' ';
714 }
715 }
716 psz[-1] = '\0';
717}
718
719
720/**
721 * Formats a full register dump.
722 *
723 * @param pVM The cross context VM structure.
724 * @param pCtx The context to format.
725 * @param pHlp Output functions.
726 * @param enmType The dump type.
727 */
728static void cpumR3InfoOne(PVM pVM, PCPUMCTX pCtx, PCDBGFINFOHLP pHlp, CPUMDUMPTYPE enmType)
729{
730 RT_NOREF(pVM);
731
732 /*
733 * Format the PSTATE.
734 */
735 char szPState[80];
736 cpumR3InfoFormatPState(&szPState[0], pCtx->fPState);
737
738 /*
739 * Format the registers.
740 */
741 switch (enmType)
742 {
743 case CPUMDUMPTYPE_TERSE:
744 if (CPUMIsGuestIn64BitCodeEx(pCtx))
745 pHlp->pfnPrintf(pHlp,
746 "x0=%016RX64 x1=%016RX64 x2=%016RX64 x3=%016RX64\n"
747 "x4=%016RX64 x5=%016RX64 x6=%016RX64 x7=%016RX64\n"
748 "x8=%016RX64 x9=%016RX64 x10=%016RX64 x11=%016RX64\n"
749 "x12=%016RX64 x13=%016RX64 x14=%016RX64 x15=%016RX64\n"
750 "x16=%016RX64 x17=%016RX64 x18=%016RX64 x19=%016RX64\n"
751 "x20=%016RX64 x21=%016RX64 x22=%016RX64 x23=%016RX64\n"
752 "x24=%016RX64 x25=%016RX64 x26=%016RX64 x27=%016RX64\n"
753 "x28=%016RX64 x29=%016RX64 x30=%016RX64\n"
754 "pc=%016RX64 pstate=%016RX64 %s\n"
755 "sp_el0=%016RX64 sp_el1=%016RX64\n",
756 pCtx->aGRegs[0], pCtx->aGRegs[1], pCtx->aGRegs[2], pCtx->aGRegs[3],
757 pCtx->aGRegs[4], pCtx->aGRegs[5], pCtx->aGRegs[6], pCtx->aGRegs[7],
758 pCtx->aGRegs[8], pCtx->aGRegs[9], pCtx->aGRegs[10], pCtx->aGRegs[11],
759 pCtx->aGRegs[12], pCtx->aGRegs[13], pCtx->aGRegs[14], pCtx->aGRegs[15],
760 pCtx->aGRegs[16], pCtx->aGRegs[17], pCtx->aGRegs[18], pCtx->aGRegs[19],
761 pCtx->aGRegs[20], pCtx->aGRegs[21], pCtx->aGRegs[22], pCtx->aGRegs[23],
762 pCtx->aGRegs[24], pCtx->aGRegs[25], pCtx->aGRegs[26], pCtx->aGRegs[27],
763 pCtx->aGRegs[28], pCtx->aGRegs[29], pCtx->aGRegs[30],
764 pCtx->Pc.u64, pCtx->fPState, szPState,
765 pCtx->aSpReg[0].u64, pCtx->aSpReg[1].u64);
766 else
767 AssertFailed();
768 break;
769
770 case CPUMDUMPTYPE_DEFAULT:
771 if (CPUMIsGuestIn64BitCodeEx(pCtx))
772 pHlp->pfnPrintf(pHlp,
773 "x0=%016RX64 x1=%016RX64 x2=%016RX64 x3=%016RX64\n"
774 "x4=%016RX64 x5=%016RX64 x6=%016RX64 x7=%016RX64\n"
775 "x8=%016RX64 x9=%016RX64 x10=%016RX64 x11=%016RX64\n"
776 "x12=%016RX64 x13=%016RX64 x14=%016RX64 x15=%016RX64\n"
777 "x16=%016RX64 x17=%016RX64 x18=%016RX64 x19=%016RX64\n"
778 "x20=%016RX64 x21=%016RX64 x22=%016RX64 x23=%016RX64\n"
779 "x24=%016RX64 x25=%016RX64 x26=%016RX64 x27=%016RX64\n"
780 "x28=%016RX64 x29=%016RX64 x30=%016RX64\n"
781 "pc=%016RX64 pstate=%016RX64 %s\n"
782 "sp_el0=%016RX64 sp_el1=%016RX64 sctlr_el1=%016RX64\n"
783 "tcr_el1=%016RX64 ttbr0_el1=%016RX64 ttbr1_el1=%016RX64\n"
784 "vbar_el1=%016RX64 elr_el1=%016RX64 esr_el1=%016RX64\n",
785 pCtx->aGRegs[0], pCtx->aGRegs[1], pCtx->aGRegs[2], pCtx->aGRegs[3],
786 pCtx->aGRegs[4], pCtx->aGRegs[5], pCtx->aGRegs[6], pCtx->aGRegs[7],
787 pCtx->aGRegs[8], pCtx->aGRegs[9], pCtx->aGRegs[10], pCtx->aGRegs[11],
788 pCtx->aGRegs[12], pCtx->aGRegs[13], pCtx->aGRegs[14], pCtx->aGRegs[15],
789 pCtx->aGRegs[16], pCtx->aGRegs[17], pCtx->aGRegs[18], pCtx->aGRegs[19],
790 pCtx->aGRegs[20], pCtx->aGRegs[21], pCtx->aGRegs[22], pCtx->aGRegs[23],
791 pCtx->aGRegs[24], pCtx->aGRegs[25], pCtx->aGRegs[26], pCtx->aGRegs[27],
792 pCtx->aGRegs[28], pCtx->aGRegs[29], pCtx->aGRegs[30],
793 pCtx->Pc.u64, pCtx->fPState, szPState,
794 pCtx->aSpReg[0].u64, pCtx->aSpReg[1].u64, pCtx->Sctlr.u64,
795 pCtx->Tcr.u64, pCtx->Ttbr0.u64, pCtx->Ttbr1.u64,
796 pCtx->VBar.u64, pCtx->Elr.u64, pCtx->Esr.u64);
797 else
798 AssertFailed();
799 break;
800
801 case CPUMDUMPTYPE_VERBOSE:
802 if (CPUMIsGuestIn64BitCodeEx(pCtx))
803 pHlp->pfnPrintf(pHlp,
804 "x0=%016RX64 x1=%016RX64 x2=%016RX64 x3=%016RX64\n"
805 "x4=%016RX64 x5=%016RX64 x6=%016RX64 x7=%016RX64\n"
806 "x8=%016RX64 x9=%016RX64 x10=%016RX64 x11=%016RX64\n"
807 "x12=%016RX64 x13=%016RX64 x14=%016RX64 x15=%016RX64\n"
808 "x16=%016RX64 x17=%016RX64 x18=%016RX64 x19=%016RX64\n"
809 "x20=%016RX64 x21=%016RX64 x22=%016RX64 x23=%016RX64\n"
810 "x24=%016RX64 x25=%016RX64 x26=%016RX64 x27=%016RX64\n"
811 "x28=%016RX64 x29=%016RX64 x30=%016RX64\n"
812 "pc=%016RX64 pstate=%016RX64 %s\n"
813 "sp_el0=%016RX64 sp_el1=%016RX64 sctlr_el1=%016RX64\n"
814 "tcr_el1=%016RX64 ttbr0_el1=%016RX64 ttbr1_el1=%016RX64\n"
815 "vbar_el1=%016RX64 elr_el1=%016RX64 esr_el1=%016RX64\n"
816 "contextidr_el1=%016RX64 tpidrr0_el0=%016RX64\n"
817 "tpidr_el0=%016RX64 tpidr_el1=%016RX64\n"
818 "far_el1=%016RX64 mair_el1=%016RX64 par_el1=%016RX64\n"
819 "cntv_ctl_el0=%016RX64 cntv_val_el0=%016RX64\n"
820 "afsr0_el1=%016RX64 afsr0_el1=%016RX64 amair_el1=%016RX64\n"
821 "cntkctl_el1=%016RX64 cpacr_el1=%016RX64 csselr_el1=%016RX64\n"
822 "mdccint_el1=%016RX64\n",
823 pCtx->aGRegs[0], pCtx->aGRegs[1], pCtx->aGRegs[2], pCtx->aGRegs[3],
824 pCtx->aGRegs[4], pCtx->aGRegs[5], pCtx->aGRegs[6], pCtx->aGRegs[7],
825 pCtx->aGRegs[8], pCtx->aGRegs[9], pCtx->aGRegs[10], pCtx->aGRegs[11],
826 pCtx->aGRegs[12], pCtx->aGRegs[13], pCtx->aGRegs[14], pCtx->aGRegs[15],
827 pCtx->aGRegs[16], pCtx->aGRegs[17], pCtx->aGRegs[18], pCtx->aGRegs[19],
828 pCtx->aGRegs[20], pCtx->aGRegs[21], pCtx->aGRegs[22], pCtx->aGRegs[23],
829 pCtx->aGRegs[24], pCtx->aGRegs[25], pCtx->aGRegs[26], pCtx->aGRegs[27],
830 pCtx->aGRegs[28], pCtx->aGRegs[29], pCtx->aGRegs[30],
831 pCtx->Pc.u64, pCtx->fPState, szPState,
832 pCtx->aSpReg[0].u64, pCtx->aSpReg[1].u64, pCtx->Sctlr.u64,
833 pCtx->Tcr.u64, pCtx->Ttbr0.u64, pCtx->Ttbr1.u64,
834 pCtx->VBar.u64, pCtx->Elr.u64, pCtx->Esr.u64,
835 pCtx->ContextIdr.u64, pCtx->TpIdrRoEl0.u64,
836 pCtx->aTpIdr[0].u64, pCtx->aTpIdr[1].u64,
837 pCtx->Far.u64, pCtx->Mair.u64, pCtx->Par.u64,
838 pCtx->CntvCtlEl0, pCtx->CntvCValEl0,
839 pCtx->Afsr0.u64, pCtx->Afsr1.u64, pCtx->Amair.u64,
840 pCtx->CntKCtl.u64, pCtx->Cpacr.u64, pCtx->Csselr.u64,
841 pCtx->MDccInt.u64);
842 else
843 AssertFailed();
844
845 pHlp->pfnPrintf(pHlp, "fpcr=%016RX64 fpsr=%016RX64\n", pCtx->fpcr, pCtx->fpsr);
846 for (unsigned i = 0; i < RT_ELEMENTS(pCtx->aVRegs); i++)
847 pHlp->pfnPrintf(pHlp,
848 i & 1
849 ? "q%u%s=%08RX32'%08RX32'%08RX32'%08RX32\n"
850 : "q%u%s=%08RX32'%08RX32'%08RX32'%08RX32 ",
851 i, i < 10 ? " " : "",
852 pCtx->aVRegs[i].au32[3],
853 pCtx->aVRegs[i].au32[2],
854 pCtx->aVRegs[i].au32[1],
855 pCtx->aVRegs[i].au32[0]);
856
857 pHlp->pfnPrintf(pHlp, "mdscr_el1=%016RX64\n", pCtx->Mdscr.u64);
858 for (unsigned i = 0; i < RT_ELEMENTS(pCtx->aBp); i++)
859 pHlp->pfnPrintf(pHlp, "DbgBp%u%s: Control=%016RX64 Value=%016RX64\n",
860 i, i < 10 ? " " : "",
861 pCtx->aBp[i].Ctrl, pCtx->aBp[i].Value);
862
863 for (unsigned i = 0; i < RT_ELEMENTS(pCtx->aWp); i++)
864 pHlp->pfnPrintf(pHlp, "DbgWp%u%s: Control=%016RX64 Value=%016RX64\n",
865 i, i < 10 ? " " : "",
866 pCtx->aWp[i].Ctrl, pCtx->aWp[i].Value);
867
868 pHlp->pfnPrintf(pHlp, "APDAKey=%016RX64'%016RX64\n", pCtx->Apda.High.u64, pCtx->Apda.Low.u64);
869 pHlp->pfnPrintf(pHlp, "APDBKey=%016RX64'%016RX64\n", pCtx->Apdb.High.u64, pCtx->Apdb.Low.u64);
870 pHlp->pfnPrintf(pHlp, "APGAKey=%016RX64'%016RX64\n", pCtx->Apga.High.u64, pCtx->Apga.Low.u64);
871 pHlp->pfnPrintf(pHlp, "APIAKey=%016RX64'%016RX64\n", pCtx->Apia.High.u64, pCtx->Apia.Low.u64);
872 pHlp->pfnPrintf(pHlp, "APIBKey=%016RX64'%016RX64\n", pCtx->Apib.High.u64, pCtx->Apib.Low.u64);
873
874 break;
875 }
876}
877
878
879/**
880 * Display all cpu states and any other cpum info.
881 *
882 * @param pVM The cross context VM structure.
883 * @param pHlp The info helper functions.
884 * @param pszArgs Arguments, ignored.
885 */
886static DECLCALLBACK(void) cpumR3InfoAll(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
887{
888 cpumR3InfoGuest(pVM, pHlp, pszArgs);
889 cpumR3InfoGuestInstr(pVM, pHlp, pszArgs);
890}
891
892
893/**
894 * Parses the info argument.
895 *
896 * The argument starts with 'verbose', 'terse' or 'default' and then
897 * continues with the comment string.
898 *
899 * @param pszArgs The pointer to the argument string.
900 * @param penmType Where to store the dump type request.
901 * @param ppszComment Where to store the pointer to the comment string.
902 */
903static void cpumR3InfoParseArg(const char *pszArgs, CPUMDUMPTYPE *penmType, const char **ppszComment)
904{
905 if (!pszArgs)
906 {
907 *penmType = CPUMDUMPTYPE_DEFAULT;
908 *ppszComment = "";
909 }
910 else
911 {
912 if (!strncmp(pszArgs, RT_STR_TUPLE("verbose")))
913 {
914 pszArgs += 7;
915 *penmType = CPUMDUMPTYPE_VERBOSE;
916 }
917 else if (!strncmp(pszArgs, RT_STR_TUPLE("terse")))
918 {
919 pszArgs += 5;
920 *penmType = CPUMDUMPTYPE_TERSE;
921 }
922 else if (!strncmp(pszArgs, RT_STR_TUPLE("default")))
923 {
924 pszArgs += 7;
925 *penmType = CPUMDUMPTYPE_DEFAULT;
926 }
927 else
928 *penmType = CPUMDUMPTYPE_DEFAULT;
929 *ppszComment = RTStrStripL(pszArgs);
930 }
931}
932
933
934/**
935 * Display the guest cpu state.
936 *
937 * @param pVM The cross context VM structure.
938 * @param pHlp The info helper functions.
939 * @param pszArgs Arguments.
940 */
941static DECLCALLBACK(void) cpumR3InfoGuest(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
942{
943 CPUMDUMPTYPE enmType;
944 const char *pszComment;
945 cpumR3InfoParseArg(pszArgs, &enmType, &pszComment);
946
947 PVMCPU pVCpu = VMMGetCpu(pVM);
948 if (!pVCpu)
949 pVCpu = pVM->apCpusR3[0];
950
951 pHlp->pfnPrintf(pHlp, "Guest CPUM (VCPU %d) state: %s\n", pVCpu->idCpu, pszComment);
952
953 PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
954 cpumR3InfoOne(pVM, pCtx, pHlp, enmType);
955}
956
957
958/**
959 * Display the current guest instruction
960 *
961 * @param pVM The cross context VM structure.
962 * @param pHlp The info helper functions.
963 * @param pszArgs Arguments, ignored.
964 */
965static DECLCALLBACK(void) cpumR3InfoGuestInstr(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
966{
967 NOREF(pszArgs);
968
969 PVMCPU pVCpu = VMMGetCpu(pVM);
970 if (!pVCpu)
971 pVCpu = pVM->apCpusR3[0];
972
973 char szInstruction[256];
974 szInstruction[0] = '\0';
975 DBGFR3DisasInstrCurrent(pVCpu, szInstruction, sizeof(szInstruction));
976 pHlp->pfnPrintf(pHlp, "\nCPUM%u: %s\n\n", pVCpu->idCpu, szInstruction);
977}
978
979
980/**
981 * Called when the ring-3 init phase completes.
982 *
983 * @returns VBox status code.
984 * @param pVM The cross context VM structure.
985 * @param enmWhat Which init phase.
986 */
987VMMR3DECL(int) CPUMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
988{
989 RT_NOREF(pVM, enmWhat);
990 return VINF_SUCCESS;
991}
992
993
994/**
995 * Called when the ring-0 init phases completed.
996 *
997 * @param pVM The cross context VM structure.
998 */
999VMMR3DECL(void) CPUMR3LogCpuIdAndMsrFeatures(PVM pVM)
1000{
1001 /*
1002 * Enable log buffering as we're going to log a lot of lines.
1003 */
1004 bool const fOldBuffered = RTLogRelSetBuffering(true /*fBuffered*/);
1005
1006 /*
1007 * Log the cpuid.
1008 */
1009 RTCPUSET OnlineSet;
1010 LogRel(("CPUM: Logical host processors: %u present, %u max, %u online, online mask: %016RX64\n",
1011 (unsigned)RTMpGetPresentCount(), (unsigned)RTMpGetCount(), (unsigned)RTMpGetOnlineCount(),
1012 RTCpuSetToU64(RTMpGetOnlineSet(&OnlineSet)) ));
1013 RTCPUID cCores = RTMpGetCoreCount();
1014 if (cCores)
1015 LogRel(("CPUM: Physical host cores: %u\n", (unsigned)cCores));
1016 LogRel(("************************* CPUID dump ************************\n"));
1017 DBGFR3Info(pVM->pUVM, "cpuid", "verbose", DBGFR3InfoLogRelHlp());
1018 LogRel(("\n"));
1019 DBGFR3_INFO_LOG_SAFE(pVM, "cpuid", "verbose"); /* macro */
1020 LogRel(("******************** End of CPUID dump **********************\n"));
1021
1022 LogRel(("******************** CPU feature dump ***********************\n"));
1023 DBGFR3Info(pVM->pUVM, "cpufeat", "verbose", DBGFR3InfoLogRelHlp());
1024 LogRel(("\n"));
1025 DBGFR3_INFO_LOG_SAFE(pVM, "cpufeat", "verbose"); /* macro */
1026 LogRel(("***************** End of CPU feature dump *******************\n"));
1027
1028 /*
1029 * Restore the log buffering state to what it was previously.
1030 */
1031 RTLogRelSetBuffering(fOldBuffered);
1032}
1033
1034
1035/**
1036 * Marks the guest debug state as active.
1037 *
1038 * @param pVCpu The cross context virtual CPU structure.
1039 *
1040 * @note This is used solely by NEM (hence the name) to set the correct flags here
1041 * without loading the host's DRx registers, which is not possible from ring-3 anyway.
1042 * The specific NEM backends have to make sure to load the correct values.
1043 */
1044VMMR3_INT_DECL(void) CPUMR3NemActivateGuestDebugState(PVMCPUCC pVCpu)
1045{
1046 ASMAtomicAndU32(&pVCpu->cpum.s.fUseFlags, ~CPUM_USED_DEBUG_REGS_HYPER);
1047 ASMAtomicOrU32(&pVCpu->cpum.s.fUseFlags, CPUM_USED_DEBUG_REGS_GUEST);
1048}
1049
1050
1051/**
1052 * Marks the hyper debug state as active.
1053 *
1054 * @param pVCpu The cross context virtual CPU structure.
1055 *
1056 * @note This is used solely by NEM (hence the name) to set the correct flags here
1057 * without loading the host's debug registers, which is not possible from ring-3 anyway.
1058 * The specific NEM backends have to make sure to load the correct values.
1059 */
1060VMMR3_INT_DECL(void) CPUMR3NemActivateHyperDebugState(PVMCPUCC pVCpu)
1061{
1062 ASMAtomicAndU32(&pVCpu->cpum.s.fUseFlags, ~CPUM_USED_DEBUG_REGS_GUEST);
1063 ASMAtomicOrU32(&pVCpu->cpum.s.fUseFlags, CPUM_USED_DEBUG_REGS_HYPER);
1064}
Note: See TracBrowser for help on using the repository browser.

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