VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/IEMR3.cpp@ 105713

最後變更 在這個檔案從105713是 105713,由 vboxsync 提交於 7 月 前

VMM/IEM: Statistics fixes. bugref:10656

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 127.2 KB
 
1/* $Id: IEMR3.cpp 105713 2024-08-16 21:09:48Z vboxsync $ */
2/** @file
3 * IEM - Interpreted Execution Manager.
4 */
5
6/*
7 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_EM
33#define VMCPU_INCL_CPUM_GST_CTX
34#include <VBox/vmm/iem.h>
35#include <VBox/vmm/cpum.h>
36#include <VBox/vmm/dbgf.h>
37#include <VBox/vmm/mm.h>
38#include <VBox/vmm/ssm.h>
39#if defined(VBOX_VMM_TARGET_ARMV8)
40# include "IEMInternal-armv8.h"
41#else
42# include "IEMInternal.h"
43#endif
44#include <VBox/vmm/vm.h>
45#include <VBox/vmm/vmapi.h>
46#include <VBox/err.h>
47#ifdef VBOX_WITH_DEBUGGER
48# include <VBox/dbg.h>
49#endif
50
51#include <iprt/assert.h>
52#include <iprt/getopt.h>
53#ifdef IEM_WITH_TLB_TRACE
54# include <iprt/mem.h>
55#endif
56#include <iprt/string.h>
57
58#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
59# include "IEMN8veRecompiler.h"
60# include "IEMThreadedFunctions.h"
61# include "IEMInline.h"
62#endif
63
64
65/*********************************************************************************************************************************
66* Internal Functions *
67*********************************************************************************************************************************/
68static FNDBGFINFOARGVINT iemR3InfoITlb;
69static FNDBGFINFOARGVINT iemR3InfoDTlb;
70#ifdef IEM_WITH_TLB_TRACE
71static FNDBGFINFOARGVINT iemR3InfoTlbTrace;
72#endif
73#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
74static FNDBGFINFOARGVINT iemR3InfoTb;
75#endif
76#ifdef VBOX_WITH_DEBUGGER
77static void iemR3RegisterDebuggerCommands(void);
78#endif
79
80
81#if !defined(VBOX_VMM_TARGET_ARMV8)
82static const char *iemGetTargetCpuName(uint32_t enmTargetCpu)
83{
84 switch (enmTargetCpu)
85 {
86#define CASE_RET_STR(enmValue) case enmValue: return #enmValue + (sizeof("IEMTARGETCPU_") - 1)
87 CASE_RET_STR(IEMTARGETCPU_8086);
88 CASE_RET_STR(IEMTARGETCPU_V20);
89 CASE_RET_STR(IEMTARGETCPU_186);
90 CASE_RET_STR(IEMTARGETCPU_286);
91 CASE_RET_STR(IEMTARGETCPU_386);
92 CASE_RET_STR(IEMTARGETCPU_486);
93 CASE_RET_STR(IEMTARGETCPU_PENTIUM);
94 CASE_RET_STR(IEMTARGETCPU_PPRO);
95 CASE_RET_STR(IEMTARGETCPU_CURRENT);
96#undef CASE_RET_STR
97 default: return "Unknown";
98 }
99}
100#endif
101
102
103/**
104 * Initializes the interpreted execution manager.
105 *
106 * This must be called after CPUM as we're quering information from CPUM about
107 * the guest and host CPUs.
108 *
109 * @returns VBox status code.
110 * @param pVM The cross context VM structure.
111 */
112VMMR3DECL(int) IEMR3Init(PVM pVM)
113{
114 /*
115 * Read configuration.
116 */
117#if (!defined(VBOX_VMM_TARGET_ARMV8) && !defined(VBOX_WITHOUT_CPUID_HOST_CALL)) || defined(VBOX_WITH_IEM_RECOMPILER)
118 PCFGMNODE const pIem = CFGMR3GetChild(CFGMR3GetRoot(pVM), "IEM");
119 int rc;
120#endif
121
122#if !defined(VBOX_VMM_TARGET_ARMV8) && !defined(VBOX_WITHOUT_CPUID_HOST_CALL)
123 /** @cfgm{/IEM/CpuIdHostCall, boolean, false}
124 * Controls whether the custom VBox specific CPUID host call interface is
125 * enabled or not. */
126# ifdef DEBUG_bird
127 rc = CFGMR3QueryBoolDef(pIem, "CpuIdHostCall", &pVM->iem.s.fCpuIdHostCall, true);
128# else
129 rc = CFGMR3QueryBoolDef(pIem, "CpuIdHostCall", &pVM->iem.s.fCpuIdHostCall, false);
130# endif
131 AssertLogRelRCReturn(rc, rc);
132#endif
133
134#ifdef VBOX_WITH_IEM_RECOMPILER
135 /** @cfgm{/IEM/MaxTbCount, uint32_t, 524288}
136 * Max number of TBs per EMT. */
137 uint32_t cMaxTbs = 0;
138 rc = CFGMR3QueryU32Def(pIem, "MaxTbCount", &cMaxTbs, _512K);
139 AssertLogRelRCReturn(rc, rc);
140 if (cMaxTbs < _16K || cMaxTbs > _8M)
141 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
142 "MaxTbCount value %u (%#x) is out of range (min %u, max %u)", cMaxTbs, cMaxTbs, _16K, _8M);
143
144 /** @cfgm{/IEM/InitialTbCount, uint32_t, 32678}
145 * Initial (minimum) number of TBs per EMT in ring-3. */
146 uint32_t cInitialTbs = 0;
147 rc = CFGMR3QueryU32Def(pIem, "InitialTbCount", &cInitialTbs, RT_MIN(cMaxTbs, _32K));
148 AssertLogRelRCReturn(rc, rc);
149 if (cInitialTbs < _16K || cInitialTbs > _8M)
150 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
151 "InitialTbCount value %u (%#x) is out of range (min %u, max %u)", cInitialTbs, cInitialTbs, _16K, _8M);
152
153 /* Check that the two values makes sense together. Expect user/api to do
154 the right thing or get lost. */
155 if (cInitialTbs > cMaxTbs)
156 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
157 "InitialTbCount value %u (%#x) is higher than the MaxTbCount value %u (%#x)",
158 cInitialTbs, cInitialTbs, cMaxTbs, cMaxTbs);
159
160 /** @cfgm{/IEM/MaxExecMem, uint64_t, 512 MiB}
161 * Max executable memory for recompiled code per EMT. */
162 uint64_t cbMaxExec = 0;
163 rc = CFGMR3QueryU64Def(pIem, "MaxExecMem", &cbMaxExec, _512M);
164 AssertLogRelRCReturn(rc, rc);
165 if (cbMaxExec < _1M || cbMaxExec > 16*_1G64)
166 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
167 "MaxExecMem value %'RU64 (%#RX64) is out of range (min %'RU64, max %'RU64)",
168 cbMaxExec, cbMaxExec, (uint64_t)_1M, 16*_1G64);
169
170 /** @cfgm{/IEM/ExecChunkSize, uint32_t, 0 (auto)}
171 * The executable memory allocator chunk size. */
172 uint32_t cbChunkExec = 0;
173 rc = CFGMR3QueryU32Def(pIem, "ExecChunkSize", &cbChunkExec, 0);
174 AssertLogRelRCReturn(rc, rc);
175 if (cbChunkExec != 0 && cbChunkExec != UINT32_MAX && (cbChunkExec < _1M || cbChunkExec > _256M))
176 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
177 "ExecChunkSize value %'RU32 (%#RX32) is out of range (min %'RU32, max %'RU32)",
178 cbChunkExec, cbChunkExec, _1M, _256M);
179
180 /** @cfgm{/IEM/InitialExecMemSize, uint64_t, 1}
181 * The initial executable memory allocator size (per EMT). The value is
182 * rounded up to the nearest chunk size, so 1 byte means one chunk. */
183 uint64_t cbInitialExec = 0;
184 rc = CFGMR3QueryU64Def(pIem, "InitialExecMemSize", &cbInitialExec, 0);
185 AssertLogRelRCReturn(rc, rc);
186 if (cbInitialExec > cbMaxExec)
187 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
188 "InitialExecMemSize value %'RU64 (%#RX64) is out of range (max %'RU64)",
189 cbInitialExec, cbInitialExec, cbMaxExec);
190
191 /** @cfgm{/IEM/NativeRecompileAtUsedCount, uint32_t, 16}
192 * The translation block use count value to do native recompilation at.
193 * Set to zero to disable native recompilation. */
194 uint32_t uTbNativeRecompileAtUsedCount = 16;
195 rc = CFGMR3QueryU32Def(pIem, "NativeRecompileAtUsedCount", &uTbNativeRecompileAtUsedCount, 16);
196 AssertLogRelRCReturn(rc, rc);
197
198#endif /* VBOX_WITH_IEM_RECOMPILER*/
199
200 /*
201 * Initialize per-CPU data and register statistics.
202 */
203#if 1
204 uint64_t const uInitialTlbRevision = UINT64_C(0) - (IEMTLB_REVISION_INCR * 200U);
205 uint64_t const uInitialTlbPhysRev = UINT64_C(0) - (IEMTLB_PHYS_REV_INCR * 100U);
206#else
207 uint64_t const uInitialTlbRevision = UINT64_C(0) + (IEMTLB_REVISION_INCR * 4U);
208 uint64_t const uInitialTlbPhysRev = UINT64_C(0) + (IEMTLB_PHYS_REV_INCR * 4U);
209#endif
210
211 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
212 {
213 PVMCPU const pVCpu = pVM->apCpusR3[idCpu];
214 AssertCompile(sizeof(pVCpu->iem.s) <= sizeof(pVCpu->iem.padding)); /* (tstVMStruct can't do it's job w/o instruction stats) */
215
216 pVCpu->iem.s.CodeTlb.uTlbRevision = pVCpu->iem.s.DataTlb.uTlbRevision = uInitialTlbRevision;
217#ifndef VBOX_VMM_TARGET_ARMV8
218 pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal = pVCpu->iem.s.DataTlb.uTlbRevisionGlobal = uInitialTlbRevision;
219#endif
220 pVCpu->iem.s.CodeTlb.uTlbPhysRev = pVCpu->iem.s.DataTlb.uTlbPhysRev = uInitialTlbPhysRev;
221#ifndef VBOX_VMM_TARGET_ARMV8
222 pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
223 pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uFirstTag = UINT64_MAX;
224 pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
225 pVCpu->iem.s.DataTlb.GlobalLargePageRange.uFirstTag = UINT64_MAX;
226#endif
227
228#ifndef VBOX_VMM_TARGET_ARMV8
229 pVCpu->iem.s.cTbsTillNextTimerPoll = 128;
230 pVCpu->iem.s.cTbsTillNextTimerPollPrev = 128;
231#endif
232
233 /*
234 * Host and guest CPU information.
235 */
236 if (idCpu == 0)
237 {
238 pVCpu->iem.s.enmCpuVendor = CPUMGetGuestCpuVendor(pVM);
239 pVCpu->iem.s.enmHostCpuVendor = CPUMGetHostCpuVendor(pVM);
240#if !defined(VBOX_VMM_TARGET_ARMV8)
241 pVCpu->iem.s.aidxTargetCpuEflFlavour[0] = pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL
242 || pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_VIA /*??*/
243 ? IEMTARGETCPU_EFL_BEHAVIOR_INTEL : IEMTARGETCPU_EFL_BEHAVIOR_AMD;
244# if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
245 if (pVCpu->iem.s.enmCpuVendor == pVCpu->iem.s.enmHostCpuVendor)
246 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = IEMTARGETCPU_EFL_BEHAVIOR_NATIVE;
247 else
248# endif
249 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = pVCpu->iem.s.aidxTargetCpuEflFlavour[0];
250#else
251 pVCpu->iem.s.aidxTargetCpuEflFlavour[0] = IEMTARGETCPU_EFL_BEHAVIOR_NATIVE;
252 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = pVCpu->iem.s.aidxTargetCpuEflFlavour[0];
253#endif
254
255#if !defined(VBOX_VMM_TARGET_ARMV8) && (IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC)
256 switch (pVM->cpum.ro.GuestFeatures.enmMicroarch)
257 {
258 case kCpumMicroarch_Intel_8086: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_8086; break;
259 case kCpumMicroarch_Intel_80186: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_186; break;
260 case kCpumMicroarch_Intel_80286: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_286; break;
261 case kCpumMicroarch_Intel_80386: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_386; break;
262 case kCpumMicroarch_Intel_80486: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_486; break;
263 case kCpumMicroarch_Intel_P5: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PENTIUM; break;
264 case kCpumMicroarch_Intel_P6: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PPRO; break;
265 case kCpumMicroarch_NEC_V20: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
266 case kCpumMicroarch_NEC_V30: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
267 default: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT; break;
268 }
269 LogRel(("IEM: TargetCpu=%s, Microarch=%s aidxTargetCpuEflFlavour={%d,%d}\n",
270 iemGetTargetCpuName(pVCpu->iem.s.uTargetCpu), CPUMMicroarchName(pVM->cpum.ro.GuestFeatures.enmMicroarch),
271 pVCpu->iem.s.aidxTargetCpuEflFlavour[0], pVCpu->iem.s.aidxTargetCpuEflFlavour[1]));
272#else
273 LogRel(("IEM: Microarch=%s aidxTargetCpuEflFlavour={%d,%d}\n",
274 CPUMMicroarchName(pVM->cpum.ro.GuestFeatures.enmMicroarch),
275 pVCpu->iem.s.aidxTargetCpuEflFlavour[0], pVCpu->iem.s.aidxTargetCpuEflFlavour[1]));
276#endif
277 }
278 else
279 {
280 pVCpu->iem.s.enmCpuVendor = pVM->apCpusR3[0]->iem.s.enmCpuVendor;
281 pVCpu->iem.s.enmHostCpuVendor = pVM->apCpusR3[0]->iem.s.enmHostCpuVendor;
282 pVCpu->iem.s.aidxTargetCpuEflFlavour[0] = pVM->apCpusR3[0]->iem.s.aidxTargetCpuEflFlavour[0];
283 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = pVM->apCpusR3[0]->iem.s.aidxTargetCpuEflFlavour[1];
284#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
285 pVCpu->iem.s.uTargetCpu = pVM->apCpusR3[0]->iem.s.uTargetCpu;
286#endif
287 }
288
289 /*
290 * Mark all buffers free.
291 */
292 uint32_t iMemMap = RT_ELEMENTS(pVCpu->iem.s.aMemMappings);
293 while (iMemMap-- > 0)
294 pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
295
296#ifdef VBOX_WITH_IEM_RECOMPILER
297 /*
298 * Recompiler state and configuration distribution.
299 */
300 pVCpu->iem.s.uRegFpCtrl = IEMNATIVE_SIMD_FP_CTRL_REG_NOT_MODIFIED;
301 pVCpu->iem.s.uTbNativeRecompileAtUsedCount = uTbNativeRecompileAtUsedCount;
302#endif
303
304#ifdef IEM_WITH_TLB_TRACE
305 /*
306 * Allocate trace buffer.
307 */
308 pVCpu->iem.s.idxTlbTraceEntry = 0;
309 pVCpu->iem.s.cTlbTraceEntriesShift = 16;
310 pVCpu->iem.s.paTlbTraceEntries = (PIEMTLBTRACEENTRY)RTMemPageAlloc( RT_BIT_Z(pVCpu->iem.s.cTlbTraceEntriesShift)
311 * sizeof(*pVCpu->iem.s.paTlbTraceEntries));
312 AssertLogRelReturn(pVCpu->iem.s.paTlbTraceEntries, VERR_NO_PAGE_MEMORY);
313#endif
314 }
315
316
317#ifdef VBOX_WITH_IEM_RECOMPILER
318 /*
319 * Initialize the TB allocator and cache (/ hash table).
320 *
321 * This is done by each EMT to try get more optimal thread/numa locality of
322 * the allocations.
323 */
324 rc = VMR3ReqCallWait(pVM, VMCPUID_ALL, (PFNRT)iemTbInit, 6,
325 pVM, cInitialTbs, cMaxTbs, cbInitialExec, cbMaxExec, cbChunkExec);
326 AssertLogRelRCReturn(rc, rc);
327#endif
328
329 /*
330 * Register statistics.
331 */
332 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
333 {
334#if !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_NESTED_HWVIRT_VMX) /* quick fix for stupid structure duplication non-sense */
335 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
336 char szPat[128];
337 RT_NOREF_PV(szPat); /* lazy bird */
338 char szVal[128];
339 RT_NOREF_PV(szVal); /* lazy bird */
340
341 STAMR3RegisterF(pVM, &pVCpu->iem.s.cInstructions, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
342 "Instructions interpreted", "/IEM/CPU%u/cInstructions", idCpu);
343 STAMR3RegisterF(pVM, &pVCpu->iem.s.cLongJumps, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
344 "Number of longjmp calls", "/IEM/CPU%u/cLongJumps", idCpu);
345 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPotentialExits, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
346 "Potential exits", "/IEM/CPU%u/cPotentialExits", idCpu);
347 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetAspectNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
348 "VERR_IEM_ASPECT_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetAspectNotImplemented", idCpu);
349 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInstrNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
350 "VERR_IEM_INSTR_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetInstrNotImplemented", idCpu);
351 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInfStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
352 "Informational statuses returned", "/IEM/CPU%u/cRetInfStatuses", idCpu);
353 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetErrStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
354 "Error statuses returned", "/IEM/CPU%u/cRetErrStatuses", idCpu);
355 STAMR3RegisterF(pVM, &pVCpu->iem.s.cbWritten, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
356 "Approx bytes written", "/IEM/CPU%u/cbWritten", idCpu);
357 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPendingCommit, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
358 "Times RC/R0 had to postpone instruction committing to ring-3", "/IEM/CPU%u/cPendingCommit", idCpu);
359 STAMR3RegisterF(pVM, &pVCpu->iem.s.cMisalignedAtomics, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
360 "Number of misaligned (for the host) atomic instructions", "/IEM/CPU%u/cMisalignedAtomics", idCpu);
361
362 /* Code TLB: */
363 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
364 "Code TLB non-global revision", "/IEM/CPU%u/Tlb/Code/RevisionNonGlobal", idCpu);
365 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
366 "Code TLB global revision", "/IEM/CPU%u/Tlb/Code/RevisionGlobal", idCpu);
367 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlsFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
368 "Code TLB non-global flushes", "/IEM/CPU%u/Tlb/Code/RevisionNonGlobalFlushes", idCpu);
369 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlsGlobalFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
370 "Code TLB global flushes", "/IEM/CPU%u/Tlb/Code/RevisionGlobalFlushes", idCpu);
371 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbRevisionRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
372 "Code TLB revision rollovers", "/IEM/CPU%u/Tlb/Code/RevisionRollovers", idCpu);
373
374 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.CodeTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
375 "Code TLB physical revision", "/IEM/CPU%u/Tlb/Code/PhysicalRevision", idCpu);
376 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbPhysRevFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
377 "Code TLB revision flushes", "/IEM/CPU%u/Tlb/Code/PhysicalRevisionFlushes", idCpu);
378 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbPhysRevRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
379 "Code TLB revision rollovers", "/IEM/CPU%u/Tlb/Code/PhysicalRevisionRollovers", idCpu);
380
381 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
382 "Code TLB global large page loads since flush", "/IEM/CPU%u/Tlb/Code/LargePageGlobalCurLoads", idCpu);
383 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
384 "Code TLB global large page range: lowest tag", "/IEM/CPU%u/Tlb/Code/LargePageGlobalFirstTag", idCpu);
385 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
386 "Code TLB global large page range: last tag", "/IEM/CPU%u/Tlb/Code/LargePageGlobalLastTag", idCpu);
387
388 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNonGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
389 "Code TLB non-global large page loads since flush", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalCurLoads", idCpu);
390 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
391 "Code TLB non-global large page range: lowest tag", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalFirstTag", idCpu);
392 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
393 "Code TLB non-global large page range: last tag", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalLastTag", idCpu);
394
395 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbInvlPg, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
396 "Code TLB page invalidation requests", "/IEM/CPU%u/Tlb/Code/InvlPg", idCpu);
397 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbInvlPgLargeGlobal, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
398 "Code TLB page invlpg scanning for global large pages", "/IEM/CPU%u/Tlb/Code/InvlPg/LargeGlobal", idCpu);
399 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbInvlPgLargeNonGlobal, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
400 "Code TLB page invlpg scanning for non-global large pages", "/IEM/CPU%u/Tlb/Code/InvlPg/LargeNonGlobal", idCpu);
401
402 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreMisses, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
403 "Code TLB misses", "/IEM/CPU%u/Tlb/Code/Misses", idCpu);
404 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreGlobalLoads, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
405 "Code TLB global loads", "/IEM/CPU%u/Tlb/Code/Misses/GlobalLoads", idCpu);
406 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbSlowCodeReadPath, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
407 "Code TLB slow read path", "/IEM/CPU%u/Tlb/Code/SlowReads", idCpu);
408# ifdef IEM_WITH_TLB_STATISTICS
409 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
410 "Code TLB hits (non-native)", "/IEM/CPU%u/Tlb/Code/Hits/Other", idCpu);
411# if defined(VBOX_WITH_IEM_NATIVE_RECOMPILER)
412 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbHitsForNewPage, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
413 "Code TLB native hits on new page", "/IEM/CPU%u/Tlb/Code/Hits/New-Page", idCpu);
414 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbHitsForNewPageWithOffset, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
415 "Code TLB native hits on new page /w offset", "/IEM/CPU%u/Tlb/Code/Hits/New-Page-With-Offset", idCpu);
416# endif
417
418 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Code/Hits/*", idCpu);
419 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Code TLB hits",
420 "/IEM/CPU%u/Tlb/Code/Hits", idCpu);
421
422 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Code/Hits|/IEM/CPU%u/Tlb/Code/Misses", idCpu, idCpu);
423 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Code TLB lookups (sum of hits and misses)",
424 "/IEM/CPU%u/Tlb/Code/AllLookups", idCpu);
425
426 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Code/Misses", idCpu);
427 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Code/Hits", idCpu);
428 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PPM, szVal, true, szPat,
429 "Code TLB actual miss rate", "/IEM/CPU%u/Tlb/Code/RateMisses", idCpu);
430
431# if defined(VBOX_WITH_IEM_NATIVE_RECOMPILER)
432 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissTag, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
433 "Code TLB misses in native code: Tag mismatch [not directly included grand parent sum]",
434 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/Tag", idCpu);
435 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissFlagsAndPhysRev, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
436 "Code TLB misses in native code: Flags or physical revision mistmatch [not directly included grand parent sum]",
437 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/FlagsAndPhysRev", idCpu);
438 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissAlignment, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
439 "Code TLB misses in native code: Alignment [not directly included grand parent sum]",
440 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/Alignment", idCpu);
441 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissCrossPage, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
442 "Code TLB misses in native code: Cross page [not directly included grand parent sum]",
443 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/CrossPage", idCpu);
444 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissNonCanonical, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
445 "Code TLB misses in native code: Non-canonical [not directly included grand parent sum]",
446 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/NonCanonical", idCpu);
447
448 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbMissesNewPage, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
449 "Code TLB native misses on new page",
450 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown2/New-Page", idCpu);
451 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbMissesNewPageWithOffset, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
452 "Code TLB native misses on new page w/ offset",
453 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown2/New-Page-With-Offset", idCpu);
454# endif
455# endif /* IEM_WITH_TLB_STATISTICS */
456
457 /* Data TLB organized as best we can... */
458 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
459 "Data TLB non-global revision", "/IEM/CPU%u/Tlb/Data/RevisionNonGlobal", idCpu);
460 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.uTlbRevisionGlobal, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
461 "Data TLB global revision", "/IEM/CPU%u/Tlb/Data/RevisionGlobal", idCpu);
462 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlsFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
463 "Data TLB non-global flushes", "/IEM/CPU%u/Tlb/Data/RevisionNonGlobalFlushes", idCpu);
464 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlsGlobalFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
465 "Data TLB global flushes", "/IEM/CPU%u/Tlb/Data/RevisionGlobalFlushes", idCpu);
466 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbRevisionRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
467 "Data TLB revision rollovers", "/IEM/CPU%u/Tlb/Data/RevisionRollovers", idCpu);
468
469 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.DataTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
470 "Data TLB physical revision", "/IEM/CPU%u/Tlb/Data/PhysicalRevision", idCpu);
471 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbPhysRevFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
472 "Data TLB revision flushes", "/IEM/CPU%u/Tlb/Data/PhysicalRevisionFlushes", idCpu);
473 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbPhysRevRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
474 "Data TLB revision rollovers", "/IEM/CPU%u/Tlb/Data/PhysicalRevisionRollovers", idCpu);
475
476 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
477 "Data TLB global large page loads since flush", "/IEM/CPU%u/Tlb/Data/LargePageGlobalCurLoads", idCpu);
478 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.GlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
479 "Data TLB global large page range: lowest tag", "/IEM/CPU%u/Tlb/Data/LargePageGlobalFirstTag", idCpu);
480 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.GlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
481 "Data TLB global large page range: last tag", "/IEM/CPU%u/Tlb/Data/LargePageGlobalLastTag", idCpu);
482
483 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNonGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
484 "Data TLB non-global large page loads since flush", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalCurLoads", idCpu);
485 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
486 "Data TLB non-global large page range: lowest tag", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalFirstTag", idCpu);
487 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
488 "Data TLB non-global large page range: last tag", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalLastTag", idCpu);
489
490 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbInvlPg, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
491 "Data TLB page invalidation requests", "/IEM/CPU%u/Tlb/Data/InvlPg", idCpu);
492 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbInvlPgLargeGlobal, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
493 "Data TLB page invlpg scanning for global large pages", "/IEM/CPU%u/Tlb/Data/InvlPg/LargeGlobal", idCpu);
494 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbInvlPgLargeNonGlobal, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
495 "Data TLB page invlpg scanning for non-global large pages", "/IEM/CPU%u/Tlb/Data/InvlPg/LargeNonGlobal", idCpu);
496
497 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreMisses, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
498 "Data TLB core misses (iemMemMap, direct iemMemMapJmp (not safe path))",
499 "/IEM/CPU%u/Tlb/Data/Misses/Core", idCpu);
500 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreGlobalLoads, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
501 "Data TLB global loads",
502 "/IEM/CPU%u/Tlb/Data/Misses/Core/GlobalLoads", idCpu);
503 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeReadPath, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
504 "Data TLB safe read path (inline/native misses going to iemMemMapJmp)",
505 "/IEM/CPU%u/Tlb/Data/Misses/Safe/Reads", idCpu);
506 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeWritePath, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
507 "Data TLB safe write path (inline/native misses going to iemMemMapJmp)",
508 "/IEM/CPU%u/Tlb/Data/Misses/Safe/Writes", idCpu);
509 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Misses/*", idCpu);
510 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB misses",
511 "/IEM/CPU%u/Tlb/Data/Misses", idCpu);
512
513 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Misses/Safe/*", idCpu);
514 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB actual safe path calls (read + write)",
515 "/IEM/CPU%u/Tlb/Data/Misses/Safe", idCpu);
516 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
517 "Data TLB hits in iemMemMapJmp - not part of safe-path total",
518 "/IEM/CPU%u/Tlb/Data/Misses/Safe/SubPartHits", idCpu);
519 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeMisses, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
520 "Data TLB misses in iemMemMapJmp - not part of safe-path total",
521 "/IEM/CPU%u/Tlb/Data/Misses/Safe/SubPartMisses", idCpu);
522 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeGlobalLoads, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
523 "Data TLB global loads",
524 "/IEM/CPU%u/Tlb/Data/Misses/Safe/SubPartMisses/GlobalLoads", idCpu);
525
526# ifdef IEM_WITH_TLB_STATISTICS
527# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
528 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissTag, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
529 "Data TLB misses in native code: Tag mismatch [not directly included grand parent sum]",
530 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/Tag", idCpu);
531 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissFlagsAndPhysRev, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
532 "Data TLB misses in native code: Flags or physical revision mistmatch [not directly included grand parent sum]",
533 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/FlagsAndPhysRev", idCpu);
534 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissAlignment, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
535 "Data TLB misses in native code: Alignment [not directly included grand parent sum]",
536 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/Alignment", idCpu);
537 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissCrossPage, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
538 "Data TLB misses in native code: Cross page [not directly included grand parent sum]",
539 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/CrossPage", idCpu);
540 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissNonCanonical, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
541 "Data TLB misses in native code: Non-canonical [not directly included grand parent sum]",
542 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/NonCanonical", idCpu);
543# endif
544# endif
545
546# ifdef IEM_WITH_TLB_STATISTICS
547 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
548 "Data TLB core hits (iemMemMap, direct iemMemMapJmp (not safe path))",
549 "/IEM/CPU%u/Tlb/Data/Hits/Core", idCpu);
550 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbInlineCodeHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
551 "Data TLB hits in IEMAllMemRWTmplInline.cpp.h",
552 "/IEM/CPU%u/Tlb/Data/Hits/Inline", idCpu);
553# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
554 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForStack, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
555 "Data TLB native stack access hits",
556 "/IEM/CPU%u/Tlb/Data/Hits/Native/Stack", idCpu);
557 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForFetch, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
558 "Data TLB native data fetch hits",
559 "/IEM/CPU%u/Tlb/Data/Hits/Native/Fetch", idCpu);
560 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForStore, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
561 "Data TLB native data store hits",
562 "/IEM/CPU%u/Tlb/Data/Hits/Native/Store", idCpu);
563 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForMapped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
564 "Data TLB native mapped data hits",
565 "/IEM/CPU%u/Tlb/Data/Hits/Native/Mapped", idCpu);
566# endif
567 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Hits/*", idCpu);
568 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB hits",
569 "/IEM/CPU%u/Tlb/Data/Hits", idCpu);
570
571# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
572 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Hits/Native/*", idCpu);
573 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB hits from native code",
574 "/IEM/CPU%u/Tlb/Data/Hits/Native", idCpu);
575# endif
576
577 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Data/Hits|/IEM/CPU%u/Tlb/Data/Misses", idCpu, idCpu);
578 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB lookups (sum of hits and misses)",
579 "/IEM/CPU%u/Tlb/Data/AllLookups", idCpu);
580
581 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Data/Misses", idCpu);
582 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Hits", idCpu);
583 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PPM, szVal, true, szPat,
584 "Data TLB actual miss rate", "/IEM/CPU%u/Tlb/Data/RateMisses", idCpu);
585
586# endif /* IEM_WITH_TLB_STATISTICS */
587
588
589#ifdef VBOX_WITH_IEM_RECOMPILER
590 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExecNative, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
591 "Executed native translation block", "/IEM/CPU%u/re/cTbExecNative", idCpu);
592 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExecThreaded, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
593 "Executed threaded translation block", "/IEM/CPU%u/re/cTbExecThreaded", idCpu);
594 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedExecBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
595 "Times threaded TB execution was interrupted/broken off", "/IEM/CPU%u/re/cTbExecThreadedBreaks", idCpu);
596# ifdef VBOX_WITH_STATISTICS
597 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedExecBreaksWithLookup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
598 "Times threaded TB execution was interrupted/broken off on a call with lookup entries", "/IEM/CPU%u/re/cTbExecThreadedBreaksWithLookup", idCpu);
599 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedExecBreaksWithoutLookup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
600 "Times threaded TB execution was interrupted/broken off on a call without lookup entries", "/IEM/CPU%u/re/cTbExecThreadedBreaksWithoutLookup", idCpu);
601# endif
602
603# ifdef VBOX_WITH_STATISTICS
604 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPoll, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
605 "Timer polling profiling", "/IEM/CPU%u/re/TimerPoll", idCpu);
606 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollRun, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
607 "Timer polling profiling", "/IEM/CPU%u/re/TimerPoll/Running", idCpu);
608 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollUnchanged, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
609 "Timer polling interval unchanged", "/IEM/CPU%u/re/TimerPoll/Unchanged", idCpu);
610 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollTiny, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
611 "Timer polling interval tiny", "/IEM/CPU%u/re/TimerPoll/Tiny", idCpu);
612 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollDefaultCalc, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
613 "Timer polling interval calculated using defaults", "/IEM/CPU%u/re/TimerPoll/DefaultCalc", idCpu);
614 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollMax, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
615 "Timer polling interval maxed out", "/IEM/CPU%u/re/TimerPoll/Max", idCpu);
616 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollFactorDivision, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_NS_PER_OCCURENCE,
617 "Timer polling factor", "/IEM/CPU%u/re/TimerPoll/FactorDivision", idCpu);
618 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTimerPollFactorMultiplication, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
619 "Timer polling factor", "/IEM/CPU%u/re/TimerPoll/FactorMultiplication", idCpu);
620# endif
621 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbsTillNextTimerPollPrev, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
622 "Timer polling interval (in TBs)", "/IEM/CPU%u/re/TimerPollInterval", idCpu);
623
624 PIEMTBALLOCATOR const pTbAllocator = pVCpu->iem.s.pTbAllocatorR3;
625 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatAllocs, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS,
626 "Translation block allocations", "/IEM/CPU%u/re/cTbAllocCalls", idCpu);
627 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatFrees, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS,
628 "Translation block frees", "/IEM/CPU%u/re/cTbFreeCalls", idCpu);
629# ifdef VBOX_WITH_STATISTICS
630 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatPrune, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
631 "Time spent freeing up TBs when full at alloc", "/IEM/CPU%u/re/TbPruningAlloc", idCpu);
632# endif
633 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatPruneNative, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
634 "Time spent freeing up native TBs when out of executable memory", "/IEM/CPU%u/re/ExecMem/TbPruningNative", idCpu);
635 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cAllocatedChunks, STAMTYPE_U16, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
636 "Populated TB chunks", "/IEM/CPU%u/re/cTbChunks", idCpu);
637 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cMaxChunks, STAMTYPE_U8, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
638 "Max number of TB chunks", "/IEM/CPU%u/re/cTbChunksMax", idCpu);
639 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cTotalTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
640 "Total number of TBs in the allocator", "/IEM/CPU%u/re/cTbTotal", idCpu);
641 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cMaxTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
642 "Max total number of TBs allowed", "/IEM/CPU%u/re/cTbTotalMax", idCpu);
643 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cInUseTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
644 "Number of currently allocated TBs", "/IEM/CPU%u/re/cTbAllocated", idCpu);
645 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cNativeTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
646 "Number of currently allocated native TBs", "/IEM/CPU%u/re/cTbAllocatedNative", idCpu);
647 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cThreadedTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
648 "Number of currently allocated threaded TBs", "/IEM/CPU%u/re/cTbAllocatedThreaded", idCpu);
649
650 PIEMTBCACHE const pTbCache = pVCpu->iem.s.pTbCacheR3;
651 STAMR3RegisterF(pVM, (void *)&pTbCache->cHash, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
652 "Translation block lookup table size", "/IEM/CPU%u/re/cTbHashTab", idCpu);
653
654 STAMR3RegisterF(pVM, (void *)&pTbCache->cLookupHits, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
655 "Translation block lookup hits", "/IEM/CPU%u/re/cTbLookupHits", idCpu);
656 STAMR3RegisterF(pVM, (void *)&pTbCache->cLookupHitsViaTbLookupTable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
657 "Translation block lookup hits via TB lookup table associated with the previous TB", "/IEM/CPU%u/re/cTbLookupHitsViaTbLookupTable", idCpu);
658 STAMR3RegisterF(pVM, (void *)&pTbCache->cLookupMisses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
659 "Translation block lookup misses", "/IEM/CPU%u/re/cTbLookupMisses", idCpu);
660 STAMR3RegisterF(pVM, (void *)&pTbCache->cCollisions, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
661 "Translation block hash table collisions", "/IEM/CPU%u/re/cTbCollisions", idCpu);
662# ifdef VBOX_WITH_STATISTICS
663 STAMR3RegisterF(pVM, (void *)&pTbCache->StatPrune, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
664 "Time spent shortening collision lists", "/IEM/CPU%u/re/TbPruningCollisions", idCpu);
665# endif
666
667 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedCalls, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS_PER_TB,
668 "Calls per threaded translation block", "/IEM/CPU%u/re/ThrdCallsPerTb", idCpu);
669 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbInstr, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_INSTR_PER_TB,
670 "Instruction per threaded translation block", "/IEM/CPU%u/re/ThrdInstrPerTb", idCpu);
671 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbLookupEntries, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_INSTR_PER_TB,
672 "TB lookup table entries per threaded translation block", "/IEM/CPU%u/re/ThrdLookupEntriesPerTb", idCpu);
673
674 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckIrqBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
675 "TB breaks by CheckIrq", "/IEM/CPU%u/re/CheckIrqBreaks", idCpu);
676 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckTimersBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
677 "TB breaks by CheckIrq", "/IEM/CPU%u/re/CheckTimersBreaks", idCpu);
678 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckModeBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
679 "TB breaks by CheckMode", "/IEM/CPU%u/re/CheckModeBreaks", idCpu);
680 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckBranchMisses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
681 "Branch target misses", "/IEM/CPU%u/re/CheckTbJmpMisses", idCpu);
682 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckNeedCsLimChecking, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
683 "Needing CS.LIM checking TB after branch or on page crossing", "/IEM/CPU%u/re/CheckTbNeedCsLimChecking", idCpu);
684
685 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbLoopFullTbDetected, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
686 "Detected loop full TB", "/IEM/CPU%u/re/LoopFullTbDetected", idCpu);
687 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbLoopInTbDetected, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
688 "Detected loop within TB", "/IEM/CPU%u/re/LoopInTbDetected", idCpu);
689
690 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeExecMemInstrBufAllocFailed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
691 "Number of times the exec memory allocator failed to allocate a large enough buffer",
692 "/IEM/CPU%u/re/NativeExecMemInstrBufAllocFailed", idCpu);
693
694 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCallsRecompiled, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS_PER_TB,
695 "Number of threaded calls per TB that have been properly recompiled to native code",
696 "/IEM/CPU%u/re/NativeCallsRecompiledPerTb", idCpu);
697 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCallsThreaded, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS_PER_TB,
698 "Number of threaded calls per TB that could not be recompiler to native code",
699 "/IEM/CPU%u/re/NativeCallsThreadedPerTb", idCpu);
700 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeFullyRecompiledTbs, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
701 "Number of threaded calls that could not be recompiler to native code",
702 "/IEM/CPU%u/re/NativeFullyRecompiledTbs", idCpu);
703
704 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbNativeCode, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES_PER_TB,
705 "Size of native code per TB", "/IEM/CPU%u/re/NativeCodeSizePerTb", idCpu);
706 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeRecompilation, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
707 "Profiling iemNativeRecompile()", "/IEM/CPU%u/re/NativeRecompilation", idCpu);
708
709# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
710# ifdef VBOX_WITH_STATISTICS
711 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFree, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
712 "Number of calls to iemNativeRegAllocFindFree.",
713 "/IEM/CPU%u/re/NativeRegFindFree", idCpu);
714# endif
715 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
716 "Number of times iemNativeRegAllocFindFree needed to free a variable.",
717 "/IEM/CPU%u/re/NativeRegFindFreeVar", idCpu);
718# ifdef VBOX_WITH_STATISTICS
719 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeNoVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
720 "Number of times iemNativeRegAllocFindFree did not needed to free any variables.",
721 "/IEM/CPU%u/re/NativeRegFindFreeNoVar", idCpu);
722 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeLivenessUnshadowed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
723 "Times liveness info freeed up shadowed guest registers in iemNativeRegAllocFindFree.",
724 "/IEM/CPU%u/re/NativeRegFindFreeLivenessUnshadowed", idCpu);
725 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeLivenessHelped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
726 "Times liveness info helped finding the return register in iemNativeRegAllocFindFree.",
727 "/IEM/CPU%u/re/NativeRegFindFreeLivenessHelped", idCpu);
728
729 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedArithmetic, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
730 "Skipped all status flag updating, arithmetic instructions",
731 "/IEM/CPU%u/re/NativeEFlagsSkippedArithmetic", idCpu);
732 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedLogical, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
733 "Skipped all status flag updating, logical instructions",
734 "/IEM/CPU%u/re/NativeEFlagsSkippedLogical", idCpu);
735
736 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsCfSkippable", idCpu);
737 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflPfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.PF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsPfSkippable", idCpu);
738 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflAfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.AF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsAfSkippable", idCpu);
739 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflZfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.ZF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsZfSkippable", idCpu);
740 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflSfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.SF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsSfSkippable", idCpu);
741 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflOfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.OF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsOfSkippable", idCpu);
742
743 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsCfRequired", idCpu);
744 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflPfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.PF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsPfRequired", idCpu);
745 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflAfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.AF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsAfRequired", idCpu);
746 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflZfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.ZF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsZfRequired", idCpu);
747 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflSfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.SF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsSfRequired", idCpu);
748 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflOfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.OF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsOfRequired", idCpu);
749
750# ifdef IEMLIVENESS_EXTENDED_LAYOUT
751 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsCfDelayable", idCpu);
752 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflPfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.PF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsPfDelayable", idCpu);
753 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflAfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.AF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsAfDelayable", idCpu);
754 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflZfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.ZF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsZfDelayable", idCpu);
755 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflSfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.SF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsSfDelayable", idCpu);
756 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflOfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.OF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsOfDelayable", idCpu);
757# endif
758
759 /* Sum up all status bits ('_' is a sorting hack). */
760 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?fSkippable*", idCpu);
761 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total skippable EFLAGS status bit updating",
762 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusSkippable", idCpu);
763
764 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?fRequired*", idCpu);
765 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total required STATUS status bit updating",
766 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusRequired", idCpu);
767
768# ifdef IEMLIVENESS_EXTENDED_LAYOUT
769 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?fDelayable*", idCpu);
770 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total potentially delayable STATUS status bit updating",
771 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusDelayable", idCpu);
772# endif
773
774 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?f*", idCpu);
775 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total STATUS status bit events of any kind",
776 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusTotal", idCpu);
777
778 /* Ratio of the status bit skippables. */
779 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags_StatusTotal", idCpu);
780 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeLivenessEFlags_StatusSkippable", idCpu);
781 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
782 "Total skippable EFLAGS status bit updating percentage",
783 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusSkippablePct", idCpu);
784
785# ifdef IEMLIVENESS_EXTENDED_LAYOUT
786 /* Ratio of the status bit skippables. */
787 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeLivenessEFlags_StatusDelayable", idCpu);
788 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
789 "Total potentially delayable EFLAGS status bit updating percentage",
790 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusDelayablePct", idCpu);
791# endif
792
793 /* Ratios of individual bits. */
794 size_t const offFlagChar = RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlagsCf*", idCpu) - 3;
795 Assert(szPat[offFlagChar] == 'C');
796 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeLivenessEFlagsCfSkippable", idCpu);
797 Assert(szVal[offFlagChar] == 'C');
798 szPat[offFlagChar] = szVal[offFlagChar] = 'C'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.CF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsCfSkippablePct", idCpu);
799 szPat[offFlagChar] = szVal[offFlagChar] = 'P'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.PF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsPfSkippablePct", idCpu);
800 szPat[offFlagChar] = szVal[offFlagChar] = 'A'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.AF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsAfSkippablePct", idCpu);
801 szPat[offFlagChar] = szVal[offFlagChar] = 'Z'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.ZF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsZfSkippablePct", idCpu);
802 szPat[offFlagChar] = szVal[offFlagChar] = 'S'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.SF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsSfSkippablePct", idCpu);
803 szPat[offFlagChar] = szVal[offFlagChar] = 'O'; STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, true, szPat, "Skippable EFLAGS.OF updating percentage", "/IEM/CPU%u/re/NativeLivenessEFlagsOfSkippablePct", idCpu);
804
805 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateTotal, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Total RIP updates", "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
806 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateDelayed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Delayed RIP updates", "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
807
808# ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
809 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFree, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
810 "Number of calls to iemNativeSimdRegAllocFindFree.",
811 "/IEM/CPU%u/re/NativeSimdRegFindFree", idCpu);
812 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
813 "Number of times iemNativeSimdRegAllocFindFree needed to free a variable.",
814 "/IEM/CPU%u/re/NativeSimdRegFindFreeVar", idCpu);
815 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeNoVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
816 "Number of times iemNativeSimdRegAllocFindFree did not needed to free any variables.",
817 "/IEM/CPU%u/re/NativeSimdRegFindFreeNoVar", idCpu);
818 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeLivenessUnshadowed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
819 "Times liveness info freeed up shadowed guest registers in iemNativeSimdRegAllocFindFree.",
820 "/IEM/CPU%u/re/NativeSimdRegFindFreeLivenessUnshadowed", idCpu);
821 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeLivenessHelped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
822 "Times liveness info helped finding the return register in iemNativeSimdRegAllocFindFree.",
823 "/IEM/CPU%u/re/NativeSimdRegFindFreeLivenessHelped", idCpu);
824
825 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeDeviceNotAvailXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE() checks",
826 "/IEM/CPU%u/re/NativeMaybeDeviceNotAvailXcptCheckPotential", idCpu);
827 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeWaitDeviceNotAvailXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_WAIT_DEVICE_NOT_AVAILABLE() checks",
828 "/IEM/CPU%u/re/NativeMaybeWaitDeviceNotAvailXcptCheckPotential", idCpu);
829 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeSseXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT() checks",
830 "/IEM/CPU%u/re/NativeMaybeSseXcptCheckPotential", idCpu);
831 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeAvxXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT() checks",
832 "/IEM/CPU%u/re/NativeMaybeAvxXcptCheckPotential", idCpu);
833
834 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeDeviceNotAvailXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE() checks omitted",
835 "/IEM/CPU%u/re/NativeMaybeDeviceNotAvailXcptCheckOmitted", idCpu);
836 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeWaitDeviceNotAvailXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_WAIT_DEVICE_NOT_AVAILABLE() checks omitted",
837 "/IEM/CPU%u/re/NativeMaybeWaitDeviceNotAvailXcptCheckOmitted", idCpu);
838 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeSseXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT() checks omitted",
839 "/IEM/CPU%u/re/NativeMaybeSseXcptCheckOmitted", idCpu);
840 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeAvxXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT() checks omitted",
841 "/IEM/CPU%u/re/NativeMaybeAvxXcptCheckOmitted", idCpu);
842# endif
843
844 /* Ratio of the status bit skippables. */
845 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
846 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
847 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
848 "Delayed RIP updating percentage",
849 "/IEM/CPU%u/re/NativePcUpdateDelayed_StatusDelayedPct", idCpu);
850
851 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbFinished, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
852 "Number of times the TB finishes execution completely",
853 "/IEM/CPU%u/re/NativeTbFinished", idCpu);
854# endif /* VBOX_WITH_STATISTICS */
855 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnBreak, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
856 "Number of times the TB finished through the ReturnBreak label",
857 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak", idCpu);
858 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnBreakFF, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
859 "Number of times the TB finished through the ReturnBreak label",
860 "/IEM/CPU%u/re/NativeTbExit/ReturnBreakFF", idCpu);
861 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnWithFlags, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
862 "Number of times the TB finished through the ReturnWithFlags label",
863 "/IEM/CPU%u/re/NativeTbExit/ReturnWithFlags", idCpu);
864 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnOtherStatus, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
865 "Number of times the TB finished with some other status value",
866 "/IEM/CPU%u/re/NativeTbExit/ReturnOtherStatus", idCpu);
867 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitLongJump, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
868 "Number of times the TB finished via long jump / throw",
869 "/IEM/CPU%u/re/NativeTbExit/LongJumps", idCpu);
870 /* These end up returning VINF_IEM_REEXEC_BREAK and are thus already counted under NativeTbExit/ReturnBreak: */
871 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitObsoleteTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
872 "Number of times the TB finished through the ObsoleteTb label",
873 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/ObsoleteTb", idCpu);
874 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatCheckNeedCsLimChecking, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
875 "Number of times the TB finished through the NeedCsLimChecking label",
876 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/NeedCsLimChecking", idCpu);
877 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatCheckBranchMisses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
878 "Number of times the TB finished through the CheckBranchMiss label",
879 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/CheckBranchMiss", idCpu);
880 /* Raising stuff will either increment NativeTbExit/LongJumps or NativeTbExit/ReturnOtherStatus
881 depending on whether VBOX_WITH_IEM_NATIVE_RECOMPILER_LONGJMP is defined: */
882# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER_LONGJMP
883# define RAISE_PREFIX "/IEM/CPU%u/re/NativeTbExit/ReturnOtherStatus/"
884# else
885# define RAISE_PREFIX "/IEM/CPU%u/re/NativeTbExit/LongJumps/"
886# endif
887 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseDe, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
888 "Number of times the TB finished raising a #DE exception",
889 RAISE_PREFIX "RaiseDe", idCpu);
890 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseUd, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
891 "Number of times the TB finished raising a #UD exception",
892 RAISE_PREFIX "RaiseUd", idCpu);
893 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseSseRelated, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
894 "Number of times the TB finished raising a SSE related exception",
895 RAISE_PREFIX "RaiseSseRelated", idCpu);
896 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseAvxRelated, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
897 "Number of times the TB finished raising a AVX related exception",
898 RAISE_PREFIX "RaiseAvxRelated", idCpu);
899 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseSseAvxFpRelated, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
900 "Number of times the TB finished raising a SSE/AVX floating point related exception",
901 RAISE_PREFIX "RaiseSseAvxFpRelated", idCpu);
902 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseNm, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
903 "Number of times the TB finished raising a #NM exception",
904 RAISE_PREFIX "RaiseNm", idCpu);
905 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseGp0, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
906 "Number of times the TB finished raising a #GP(0) exception",
907 RAISE_PREFIX "RaiseGp0", idCpu);
908 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseMf, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
909 "Number of times the TB finished raising a #MF exception",
910 RAISE_PREFIX "RaiseMf", idCpu);
911 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseXf, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
912 "Number of times the TB finished raising a #XF exception",
913 RAISE_PREFIX "RaiseXf", idCpu);
914
915# ifdef VBOX_WITH_STATISTICS
916 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitLoopFullTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
917 "Number of full TB loops.",
918 "/IEM/CPU%u/re/NativeTbExit/LoopFullTb", idCpu);
919# endif
920
921 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1Irq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
922 "Direct linking #1 with IRQ check succeeded",
923 "/IEM/CPU%u/re/NativeTbExit/DirectLinking1Irq", idCpu);
924 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1NoIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
925 "Direct linking #1 w/o IRQ check succeeded",
926 "/IEM/CPU%u/re/NativeTbExit/DirectLinking1NoIrq", idCpu);
927# ifdef VBOX_WITH_STATISTICS
928 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1NoTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
929 "Direct linking #1 failed: No TB in lookup table",
930 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1NoTb", idCpu);
931 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1MismatchGCPhysPc, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
932 "Direct linking #1 failed: GCPhysPc mismatch",
933 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1MismatchGCPhysPc", idCpu);
934 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1MismatchFlags, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
935 "Direct linking #1 failed: TB flags mismatch",
936 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1MismatchFlags", idCpu);
937 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1PendingIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
938 "Direct linking #1 failed: IRQ or FF pending",
939 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1PendingIrq", idCpu);
940# endif
941
942 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2Irq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
943 "Direct linking #2 with IRQ check succeeded",
944 "/IEM/CPU%u/re/NativeTbExit/DirectLinking2Irq", idCpu);
945 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2NoIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
946 "Direct linking #2 w/o IRQ check succeeded",
947 "/IEM/CPU%u/re/NativeTbExit/DirectLinking2NoIrq", idCpu);
948# ifdef VBOX_WITH_STATISTICS
949 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2NoTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
950 "Direct linking #2 failed: No TB in lookup table",
951 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2NoTb", idCpu);
952 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2MismatchGCPhysPc, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
953 "Direct linking #2 failed: GCPhysPc mismatch",
954 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2MismatchGCPhysPc", idCpu);
955 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2MismatchFlags, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
956 "Direct linking #2 failed: TB flags mismatch",
957 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2MismatchFlags", idCpu);
958 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2PendingIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
959 "Direct linking #2 failed: IRQ or FF pending",
960 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2PendingIrq", idCpu);
961# endif
962
963 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeTbExit/*", idCpu); /* only immediate children, no sub folders */
964 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat,
965 "Number of times native TB execution finished before the end (not counting thrown memory++ exceptions)",
966 "/IEM/CPU%u/re/NativeTbExit", idCpu);
967
968
969# endif /* VBOX_WITH_IEM_NATIVE_RECOMPILER */
970
971
972# ifdef VBOX_WITH_STATISTICS
973 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemMapJmp, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
974 "iemMemMapJmp calls", "/IEM/CPU%u/iemMemMapJmp", idCpu);
975 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemMapNoJmp, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
976 "iemMemMap calls", "/IEM/CPU%u/iemMemMapNoJmp", idCpu);
977 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemBounceBufferCrossPage, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
978 "iemMemBounceBufferMapCrossPage calls", "/IEM/CPU%u/iemMemMapBounceBufferCrossPage", idCpu);
979 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemBounceBufferMapPhys, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
980 "iemMemBounceBufferMapPhys calls", "/IEM/CPU%u/iemMemMapBounceBufferMapPhys", idCpu);
981# endif
982
983
984#endif /* VBOX_WITH_IEM_RECOMPILER */
985
986 for (uint32_t i = 0; i < RT_ELEMENTS(pVCpu->iem.s.aStatXcpts); i++)
987 STAMR3RegisterF(pVM, &pVCpu->iem.s.aStatXcpts[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
988 "", "/IEM/CPU%u/Exceptions/%02x", idCpu, i);
989 for (uint32_t i = 0; i < RT_ELEMENTS(pVCpu->iem.s.aStatInts); i++)
990 STAMR3RegisterF(pVM, &pVCpu->iem.s.aStatInts[i], STAMTYPE_U32_RESET, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
991 "", "/IEM/CPU%u/Interrupts/%02x", idCpu, i);
992
993# if !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_STATISTICS) && !defined(DOXYGEN_RUNNING)
994 /* Instruction statistics: */
995# define IEM_DO_INSTR_STAT(a_Name, a_szDesc) \
996 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatsRZ.a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
997 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-RZ/" #a_Name, idCpu); \
998 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatsR3.a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
999 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-R3/" #a_Name, idCpu);
1000# include "IEMInstructionStatisticsTmpl.h"
1001# undef IEM_DO_INSTR_STAT
1002# endif
1003
1004# if defined(VBOX_WITH_STATISTICS) && defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
1005 /* Threaded function statistics: */
1006 for (unsigned i = 1; i < (unsigned)kIemThreadedFunc_End; i++)
1007 STAMR3RegisterF(pVM, &pVCpu->iem.s.acThreadedFuncStats[i], STAMTYPE_U32_RESET, STAMVISIBILITY_USED,
1008 STAMUNIT_COUNT, NULL, "/IEM/CPU%u/ThrdFuncs/%s", idCpu, g_apszIemThreadedFunctionStats[i]);
1009# endif
1010
1011#endif /* !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_NESTED_HWVIRT_VMX) - quick fix for stupid structure duplication non-sense */
1012 }
1013
1014#if !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_NESTED_HWVIRT_VMX)
1015 /*
1016 * Register the per-VM VMX APIC-access page handler type.
1017 */
1018 if (pVM->cpum.ro.GuestFeatures.fVmx)
1019 {
1020 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_ALL, PGMPHYSHANDLER_F_NOT_IN_HM,
1021 iemVmxApicAccessPageHandler,
1022 "VMX APIC-access page", &pVM->iem.s.hVmxApicAccessPage);
1023 AssertLogRelRCReturn(rc, rc);
1024 }
1025#endif
1026
1027 DBGFR3InfoRegisterInternalArgv(pVM, "itlb", "IEM instruction TLB", iemR3InfoITlb, DBGFINFO_FLAGS_RUN_ON_EMT);
1028 DBGFR3InfoRegisterInternalArgv(pVM, "dtlb", "IEM instruction TLB", iemR3InfoDTlb, DBGFINFO_FLAGS_RUN_ON_EMT);
1029#ifdef IEM_WITH_TLB_TRACE
1030 DBGFR3InfoRegisterInternalArgv(pVM, "tlbtrace", "IEM TLB trace log", iemR3InfoTlbTrace, DBGFINFO_FLAGS_RUN_ON_EMT);
1031#endif
1032#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
1033 DBGFR3InfoRegisterInternalArgv(pVM, "tb", "IEM translation block", iemR3InfoTb, DBGFINFO_FLAGS_RUN_ON_EMT);
1034#endif
1035#ifdef VBOX_WITH_DEBUGGER
1036 iemR3RegisterDebuggerCommands();
1037#endif
1038
1039 return VINF_SUCCESS;
1040}
1041
1042
1043VMMR3DECL(int) IEMR3Term(PVM pVM)
1044{
1045 NOREF(pVM);
1046#ifdef IEM_WITH_TLB_TRACE
1047 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1048 {
1049 PVMCPU const pVCpu = pVM->apCpusR3[idCpu];
1050 RTMemPageFree(pVCpu->iem.s.paTlbTraceEntries,
1051 RT_BIT_Z(pVCpu->iem.s.cTlbTraceEntriesShift) * sizeof(*pVCpu->iem.s.paTlbTraceEntries));
1052 }
1053#endif
1054 return VINF_SUCCESS;
1055}
1056
1057
1058VMMR3DECL(void) IEMR3Relocate(PVM pVM)
1059{
1060 RT_NOREF(pVM);
1061}
1062
1063
1064/**
1065 * Gets the name of a generic IEM exit code.
1066 *
1067 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
1068 * @param uExit The IEM exit to name.
1069 */
1070VMMR3DECL(const char *) IEMR3GetExitName(uint32_t uExit)
1071{
1072 static const char * const s_apszNames[] =
1073 {
1074 /* external interrupts */
1075 "ExtInt 00h", "ExtInt 01h", "ExtInt 02h", "ExtInt 03h", "ExtInt 04h", "ExtInt 05h", "ExtInt 06h", "ExtInt 07h",
1076 "ExtInt 08h", "ExtInt 09h", "ExtInt 0ah", "ExtInt 0bh", "ExtInt 0ch", "ExtInt 0dh", "ExtInt 0eh", "ExtInt 0fh",
1077 "ExtInt 10h", "ExtInt 11h", "ExtInt 12h", "ExtInt 13h", "ExtInt 14h", "ExtInt 15h", "ExtInt 16h", "ExtInt 17h",
1078 "ExtInt 18h", "ExtInt 19h", "ExtInt 1ah", "ExtInt 1bh", "ExtInt 1ch", "ExtInt 1dh", "ExtInt 1eh", "ExtInt 1fh",
1079 "ExtInt 20h", "ExtInt 21h", "ExtInt 22h", "ExtInt 23h", "ExtInt 24h", "ExtInt 25h", "ExtInt 26h", "ExtInt 27h",
1080 "ExtInt 28h", "ExtInt 29h", "ExtInt 2ah", "ExtInt 2bh", "ExtInt 2ch", "ExtInt 2dh", "ExtInt 2eh", "ExtInt 2fh",
1081 "ExtInt 30h", "ExtInt 31h", "ExtInt 32h", "ExtInt 33h", "ExtInt 34h", "ExtInt 35h", "ExtInt 36h", "ExtInt 37h",
1082 "ExtInt 38h", "ExtInt 39h", "ExtInt 3ah", "ExtInt 3bh", "ExtInt 3ch", "ExtInt 3dh", "ExtInt 3eh", "ExtInt 3fh",
1083 "ExtInt 40h", "ExtInt 41h", "ExtInt 42h", "ExtInt 43h", "ExtInt 44h", "ExtInt 45h", "ExtInt 46h", "ExtInt 47h",
1084 "ExtInt 48h", "ExtInt 49h", "ExtInt 4ah", "ExtInt 4bh", "ExtInt 4ch", "ExtInt 4dh", "ExtInt 4eh", "ExtInt 4fh",
1085 "ExtInt 50h", "ExtInt 51h", "ExtInt 52h", "ExtInt 53h", "ExtInt 54h", "ExtInt 55h", "ExtInt 56h", "ExtInt 57h",
1086 "ExtInt 58h", "ExtInt 59h", "ExtInt 5ah", "ExtInt 5bh", "ExtInt 5ch", "ExtInt 5dh", "ExtInt 5eh", "ExtInt 5fh",
1087 "ExtInt 60h", "ExtInt 61h", "ExtInt 62h", "ExtInt 63h", "ExtInt 64h", "ExtInt 65h", "ExtInt 66h", "ExtInt 67h",
1088 "ExtInt 68h", "ExtInt 69h", "ExtInt 6ah", "ExtInt 6bh", "ExtInt 6ch", "ExtInt 6dh", "ExtInt 6eh", "ExtInt 6fh",
1089 "ExtInt 70h", "ExtInt 71h", "ExtInt 72h", "ExtInt 73h", "ExtInt 74h", "ExtInt 75h", "ExtInt 76h", "ExtInt 77h",
1090 "ExtInt 78h", "ExtInt 79h", "ExtInt 7ah", "ExtInt 7bh", "ExtInt 7ch", "ExtInt 7dh", "ExtInt 7eh", "ExtInt 7fh",
1091 "ExtInt 80h", "ExtInt 81h", "ExtInt 82h", "ExtInt 83h", "ExtInt 84h", "ExtInt 85h", "ExtInt 86h", "ExtInt 87h",
1092 "ExtInt 88h", "ExtInt 89h", "ExtInt 8ah", "ExtInt 8bh", "ExtInt 8ch", "ExtInt 8dh", "ExtInt 8eh", "ExtInt 8fh",
1093 "ExtInt 90h", "ExtInt 91h", "ExtInt 92h", "ExtInt 93h", "ExtInt 94h", "ExtInt 95h", "ExtInt 96h", "ExtInt 97h",
1094 "ExtInt 98h", "ExtInt 99h", "ExtInt 9ah", "ExtInt 9bh", "ExtInt 9ch", "ExtInt 9dh", "ExtInt 9eh", "ExtInt 9fh",
1095 "ExtInt a0h", "ExtInt a1h", "ExtInt a2h", "ExtInt a3h", "ExtInt a4h", "ExtInt a5h", "ExtInt a6h", "ExtInt a7h",
1096 "ExtInt a8h", "ExtInt a9h", "ExtInt aah", "ExtInt abh", "ExtInt ach", "ExtInt adh", "ExtInt aeh", "ExtInt afh",
1097 "ExtInt b0h", "ExtInt b1h", "ExtInt b2h", "ExtInt b3h", "ExtInt b4h", "ExtInt b5h", "ExtInt b6h", "ExtInt b7h",
1098 "ExtInt b8h", "ExtInt b9h", "ExtInt bah", "ExtInt bbh", "ExtInt bch", "ExtInt bdh", "ExtInt beh", "ExtInt bfh",
1099 "ExtInt c0h", "ExtInt c1h", "ExtInt c2h", "ExtInt c3h", "ExtInt c4h", "ExtInt c5h", "ExtInt c6h", "ExtInt c7h",
1100 "ExtInt c8h", "ExtInt c9h", "ExtInt cah", "ExtInt cbh", "ExtInt cch", "ExtInt cdh", "ExtInt ceh", "ExtInt cfh",
1101 "ExtInt d0h", "ExtInt d1h", "ExtInt d2h", "ExtInt d3h", "ExtInt d4h", "ExtInt d5h", "ExtInt d6h", "ExtInt d7h",
1102 "ExtInt d8h", "ExtInt d9h", "ExtInt dah", "ExtInt dbh", "ExtInt dch", "ExtInt ddh", "ExtInt deh", "ExtInt dfh",
1103 "ExtInt e0h", "ExtInt e1h", "ExtInt e2h", "ExtInt e3h", "ExtInt e4h", "ExtInt e5h", "ExtInt e6h", "ExtInt e7h",
1104 "ExtInt e8h", "ExtInt e9h", "ExtInt eah", "ExtInt ebh", "ExtInt ech", "ExtInt edh", "ExtInt eeh", "ExtInt efh",
1105 "ExtInt f0h", "ExtInt f1h", "ExtInt f2h", "ExtInt f3h", "ExtInt f4h", "ExtInt f5h", "ExtInt f6h", "ExtInt f7h",
1106 "ExtInt f8h", "ExtInt f9h", "ExtInt fah", "ExtInt fbh", "ExtInt fch", "ExtInt fdh", "ExtInt feh", "ExtInt ffh",
1107 /* software interrups */
1108 "SoftInt 00h", "SoftInt 01h", "SoftInt 02h", "SoftInt 03h", "SoftInt 04h", "SoftInt 05h", "SoftInt 06h", "SoftInt 07h",
1109 "SoftInt 08h", "SoftInt 09h", "SoftInt 0ah", "SoftInt 0bh", "SoftInt 0ch", "SoftInt 0dh", "SoftInt 0eh", "SoftInt 0fh",
1110 "SoftInt 10h", "SoftInt 11h", "SoftInt 12h", "SoftInt 13h", "SoftInt 14h", "SoftInt 15h", "SoftInt 16h", "SoftInt 17h",
1111 "SoftInt 18h", "SoftInt 19h", "SoftInt 1ah", "SoftInt 1bh", "SoftInt 1ch", "SoftInt 1dh", "SoftInt 1eh", "SoftInt 1fh",
1112 "SoftInt 20h", "SoftInt 21h", "SoftInt 22h", "SoftInt 23h", "SoftInt 24h", "SoftInt 25h", "SoftInt 26h", "SoftInt 27h",
1113 "SoftInt 28h", "SoftInt 29h", "SoftInt 2ah", "SoftInt 2bh", "SoftInt 2ch", "SoftInt 2dh", "SoftInt 2eh", "SoftInt 2fh",
1114 "SoftInt 30h", "SoftInt 31h", "SoftInt 32h", "SoftInt 33h", "SoftInt 34h", "SoftInt 35h", "SoftInt 36h", "SoftInt 37h",
1115 "SoftInt 38h", "SoftInt 39h", "SoftInt 3ah", "SoftInt 3bh", "SoftInt 3ch", "SoftInt 3dh", "SoftInt 3eh", "SoftInt 3fh",
1116 "SoftInt 40h", "SoftInt 41h", "SoftInt 42h", "SoftInt 43h", "SoftInt 44h", "SoftInt 45h", "SoftInt 46h", "SoftInt 47h",
1117 "SoftInt 48h", "SoftInt 49h", "SoftInt 4ah", "SoftInt 4bh", "SoftInt 4ch", "SoftInt 4dh", "SoftInt 4eh", "SoftInt 4fh",
1118 "SoftInt 50h", "SoftInt 51h", "SoftInt 52h", "SoftInt 53h", "SoftInt 54h", "SoftInt 55h", "SoftInt 56h", "SoftInt 57h",
1119 "SoftInt 58h", "SoftInt 59h", "SoftInt 5ah", "SoftInt 5bh", "SoftInt 5ch", "SoftInt 5dh", "SoftInt 5eh", "SoftInt 5fh",
1120 "SoftInt 60h", "SoftInt 61h", "SoftInt 62h", "SoftInt 63h", "SoftInt 64h", "SoftInt 65h", "SoftInt 66h", "SoftInt 67h",
1121 "SoftInt 68h", "SoftInt 69h", "SoftInt 6ah", "SoftInt 6bh", "SoftInt 6ch", "SoftInt 6dh", "SoftInt 6eh", "SoftInt 6fh",
1122 "SoftInt 70h", "SoftInt 71h", "SoftInt 72h", "SoftInt 73h", "SoftInt 74h", "SoftInt 75h", "SoftInt 76h", "SoftInt 77h",
1123 "SoftInt 78h", "SoftInt 79h", "SoftInt 7ah", "SoftInt 7bh", "SoftInt 7ch", "SoftInt 7dh", "SoftInt 7eh", "SoftInt 7fh",
1124 "SoftInt 80h", "SoftInt 81h", "SoftInt 82h", "SoftInt 83h", "SoftInt 84h", "SoftInt 85h", "SoftInt 86h", "SoftInt 87h",
1125 "SoftInt 88h", "SoftInt 89h", "SoftInt 8ah", "SoftInt 8bh", "SoftInt 8ch", "SoftInt 8dh", "SoftInt 8eh", "SoftInt 8fh",
1126 "SoftInt 90h", "SoftInt 91h", "SoftInt 92h", "SoftInt 93h", "SoftInt 94h", "SoftInt 95h", "SoftInt 96h", "SoftInt 97h",
1127 "SoftInt 98h", "SoftInt 99h", "SoftInt 9ah", "SoftInt 9bh", "SoftInt 9ch", "SoftInt 9dh", "SoftInt 9eh", "SoftInt 9fh",
1128 "SoftInt a0h", "SoftInt a1h", "SoftInt a2h", "SoftInt a3h", "SoftInt a4h", "SoftInt a5h", "SoftInt a6h", "SoftInt a7h",
1129 "SoftInt a8h", "SoftInt a9h", "SoftInt aah", "SoftInt abh", "SoftInt ach", "SoftInt adh", "SoftInt aeh", "SoftInt afh",
1130 "SoftInt b0h", "SoftInt b1h", "SoftInt b2h", "SoftInt b3h", "SoftInt b4h", "SoftInt b5h", "SoftInt b6h", "SoftInt b7h",
1131 "SoftInt b8h", "SoftInt b9h", "SoftInt bah", "SoftInt bbh", "SoftInt bch", "SoftInt bdh", "SoftInt beh", "SoftInt bfh",
1132 "SoftInt c0h", "SoftInt c1h", "SoftInt c2h", "SoftInt c3h", "SoftInt c4h", "SoftInt c5h", "SoftInt c6h", "SoftInt c7h",
1133 "SoftInt c8h", "SoftInt c9h", "SoftInt cah", "SoftInt cbh", "SoftInt cch", "SoftInt cdh", "SoftInt ceh", "SoftInt cfh",
1134 "SoftInt d0h", "SoftInt d1h", "SoftInt d2h", "SoftInt d3h", "SoftInt d4h", "SoftInt d5h", "SoftInt d6h", "SoftInt d7h",
1135 "SoftInt d8h", "SoftInt d9h", "SoftInt dah", "SoftInt dbh", "SoftInt dch", "SoftInt ddh", "SoftInt deh", "SoftInt dfh",
1136 "SoftInt e0h", "SoftInt e1h", "SoftInt e2h", "SoftInt e3h", "SoftInt e4h", "SoftInt e5h", "SoftInt e6h", "SoftInt e7h",
1137 "SoftInt e8h", "SoftInt e9h", "SoftInt eah", "SoftInt ebh", "SoftInt ech", "SoftInt edh", "SoftInt eeh", "SoftInt efh",
1138 "SoftInt f0h", "SoftInt f1h", "SoftInt f2h", "SoftInt f3h", "SoftInt f4h", "SoftInt f5h", "SoftInt f6h", "SoftInt f7h",
1139 "SoftInt f8h", "SoftInt f9h", "SoftInt fah", "SoftInt fbh", "SoftInt fch", "SoftInt fdh", "SoftInt feh", "SoftInt ffh",
1140 };
1141 if (uExit < RT_ELEMENTS(s_apszNames))
1142 return s_apszNames[uExit];
1143 return NULL;
1144}
1145
1146
1147/** Worker for iemR3InfoTlbPrintSlots and iemR3InfoTlbPrintAddress. */
1148static void iemR3InfoTlbPrintHeader(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, bool *pfHeader)
1149{
1150 if (*pfHeader)
1151 return;
1152 pHlp->pfnPrintf(pHlp, "%cTLB for CPU %u:\n", &pVCpu->iem.s.CodeTlb == pTlb ? 'I' : 'D', pVCpu->idCpu);
1153 *pfHeader = true;
1154}
1155
1156
1157#define IEMR3INFOTLB_F_ONLY_VALID RT_BIT_32(0)
1158#define IEMR3INFOTLB_F_CHECK RT_BIT_32(1)
1159
1160/** Worker for iemR3InfoTlbPrintSlots and iemR3InfoTlbPrintAddress. */
1161static void iemR3InfoTlbPrintSlot(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, IEMTLBENTRY const *pTlbe,
1162 uint32_t uSlot, uint32_t fFlags)
1163{
1164#ifndef VBOX_VMM_TARGET_ARMV8
1165 uint64_t const uTlbRevision = !(uSlot & 1) ? pTlb->uTlbRevision : pTlb->uTlbRevisionGlobal;
1166#else
1167 uint64_t const uTlbRevision = pTlb->uTlbRevision;
1168#endif
1169 if ((fFlags & IEMR3INFOTLB_F_ONLY_VALID) && (pTlbe->uTag & IEMTLB_REVISION_MASK) != uTlbRevision)
1170 return;
1171
1172 /* The address needs to be sign extended, thus the shifting fun here.*/
1173 RTGCPTR const GCPtr = (RTGCINTPTR)((pTlbe->uTag & ~IEMTLB_REVISION_MASK) << (64 - IEMTLB_TAG_ADDR_WIDTH))
1174 >> (64 - IEMTLB_TAG_ADDR_WIDTH - GUEST_PAGE_SHIFT);
1175 const char *pszValid = "";
1176#ifndef VBOX_VMM_TARGET_ARMV8
1177 char szTmp[128];
1178 if (fFlags & IEMR3INFOTLB_F_CHECK)
1179 {
1180 uint32_t const fInvSlotG = (uint32_t)!(uSlot & 1) << X86_PTE_BIT_G;
1181 PGMPTWALKFAST WalkFast;
1182 int rc = PGMGstQueryPageFast(pVCpu, GCPtr, 0 /*fFlags - don't check or modify anything */, &WalkFast);
1183 pszValid = szTmp;
1184 if (RT_FAILURE(rc))
1185 switch (rc)
1186 {
1187 case VERR_PAGE_TABLE_NOT_PRESENT:
1188 switch ((WalkFast.fFailed & PGM_WALKFAIL_LEVEL_MASK) >> PGM_WALKFAIL_LEVEL_SHIFT)
1189 {
1190 case 1: pszValid = " stale(page-not-present)"; break;
1191 case 2: pszValid = " stale(pd-entry-not-present)"; break;
1192 case 3: pszValid = " stale(pdptr-entry-not-present)"; break;
1193 case 4: pszValid = " stale(pml4-entry-not-present)"; break;
1194 case 5: pszValid = " stale(pml5-entry-not-present)"; break;
1195 default: pszValid = " stale(VERR_PAGE_TABLE_NOT_PRESENT)"; break;
1196 }
1197 break;
1198 default: RTStrPrintf(szTmp, sizeof(szTmp), " stale(rc=%d)", rc); break;
1199 }
1200 else if (WalkFast.GCPhys != pTlbe->GCPhys)
1201 RTStrPrintf(szTmp, sizeof(szTmp), " stale(GCPhys=%RGp)", WalkFast.GCPhys);
1202 else if ( (~WalkFast.fEffective & (X86_PTE_RW | X86_PTE_US | X86_PTE_G | X86_PTE_A | X86_PTE_D))
1203 == ( (pTlbe->fFlagsAndPhysRev & ( IEMTLBE_F_PT_NO_WRITE | IEMTLBE_F_PT_NO_USER
1204 | IEMTLBE_F_PT_NO_DIRTY | IEMTLBE_F_PT_NO_ACCESSED))
1205 | fInvSlotG ) )
1206 pszValid = " still-valid";
1207 else if ( (~WalkFast.fEffective & (X86_PTE_RW | X86_PTE_US | X86_PTE_G))
1208 == ((pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PT_NO_WRITE | IEMTLBE_F_PT_NO_USER)) | fInvSlotG) )
1209 switch ( (~WalkFast.fEffective & (X86_PTE_A | X86_PTE_D))
1210 ^ (pTlbe->fFlagsAndPhysRev & (IEMTLBE_F_PT_NO_DIRTY | IEMTLBE_F_PT_NO_ACCESSED)) )
1211 {
1212 case X86_PTE_A:
1213 pszValid = WalkFast.fEffective & X86_PTE_A ? " still-valid(accessed-now)" : " still-valid(accessed-no-more)";
1214 break;
1215 case X86_PTE_D:
1216 pszValid = WalkFast.fEffective & X86_PTE_D ? " still-valid(dirty-now)" : " still-valid(dirty-no-more)";
1217 break;
1218 case X86_PTE_D | X86_PTE_A:
1219 RTStrPrintf(szTmp, sizeof(szTmp), " still-valid(%s%s)",
1220 (~WalkFast.fEffective & X86_PTE_D) == (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY) ? ""
1221 : WalkFast.fEffective & X86_PTE_D ? "dirty-now" : "dirty-no-more",
1222 (~WalkFast.fEffective & X86_PTE_A) == (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED) ? ""
1223 : WalkFast.fEffective & X86_PTE_A ? " accessed-now" : " accessed-no-more");
1224 break;
1225 default: AssertFailed(); break;
1226 }
1227 else
1228 RTStrPrintf(szTmp, sizeof(szTmp), " stale(%s%s%s%s%s)",
1229 (~WalkFast.fEffective & X86_PTE_RW) == (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_WRITE) ? ""
1230 : WalkFast.fEffective & X86_PTE_RW ? "writeable-now" : "writable-no-more",
1231 (~WalkFast.fEffective & X86_PTE_US) == (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_USER) ? ""
1232 : WalkFast.fEffective & X86_PTE_US ? " user-now" : " user-no-more",
1233 (~WalkFast.fEffective & X86_PTE_G) == fInvSlotG ? ""
1234 : WalkFast.fEffective & X86_PTE_G ? " global-now" : " global-no-more",
1235 (~WalkFast.fEffective & X86_PTE_D) == (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY) ? ""
1236 : WalkFast.fEffective & X86_PTE_D ? " dirty-now" : " dirty-no-more",
1237 (~WalkFast.fEffective & X86_PTE_A) == (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED) ? ""
1238 : WalkFast.fEffective & X86_PTE_A ? " accessed-now" : " accessed-no-more");
1239 }
1240#else
1241 RT_NOREF(pVCpu);
1242#endif
1243
1244 pHlp->pfnPrintf(pHlp, IEMTLB_SLOT_FMT ": %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s%s%s%s/%s%s%s%s/%s %s%s\n",
1245 uSlot,
1246 (pTlbe->uTag & IEMTLB_REVISION_MASK) == uTlbRevision ? "valid "
1247 : (pTlbe->uTag & IEMTLB_REVISION_MASK) == 0 ? "empty "
1248 : "expired",
1249 GCPtr, /* -> */
1250 pTlbe->GCPhys, /* / */ pTlbe->pbMappingR3,
1251 /* / */
1252 (uint32_t)(pTlbe->fFlagsAndPhysRev & ~IEMTLBE_F_PHYS_REV),
1253 /* */
1254 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_WRITE ? "R-" : "RW",
1255 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_EXEC ? "-" : "X",
1256 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED ? "-" : "A",
1257 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY ? "-" : "D",
1258 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_USER ? "U" : "S",
1259 !(uSlot & 1) ? "-" : "G",
1260 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE ? "4K" : "2M",
1261 /* / */
1262 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_WRITE ? "-" : "w",
1263 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_READ ? "-" : "r",
1264 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_UNASSIGNED ? "u" : "-",
1265 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_CODE_PAGE ? "c" : "-",
1266 /* / */
1267 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_NO_MAPPINGR3 ? "N" : "M",
1268 (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == pTlb->uTlbPhysRev ? "phys-valid"
1269 : (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == 0 ? "phys-empty" : "phys-expired",
1270 pszValid);
1271}
1272
1273
1274/** Displays one or more TLB slots. */
1275static void iemR3InfoTlbPrintSlots(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb,
1276 uint32_t uSlot, uint32_t cSlots, uint32_t fFlags, bool *pfHeader)
1277{
1278 if (uSlot < RT_ELEMENTS(pTlb->aEntries))
1279 {
1280 if (cSlots > RT_ELEMENTS(pTlb->aEntries))
1281 {
1282 pHlp->pfnPrintf(pHlp, "error: Too many slots given: %u, adjusting it down to the max (%u)\n",
1283 cSlots, RT_ELEMENTS(pTlb->aEntries));
1284 cSlots = RT_ELEMENTS(pTlb->aEntries);
1285 }
1286
1287 iemR3InfoTlbPrintHeader(pVCpu, pHlp, pTlb, pfHeader);
1288 while (cSlots-- > 0)
1289 {
1290 IEMTLBENTRY const Tlbe = pTlb->aEntries[uSlot];
1291 iemR3InfoTlbPrintSlot(pVCpu, pHlp, pTlb, &Tlbe, uSlot, fFlags);
1292 uSlot = (uSlot + 1) % RT_ELEMENTS(pTlb->aEntries);
1293 }
1294 }
1295 else
1296 pHlp->pfnPrintf(pHlp, "error: TLB slot is out of range: %u (%#x), max %u (%#x)\n",
1297 uSlot, uSlot, RT_ELEMENTS(pTlb->aEntries) - 1, RT_ELEMENTS(pTlb->aEntries) - 1);
1298}
1299
1300
1301/** Displays the TLB slot for the given address. */
1302static void iemR3InfoTlbPrintAddress(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb,
1303 uint64_t uAddress, uint32_t fFlags, bool *pfHeader)
1304{
1305 iemR3InfoTlbPrintHeader(pVCpu, pHlp, pTlb, pfHeader);
1306
1307 uint64_t const uTag = IEMTLB_CALC_TAG_NO_REV(uAddress);
1308#ifdef IEMTLB_TAG_TO_EVEN_INDEX
1309 uint32_t const uSlot = IEMTLB_TAG_TO_EVEN_INDEX(uTag);
1310#else
1311 uint32_t const uSlot = IEMTLB_TAG_TO_INDEX(uTag);
1312#endif
1313 IEMTLBENTRY const TlbeL = pTlb->aEntries[uSlot];
1314#ifndef VBOX_VMM_TARGET_ARMV8
1315 IEMTLBENTRY const TlbeG = pTlb->aEntries[uSlot + 1];
1316#endif
1317 pHlp->pfnPrintf(pHlp, "Address %#RX64 -> slot %#x - %s\n", uAddress, uSlot,
1318 TlbeL.uTag == (uTag | pTlb->uTlbRevision) ? "match"
1319 : (TlbeL.uTag & ~IEMTLB_REVISION_MASK) == uTag ? "expired" : "mismatch");
1320 iemR3InfoTlbPrintSlot(pVCpu, pHlp, pTlb, &TlbeL, uSlot, fFlags);
1321
1322#ifndef VBOX_VMM_TARGET_ARMV8
1323 pHlp->pfnPrintf(pHlp, "Address %#RX64 -> slot %#x - %s\n", uAddress, uSlot + 1,
1324 TlbeG.uTag == (uTag | pTlb->uTlbRevisionGlobal) ? "match"
1325 : (TlbeG.uTag & ~IEMTLB_REVISION_MASK) == uTag ? "expired" : "mismatch");
1326 iemR3InfoTlbPrintSlot(pVCpu, pHlp, pTlb, &TlbeG, uSlot + 1, fFlags);
1327#endif
1328}
1329
1330
1331/** Common worker for iemR3InfoDTlb and iemR3InfoITlb. */
1332static void iemR3InfoTlbCommon(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs, bool fITlb)
1333{
1334 /*
1335 * This is entirely argument driven.
1336 */
1337 static RTGETOPTDEF const s_aOptions[] =
1338 {
1339 { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
1340 { "--vcpu", 'c', RTGETOPT_REQ_UINT32 },
1341 { "--check", 'C', RTGETOPT_REQ_NOTHING },
1342 { "all", 'A', RTGETOPT_REQ_NOTHING },
1343 { "--all", 'A', RTGETOPT_REQ_NOTHING },
1344 { "--address", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1345 { "--range", 'r', RTGETOPT_REQ_UINT32_PAIR | RTGETOPT_FLAG_HEX },
1346 { "--slot", 's', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX },
1347 { "--only-valid", 'v', RTGETOPT_REQ_NOTHING },
1348 };
1349
1350 RTGETOPTSTATE State;
1351 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
1352 AssertRCReturnVoid(rc);
1353
1354 uint32_t cActionArgs = 0;
1355 bool fNeedHeader = true;
1356 bool fAddressMode = true;
1357 uint32_t fFlags = 0;
1358 PVMCPU const pVCpuCall = VMMGetCpu(pVM);
1359 PVMCPU pVCpu = pVCpuCall;
1360 if (!pVCpu)
1361 pVCpu = VMMGetCpuById(pVM, 0);
1362
1363 RTGETOPTUNION ValueUnion;
1364 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
1365 {
1366 switch (rc)
1367 {
1368 case 'c':
1369 if (ValueUnion.u32 >= pVM->cCpus)
1370 pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
1371 else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
1372 {
1373 pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
1374 fNeedHeader = true;
1375 if (!pVCpuCall || pVCpuCall->idCpu != ValueUnion.u32)
1376 {
1377 pHlp->pfnPrintf(pHlp, "info: Can't check guest PTs when switching to a different VCpu! Targetting %u, on %u.\n",
1378 ValueUnion.u32, pVCpuCall->idCpu);
1379 fFlags &= ~IEMR3INFOTLB_F_CHECK;
1380 }
1381 }
1382 break;
1383
1384 case 'C':
1385 if (!pVCpuCall)
1386 pHlp->pfnPrintf(pHlp, "error: Can't check guest PT when not running on an EMT!\n");
1387 else if (pVCpu != pVCpuCall)
1388 pHlp->pfnPrintf(pHlp, "error: Can't check guest PTs when on a different EMT! Targetting %u, on %u.\n",
1389 pVCpu->idCpu, pVCpuCall->idCpu);
1390 else
1391 fFlags |= IEMR3INFOTLB_F_CHECK;
1392 break;
1393
1394 case 'a':
1395 iemR3InfoTlbPrintAddress(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1396 ValueUnion.u64, fFlags, &fNeedHeader);
1397 fAddressMode = true;
1398 cActionArgs++;
1399 break;
1400
1401 case 'A':
1402 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1403 0, RT_ELEMENTS(pVCpu->iem.s.CodeTlb.aEntries), fFlags, &fNeedHeader);
1404 cActionArgs++;
1405 break;
1406
1407 case 'r':
1408 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1409 ValueUnion.PairU32.uFirst, ValueUnion.PairU32.uSecond, fFlags, &fNeedHeader);
1410 fAddressMode = false;
1411 cActionArgs++;
1412 break;
1413
1414 case 's':
1415 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1416 ValueUnion.u32, 1, fFlags, &fNeedHeader);
1417 fAddressMode = false;
1418 cActionArgs++;
1419 break;
1420
1421 case 'v':
1422 fFlags |= IEMR3INFOTLB_F_ONLY_VALID;
1423 break;
1424
1425 case VINF_GETOPT_NOT_OPTION:
1426 if (fAddressMode)
1427 {
1428 uint64_t uAddr;
1429 rc = RTStrToUInt64Full(ValueUnion.psz, 16, &uAddr);
1430 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG)
1431 iemR3InfoTlbPrintAddress(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1432 uAddr, fFlags, &fNeedHeader);
1433 else
1434 pHlp->pfnPrintf(pHlp, "error: Invalid or malformed guest address '%s': %Rrc\n", ValueUnion.psz, rc);
1435 }
1436 else
1437 {
1438 uint32_t uSlot;
1439 rc = RTStrToUInt32Full(ValueUnion.psz, 16, &uSlot);
1440 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG)
1441 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1442 uSlot, 1, fFlags, &fNeedHeader);
1443 else
1444 pHlp->pfnPrintf(pHlp, "error: Invalid or malformed TLB slot number '%s': %Rrc\n", ValueUnion.psz, rc);
1445 }
1446 cActionArgs++;
1447 break;
1448
1449 case 'h':
1450 pHlp->pfnPrintf(pHlp,
1451 "Usage: info %ctlb [options]\n"
1452 "\n"
1453 "Options:\n"
1454 " -c<n>, --cpu=<n>, --vcpu=<n>\n"
1455 " Selects the CPU which TLBs we're looking at. Default: Caller / 0\n"
1456 " -C,--check\n"
1457 " Check valid entries against guest PTs.\n"
1458 " -A, --all, all\n"
1459 " Display all the TLB entries (default if no other args).\n"
1460 " -a<virt>, --address=<virt>\n"
1461 " Shows the TLB entry for the specified guest virtual address.\n"
1462 " -r<slot:count>, --range=<slot:count>\n"
1463 " Shows the TLB entries for the specified slot range.\n"
1464 " -s<slot>,--slot=<slot>\n"
1465 " Shows the given TLB slot.\n"
1466 " -v,--only-valid\n"
1467 " Only show valid TLB entries (TAG, not phys)\n"
1468 "\n"
1469 "Non-options are interpreted according to the last -a, -r or -s option,\n"
1470 "defaulting to addresses if not preceeded by any of those options.\n"
1471 , fITlb ? 'i' : 'd');
1472 return;
1473
1474 default:
1475 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
1476 return;
1477 }
1478 }
1479
1480 /*
1481 * If no action taken, we display all (-A) by default.
1482 */
1483 if (!cActionArgs)
1484 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1485 0, RT_ELEMENTS(pVCpu->iem.s.CodeTlb.aEntries), fFlags, &fNeedHeader);
1486}
1487
1488
1489/**
1490 * @callback_method_impl{FNDBGFINFOARGVINT, itlb}
1491 */
1492static DECLCALLBACK(void) iemR3InfoITlb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1493{
1494 return iemR3InfoTlbCommon(pVM, pHlp, cArgs, papszArgs, true /*fITlb*/);
1495}
1496
1497
1498/**
1499 * @callback_method_impl{FNDBGFINFOARGVINT, dtlb}
1500 */
1501static DECLCALLBACK(void) iemR3InfoDTlb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1502{
1503 return iemR3InfoTlbCommon(pVM, pHlp, cArgs, papszArgs, false /*fITlb*/);
1504}
1505
1506
1507#ifdef IEM_WITH_TLB_TRACE
1508/**
1509 * @callback_method_impl{FNDBGFINFOARGVINT, tlbtrace}
1510 */
1511static DECLCALLBACK(void) iemR3InfoTlbTrace(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1512{
1513 /*
1514 * Parse arguments.
1515 */
1516 static RTGETOPTDEF const s_aOptions[] =
1517 {
1518 { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
1519 { "--vcpu", 'c', RTGETOPT_REQ_UINT32 },
1520 { "--last", 'l', RTGETOPT_REQ_UINT32 },
1521 { "--limit", 'l', RTGETOPT_REQ_UINT32 },
1522 { "--stop-at-global-flush", 'g', RTGETOPT_REQ_NOTHING },
1523 { "--resolve-rip", 'r', RTGETOPT_REQ_NOTHING },
1524 };
1525
1526 RTGETOPTSTATE State;
1527 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
1528 AssertRCReturnVoid(rc);
1529
1530 uint32_t cLimit = UINT32_MAX;
1531 bool fStopAtGlobalFlush = false;
1532 bool fResolveRip = false;
1533 PVMCPU const pVCpuCall = VMMGetCpu(pVM);
1534 PVMCPU pVCpu = pVCpuCall;
1535 if (!pVCpu)
1536 pVCpu = VMMGetCpuById(pVM, 0);
1537
1538 RTGETOPTUNION ValueUnion;
1539 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
1540 {
1541 switch (rc)
1542 {
1543 case 'c':
1544 if (ValueUnion.u32 >= pVM->cCpus)
1545 pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
1546 else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
1547 pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
1548 break;
1549
1550 case 'l':
1551 cLimit = ValueUnion.u32;
1552 break;
1553
1554 case 'g':
1555 fStopAtGlobalFlush = true;
1556 break;
1557
1558 case 'r':
1559 fResolveRip = true;
1560 break;
1561
1562 case 'h':
1563 pHlp->pfnPrintf(pHlp,
1564 "Usage: info tlbtrace [options] [n]\n"
1565 "\n"
1566 "Options:\n"
1567 " -c<n>, --cpu=<n>, --vcpu=<n>\n"
1568 " Selects the CPU which TLB trace we're looking at. Default: Caller / 0\n"
1569 " [n], -l<n>, --last=<n>\n"
1570 " Limit display to the last N entries. Default: all\n"
1571 " -g, --stop-at-global-flush\n"
1572 " Stop after the first global flush entry.\n"
1573 " -r, --resolve-rip\n"
1574 " Resolve symbols for the flattened RIP addresses.\n"
1575 );
1576 return;
1577
1578 case VINF_GETOPT_NOT_OPTION:
1579 rc = RTStrToUInt32Full(ValueUnion.psz, 0, &cLimit);
1580 if (RT_SUCCESS(rc))
1581 break;
1582 pHlp->pfnPrintf(pHlp, "error: failed to convert '%s' to a number: %Rrc\n", ValueUnion.psz, rc);
1583 return;
1584
1585 default:
1586 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
1587 return;
1588 }
1589 }
1590
1591 /*
1592 * Get the details.
1593 */
1594 AssertReturnVoid(pVCpu);
1595 Assert(pVCpu->iem.s.cTlbTraceEntriesShift <= 28);
1596 uint32_t idx = pVCpu->iem.s.idxTlbTraceEntry;
1597 uint32_t const cShift = RT_MIN(pVCpu->iem.s.cTlbTraceEntriesShift, 28);
1598 uint32_t const fMask = RT_BIT_32(cShift) - 1;
1599 uint32_t cLeft = RT_MIN(RT_MIN(idx, RT_BIT_32(cShift)), cLimit);
1600 PCIEMTLBTRACEENTRY paEntries = pVCpu->iem.s.paTlbTraceEntries;
1601 if (cLeft && paEntries)
1602 {
1603 /*
1604 * Display the entries.
1605 */
1606 pHlp->pfnPrintf(pHlp, "TLB Trace for CPU %u:\n", pVCpu->idCpu);
1607 while (cLeft-- > 0)
1608 {
1609 PCIEMTLBTRACEENTRY const pCur = &paEntries[--idx & fMask];
1610 const char *pszSymbol = "";
1611 union
1612 {
1613 RTDBGSYMBOL Symbol;
1614 char ach[sizeof(RTDBGSYMBOL) + 32];
1615 } uBuf;
1616 if (fResolveRip)
1617 {
1618 RTGCINTPTR offDisp = 0;
1619 DBGFADDRESS Addr;
1620 rc = DBGFR3AsSymbolByAddr(pVM->pUVM, DBGF_AS_GLOBAL, DBGFR3AddrFromFlat(pVM->pUVM, &Addr, pCur->rip),
1621 RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL
1622 | RTDBGSYMADDR_FLAGS_SKIP_ABS
1623 | RTDBGSYMADDR_FLAGS_SKIP_ABS_IN_DEFERRED,
1624 &offDisp, &uBuf.Symbol, NULL);
1625 if (RT_SUCCESS(rc))
1626 {
1627 /* Add displacement. */
1628 if (offDisp)
1629 {
1630 size_t const cchName = strlen(uBuf.Symbol.szName);
1631 char * const pszEndName = &uBuf.Symbol.szName[cchName];
1632 size_t const cbLeft = sizeof(uBuf) - sizeof(uBuf.Symbol) + sizeof(uBuf.Symbol.szName) - cchName;
1633 if (offDisp > 0)
1634 RTStrPrintf(pszEndName, cbLeft, "+%#1RGv", offDisp);
1635 else
1636 RTStrPrintf(pszEndName, cbLeft, "-%#1RGv", -offDisp);
1637 }
1638
1639 /* Put a space before it. */
1640 AssertCompile(RTASSERT_OFFSET_OF(RTDBGSYMBOL, szName) > 0);
1641 char *pszName = uBuf.Symbol.szName;
1642 *--pszName = ' ';
1643 pszSymbol = pszName;
1644 }
1645 }
1646 static const char *s_apszTlbType[2] = { "code", "data" };
1647 static const char *s_apszScanType[4] = { "skipped", "global", "non-global", "both" };
1648 switch (pCur->enmType)
1649 {
1650 case kIemTlbTraceType_InvlPg:
1651 pHlp->pfnPrintf(pHlp, "%u: %016RX64 invlpg %RGv slot=" IEMTLB_SLOT_FMT "%s\n", idx, pCur->rip,
1652 pCur->u64Param, (uint32_t)IEMTLB_ADDR_TO_EVEN_INDEX(pCur->u64Param), pszSymbol);
1653 break;
1654 case kIemTlbTraceType_EvictSlot:
1655 pHlp->pfnPrintf(pHlp, "%u: %016RX64 evict %s slot=" IEMTLB_SLOT_FMT " %RGv (%#RX64) gcphys=%RGp%s\n",
1656 idx, pCur->rip, s_apszTlbType[pCur->bParam & 1], pCur->u32Param,
1657 (RTGCINTPTR)((pCur->u64Param & ~IEMTLB_REVISION_MASK) << (64 - IEMTLB_TAG_ADDR_WIDTH))
1658 >> (64 - IEMTLB_TAG_ADDR_WIDTH - GUEST_PAGE_SHIFT), pCur->u64Param,
1659 pCur->u64Param2, pszSymbol);
1660 break;
1661 case kIemTlbTraceType_LargeEvictSlot:
1662 pHlp->pfnPrintf(pHlp, "%u: %016RX64 large evict %s slot=" IEMTLB_SLOT_FMT " %RGv (%#RX64) gcphys=%RGp%s\n",
1663 idx, pCur->rip, s_apszTlbType[pCur->bParam & 1], pCur->u32Param,
1664 (RTGCINTPTR)((pCur->u64Param & ~IEMTLB_REVISION_MASK) << (64 - IEMTLB_TAG_ADDR_WIDTH))
1665 >> (64 - IEMTLB_TAG_ADDR_WIDTH - GUEST_PAGE_SHIFT), pCur->u64Param,
1666 pCur->u64Param2, pszSymbol);
1667 break;
1668 case kIemTlbTraceType_LargeScan:
1669 pHlp->pfnPrintf(pHlp, "%u: %016RX64 large scan %s %s%s\n", idx, pCur->rip, s_apszTlbType[pCur->bParam & 1],
1670 s_apszScanType[pCur->u32Param & 3], pszSymbol);
1671 break;
1672
1673 case kIemTlbTraceType_Flush:
1674 pHlp->pfnPrintf(pHlp, "%u: %016RX64 flush %s rev=%#RX64%s\n", idx, pCur->rip,
1675 s_apszTlbType[pCur->bParam & 1], pCur->u64Param, pszSymbol);
1676 break;
1677 case kIemTlbTraceType_FlushGlobal:
1678 pHlp->pfnPrintf(pHlp, "%u: %016RX64 flush %s rev=%#RX64 grev=%#RX64%s\n", idx, pCur->rip,
1679 s_apszTlbType[pCur->bParam & 1], pCur->u64Param, pCur->u64Param2, pszSymbol);
1680 if (fStopAtGlobalFlush)
1681 return;
1682 break;
1683 case kIemTlbTraceType_Load:
1684 case kIemTlbTraceType_LoadGlobal:
1685 pHlp->pfnPrintf(pHlp, "%u: %016RX64 %cload %s %RGv slot=" IEMTLB_SLOT_FMT " gcphys=%RGp fTlb=%#RX32%s\n",
1686 idx, pCur->rip,
1687 pCur->enmType == kIemTlbTraceType_LoadGlobal ? 'g' : 'l', s_apszTlbType[pCur->bParam & 1],
1688 pCur->u64Param,
1689 (uint32_t)IEMTLB_ADDR_TO_EVEN_INDEX(pCur->u64Param)
1690 | (pCur->enmType == kIemTlbTraceType_LoadGlobal),
1691 (RTGCPTR)pCur->u64Param2, pCur->u32Param, pszSymbol);
1692 break;
1693
1694 case kIemTlbTraceType_Load_Cr0:
1695 pHlp->pfnPrintf(pHlp, "%u: %016RX64 load cr0 %08RX64 (was %08RX64)%s\n",
1696 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pszSymbol);
1697 break;
1698 case kIemTlbTraceType_Load_Cr3:
1699 pHlp->pfnPrintf(pHlp, "%u: %016RX64 load cr3 %016RX64 (was %016RX64)%s\n",
1700 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pszSymbol);
1701 break;
1702 case kIemTlbTraceType_Load_Cr4:
1703 pHlp->pfnPrintf(pHlp, "%u: %016RX64 load cr4 %08RX64 (was %08RX64)%s\n",
1704 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pszSymbol);
1705 break;
1706 case kIemTlbTraceType_Load_Efer:
1707 pHlp->pfnPrintf(pHlp, "%u: %016RX64 load efer %016RX64 (was %016RX64)%s\n",
1708 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pszSymbol);
1709 break;
1710
1711 case kIemTlbTraceType_Irq:
1712 pHlp->pfnPrintf(pHlp, "%u: %016RX64 irq %#04x flags=%#x eflboth=%#RX64%s\n",
1713 idx, pCur->rip, pCur->bParam, pCur->u32Param,
1714 pCur->u64Param & ((RT_BIT_64(CPUMX86EFLAGS_HW_BITS) - 1) | CPUMX86EFLAGS_INT_MASK_64),
1715 pszSymbol);
1716 break;
1717 case kIemTlbTraceType_Xcpt:
1718 if (pCur->u32Param & IEM_XCPT_FLAGS_CR2)
1719 pHlp->pfnPrintf(pHlp, "%u: %016RX64 xcpt %#04x flags=%#x errcd=%#x cr2=%RX64%s\n",
1720 idx, pCur->rip, pCur->bParam, pCur->u32Param, pCur->u64Param, pCur->u64Param2, pszSymbol);
1721 else if (pCur->u32Param & IEM_XCPT_FLAGS_ERR)
1722 pHlp->pfnPrintf(pHlp, "%u: %016RX64 xcpt %#04x flags=%#x errcd=%#x%s\n",
1723 idx, pCur->rip, pCur->bParam, pCur->u32Param, pCur->u64Param, pszSymbol);
1724 else
1725 pHlp->pfnPrintf(pHlp, "%u: %016RX64 xcpt %#04x flags=%#x%s\n",
1726 idx, pCur->rip, pCur->bParam, pCur->u32Param, pszSymbol);
1727 break;
1728 case kIemTlbTraceType_IRet:
1729 pHlp->pfnPrintf(pHlp, "%u: %016RX64 iret cs:rip=%04x:%016RX64 efl=%08RX32%s\n",
1730 idx, pCur->rip, pCur->u32Param, pCur->u64Param, (uint32_t)pCur->u64Param2, pszSymbol);
1731 break;
1732
1733 case kIemTlbTraceType_Tb_Compile:
1734 pHlp->pfnPrintf(pHlp, "%u: %016RX64 tb comp GCPhysPc=%012RX64%s\n",
1735 idx, pCur->rip, pCur->u64Param, pszSymbol);
1736 break;
1737 case kIemTlbTraceType_Tb_Exec_Threaded:
1738 pHlp->pfnPrintf(pHlp, "%u: %016RX64 tb thrd GCPhysPc=%012RX64 tb=%p used=%u%s\n",
1739 idx, pCur->rip, pCur->u64Param, (uintptr_t)pCur->u64Param2, pCur->u32Param, pszSymbol);
1740 break;
1741 case kIemTlbTraceType_Tb_Exec_Native:
1742 pHlp->pfnPrintf(pHlp, "%u: %016RX64 tb n8ve GCPhysPc=%012RX64 tb=%p used=%u%s\n",
1743 idx, pCur->rip, pCur->u64Param, (uintptr_t)pCur->u64Param2, pCur->u32Param, pszSymbol);
1744 break;
1745
1746 case kIemTlbTraceType_User0:
1747 pHlp->pfnPrintf(pHlp, "%u: %016RX64 user0 %016RX64 %016RX64 %08RX32 %02RX8%s\n",
1748 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pCur->u32Param, pCur->bParam, pszSymbol);
1749 break;
1750 case kIemTlbTraceType_User1:
1751 pHlp->pfnPrintf(pHlp, "%u: %016RX64 user1 %016RX64 %016RX64 %08RX32 %02RX8%s\n",
1752 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pCur->u32Param, pCur->bParam, pszSymbol);
1753 break;
1754 case kIemTlbTraceType_User2:
1755 pHlp->pfnPrintf(pHlp, "%u: %016RX64 user2 %016RX64 %016RX64 %08RX32 %02RX8%s\n",
1756 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pCur->u32Param, pCur->bParam, pszSymbol);
1757 break;
1758 case kIemTlbTraceType_User3:
1759 pHlp->pfnPrintf(pHlp, "%u: %016RX64 user3 %016RX64 %016RX64 %08RX32 %02RX8%s\n",
1760 idx, pCur->rip, pCur->u64Param, pCur->u64Param2, pCur->u32Param, pCur->bParam, pszSymbol);
1761 break;
1762
1763 case kIemTlbTraceType_Invalid:
1764 pHlp->pfnPrintf(pHlp, "%u: Invalid!\n");
1765 break;
1766 }
1767 }
1768 }
1769 else
1770 pHlp->pfnPrintf(pHlp, "No trace entries to display\n");
1771}
1772#endif /* IEM_WITH_TLB_TRACE */
1773
1774#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
1775/**
1776 * @callback_method_impl{FNDBGFINFOARGVINT, tb}
1777 */
1778static DECLCALLBACK(void) iemR3InfoTb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1779{
1780 /*
1781 * Parse arguments.
1782 */
1783 static RTGETOPTDEF const s_aOptions[] =
1784 {
1785 { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
1786 { "--vcpu", 'c', RTGETOPT_REQ_UINT32 },
1787 { "--addr", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1788 { "--address", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1789 { "--phys", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1790 { "--physical", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1791 { "--phys-addr", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1792 { "--phys-address", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1793 { "--physical-address", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1794 { "--flags", 'f', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX },
1795 };
1796
1797 RTGETOPTSTATE State;
1798 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
1799 AssertRCReturnVoid(rc);
1800
1801 PVMCPU const pVCpuThis = VMMGetCpu(pVM);
1802 PVMCPU pVCpu = pVCpuThis ? pVCpuThis : VMMGetCpuById(pVM, 0);
1803 RTGCPHYS GCPhysPc = NIL_RTGCPHYS;
1804 RTGCPHYS GCVirt = NIL_RTGCPTR;
1805 uint32_t fFlags = UINT32_MAX;
1806
1807 RTGETOPTUNION ValueUnion;
1808 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
1809 {
1810 switch (rc)
1811 {
1812 case 'c':
1813 if (ValueUnion.u32 >= pVM->cCpus)
1814 pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
1815 else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
1816 pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
1817 break;
1818
1819 case 'a':
1820 GCVirt = ValueUnion.u64;
1821 GCPhysPc = NIL_RTGCPHYS;
1822 break;
1823
1824 case 'p':
1825 GCVirt = NIL_RTGCPHYS;
1826 GCPhysPc = ValueUnion.u64;
1827 break;
1828
1829 case 'f':
1830 fFlags = ValueUnion.u32;
1831 break;
1832
1833 case 'h':
1834 pHlp->pfnPrintf(pHlp,
1835 "Usage: info tb [options]\n"
1836 "\n"
1837 "Options:\n"
1838 " -c<n>, --cpu=<n>, --vcpu=<n>\n"
1839 " Selects the CPU which TBs we're looking at. Default: Caller / 0\n"
1840 " -a<virt>, --address=<virt>\n"
1841 " Shows the TB for the specified guest virtual address.\n"
1842 " -p<phys>, --phys=<phys>, --phys-addr=<phys>\n"
1843 " Shows the TB for the specified guest physical address.\n"
1844 " -f<flags>,--flags=<flags>\n"
1845 " The TB flags value (hex) to use when looking up the TB.\n"
1846 "\n"
1847 "The default is to use CS:RIP and derive flags from the CPU mode.\n");
1848 return;
1849
1850 default:
1851 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
1852 return;
1853 }
1854 }
1855
1856 /* Currently, only do work on the same EMT. */
1857 if (pVCpu != pVCpuThis)
1858 {
1859 pHlp->pfnPrintf(pHlp, "TODO: Cross EMT calling not supported yet: targeting %u, caller on %d\n",
1860 pVCpu->idCpu, pVCpuThis ? (int)pVCpuThis->idCpu : -1);
1861 return;
1862 }
1863
1864 /*
1865 * Defaults.
1866 */
1867 if (GCPhysPc == NIL_RTGCPHYS)
1868 {
1869 if (GCVirt == NIL_RTGCPTR)
1870 GCVirt = CPUMGetGuestFlatPC(pVCpu);
1871 rc = PGMPhysGCPtr2GCPhys(pVCpu, GCVirt, &GCPhysPc);
1872 if (RT_FAILURE(rc))
1873 {
1874 pHlp->pfnPrintf(pHlp, "Failed to convert %%%RGv to an guest physical address: %Rrc\n", GCVirt, rc);
1875 return;
1876 }
1877 }
1878 if (fFlags == UINT32_MAX)
1879 {
1880 /* Note! This is duplicating code in IEMAllThrdRecompiler. */
1881 fFlags = iemCalcExecFlags(pVCpu);
1882 if (pVM->cCpus == 1)
1883 fFlags |= IEM_F_X86_DISREGARD_LOCK;
1884 if (CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
1885 fFlags |= IEMTB_F_INHIBIT_SHADOW;
1886 if (CPUMAreInterruptsInhibitedByNmiEx(&pVCpu->cpum.GstCtx))
1887 fFlags |= IEMTB_F_INHIBIT_NMI;
1888 if ((IEM_F_MODE_CPUMODE_MASK & fFlags) != IEMMODE_64BIT)
1889 {
1890 int64_t const offFromLim = (int64_t)pVCpu->cpum.GstCtx.cs.u32Limit - (int64_t)pVCpu->cpum.GstCtx.eip;
1891 if (offFromLim < X86_PAGE_SIZE + 16 - (int32_t)(pVCpu->cpum.GstCtx.cs.u64Base & GUEST_PAGE_OFFSET_MASK))
1892 fFlags |= IEMTB_F_CS_LIM_CHECKS;
1893 }
1894 }
1895
1896 /*
1897 * Do the lookup...
1898 *
1899 * Note! This is also duplicating code in IEMAllThrdRecompiler. We don't
1900 * have much choice since we don't want to increase use counters and
1901 * trigger native recompilation.
1902 */
1903 fFlags &= IEMTB_F_KEY_MASK;
1904 IEMTBCACHE const * const pTbCache = pVCpu->iem.s.pTbCacheR3;
1905 uint32_t const idxHash = IEMTBCACHE_HASH(pTbCache, fFlags, GCPhysPc);
1906 PCIEMTB pTb = IEMTBCACHE_PTR_GET_TB(pTbCache->apHash[idxHash]);
1907 while (pTb)
1908 {
1909 if (pTb->GCPhysPc == GCPhysPc)
1910 {
1911 if ((pTb->fFlags & IEMTB_F_KEY_MASK) == fFlags)
1912 {
1913 /// @todo if (pTb->x86.fAttr == (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u)
1914 break;
1915 }
1916 }
1917 pTb = pTb->pNext;
1918 }
1919 if (!pTb)
1920 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x - no TB found on #%u\n", GCPhysPc, fFlags, pVCpu->idCpu);
1921 else
1922 {
1923 /*
1924 * Disassemble according to type.
1925 */
1926 switch (pTb->fFlags & IEMTB_F_TYPE_MASK)
1927 {
1928# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
1929 case IEMTB_F_TYPE_NATIVE:
1930 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - native\n", GCPhysPc, fFlags, pVCpu->idCpu, pTb);
1931 iemNativeDisassembleTb(pVCpu, pTb, pHlp);
1932 break;
1933# endif
1934
1935 case IEMTB_F_TYPE_THREADED:
1936 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - threaded\n", GCPhysPc, fFlags, pVCpu->idCpu, pTb);
1937 iemThreadedDisassembleTb(pTb, pHlp);
1938 break;
1939
1940 default:
1941 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - ??? %#x\n",
1942 GCPhysPc, fFlags, pVCpu->idCpu, pTb, pTb->fFlags);
1943 break;
1944 }
1945 }
1946}
1947#endif /* VBOX_WITH_IEM_RECOMPILER && !VBOX_VMM_TARGET_ARMV8 */
1948
1949
1950#ifdef VBOX_WITH_DEBUGGER
1951
1952/** @callback_method_impl{FNDBGCCMD,
1953 * Implements the '.alliem' command. }
1954 */
1955static DECLCALLBACK(int) iemR3DbgFlushTlbs(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
1956{
1957 VMCPUID idCpu = DBGCCmdHlpGetCurrentCpu(pCmdHlp);
1958 PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, idCpu);
1959 if (pVCpu)
1960 {
1961 VMR3ReqPriorityCallVoidWaitU(pUVM, idCpu, (PFNRT)IEMTlbInvalidateAllGlobal, 1, pVCpu);
1962 return VINF_SUCCESS;
1963 }
1964 RT_NOREF(paArgs, cArgs);
1965 return DBGCCmdHlpFail(pCmdHlp, pCmd, "failed to get the PVMCPU for the current CPU");
1966}
1967
1968
1969/**
1970 * Called by IEMR3Init to register debugger commands.
1971 */
1972static void iemR3RegisterDebuggerCommands(void)
1973{
1974 /*
1975 * Register debugger commands.
1976 */
1977 static DBGCCMD const s_aCmds[] =
1978 {
1979 {
1980 /* .pszCmd = */ "iemflushtlb",
1981 /* .cArgsMin = */ 0,
1982 /* .cArgsMax = */ 0,
1983 /* .paArgDescs = */ NULL,
1984 /* .cArgDescs = */ 0,
1985 /* .fFlags = */ 0,
1986 /* .pfnHandler = */ iemR3DbgFlushTlbs,
1987 /* .pszSyntax = */ "",
1988 /* .pszDescription = */ "Flushed the code and data TLBs"
1989 },
1990 };
1991
1992 int rc = DBGCRegisterCommands(&s_aCmds[0], RT_ELEMENTS(s_aCmds));
1993 AssertLogRelRC(rc);
1994}
1995
1996#endif /* VBOX_WITH_DEBUGGER */
1997
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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