VirtualBox

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

Last change on this file since 105399 was 105376, checked in by vboxsync, 9 months ago

VMM/IEM: Format string fix. bugref:10725

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 99.5 KB
Line 
1/* $Id: IEMR3.cpp 105376 2024-07-17 13:41:22Z 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.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#define LOG_GROUP LOG_GROUP_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#if defined(VBOX_VMM_TARGET_ARMV8)
39# include "IEMInternal-armv8.h"
40#else
41# include "IEMInternal.h"
42#endif
43#include <VBox/vmm/vm.h>
44#include <VBox/vmm/vmapi.h>
45#include <VBox/err.h>
46#ifdef VBOX_WITH_DEBUGGER
47# include <VBox/dbg.h>
48#endif
49
50#include <iprt/assert.h>
51#include <iprt/getopt.h>
52#include <iprt/string.h>
53
54#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
55# include "IEMN8veRecompiler.h"
56# include "IEMThreadedFunctions.h"
57# include "IEMInline.h"
58#endif
59
60
61/*********************************************************************************************************************************
62* Internal Functions *
63*********************************************************************************************************************************/
64static FNDBGFINFOARGVINT iemR3InfoITlb;
65static FNDBGFINFOARGVINT iemR3InfoDTlb;
66#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
67static FNDBGFINFOARGVINT iemR3InfoTb;
68#endif
69#ifdef VBOX_WITH_DEBUGGER
70static void iemR3RegisterDebuggerCommands(void);
71#endif
72
73
74#if !defined(VBOX_VMM_TARGET_ARMV8)
75static const char *iemGetTargetCpuName(uint32_t enmTargetCpu)
76{
77 switch (enmTargetCpu)
78 {
79#define CASE_RET_STR(enmValue) case enmValue: return #enmValue + (sizeof("IEMTARGETCPU_") - 1)
80 CASE_RET_STR(IEMTARGETCPU_8086);
81 CASE_RET_STR(IEMTARGETCPU_V20);
82 CASE_RET_STR(IEMTARGETCPU_186);
83 CASE_RET_STR(IEMTARGETCPU_286);
84 CASE_RET_STR(IEMTARGETCPU_386);
85 CASE_RET_STR(IEMTARGETCPU_486);
86 CASE_RET_STR(IEMTARGETCPU_PENTIUM);
87 CASE_RET_STR(IEMTARGETCPU_PPRO);
88 CASE_RET_STR(IEMTARGETCPU_CURRENT);
89#undef CASE_RET_STR
90 default: return "Unknown";
91 }
92}
93#endif
94
95
96/**
97 * Initializes the interpreted execution manager.
98 *
99 * This must be called after CPUM as we're quering information from CPUM about
100 * the guest and host CPUs.
101 *
102 * @returns VBox status code.
103 * @param pVM The cross context VM structure.
104 */
105VMMR3DECL(int) IEMR3Init(PVM pVM)
106{
107 /*
108 * Read configuration.
109 */
110#if (!defined(VBOX_VMM_TARGET_ARMV8) && !defined(VBOX_WITHOUT_CPUID_HOST_CALL)) || defined(VBOX_WITH_IEM_RECOMPILER)
111 PCFGMNODE const pIem = CFGMR3GetChild(CFGMR3GetRoot(pVM), "IEM");
112 int rc;
113#endif
114
115#if !defined(VBOX_VMM_TARGET_ARMV8) && !defined(VBOX_WITHOUT_CPUID_HOST_CALL)
116 /** @cfgm{/IEM/CpuIdHostCall, boolean, false}
117 * Controls whether the custom VBox specific CPUID host call interface is
118 * enabled or not. */
119# ifdef DEBUG_bird
120 rc = CFGMR3QueryBoolDef(pIem, "CpuIdHostCall", &pVM->iem.s.fCpuIdHostCall, true);
121# else
122 rc = CFGMR3QueryBoolDef(pIem, "CpuIdHostCall", &pVM->iem.s.fCpuIdHostCall, false);
123# endif
124 AssertLogRelRCReturn(rc, rc);
125#endif
126
127#ifdef VBOX_WITH_IEM_RECOMPILER
128 /** @cfgm{/IEM/MaxTbCount, uint32_t, 524288}
129 * Max number of TBs per EMT. */
130 uint32_t cMaxTbs = 0;
131 rc = CFGMR3QueryU32Def(pIem, "MaxTbCount", &cMaxTbs, _512K);
132 AssertLogRelRCReturn(rc, rc);
133 if (cMaxTbs < _16K || cMaxTbs > _8M)
134 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
135 "MaxTbCount value %u (%#x) is out of range (min %u, max %u)", cMaxTbs, cMaxTbs, _16K, _8M);
136
137 /** @cfgm{/IEM/InitialTbCount, uint32_t, 32678}
138 * Initial (minimum) number of TBs per EMT in ring-3. */
139 uint32_t cInitialTbs = 0;
140 rc = CFGMR3QueryU32Def(pIem, "InitialTbCount", &cInitialTbs, RT_MIN(cMaxTbs, _32K));
141 AssertLogRelRCReturn(rc, rc);
142 if (cInitialTbs < _16K || cInitialTbs > _8M)
143 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
144 "InitialTbCount value %u (%#x) is out of range (min %u, max %u)", cInitialTbs, cInitialTbs, _16K, _8M);
145
146 /* Check that the two values makes sense together. Expect user/api to do
147 the right thing or get lost. */
148 if (cInitialTbs > cMaxTbs)
149 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
150 "InitialTbCount value %u (%#x) is higher than the MaxTbCount value %u (%#x)",
151 cInitialTbs, cInitialTbs, cMaxTbs, cMaxTbs);
152
153 /** @cfgm{/IEM/MaxExecMem, uint64_t, 512 MiB}
154 * Max executable memory for recompiled code per EMT. */
155 uint64_t cbMaxExec = 0;
156 rc = CFGMR3QueryU64Def(pIem, "MaxExecMem", &cbMaxExec, _512M);
157 AssertLogRelRCReturn(rc, rc);
158 if (cbMaxExec < _1M || cbMaxExec > 16*_1G64)
159 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
160 "MaxExecMem value %'RU64 (%#RX64) is out of range (min %'RU64, max %'RU64)",
161 cbMaxExec, cbMaxExec, (uint64_t)_1M, 16*_1G64);
162
163 /** @cfgm{/IEM/ExecChunkSize, uint32_t, 0 (auto)}
164 * The executable memory allocator chunk size. */
165 uint32_t cbChunkExec = 0;
166 rc = CFGMR3QueryU32Def(pIem, "ExecChunkSize", &cbChunkExec, 0);
167 AssertLogRelRCReturn(rc, rc);
168 if (cbChunkExec != 0 && cbChunkExec != UINT32_MAX && (cbChunkExec < _1M || cbChunkExec > _256M))
169 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
170 "ExecChunkSize value %'RU32 (%#RX32) is out of range (min %'RU32, max %'RU32)",
171 cbChunkExec, cbChunkExec, _1M, _256M);
172
173 /** @cfgm{/IEM/InitialExecMemSize, uint64_t, 1}
174 * The initial executable memory allocator size (per EMT). The value is
175 * rounded up to the nearest chunk size, so 1 byte means one chunk. */
176 uint64_t cbInitialExec = 0;
177 rc = CFGMR3QueryU64Def(pIem, "InitialExecMemSize", &cbInitialExec, 0);
178 AssertLogRelRCReturn(rc, rc);
179 if (cbInitialExec > cbMaxExec)
180 return VMSetError(pVM, VERR_OUT_OF_RANGE, RT_SRC_POS,
181 "InitialExecMemSize value %'RU64 (%#RX64) is out of range (max %'RU64)",
182 cbInitialExec, cbInitialExec, cbMaxExec);
183
184 /** @cfgm{/IEM/NativeRecompileAtUsedCount, uint32_t, 16}
185 * The translation block use count value to do native recompilation at. */
186 uint32_t uTbNativeRecompileAtUsedCount = 16;
187 rc = CFGMR3QueryU32Def(pIem, "NativeRecompileAtUsedCount", &uTbNativeRecompileAtUsedCount, 16);
188 AssertLogRelRCReturn(rc, rc);
189
190#endif /* VBOX_WITH_IEM_RECOMPILER*/
191
192 /*
193 * Initialize per-CPU data and register statistics.
194 */
195 uint64_t const uInitialTlbRevision = UINT64_C(0) - (IEMTLB_REVISION_INCR * 200U);
196 uint64_t const uInitialTlbPhysRev = UINT64_C(0) - (IEMTLB_PHYS_REV_INCR * 100U);
197
198 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
199 {
200 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
201 AssertCompile(sizeof(pVCpu->iem.s) <= sizeof(pVCpu->iem.padding)); /* (tstVMStruct can't do it's job w/o instruction stats) */
202
203 pVCpu->iem.s.CodeTlb.uTlbRevision = pVCpu->iem.s.DataTlb.uTlbRevision = uInitialTlbRevision;
204#ifndef VBOX_VMM_TARGET_ARMV8
205 pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal = pVCpu->iem.s.DataTlb.uTlbRevisionGlobal = uInitialTlbRevision;
206#endif
207 pVCpu->iem.s.CodeTlb.uTlbPhysRev = pVCpu->iem.s.DataTlb.uTlbPhysRev = uInitialTlbPhysRev;
208#ifndef VBOX_VMM_TARGET_ARMV8
209 pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
210 pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uFirstTag = UINT64_MAX;
211 pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uFirstTag = UINT64_MAX;
212 pVCpu->iem.s.DataTlb.GlobalLargePageRange.uFirstTag = UINT64_MAX;
213#endif
214
215 /*
216 * Host and guest CPU information.
217 */
218 if (idCpu == 0)
219 {
220 pVCpu->iem.s.enmCpuVendor = CPUMGetGuestCpuVendor(pVM);
221 pVCpu->iem.s.enmHostCpuVendor = CPUMGetHostCpuVendor(pVM);
222#if !defined(VBOX_VMM_TARGET_ARMV8)
223 pVCpu->iem.s.aidxTargetCpuEflFlavour[0] = pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_INTEL
224 || pVCpu->iem.s.enmCpuVendor == CPUMCPUVENDOR_VIA /*??*/
225 ? IEMTARGETCPU_EFL_BEHAVIOR_INTEL : IEMTARGETCPU_EFL_BEHAVIOR_AMD;
226# if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
227 if (pVCpu->iem.s.enmCpuVendor == pVCpu->iem.s.enmHostCpuVendor)
228 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = IEMTARGETCPU_EFL_BEHAVIOR_NATIVE;
229 else
230# endif
231 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = pVCpu->iem.s.aidxTargetCpuEflFlavour[0];
232#else
233 pVCpu->iem.s.aidxTargetCpuEflFlavour[0] = IEMTARGETCPU_EFL_BEHAVIOR_NATIVE;
234 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = pVCpu->iem.s.aidxTargetCpuEflFlavour[0];
235#endif
236
237#if !defined(VBOX_VMM_TARGET_ARMV8) && (IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC)
238 switch (pVM->cpum.ro.GuestFeatures.enmMicroarch)
239 {
240 case kCpumMicroarch_Intel_8086: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_8086; break;
241 case kCpumMicroarch_Intel_80186: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_186; break;
242 case kCpumMicroarch_Intel_80286: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_286; break;
243 case kCpumMicroarch_Intel_80386: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_386; break;
244 case kCpumMicroarch_Intel_80486: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_486; break;
245 case kCpumMicroarch_Intel_P5: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PENTIUM; break;
246 case kCpumMicroarch_Intel_P6: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PPRO; break;
247 case kCpumMicroarch_NEC_V20: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
248 case kCpumMicroarch_NEC_V30: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
249 default: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT; break;
250 }
251 LogRel(("IEM: TargetCpu=%s, Microarch=%s aidxTargetCpuEflFlavour={%d,%d}\n",
252 iemGetTargetCpuName(pVCpu->iem.s.uTargetCpu), CPUMMicroarchName(pVM->cpum.ro.GuestFeatures.enmMicroarch),
253 pVCpu->iem.s.aidxTargetCpuEflFlavour[0], pVCpu->iem.s.aidxTargetCpuEflFlavour[1]));
254#else
255 LogRel(("IEM: Microarch=%s aidxTargetCpuEflFlavour={%d,%d}\n",
256 CPUMMicroarchName(pVM->cpum.ro.GuestFeatures.enmMicroarch),
257 pVCpu->iem.s.aidxTargetCpuEflFlavour[0], pVCpu->iem.s.aidxTargetCpuEflFlavour[1]));
258#endif
259 }
260 else
261 {
262 pVCpu->iem.s.enmCpuVendor = pVM->apCpusR3[0]->iem.s.enmCpuVendor;
263 pVCpu->iem.s.enmHostCpuVendor = pVM->apCpusR3[0]->iem.s.enmHostCpuVendor;
264 pVCpu->iem.s.aidxTargetCpuEflFlavour[0] = pVM->apCpusR3[0]->iem.s.aidxTargetCpuEflFlavour[0];
265 pVCpu->iem.s.aidxTargetCpuEflFlavour[1] = pVM->apCpusR3[0]->iem.s.aidxTargetCpuEflFlavour[1];
266#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
267 pVCpu->iem.s.uTargetCpu = pVM->apCpusR3[0]->iem.s.uTargetCpu;
268#endif
269 }
270
271 /*
272 * Mark all buffers free.
273 */
274 uint32_t iMemMap = RT_ELEMENTS(pVCpu->iem.s.aMemMappings);
275 while (iMemMap-- > 0)
276 pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
277
278#ifdef VBOX_WITH_IEM_RECOMPILER
279 /*
280 * Distribute recompiler configuration.
281 */
282 pVCpu->iem.s.uTbNativeRecompileAtUsedCount = uTbNativeRecompileAtUsedCount;
283#endif
284 }
285
286
287#ifdef VBOX_WITH_IEM_RECOMPILER
288 /*
289 * Initialize the TB allocator and cache (/ hash table).
290 *
291 * This is done by each EMT to try get more optimal thread/numa locality of
292 * the allocations.
293 */
294 rc = VMR3ReqCallWait(pVM, VMCPUID_ALL, (PFNRT)iemTbInit, 6,
295 pVM, cInitialTbs, cMaxTbs, cbInitialExec, cbMaxExec, cbChunkExec);
296 AssertLogRelRCReturn(rc, rc);
297#endif
298
299 /*
300 * Register statistics.
301 */
302 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
303 {
304#if !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_NESTED_HWVIRT_VMX) /* quick fix for stupid structure duplication non-sense */
305 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
306 char szPat[128];
307 RT_NOREF_PV(szPat); /* lazy bird */
308 char szVal[128];
309 RT_NOREF_PV(szVal); /* lazy bird */
310
311 STAMR3RegisterF(pVM, &pVCpu->iem.s.cInstructions, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
312 "Instructions interpreted", "/IEM/CPU%u/cInstructions", idCpu);
313 STAMR3RegisterF(pVM, &pVCpu->iem.s.cLongJumps, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
314 "Number of longjmp calls", "/IEM/CPU%u/cLongJumps", idCpu);
315 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPotentialExits, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
316 "Potential exits", "/IEM/CPU%u/cPotentialExits", idCpu);
317 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetAspectNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
318 "VERR_IEM_ASPECT_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetAspectNotImplemented", idCpu);
319 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInstrNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
320 "VERR_IEM_INSTR_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetInstrNotImplemented", idCpu);
321 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInfStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
322 "Informational statuses returned", "/IEM/CPU%u/cRetInfStatuses", idCpu);
323 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetErrStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
324 "Error statuses returned", "/IEM/CPU%u/cRetErrStatuses", idCpu);
325 STAMR3RegisterF(pVM, &pVCpu->iem.s.cbWritten, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
326 "Approx bytes written", "/IEM/CPU%u/cbWritten", idCpu);
327 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPendingCommit, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
328 "Times RC/R0 had to postpone instruction committing to ring-3", "/IEM/CPU%u/cPendingCommit", idCpu);
329 STAMR3RegisterF(pVM, &pVCpu->iem.s.cMisalignedAtomics, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
330 "Number of misaligned (for the host) atomic instructions", "/IEM/CPU%u/cMisalignedAtomics", idCpu);
331
332 /* Code TLB: */
333 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
334 "Code TLB non-global revision", "/IEM/CPU%u/Tlb/Code/RevisionNonGlobal", idCpu);
335 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.uTlbRevisionGlobal, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
336 "Code TLB global revision", "/IEM/CPU%u/Tlb/Code/RevisionGlobal", idCpu);
337 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlsFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
338 "Code TLB non-global flushes", "/IEM/CPU%u/Tlb/Code/RevisionNonGlobalFlushes", idCpu);
339 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlsGlobalFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
340 "Code TLB global flushes", "/IEM/CPU%u/Tlb/Code/RevisionGlobalFlushes", idCpu);
341 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbRevisionRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
342 "Code TLB revision rollovers", "/IEM/CPU%u/Tlb/Code/RevisionRollovers", idCpu);
343
344 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.CodeTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
345 "Code TLB physical revision", "/IEM/CPU%u/Tlb/Code/PhysicalRevision", idCpu);
346 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbPhysRevFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
347 "Code TLB revision flushes", "/IEM/CPU%u/Tlb/Code/PhysicalRevisionFlushes", idCpu);
348 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbPhysRevRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
349 "Code TLB revision rollovers", "/IEM/CPU%u/Tlb/Code/PhysicalRevisionRollovers", idCpu);
350
351 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
352 "Code TLB global large page loads since flush", "/IEM/CPU%u/Tlb/Code/LargePageGlobalCurLoads", idCpu);
353 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
354 "Code TLB global large page range: lowest tag", "/IEM/CPU%u/Tlb/Code/LargePageGlobalFirstTag", idCpu);
355 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.GlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
356 "Code TLB global large page range: last tag", "/IEM/CPU%u/Tlb/Code/LargePageGlobalLastTag", idCpu);
357
358 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNonGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
359 "Code TLB non-global large page loads since flush", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalCurLoads", idCpu);
360 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
361 "Code TLB non-global large page range: lowest tag", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalFirstTag", idCpu);
362 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.NonGlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
363 "Code TLB non-global large page range: last tag", "/IEM/CPU%u/Tlb/Code/LargePageNonGlobalLastTag", idCpu);
364
365 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreMisses, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
366 "Code TLB misses", "/IEM/CPU%u/Tlb/Code/Misses", idCpu);
367 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreGlobalLoads, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
368 "Code TLB global loads", "/IEM/CPU%u/Tlb/Code/Misses/GlobalLoads", idCpu);
369 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbSlowCodeReadPath, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
370 "Code TLB slow read path", "/IEM/CPU%u/Tlb/Code/SlowReads", idCpu);
371# ifdef IEM_WITH_TLB_STATISTICS
372 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbCoreHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
373 "Code TLB hits (non-native)", "/IEM/CPU%u/Tlb/Code/Hits/Other", idCpu);
374# if defined(VBOX_WITH_IEM_NATIVE_RECOMPILER)
375 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbHitsForNewPage, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
376 "Code TLB native hits on new page", "/IEM/CPU%u/Tlb/Code/Hits/New-Page", idCpu);
377 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbHitsForNewPageWithOffset, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
378 "Code TLB native hits on new page /w offset", "/IEM/CPU%u/Tlb/Code/Hits/New-Page-With-Offset", idCpu);
379# endif
380
381 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Code/Hits/*", idCpu);
382 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Code TLB hits",
383 "/IEM/CPU%u/Tlb/Code/Hits", idCpu);
384
385 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Code/Hits|/IEM/CPU%u/Tlb/Code/Misses", idCpu, idCpu);
386 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Code TLB lookups (sum of hits and misses)",
387 "/IEM/CPU%u/Tlb/Code/AllLookups", idCpu);
388
389 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Code/Misses", idCpu);
390 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Code/Hits", idCpu);
391 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PPM, szVal, true, szPat,
392 "Code TLB actual miss rate", "/IEM/CPU%u/Tlb/Code/RateMisses", idCpu);
393
394# if defined(VBOX_WITH_IEM_NATIVE_RECOMPILER)
395 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissTag, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
396 "Code TLB misses in native code: Tag mismatch [not directly included grand parent sum]",
397 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/Tag", idCpu);
398 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissFlagsAndPhysRev, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
399 "Code TLB misses in native code: Flags or physical revision mistmatch [not directly included grand parent sum]",
400 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/FlagsAndPhysRev", idCpu);
401 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissAlignment, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
402 "Code TLB misses in native code: Alignment [not directly included grand parent sum]",
403 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/Alignment", idCpu);
404 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissCrossPage, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
405 "Code TLB misses in native code: Cross page [not directly included grand parent sum]",
406 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/CrossPage", idCpu);
407 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbNativeMissNonCanonical, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
408 "Code TLB misses in native code: Non-canonical [not directly included grand parent sum]",
409 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown/NonCanonical", idCpu);
410
411 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbMissesNewPage, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
412 "Code TLB native misses on new page",
413 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown2/New-Page", idCpu);
414 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCodeTlbMissesNewPageWithOffset, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
415 "Code TLB native misses on new page w/ offset",
416 "/IEM/CPU%u/Tlb/Code/Misses/NativeBreakdown2/New-Page-With-Offset", idCpu);
417# endif
418# endif /* IEM_WITH_TLB_STATISTICS */
419
420 /* Data TLB organized as best we can... */
421 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
422 "Data TLB non-global revision", "/IEM/CPU%u/Tlb/Data/RevisionNonGlobal", idCpu);
423 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.uTlbRevisionGlobal, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
424 "Data TLB global revision", "/IEM/CPU%u/Tlb/Data/RevisionGlobal", idCpu);
425 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlsFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
426 "Data TLB non-global flushes", "/IEM/CPU%u/Tlb/Data/RevisionNonGlobalFlushes", idCpu);
427 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlsGlobalFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
428 "Data TLB global flushes", "/IEM/CPU%u/Tlb/Data/RevisionGlobalFlushes", idCpu);
429 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbRevisionRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
430 "Data TLB revision rollovers", "/IEM/CPU%u/Tlb/Data/RevisionRollovers", idCpu);
431
432 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.DataTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
433 "Data TLB physical revision", "/IEM/CPU%u/Tlb/Data/PhysicalRevision", idCpu);
434 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbPhysRevFlushes, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
435 "Data TLB revision flushes", "/IEM/CPU%u/Tlb/Data/PhysicalRevisionFlushes", idCpu);
436 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbPhysRevRollovers, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
437 "Data TLB revision rollovers", "/IEM/CPU%u/Tlb/Data/PhysicalRevisionRollovers", idCpu);
438
439 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
440 "Data TLB global large page loads since flush", "/IEM/CPU%u/Tlb/Data/LargePageGlobalCurLoads", idCpu);
441 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.GlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
442 "Data TLB global large page range: lowest tag", "/IEM/CPU%u/Tlb/Data/LargePageGlobalFirstTag", idCpu);
443 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.GlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
444 "Data TLB global large page range: last tag", "/IEM/CPU%u/Tlb/Data/LargePageGlobalLastTag", idCpu);
445
446 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNonGlobalLargePageCurLoads, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
447 "Data TLB non-global large page loads since flush", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalCurLoads", idCpu);
448 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uFirstTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
449 "Data TLB non-global large page range: lowest tag", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalFirstTag", idCpu);
450 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.NonGlobalLargePageRange.uLastTag, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
451 "Data TLB non-global large page range: last tag", "/IEM/CPU%u/Tlb/Data/LargePageNonGlobalLastTag", idCpu);
452
453 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreMisses, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
454 "Data TLB core misses (iemMemMap, direct iemMemMapJmp (not safe path))",
455 "/IEM/CPU%u/Tlb/Data/Misses/Core", idCpu);
456 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreGlobalLoads, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
457 "Data TLB global loads",
458 "/IEM/CPU%u/Tlb/Data/Misses/Core/GlobalLoads", idCpu);
459 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeReadPath, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
460 "Data TLB safe read path (inline/native misses going to iemMemMapJmp)",
461 "/IEM/CPU%u/Tlb/Data/Misses/Safe/Reads", idCpu);
462 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeWritePath, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
463 "Data TLB safe write path (inline/native misses going to iemMemMapJmp)",
464 "/IEM/CPU%u/Tlb/Data/Misses/Safe/Writes", idCpu);
465 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Misses/*", idCpu);
466 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB misses",
467 "/IEM/CPU%u/Tlb/Data/Misses", idCpu);
468
469 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Misses/Safe/*", idCpu);
470 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB actual safe path calls (read + write)",
471 "/IEM/CPU%u/Tlb/Data/Misses/Safe", idCpu);
472 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
473 "Data TLB hits in iemMemMapJmp - not part of safe-path total",
474 "/IEM/CPU%u/Tlb/Data/Misses/Safe/SubPartHits", idCpu);
475 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeMisses, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
476 "Data TLB misses in iemMemMapJmp - not part of safe-path total",
477 "/IEM/CPU%u/Tlb/Data/Misses/Safe/SubPartMisses", idCpu);
478 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbSafeGlobalLoads, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
479 "Data TLB global loads",
480 "/IEM/CPU%u/Tlb/Data/Misses/Safe/SubPartMisses/GlobalLoads", idCpu);
481
482# ifdef IEM_WITH_TLB_STATISTICS
483# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
484 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissTag, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
485 "Data TLB misses in native code: Tag mismatch [not directly included grand parent sum]",
486 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/Tag", idCpu);
487 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissFlagsAndPhysRev, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
488 "Data TLB misses in native code: Flags or physical revision mistmatch [not directly included grand parent sum]",
489 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/FlagsAndPhysRev", idCpu);
490 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissAlignment, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
491 "Data TLB misses in native code: Alignment [not directly included grand parent sum]",
492 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/Alignment", idCpu);
493 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissCrossPage, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
494 "Data TLB misses in native code: Cross page [not directly included grand parent sum]",
495 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/CrossPage", idCpu);
496 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbNativeMissNonCanonical, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
497 "Data TLB misses in native code: Non-canonical [not directly included grand parent sum]",
498 "/IEM/CPU%u/Tlb/Data/Misses/NativeBreakdown/NonCanonical", idCpu);
499# endif
500# endif
501
502# ifdef IEM_WITH_TLB_STATISTICS
503 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbCoreHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
504 "Data TLB core hits (iemMemMap, direct iemMemMapJmp (not safe path))",
505 "/IEM/CPU%u/Tlb/Data/Hits/Core", idCpu);
506 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbInlineCodeHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
507 "Data TLB hits in IEMAllMemRWTmplInline.cpp.h",
508 "/IEM/CPU%u/Tlb/Data/Hits/Inline", idCpu);
509# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
510 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForStack, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
511 "Data TLB native stack access hits",
512 "/IEM/CPU%u/Tlb/Data/Hits/Native/Stack", idCpu);
513 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForFetch, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
514 "Data TLB native data fetch hits",
515 "/IEM/CPU%u/Tlb/Data/Hits/Native/Fetch", idCpu);
516 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForStore, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
517 "Data TLB native data store hits",
518 "/IEM/CPU%u/Tlb/Data/Hits/Native/Store", idCpu);
519 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeTlbHitsForMapped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
520 "Data TLB native mapped data hits",
521 "/IEM/CPU%u/Tlb/Data/Hits/Native/Mapped", idCpu);
522# endif
523 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Hits/*", idCpu);
524 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB hits",
525 "/IEM/CPU%u/Tlb/Data/Hits", idCpu);
526
527# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
528 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Hits/Native/*", idCpu);
529 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB hits from native code",
530 "/IEM/CPU%u/Tlb/Data/Hits/Native", idCpu);
531# endif
532
533 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Data/Hits|/IEM/CPU%u/Tlb/Data/Misses", idCpu, idCpu);
534 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Data TLB lookups (sum of hits and misses)",
535 "/IEM/CPU%u/Tlb/Data/AllLookups", idCpu);
536
537 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/Tlb/Data/Misses", idCpu);
538 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/Tlb/Data/Hits", idCpu);
539 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PPM, szVal, true, szPat,
540 "Data TLB actual miss rate", "/IEM/CPU%u/Tlb/Data/RateMisses", idCpu);
541
542# endif /* IEM_WITH_TLB_STATISTICS */
543
544
545#ifdef VBOX_WITH_IEM_RECOMPILER
546 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExecNative, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
547 "Executed native translation block", "/IEM/CPU%u/re/cTbExecNative", idCpu);
548 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.cTbExecThreaded, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
549 "Executed threaded translation block", "/IEM/CPU%u/re/cTbExecThreaded", idCpu);
550 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedExecBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
551 "Times threaded TB execution was interrupted/broken off", "/IEM/CPU%u/re/cTbExecThreadedBreaks", idCpu);
552# ifdef VBOX_WITH_STATISTICS
553 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedExecBreaksWithLookup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
554 "Times threaded TB execution was interrupted/broken off on a call with lookup entries", "/IEM/CPU%u/re/cTbExecThreadedBreaksWithLookup", idCpu);
555 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedExecBreaksWithoutLookup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
556 "Times threaded TB execution was interrupted/broken off on a call without lookup entries", "/IEM/CPU%u/re/cTbExecThreadedBreaksWithoutLookup", idCpu);
557# endif
558
559 PIEMTBALLOCATOR const pTbAllocator = pVCpu->iem.s.pTbAllocatorR3;
560 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatAllocs, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS,
561 "Translation block allocations", "/IEM/CPU%u/re/cTbAllocCalls", idCpu);
562 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatFrees, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS,
563 "Translation block frees", "/IEM/CPU%u/re/cTbFreeCalls", idCpu);
564# ifdef VBOX_WITH_STATISTICS
565 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatPrune, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
566 "Time spent freeing up TBs when full at alloc", "/IEM/CPU%u/re/TbPruningAlloc", idCpu);
567# endif
568 STAMR3RegisterF(pVM, (void *)&pTbAllocator->StatPruneNative, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
569 "Time spent freeing up native TBs when out of executable memory", "/IEM/CPU%u/re/ExecMem/TbPruningNative", idCpu);
570 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cAllocatedChunks, STAMTYPE_U16, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
571 "Populated TB chunks", "/IEM/CPU%u/re/cTbChunks", idCpu);
572 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cMaxChunks, STAMTYPE_U8, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
573 "Max number of TB chunks", "/IEM/CPU%u/re/cTbChunksMax", idCpu);
574 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cTotalTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
575 "Total number of TBs in the allocator", "/IEM/CPU%u/re/cTbTotal", idCpu);
576 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cMaxTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
577 "Max total number of TBs allowed", "/IEM/CPU%u/re/cTbTotalMax", idCpu);
578 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cInUseTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
579 "Number of currently allocated TBs", "/IEM/CPU%u/re/cTbAllocated", idCpu);
580 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cNativeTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
581 "Number of currently allocated native TBs", "/IEM/CPU%u/re/cTbAllocatedNative", idCpu);
582 STAMR3RegisterF(pVM, (void *)&pTbAllocator->cThreadedTbs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
583 "Number of currently allocated threaded TBs", "/IEM/CPU%u/re/cTbAllocatedThreaded", idCpu);
584
585 PIEMTBCACHE const pTbCache = pVCpu->iem.s.pTbCacheR3;
586 STAMR3RegisterF(pVM, (void *)&pTbCache->cHash, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
587 "Translation block lookup table size", "/IEM/CPU%u/re/cTbHashTab", idCpu);
588
589 STAMR3RegisterF(pVM, (void *)&pTbCache->cLookupHits, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
590 "Translation block lookup hits", "/IEM/CPU%u/re/cTbLookupHits", idCpu);
591 STAMR3RegisterF(pVM, (void *)&pTbCache->cLookupHitsViaTbLookupTable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
592 "Translation block lookup hits via TB lookup table associated with the previous TB", "/IEM/CPU%u/re/cTbLookupHitsViaTbLookupTable", idCpu);
593 STAMR3RegisterF(pVM, (void *)&pTbCache->cLookupMisses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
594 "Translation block lookup misses", "/IEM/CPU%u/re/cTbLookupMisses", idCpu);
595 STAMR3RegisterF(pVM, (void *)&pTbCache->cCollisions, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
596 "Translation block hash table collisions", "/IEM/CPU%u/re/cTbCollisions", idCpu);
597# ifdef VBOX_WITH_STATISTICS
598 STAMR3RegisterF(pVM, (void *)&pTbCache->StatPrune, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
599 "Time spent shortening collision lists", "/IEM/CPU%u/re/TbPruningCollisions", idCpu);
600# endif
601
602 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbThreadedCalls, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS_PER_TB,
603 "Calls per threaded translation block", "/IEM/CPU%u/re/ThrdCallsPerTb", idCpu);
604 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbInstr, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_INSTR_PER_TB,
605 "Instruction per threaded translation block", "/IEM/CPU%u/re/ThrdInstrPerTb", idCpu);
606 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbLookupEntries, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_INSTR_PER_TB,
607 "TB lookup table entries per threaded translation block", "/IEM/CPU%u/re/ThrdLookupEntriesPerTb", idCpu);
608
609 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckIrqBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
610 "TB breaks by CheckIrq", "/IEM/CPU%u/re/CheckIrqBreaks", idCpu);
611 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckModeBreaks, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
612 "TB breaks by CheckMode", "/IEM/CPU%u/re/CheckModeBreaks", idCpu);
613 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckBranchMisses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
614 "Branch target misses", "/IEM/CPU%u/re/CheckTbJmpMisses", idCpu);
615 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatCheckNeedCsLimChecking, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
616 "Needing CS.LIM checking TB after branch or on page crossing", "/IEM/CPU%u/re/CheckTbNeedCsLimChecking", idCpu);
617# ifdef VBOX_WITH_STATISTICS
618 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbLoopInTbDetected, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
619 "Detected loop within TB", "/IEM/CPU%u/re/LoopInTbDetected", idCpu);
620#endif
621
622 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeExecMemInstrBufAllocFailed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
623 "Number of times the exec memory allocator failed to allocate a large enough buffer",
624 "/IEM/CPU%u/re/NativeExecMemInstrBufAllocFailed", idCpu);
625
626 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCallsRecompiled, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS_PER_TB,
627 "Number of threaded calls per TB that have been properly recompiled to native code",
628 "/IEM/CPU%u/re/NativeCallsRecompiledPerTb", idCpu);
629 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeCallsThreaded, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS_PER_TB,
630 "Number of threaded calls per TB that could not be recompiler to native code",
631 "/IEM/CPU%u/re/NativeCallsThreadedPerTb", idCpu);
632 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeFullyRecompiledTbs, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
633 "Number of threaded calls that could not be recompiler to native code",
634 "/IEM/CPU%u/re/NativeFullyRecompiledTbs", idCpu);
635
636 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatTbNativeCode, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES_PER_TB,
637 "Size of native code per TB", "/IEM/CPU%u/re/NativeCodeSizePerTb", idCpu);
638 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.StatNativeRecompilation, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
639 "Profiling iemNativeRecompile()", "/IEM/CPU%u/re/NativeRecompilation", idCpu);
640
641# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
642# ifdef VBOX_WITH_STATISTICS
643 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFree, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
644 "Number of calls to iemNativeRegAllocFindFree.",
645 "/IEM/CPU%u/re/NativeRegFindFree", idCpu);
646# endif
647 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
648 "Number of times iemNativeRegAllocFindFree needed to free a variable.",
649 "/IEM/CPU%u/re/NativeRegFindFreeVar", idCpu);
650# ifdef VBOX_WITH_STATISTICS
651 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeNoVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
652 "Number of times iemNativeRegAllocFindFree did not needed to free any variables.",
653 "/IEM/CPU%u/re/NativeRegFindFreeNoVar", idCpu);
654 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeLivenessUnshadowed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
655 "Times liveness info freeed up shadowed guest registers in iemNativeRegAllocFindFree.",
656 "/IEM/CPU%u/re/NativeRegFindFreeLivenessUnshadowed", idCpu);
657 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeRegFindFreeLivenessHelped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
658 "Times liveness info helped finding the return register in iemNativeRegAllocFindFree.",
659 "/IEM/CPU%u/re/NativeRegFindFreeLivenessHelped", idCpu);
660
661 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedArithmetic, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
662 "Skipped all status flag updating, arithmetic instructions",
663 "/IEM/CPU%u/re/NativeEFlagsSkippedArithmetic", idCpu);
664 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeEflSkippedLogical, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
665 "Skipped all status flag updating, logical instructions",
666 "/IEM/CPU%u/re/NativeEFlagsSkippedLogical", idCpu);
667
668 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsCfSkippable", idCpu);
669 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflPfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.PF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsPfSkippable", idCpu);
670 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflAfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.AF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsAfSkippable", idCpu);
671 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflZfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.ZF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsZfSkippable", idCpu);
672 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflSfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.SF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsSfSkippable", idCpu);
673 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflOfSkippable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Skippable EFLAGS.OF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsOfSkippable", idCpu);
674
675 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsCfRequired", idCpu);
676 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflPfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.PF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsPfRequired", idCpu);
677 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflAfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.AF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsAfRequired", idCpu);
678 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflZfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.ZF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsZfRequired", idCpu);
679 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflSfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.SF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsSfRequired", idCpu);
680 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflOfRequired, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Required EFLAGS.OF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsOfRequired", idCpu);
681
682# ifdef IEMLIVENESS_EXTENDED_LAYOUT
683 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflCfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.CF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsCfDelayable", idCpu);
684 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflPfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.PF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsPfDelayable", idCpu);
685 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflAfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.AF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsAfDelayable", idCpu);
686 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflZfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.ZF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsZfDelayable", idCpu);
687 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflSfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.SF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsSfDelayable", idCpu);
688 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeLivenessEflOfDelayable, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Maybe delayable EFLAGS.OF updating", "/IEM/CPU%u/re/NativeLivenessEFlagsOfDelayable", idCpu);
689# endif
690
691 /* Sum up all status bits ('_' is a sorting hack). */
692 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?fSkippable*", idCpu);
693 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total skippable EFLAGS status bit updating",
694 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusSkippable", idCpu);
695
696 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?fRequired*", idCpu);
697 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total required STATUS status bit updating",
698 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusRequired", idCpu);
699
700# ifdef IEMLIVENESS_EXTENDED_LAYOUT
701 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?fDelayable*", idCpu);
702 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total potentially delayable STATUS status bit updating",
703 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusDelayable", idCpu);
704# endif
705
706 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags?f*", idCpu);
707 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat, "Total STATUS status bit events of any kind",
708 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusTotal", idCpu);
709
710 /* Ratio of the status bit skippables. */
711 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlags_StatusTotal", idCpu);
712 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeLivenessEFlags_StatusSkippable", idCpu);
713 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
714 "Total skippable EFLAGS status bit updating percentage",
715 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusSkippablePct", idCpu);
716
717# ifdef IEMLIVENESS_EXTENDED_LAYOUT
718 /* Ratio of the status bit skippables. */
719 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeLivenessEFlags_StatusDelayable", idCpu);
720 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
721 "Total potentially delayable EFLAGS status bit updating percentage",
722 "/IEM/CPU%u/re/NativeLivenessEFlags_StatusDelayablePct", idCpu);
723# endif
724
725 /* Ratios of individual bits. */
726 size_t const offFlagChar = RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeLivenessEFlagsCf*", idCpu) - 3;
727 Assert(szPat[offFlagChar] == 'C');
728 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativeLivenessEFlagsCfSkippable", idCpu);
729 Assert(szVal[offFlagChar] == 'C');
730 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);
731 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);
732 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);
733 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);
734 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);
735 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);
736
737 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateTotal, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Total RIP updates", "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
738 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativePcUpdateDelayed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Delayed RIP updates", "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
739
740# ifdef IEMNATIVE_WITH_SIMD_REG_ALLOCATOR
741 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFree, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
742 "Number of calls to iemNativeSimdRegAllocFindFree.",
743 "/IEM/CPU%u/re/NativeSimdRegFindFree", idCpu);
744 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
745 "Number of times iemNativeSimdRegAllocFindFree needed to free a variable.",
746 "/IEM/CPU%u/re/NativeSimdRegFindFreeVar", idCpu);
747 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeNoVar, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
748 "Number of times iemNativeSimdRegAllocFindFree did not needed to free any variables.",
749 "/IEM/CPU%u/re/NativeSimdRegFindFreeNoVar", idCpu);
750 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeLivenessUnshadowed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
751 "Times liveness info freeed up shadowed guest registers in iemNativeSimdRegAllocFindFree.",
752 "/IEM/CPU%u/re/NativeSimdRegFindFreeLivenessUnshadowed", idCpu);
753 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeSimdRegFindFreeLivenessHelped, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
754 "Times liveness info helped finding the return register in iemNativeSimdRegAllocFindFree.",
755 "/IEM/CPU%u/re/NativeSimdRegFindFreeLivenessHelped", idCpu);
756
757 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeDeviceNotAvailXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE() checks",
758 "/IEM/CPU%u/re/NativeMaybeDeviceNotAvailXcptCheckPotential", idCpu);
759 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeWaitDeviceNotAvailXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_WAIT_DEVICE_NOT_AVAILABLE() checks",
760 "/IEM/CPU%u/re/NativeMaybeWaitDeviceNotAvailXcptCheckPotential", idCpu);
761 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeSseXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT() checks",
762 "/IEM/CPU%u/re/NativeMaybeSseXcptCheckPotential", idCpu);
763 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeAvxXcptCheckPotential, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Potential IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT() checks",
764 "/IEM/CPU%u/re/NativeMaybeAvxXcptCheckPotential", idCpu);
765
766 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeDeviceNotAvailXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_DEVICE_NOT_AVAILABLE() checks omitted",
767 "/IEM/CPU%u/re/NativeMaybeDeviceNotAvailXcptCheckOmitted", idCpu);
768 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeWaitDeviceNotAvailXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_WAIT_DEVICE_NOT_AVAILABLE() checks omitted",
769 "/IEM/CPU%u/re/NativeMaybeWaitDeviceNotAvailXcptCheckOmitted", idCpu);
770 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeSseXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_SSE_RELATED_XCPT() checks omitted",
771 "/IEM/CPU%u/re/NativeMaybeSseXcptCheckOmitted", idCpu);
772 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeMaybeAvxXcptCheckOmitted, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "IEM_MC_MAYBE_RAISE_AVX_RELATED_XCPT() checks omitted",
773 "/IEM/CPU%u/re/NativeMaybeAvxXcptCheckOmitted", idCpu);
774# endif
775
776 /* Ratio of the status bit skippables. */
777 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativePcUpdateTotal", idCpu);
778 RTStrPrintf(szVal, sizeof(szVal), "/IEM/CPU%u/re/NativePcUpdateDelayed", idCpu);
779 STAMR3RegisterPctOfSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, STAMUNIT_PCT, szVal, false, szPat,
780 "Delayed RIP updating percentage",
781 "/IEM/CPU%u/re/NativePcUpdateDelayed_StatusDelayedPct", idCpu);
782
783 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbFinished, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
784 "Number of times the TB finishes execution completely",
785 "/IEM/CPU%u/re/NativeTbFinished", idCpu);
786# endif /* VBOX_WITH_STATISTICS */
787 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnBreak, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
788 "Number of times the TB finished through the ReturnBreak label",
789 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak", idCpu);
790 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnBreakFF, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
791 "Number of times the TB finished through the ReturnBreak label",
792 "/IEM/CPU%u/re/NativeTbExit/ReturnBreakFF", idCpu);
793 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnWithFlags, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
794 "Number of times the TB finished through the ReturnWithFlags label",
795 "/IEM/CPU%u/re/NativeTbExit/ReturnWithFlags", idCpu);
796 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitReturnOtherStatus, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
797 "Number of times the TB finished with some other status value",
798 "/IEM/CPU%u/re/NativeTbExit/ReturnOtherStatus", idCpu);
799 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitLongJump, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
800 "Number of times the TB finished via long jump / throw",
801 "/IEM/CPU%u/re/NativeTbExit/LongJumps", idCpu);
802 /* These end up returning VINF_IEM_REEXEC_BREAK and are thus already counted under NativeTbExit/ReturnBreak: */
803 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitObsoleteTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
804 "Number of times the TB finished through the ObsoleteTb label",
805 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/ObsoleteTb", idCpu);
806 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatCheckNeedCsLimChecking, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
807 "Number of times the TB finished through the NeedCsLimChecking label",
808 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/NeedCsLimChecking", idCpu);
809 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatCheckBranchMisses, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
810 "Number of times the TB finished through the CheckBranchMiss label",
811 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/CheckBranchMiss", idCpu);
812 /* Raising stuff will either increment NativeTbExit/LongJumps or NativeTbExit/ReturnOtherStatus
813 depending on whether VBOX_WITH_IEM_NATIVE_RECOMPILER_LONGJMP is defined: */
814# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER_LONGJMP
815# define RAISE_PREFIX "/IEM/CPU%u/re/NativeTbExit/ReturnOtherStatus/"
816# else
817# define RAISE_PREFIX "/IEM/CPU%u/re/NativeTbExit/LongJumps/"
818# endif
819 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseDe, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
820 "Number of times the TB finished raising a #DE exception",
821 RAISE_PREFIX "RaiseDe", idCpu);
822 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseUd, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
823 "Number of times the TB finished raising a #UD exception",
824 RAISE_PREFIX "RaiseUd", idCpu);
825 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseSseRelated, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
826 "Number of times the TB finished raising a SSE related exception",
827 RAISE_PREFIX "RaiseSseRelated", idCpu);
828 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseAvxRelated, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
829 "Number of times the TB finished raising a AVX related exception",
830 RAISE_PREFIX "RaiseAvxRelated", idCpu);
831 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseSseAvxFpRelated, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
832 "Number of times the TB finished raising a SSE/AVX floating point related exception",
833 RAISE_PREFIX "RaiseSseAvxFpRelated", idCpu);
834 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseNm, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
835 "Number of times the TB finished raising a #NM exception",
836 RAISE_PREFIX "RaiseNm", idCpu);
837 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseGp0, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
838 "Number of times the TB finished raising a #GP(0) exception",
839 RAISE_PREFIX "RaiseGp0", idCpu);
840 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseMf, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
841 "Number of times the TB finished raising a #MF exception",
842 RAISE_PREFIX "RaiseMf", idCpu);
843 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitRaiseXf, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
844 "Number of times the TB finished raising a #XF exception",
845 RAISE_PREFIX "RaiseXf", idCpu);
846
847 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1Irq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
848 "Direct linking #1 with IRQ check succeeded",
849 "/IEM/CPU%u/re/NativeTbExit/DirectLinking1Irq", idCpu);
850 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1NoIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
851 "Direct linking #1 w/o IRQ check succeeded",
852 "/IEM/CPU%u/re/NativeTbExit/DirectLinking1NoIrq", idCpu);
853# ifdef VBOX_WITH_STATISTICS
854 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1NoTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
855 "Direct linking #1 failed: No TB in lookup table",
856 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1NoTb", idCpu);
857 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1MismatchGCPhysPc, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
858 "Direct linking #1 failed: GCPhysPc mismatch",
859 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1MismatchGCPhysPc", idCpu);
860 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1MismatchFlags, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
861 "Direct linking #1 failed: TB flags mismatch",
862 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1MismatchFlags", idCpu);
863 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking1PendingIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
864 "Direct linking #1 failed: IRQ or FF pending",
865 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking1PendingIrq", idCpu);
866# endif
867
868 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2Irq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
869 "Direct linking #2 with IRQ check succeeded",
870 "/IEM/CPU%u/re/NativeTbExit/DirectLinking2Irq", idCpu);
871 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2NoIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
872 "Direct linking #2 w/o IRQ check succeeded",
873 "/IEM/CPU%u/re/NativeTbExit/DirectLinking2NoIrq", idCpu);
874# ifdef VBOX_WITH_STATISTICS
875 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2NoTb, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
876 "Direct linking #2 failed: No TB in lookup table",
877 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2NoTb", idCpu);
878 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2MismatchGCPhysPc, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
879 "Direct linking #2 failed: GCPhysPc mismatch",
880 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2MismatchGCPhysPc", idCpu);
881 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2MismatchFlags, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
882 "Direct linking #2 failed: TB flags mismatch",
883 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2MismatchFlags", idCpu);
884 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatNativeTbExitDirectLinking2PendingIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
885 "Direct linking #2 failed: IRQ or FF pending",
886 "/IEM/CPU%u/re/NativeTbExit/ReturnBreak/DirectLinking2PendingIrq", idCpu);
887# endif
888
889 RTStrPrintf(szPat, sizeof(szPat), "/IEM/CPU%u/re/NativeTbExit/*", idCpu); /* only immediate children, no sub folders */
890 STAMR3RegisterSum(pVM->pUVM, STAMVISIBILITY_ALWAYS, szPat,
891 "Number of times native TB execution finished before the end (not counting thrown memory++ exceptions)",
892 "/IEM/CPU%u/re/NativeTbExit", idCpu);
893
894
895# endif /* VBOX_WITH_IEM_NATIVE_RECOMPILER */
896
897
898# ifdef VBOX_WITH_STATISTICS
899 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemMapJmp, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
900 "iemMemMapJmp calls", "/IEM/CPU%u/iemMemMapJmp", idCpu);
901 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemMapNoJmp, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
902 "iemMemMap calls", "/IEM/CPU%u/iemMemMapNoJmp", idCpu);
903 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemBounceBufferCrossPage, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
904 "iemMemBounceBufferMapCrossPage calls", "/IEM/CPU%u/iemMemMapBounceBufferCrossPage", idCpu);
905 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatMemBounceBufferMapPhys, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
906 "iemMemBounceBufferMapPhys calls", "/IEM/CPU%u/iemMemMapBounceBufferMapPhys", idCpu);
907# endif
908
909
910#endif /* VBOX_WITH_IEM_RECOMPILER */
911
912 for (uint32_t i = 0; i < RT_ELEMENTS(pVCpu->iem.s.aStatXcpts); i++)
913 STAMR3RegisterF(pVM, &pVCpu->iem.s.aStatXcpts[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
914 "", "/IEM/CPU%u/Exceptions/%02x", idCpu, i);
915 for (uint32_t i = 0; i < RT_ELEMENTS(pVCpu->iem.s.aStatInts); i++)
916 STAMR3RegisterF(pVM, &pVCpu->iem.s.aStatInts[i], STAMTYPE_U32_RESET, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
917 "", "/IEM/CPU%u/Interrupts/%02x", idCpu, i);
918
919# if !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_STATISTICS) && !defined(DOXYGEN_RUNNING)
920 /* Instruction statistics: */
921# define IEM_DO_INSTR_STAT(a_Name, a_szDesc) \
922 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatsRZ.a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
923 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-RZ/" #a_Name, idCpu); \
924 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatsR3.a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
925 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-R3/" #a_Name, idCpu);
926# include "IEMInstructionStatisticsTmpl.h"
927# undef IEM_DO_INSTR_STAT
928# endif
929
930# if defined(VBOX_WITH_STATISTICS) && defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
931 /* Threaded function statistics: */
932 for (unsigned i = 1; i < (unsigned)kIemThreadedFunc_End; i++)
933 STAMR3RegisterF(pVM, &pVCpu->iem.s.acThreadedFuncStats[i], STAMTYPE_U32_RESET, STAMVISIBILITY_USED,
934 STAMUNIT_COUNT, NULL, "/IEM/CPU%u/ThrdFuncs/%s", idCpu, g_apszIemThreadedFunctionStats[i]);
935# endif
936
937#endif /* !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_NESTED_HWVIRT_VMX) - quick fix for stupid structure duplication non-sense */
938 }
939
940#if !defined(VBOX_VMM_TARGET_ARMV8) && defined(VBOX_WITH_NESTED_HWVIRT_VMX)
941 /*
942 * Register the per-VM VMX APIC-access page handler type.
943 */
944 if (pVM->cpum.ro.GuestFeatures.fVmx)
945 {
946 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_ALL, PGMPHYSHANDLER_F_NOT_IN_HM,
947 iemVmxApicAccessPageHandler,
948 "VMX APIC-access page", &pVM->iem.s.hVmxApicAccessPage);
949 AssertLogRelRCReturn(rc, rc);
950 }
951#endif
952
953 DBGFR3InfoRegisterInternalArgv(pVM, "itlb", "IEM instruction TLB", iemR3InfoITlb, DBGFINFO_FLAGS_RUN_ON_EMT);
954 DBGFR3InfoRegisterInternalArgv(pVM, "dtlb", "IEM instruction TLB", iemR3InfoDTlb, DBGFINFO_FLAGS_RUN_ON_EMT);
955#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
956 DBGFR3InfoRegisterInternalArgv(pVM, "tb", "IEM translation block", iemR3InfoTb, DBGFINFO_FLAGS_RUN_ON_EMT);
957#endif
958#ifdef VBOX_WITH_DEBUGGER
959 iemR3RegisterDebuggerCommands();
960#endif
961
962 return VINF_SUCCESS;
963}
964
965
966VMMR3DECL(int) IEMR3Term(PVM pVM)
967{
968 NOREF(pVM);
969 return VINF_SUCCESS;
970}
971
972
973VMMR3DECL(void) IEMR3Relocate(PVM pVM)
974{
975 RT_NOREF(pVM);
976}
977
978
979/**
980 * Gets the name of a generic IEM exit code.
981 *
982 * @returns Pointer to read only string if @a uExit is known, otherwise NULL.
983 * @param uExit The IEM exit to name.
984 */
985VMMR3DECL(const char *) IEMR3GetExitName(uint32_t uExit)
986{
987 static const char * const s_apszNames[] =
988 {
989 /* external interrupts */
990 "ExtInt 00h", "ExtInt 01h", "ExtInt 02h", "ExtInt 03h", "ExtInt 04h", "ExtInt 05h", "ExtInt 06h", "ExtInt 07h",
991 "ExtInt 08h", "ExtInt 09h", "ExtInt 0ah", "ExtInt 0bh", "ExtInt 0ch", "ExtInt 0dh", "ExtInt 0eh", "ExtInt 0fh",
992 "ExtInt 10h", "ExtInt 11h", "ExtInt 12h", "ExtInt 13h", "ExtInt 14h", "ExtInt 15h", "ExtInt 16h", "ExtInt 17h",
993 "ExtInt 18h", "ExtInt 19h", "ExtInt 1ah", "ExtInt 1bh", "ExtInt 1ch", "ExtInt 1dh", "ExtInt 1eh", "ExtInt 1fh",
994 "ExtInt 20h", "ExtInt 21h", "ExtInt 22h", "ExtInt 23h", "ExtInt 24h", "ExtInt 25h", "ExtInt 26h", "ExtInt 27h",
995 "ExtInt 28h", "ExtInt 29h", "ExtInt 2ah", "ExtInt 2bh", "ExtInt 2ch", "ExtInt 2dh", "ExtInt 2eh", "ExtInt 2fh",
996 "ExtInt 30h", "ExtInt 31h", "ExtInt 32h", "ExtInt 33h", "ExtInt 34h", "ExtInt 35h", "ExtInt 36h", "ExtInt 37h",
997 "ExtInt 38h", "ExtInt 39h", "ExtInt 3ah", "ExtInt 3bh", "ExtInt 3ch", "ExtInt 3dh", "ExtInt 3eh", "ExtInt 3fh",
998 "ExtInt 40h", "ExtInt 41h", "ExtInt 42h", "ExtInt 43h", "ExtInt 44h", "ExtInt 45h", "ExtInt 46h", "ExtInt 47h",
999 "ExtInt 48h", "ExtInt 49h", "ExtInt 4ah", "ExtInt 4bh", "ExtInt 4ch", "ExtInt 4dh", "ExtInt 4eh", "ExtInt 4fh",
1000 "ExtInt 50h", "ExtInt 51h", "ExtInt 52h", "ExtInt 53h", "ExtInt 54h", "ExtInt 55h", "ExtInt 56h", "ExtInt 57h",
1001 "ExtInt 58h", "ExtInt 59h", "ExtInt 5ah", "ExtInt 5bh", "ExtInt 5ch", "ExtInt 5dh", "ExtInt 5eh", "ExtInt 5fh",
1002 "ExtInt 60h", "ExtInt 61h", "ExtInt 62h", "ExtInt 63h", "ExtInt 64h", "ExtInt 65h", "ExtInt 66h", "ExtInt 67h",
1003 "ExtInt 68h", "ExtInt 69h", "ExtInt 6ah", "ExtInt 6bh", "ExtInt 6ch", "ExtInt 6dh", "ExtInt 6eh", "ExtInt 6fh",
1004 "ExtInt 70h", "ExtInt 71h", "ExtInt 72h", "ExtInt 73h", "ExtInt 74h", "ExtInt 75h", "ExtInt 76h", "ExtInt 77h",
1005 "ExtInt 78h", "ExtInt 79h", "ExtInt 7ah", "ExtInt 7bh", "ExtInt 7ch", "ExtInt 7dh", "ExtInt 7eh", "ExtInt 7fh",
1006 "ExtInt 80h", "ExtInt 81h", "ExtInt 82h", "ExtInt 83h", "ExtInt 84h", "ExtInt 85h", "ExtInt 86h", "ExtInt 87h",
1007 "ExtInt 88h", "ExtInt 89h", "ExtInt 8ah", "ExtInt 8bh", "ExtInt 8ch", "ExtInt 8dh", "ExtInt 8eh", "ExtInt 8fh",
1008 "ExtInt 90h", "ExtInt 91h", "ExtInt 92h", "ExtInt 93h", "ExtInt 94h", "ExtInt 95h", "ExtInt 96h", "ExtInt 97h",
1009 "ExtInt 98h", "ExtInt 99h", "ExtInt 9ah", "ExtInt 9bh", "ExtInt 9ch", "ExtInt 9dh", "ExtInt 9eh", "ExtInt 9fh",
1010 "ExtInt a0h", "ExtInt a1h", "ExtInt a2h", "ExtInt a3h", "ExtInt a4h", "ExtInt a5h", "ExtInt a6h", "ExtInt a7h",
1011 "ExtInt a8h", "ExtInt a9h", "ExtInt aah", "ExtInt abh", "ExtInt ach", "ExtInt adh", "ExtInt aeh", "ExtInt afh",
1012 "ExtInt b0h", "ExtInt b1h", "ExtInt b2h", "ExtInt b3h", "ExtInt b4h", "ExtInt b5h", "ExtInt b6h", "ExtInt b7h",
1013 "ExtInt b8h", "ExtInt b9h", "ExtInt bah", "ExtInt bbh", "ExtInt bch", "ExtInt bdh", "ExtInt beh", "ExtInt bfh",
1014 "ExtInt c0h", "ExtInt c1h", "ExtInt c2h", "ExtInt c3h", "ExtInt c4h", "ExtInt c5h", "ExtInt c6h", "ExtInt c7h",
1015 "ExtInt c8h", "ExtInt c9h", "ExtInt cah", "ExtInt cbh", "ExtInt cch", "ExtInt cdh", "ExtInt ceh", "ExtInt cfh",
1016 "ExtInt d0h", "ExtInt d1h", "ExtInt d2h", "ExtInt d3h", "ExtInt d4h", "ExtInt d5h", "ExtInt d6h", "ExtInt d7h",
1017 "ExtInt d8h", "ExtInt d9h", "ExtInt dah", "ExtInt dbh", "ExtInt dch", "ExtInt ddh", "ExtInt deh", "ExtInt dfh",
1018 "ExtInt e0h", "ExtInt e1h", "ExtInt e2h", "ExtInt e3h", "ExtInt e4h", "ExtInt e5h", "ExtInt e6h", "ExtInt e7h",
1019 "ExtInt e8h", "ExtInt e9h", "ExtInt eah", "ExtInt ebh", "ExtInt ech", "ExtInt edh", "ExtInt eeh", "ExtInt efh",
1020 "ExtInt f0h", "ExtInt f1h", "ExtInt f2h", "ExtInt f3h", "ExtInt f4h", "ExtInt f5h", "ExtInt f6h", "ExtInt f7h",
1021 "ExtInt f8h", "ExtInt f9h", "ExtInt fah", "ExtInt fbh", "ExtInt fch", "ExtInt fdh", "ExtInt feh", "ExtInt ffh",
1022 /* software interrups */
1023 "SoftInt 00h", "SoftInt 01h", "SoftInt 02h", "SoftInt 03h", "SoftInt 04h", "SoftInt 05h", "SoftInt 06h", "SoftInt 07h",
1024 "SoftInt 08h", "SoftInt 09h", "SoftInt 0ah", "SoftInt 0bh", "SoftInt 0ch", "SoftInt 0dh", "SoftInt 0eh", "SoftInt 0fh",
1025 "SoftInt 10h", "SoftInt 11h", "SoftInt 12h", "SoftInt 13h", "SoftInt 14h", "SoftInt 15h", "SoftInt 16h", "SoftInt 17h",
1026 "SoftInt 18h", "SoftInt 19h", "SoftInt 1ah", "SoftInt 1bh", "SoftInt 1ch", "SoftInt 1dh", "SoftInt 1eh", "SoftInt 1fh",
1027 "SoftInt 20h", "SoftInt 21h", "SoftInt 22h", "SoftInt 23h", "SoftInt 24h", "SoftInt 25h", "SoftInt 26h", "SoftInt 27h",
1028 "SoftInt 28h", "SoftInt 29h", "SoftInt 2ah", "SoftInt 2bh", "SoftInt 2ch", "SoftInt 2dh", "SoftInt 2eh", "SoftInt 2fh",
1029 "SoftInt 30h", "SoftInt 31h", "SoftInt 32h", "SoftInt 33h", "SoftInt 34h", "SoftInt 35h", "SoftInt 36h", "SoftInt 37h",
1030 "SoftInt 38h", "SoftInt 39h", "SoftInt 3ah", "SoftInt 3bh", "SoftInt 3ch", "SoftInt 3dh", "SoftInt 3eh", "SoftInt 3fh",
1031 "SoftInt 40h", "SoftInt 41h", "SoftInt 42h", "SoftInt 43h", "SoftInt 44h", "SoftInt 45h", "SoftInt 46h", "SoftInt 47h",
1032 "SoftInt 48h", "SoftInt 49h", "SoftInt 4ah", "SoftInt 4bh", "SoftInt 4ch", "SoftInt 4dh", "SoftInt 4eh", "SoftInt 4fh",
1033 "SoftInt 50h", "SoftInt 51h", "SoftInt 52h", "SoftInt 53h", "SoftInt 54h", "SoftInt 55h", "SoftInt 56h", "SoftInt 57h",
1034 "SoftInt 58h", "SoftInt 59h", "SoftInt 5ah", "SoftInt 5bh", "SoftInt 5ch", "SoftInt 5dh", "SoftInt 5eh", "SoftInt 5fh",
1035 "SoftInt 60h", "SoftInt 61h", "SoftInt 62h", "SoftInt 63h", "SoftInt 64h", "SoftInt 65h", "SoftInt 66h", "SoftInt 67h",
1036 "SoftInt 68h", "SoftInt 69h", "SoftInt 6ah", "SoftInt 6bh", "SoftInt 6ch", "SoftInt 6dh", "SoftInt 6eh", "SoftInt 6fh",
1037 "SoftInt 70h", "SoftInt 71h", "SoftInt 72h", "SoftInt 73h", "SoftInt 74h", "SoftInt 75h", "SoftInt 76h", "SoftInt 77h",
1038 "SoftInt 78h", "SoftInt 79h", "SoftInt 7ah", "SoftInt 7bh", "SoftInt 7ch", "SoftInt 7dh", "SoftInt 7eh", "SoftInt 7fh",
1039 "SoftInt 80h", "SoftInt 81h", "SoftInt 82h", "SoftInt 83h", "SoftInt 84h", "SoftInt 85h", "SoftInt 86h", "SoftInt 87h",
1040 "SoftInt 88h", "SoftInt 89h", "SoftInt 8ah", "SoftInt 8bh", "SoftInt 8ch", "SoftInt 8dh", "SoftInt 8eh", "SoftInt 8fh",
1041 "SoftInt 90h", "SoftInt 91h", "SoftInt 92h", "SoftInt 93h", "SoftInt 94h", "SoftInt 95h", "SoftInt 96h", "SoftInt 97h",
1042 "SoftInt 98h", "SoftInt 99h", "SoftInt 9ah", "SoftInt 9bh", "SoftInt 9ch", "SoftInt 9dh", "SoftInt 9eh", "SoftInt 9fh",
1043 "SoftInt a0h", "SoftInt a1h", "SoftInt a2h", "SoftInt a3h", "SoftInt a4h", "SoftInt a5h", "SoftInt a6h", "SoftInt a7h",
1044 "SoftInt a8h", "SoftInt a9h", "SoftInt aah", "SoftInt abh", "SoftInt ach", "SoftInt adh", "SoftInt aeh", "SoftInt afh",
1045 "SoftInt b0h", "SoftInt b1h", "SoftInt b2h", "SoftInt b3h", "SoftInt b4h", "SoftInt b5h", "SoftInt b6h", "SoftInt b7h",
1046 "SoftInt b8h", "SoftInt b9h", "SoftInt bah", "SoftInt bbh", "SoftInt bch", "SoftInt bdh", "SoftInt beh", "SoftInt bfh",
1047 "SoftInt c0h", "SoftInt c1h", "SoftInt c2h", "SoftInt c3h", "SoftInt c4h", "SoftInt c5h", "SoftInt c6h", "SoftInt c7h",
1048 "SoftInt c8h", "SoftInt c9h", "SoftInt cah", "SoftInt cbh", "SoftInt cch", "SoftInt cdh", "SoftInt ceh", "SoftInt cfh",
1049 "SoftInt d0h", "SoftInt d1h", "SoftInt d2h", "SoftInt d3h", "SoftInt d4h", "SoftInt d5h", "SoftInt d6h", "SoftInt d7h",
1050 "SoftInt d8h", "SoftInt d9h", "SoftInt dah", "SoftInt dbh", "SoftInt dch", "SoftInt ddh", "SoftInt deh", "SoftInt dfh",
1051 "SoftInt e0h", "SoftInt e1h", "SoftInt e2h", "SoftInt e3h", "SoftInt e4h", "SoftInt e5h", "SoftInt e6h", "SoftInt e7h",
1052 "SoftInt e8h", "SoftInt e9h", "SoftInt eah", "SoftInt ebh", "SoftInt ech", "SoftInt edh", "SoftInt eeh", "SoftInt efh",
1053 "SoftInt f0h", "SoftInt f1h", "SoftInt f2h", "SoftInt f3h", "SoftInt f4h", "SoftInt f5h", "SoftInt f6h", "SoftInt f7h",
1054 "SoftInt f8h", "SoftInt f9h", "SoftInt fah", "SoftInt fbh", "SoftInt fch", "SoftInt fdh", "SoftInt feh", "SoftInt ffh",
1055 };
1056 if (uExit < RT_ELEMENTS(s_apszNames))
1057 return s_apszNames[uExit];
1058 return NULL;
1059}
1060
1061
1062/** Worker for iemR3InfoTlbPrintSlots and iemR3InfoTlbPrintAddress. */
1063static void iemR3InfoTlbPrintHeader(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, bool *pfHeader)
1064{
1065 if (*pfHeader)
1066 return;
1067 pHlp->pfnPrintf(pHlp, "%cTLB for CPU %u:\n", &pVCpu->iem.s.CodeTlb == pTlb ? 'I' : 'D', pVCpu->idCpu);
1068 *pfHeader = true;
1069}
1070
1071
1072/** Worker for iemR3InfoTlbPrintSlots and iemR3InfoTlbPrintAddress. */
1073static void iemR3InfoTlbPrintSlot(PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, IEMTLBENTRY const *pTlbe, uint32_t uSlot)
1074{
1075 pHlp->pfnPrintf(pHlp, "%02x: %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s%s/%s%s%s/%s %s\n",
1076 uSlot,
1077 (pTlbe->uTag & IEMTLB_REVISION_MASK) == pTlb->uTlbRevision ? "valid "
1078 : (pTlbe->uTag & IEMTLB_REVISION_MASK) == 0 ? "empty "
1079 : "expired",
1080 (pTlbe->uTag & ~IEMTLB_REVISION_MASK) << X86_PAGE_SHIFT,
1081 pTlbe->GCPhys, pTlbe->pbMappingR3,
1082 (uint32_t)(pTlbe->fFlagsAndPhysRev & ~IEMTLBE_F_PHYS_REV),
1083 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_EXEC ? "NX" : " X",
1084 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_WRITE ? "RO" : "RW",
1085 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_ACCESSED ? "-" : "A",
1086 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY ? "-" : "D",
1087 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_LARGE_PAGE ? "-" : "S",
1088 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_WRITE ? "-" : "w",
1089 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_READ ? "-" : "r",
1090 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_UNASSIGNED ? "U" : "-",
1091 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_NO_MAPPINGR3 ? "S" : "M",
1092 (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == pTlb->uTlbPhysRev ? "phys-valid"
1093 : (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == 0 ? "phys-empty" : "phys-expired");
1094}
1095
1096
1097/** Displays one or more TLB slots. */
1098static void iemR3InfoTlbPrintSlots(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb,
1099 uint32_t uSlot, uint32_t cSlots, bool *pfHeader)
1100{
1101 if (uSlot < RT_ELEMENTS(pTlb->aEntries))
1102 {
1103 if (cSlots > RT_ELEMENTS(pTlb->aEntries))
1104 {
1105 pHlp->pfnPrintf(pHlp, "error: Too many slots given: %u, adjusting it down to the max (%u)\n",
1106 cSlots, RT_ELEMENTS(pTlb->aEntries));
1107 cSlots = RT_ELEMENTS(pTlb->aEntries);
1108 }
1109
1110 iemR3InfoTlbPrintHeader(pVCpu, pHlp, pTlb, pfHeader);
1111 while (cSlots-- > 0)
1112 {
1113 IEMTLBENTRY const Tlbe = pTlb->aEntries[uSlot];
1114 iemR3InfoTlbPrintSlot(pHlp, pTlb, &Tlbe, uSlot);
1115 uSlot = (uSlot + 1) % RT_ELEMENTS(pTlb->aEntries);
1116 }
1117 }
1118 else
1119 pHlp->pfnPrintf(pHlp, "error: TLB slot is out of range: %u (%#x), max %u (%#x)\n",
1120 uSlot, uSlot, RT_ELEMENTS(pTlb->aEntries) - 1, RT_ELEMENTS(pTlb->aEntries) - 1);
1121}
1122
1123
1124/** Displays the TLB slot for the given address. */
1125static void iemR3InfoTlbPrintAddress(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb,
1126 uint64_t uAddress, bool *pfHeader)
1127{
1128 iemR3InfoTlbPrintHeader(pVCpu, pHlp, pTlb, pfHeader);
1129
1130 uint64_t const uTag = (uAddress << 16) >> (X86_PAGE_SHIFT + 16);
1131 uint32_t const uSlot = (uint8_t)uTag;
1132 IEMTLBENTRY const Tlbe = pTlb->aEntries[uSlot];
1133 pHlp->pfnPrintf(pHlp, "Address %#RX64 -> slot %#x - %s\n", uAddress, uSlot,
1134 Tlbe.uTag == (uTag | pTlb->uTlbRevision) ? "match"
1135 : (Tlbe.uTag & ~IEMTLB_REVISION_MASK) == uTag ? "expired" : "mismatch");
1136 iemR3InfoTlbPrintSlot(pHlp, pTlb, &Tlbe, uSlot);
1137}
1138
1139
1140/** Common worker for iemR3InfoDTlb and iemR3InfoITlb. */
1141static void iemR3InfoTlbCommon(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs, bool fITlb)
1142{
1143 /*
1144 * This is entirely argument driven.
1145 */
1146 static RTGETOPTDEF const s_aOptions[] =
1147 {
1148 { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
1149 { "--vcpu", 'c', RTGETOPT_REQ_UINT32 },
1150 { "all", 'A', RTGETOPT_REQ_NOTHING },
1151 { "--all", 'A', RTGETOPT_REQ_NOTHING },
1152 { "--address", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1153 { "--range", 'r', RTGETOPT_REQ_UINT32_PAIR | RTGETOPT_FLAG_HEX },
1154 { "--slot", 's', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX },
1155 };
1156
1157 char szDefault[] = "-A";
1158 char *papszDefaults[2] = { szDefault, NULL };
1159 if (cArgs == 0)
1160 {
1161 cArgs = 1;
1162 papszArgs = papszDefaults;
1163 }
1164
1165 RTGETOPTSTATE State;
1166 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
1167 AssertRCReturnVoid(rc);
1168
1169 bool fNeedHeader = true;
1170 bool fAddressMode = true;
1171 PVMCPU pVCpu = VMMGetCpu(pVM);
1172 if (!pVCpu)
1173 pVCpu = VMMGetCpuById(pVM, 0);
1174
1175 RTGETOPTUNION ValueUnion;
1176 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
1177 {
1178 switch (rc)
1179 {
1180 case 'c':
1181 if (ValueUnion.u32 >= pVM->cCpus)
1182 pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
1183 else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
1184 {
1185 pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
1186 fNeedHeader = true;
1187 }
1188 break;
1189
1190 case 'a':
1191 iemR3InfoTlbPrintAddress(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1192 ValueUnion.u64, &fNeedHeader);
1193 fAddressMode = true;
1194 break;
1195
1196 case 'A':
1197 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1198 0, RT_ELEMENTS(pVCpu->iem.s.CodeTlb.aEntries), &fNeedHeader);
1199 break;
1200
1201 case 'r':
1202 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1203 ValueUnion.PairU32.uFirst, ValueUnion.PairU32.uSecond, &fNeedHeader);
1204 fAddressMode = false;
1205 break;
1206
1207 case 's':
1208 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1209 ValueUnion.u32, 1, &fNeedHeader);
1210 fAddressMode = false;
1211 break;
1212
1213 case VINF_GETOPT_NOT_OPTION:
1214 if (fAddressMode)
1215 {
1216 uint64_t uAddr;
1217 rc = RTStrToUInt64Full(ValueUnion.psz, 16, &uAddr);
1218 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG)
1219 iemR3InfoTlbPrintAddress(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1220 uAddr, &fNeedHeader);
1221 else
1222 pHlp->pfnPrintf(pHlp, "error: Invalid or malformed guest address '%s': %Rrc\n", ValueUnion.psz, rc);
1223 }
1224 else
1225 {
1226 uint32_t uSlot;
1227 rc = RTStrToUInt32Full(ValueUnion.psz, 16, &uSlot);
1228 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG)
1229 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
1230 uSlot, 1, &fNeedHeader);
1231 else
1232 pHlp->pfnPrintf(pHlp, "error: Invalid or malformed TLB slot number '%s': %Rrc\n", ValueUnion.psz, rc);
1233 }
1234 break;
1235
1236 case 'h':
1237 pHlp->pfnPrintf(pHlp,
1238 "Usage: info %ctlb [options]\n"
1239 "\n"
1240 "Options:\n"
1241 " -c<n>, --cpu=<n>, --vcpu=<n>\n"
1242 " Selects the CPU which TLBs we're looking at. Default: Caller / 0\n"
1243 " -A, --all, all\n"
1244 " Display all the TLB entries (default if no other args).\n"
1245 " -a<virt>, --address=<virt>\n"
1246 " Shows the TLB entry for the specified guest virtual address.\n"
1247 " -r<slot:count>, --range=<slot:count>\n"
1248 " Shows the TLB entries for the specified slot range.\n"
1249 " -s<slot>,--slot=<slot>\n"
1250 " Shows the given TLB slot.\n"
1251 "\n"
1252 "Non-options are interpreted according to the last -a, -r or -s option,\n"
1253 "defaulting to addresses if not preceeded by any of those options.\n"
1254 , fITlb ? 'i' : 'd');
1255 return;
1256
1257 default:
1258 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
1259 return;
1260 }
1261 }
1262}
1263
1264
1265/**
1266 * @callback_method_impl{FNDBGFINFOARGVINT, itlb}
1267 */
1268static DECLCALLBACK(void) iemR3InfoITlb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1269{
1270 return iemR3InfoTlbCommon(pVM, pHlp, cArgs, papszArgs, true /*fITlb*/);
1271}
1272
1273
1274/**
1275 * @callback_method_impl{FNDBGFINFOARGVINT, dtlb}
1276 */
1277static DECLCALLBACK(void) iemR3InfoDTlb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1278{
1279 return iemR3InfoTlbCommon(pVM, pHlp, cArgs, papszArgs, false /*fITlb*/);
1280}
1281
1282#if defined(VBOX_WITH_IEM_RECOMPILER) && !defined(VBOX_VMM_TARGET_ARMV8)
1283/**
1284 * @callback_method_impl{FNDBGFINFOARGVINT, tb}
1285 */
1286static DECLCALLBACK(void) iemR3InfoTb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
1287{
1288 /*
1289 * Parse arguments.
1290 */
1291 static RTGETOPTDEF const s_aOptions[] =
1292 {
1293 { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
1294 { "--vcpu", 'c', RTGETOPT_REQ_UINT32 },
1295 { "--addr", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1296 { "--address", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1297 { "--phys", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1298 { "--physical", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1299 { "--phys-addr", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1300 { "--phys-address", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1301 { "--physical-address", 'p', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
1302 { "--flags", 'f', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX },
1303 };
1304
1305 RTGETOPTSTATE State;
1306 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
1307 AssertRCReturnVoid(rc);
1308
1309 PVMCPU const pVCpuThis = VMMGetCpu(pVM);
1310 PVMCPU pVCpu = pVCpuThis ? pVCpuThis : VMMGetCpuById(pVM, 0);
1311 RTGCPHYS GCPhysPc = NIL_RTGCPHYS;
1312 RTGCPHYS GCVirt = NIL_RTGCPTR;
1313 uint32_t fFlags = UINT32_MAX;
1314
1315 RTGETOPTUNION ValueUnion;
1316 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
1317 {
1318 switch (rc)
1319 {
1320 case 'c':
1321 if (ValueUnion.u32 >= pVM->cCpus)
1322 pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
1323 else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
1324 pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
1325 break;
1326
1327 case 'a':
1328 GCVirt = ValueUnion.u64;
1329 GCPhysPc = NIL_RTGCPHYS;
1330 break;
1331
1332 case 'p':
1333 GCVirt = NIL_RTGCPHYS;
1334 GCPhysPc = ValueUnion.u64;
1335 break;
1336
1337 case 'f':
1338 fFlags = ValueUnion.u32;
1339 break;
1340
1341 case 'h':
1342 pHlp->pfnPrintf(pHlp,
1343 "Usage: info tb [options]\n"
1344 "\n"
1345 "Options:\n"
1346 " -c<n>, --cpu=<n>, --vcpu=<n>\n"
1347 " Selects the CPU which TBs we're looking at. Default: Caller / 0\n"
1348 " -a<virt>, --address=<virt>\n"
1349 " Shows the TB for the specified guest virtual address.\n"
1350 " -p<phys>, --phys=<phys>, --phys-addr=<phys>\n"
1351 " Shows the TB for the specified guest physical address.\n"
1352 " -f<flags>,--flags=<flags>\n"
1353 " The TB flags value (hex) to use when looking up the TB.\n"
1354 "\n"
1355 "The default is to use CS:RIP and derive flags from the CPU mode.\n");
1356 return;
1357
1358 default:
1359 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
1360 return;
1361 }
1362 }
1363
1364 /* Currently, only do work on the same EMT. */
1365 if (pVCpu != pVCpuThis)
1366 {
1367 pHlp->pfnPrintf(pHlp, "TODO: Cross EMT calling not supported yet: targeting %u, caller on %d\n",
1368 pVCpu->idCpu, pVCpuThis ? (int)pVCpuThis->idCpu : -1);
1369 return;
1370 }
1371
1372 /*
1373 * Defaults.
1374 */
1375 if (GCPhysPc == NIL_RTGCPHYS)
1376 {
1377 if (GCVirt == NIL_RTGCPTR)
1378 GCVirt = CPUMGetGuestFlatPC(pVCpu);
1379 rc = PGMPhysGCPtr2GCPhys(pVCpu, GCVirt, &GCPhysPc);
1380 if (RT_FAILURE(rc))
1381 {
1382 pHlp->pfnPrintf(pHlp, "Failed to convert %%%RGv to an guest physical address: %Rrc\n", GCVirt, rc);
1383 return;
1384 }
1385 }
1386 if (fFlags == UINT32_MAX)
1387 {
1388 /* Note! This is duplicating code in IEMAllThrdRecompiler. */
1389 fFlags = iemCalcExecFlags(pVCpu);
1390 if (pVM->cCpus == 1)
1391 fFlags |= IEM_F_X86_DISREGARD_LOCK;
1392 if (CPUMIsInInterruptShadow(&pVCpu->cpum.GstCtx))
1393 fFlags |= IEMTB_F_INHIBIT_SHADOW;
1394 if (CPUMAreInterruptsInhibitedByNmiEx(&pVCpu->cpum.GstCtx))
1395 fFlags |= IEMTB_F_INHIBIT_NMI;
1396 if ((IEM_F_MODE_CPUMODE_MASK & fFlags) != IEMMODE_64BIT)
1397 {
1398 int64_t const offFromLim = (int64_t)pVCpu->cpum.GstCtx.cs.u32Limit - (int64_t)pVCpu->cpum.GstCtx.eip;
1399 if (offFromLim < X86_PAGE_SIZE + 16 - (int32_t)(pVCpu->cpum.GstCtx.cs.u64Base & GUEST_PAGE_OFFSET_MASK))
1400 fFlags |= IEMTB_F_CS_LIM_CHECKS;
1401 }
1402 }
1403
1404 /*
1405 * Do the lookup...
1406 *
1407 * Note! This is also duplicating code in IEMAllThrdRecompiler. We don't
1408 * have much choice since we don't want to increase use counters and
1409 * trigger native recompilation.
1410 */
1411 fFlags &= IEMTB_F_KEY_MASK;
1412 IEMTBCACHE const * const pTbCache = pVCpu->iem.s.pTbCacheR3;
1413 uint32_t const idxHash = IEMTBCACHE_HASH(pTbCache, fFlags, GCPhysPc);
1414 PCIEMTB pTb = IEMTBCACHE_PTR_GET_TB(pTbCache->apHash[idxHash]);
1415 while (pTb)
1416 {
1417 if (pTb->GCPhysPc == GCPhysPc)
1418 {
1419 if ((pTb->fFlags & IEMTB_F_KEY_MASK) == fFlags)
1420 {
1421 /// @todo if (pTb->x86.fAttr == (uint16_t)pVCpu->cpum.GstCtx.cs.Attr.u)
1422 break;
1423 }
1424 }
1425 pTb = pTb->pNext;
1426 }
1427 if (!pTb)
1428 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x - no TB found on #%u\n", GCPhysPc, fFlags, pVCpu->idCpu);
1429 else
1430 {
1431 /*
1432 * Disassemble according to type.
1433 */
1434 switch (pTb->fFlags & IEMTB_F_TYPE_MASK)
1435 {
1436# ifdef VBOX_WITH_IEM_NATIVE_RECOMPILER
1437 case IEMTB_F_TYPE_NATIVE:
1438 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - native\n", GCPhysPc, fFlags, pVCpu->idCpu, pTb);
1439 iemNativeDisassembleTb(pVCpu, pTb, pHlp);
1440 break;
1441# endif
1442
1443 case IEMTB_F_TYPE_THREADED:
1444 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - threaded\n", GCPhysPc, fFlags, pVCpu->idCpu, pTb);
1445 iemThreadedDisassembleTb(pTb, pHlp);
1446 break;
1447
1448 default:
1449 pHlp->pfnPrintf(pHlp, "PC=%RGp fFlags=%#x on #%u: %p - ??? %#x\n",
1450 GCPhysPc, fFlags, pVCpu->idCpu, pTb, pTb->fFlags);
1451 break;
1452 }
1453 }
1454}
1455#endif /* VBOX_WITH_IEM_RECOMPILER && !VBOX_VMM_TARGET_ARMV8 */
1456
1457
1458#ifdef VBOX_WITH_DEBUGGER
1459
1460/** @callback_method_impl{FNDBGCCMD,
1461 * Implements the '.alliem' command. }
1462 */
1463static DECLCALLBACK(int) iemR3DbgFlushTlbs(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
1464{
1465 VMCPUID idCpu = DBGCCmdHlpGetCurrentCpu(pCmdHlp);
1466 PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, idCpu);
1467 if (pVCpu)
1468 {
1469 VMR3ReqPriorityCallVoidWaitU(pUVM, idCpu, (PFNRT)IEMTlbInvalidateAllGlobal, 1, pVCpu);
1470 return VINF_SUCCESS;
1471 }
1472 RT_NOREF(paArgs, cArgs);
1473 return DBGCCmdHlpFail(pCmdHlp, pCmd, "failed to get the PVMCPU for the current CPU");
1474}
1475
1476
1477/**
1478 * Called by IEMR3Init to register debugger commands.
1479 */
1480static void iemR3RegisterDebuggerCommands(void)
1481{
1482 /*
1483 * Register debugger commands.
1484 */
1485 static DBGCCMD const s_aCmds[] =
1486 {
1487 {
1488 /* .pszCmd = */ "iemflushtlb",
1489 /* .cArgsMin = */ 0,
1490 /* .cArgsMax = */ 0,
1491 /* .paArgDescs = */ NULL,
1492 /* .cArgDescs = */ 0,
1493 /* .fFlags = */ 0,
1494 /* .pfnHandler = */ iemR3DbgFlushTlbs,
1495 /* .pszSyntax = */ "",
1496 /* .pszDescription = */ "Flushed the code and data TLBs"
1497 },
1498 };
1499
1500 int rc = DBGCRegisterCommands(&s_aCmds[0], RT_ELEMENTS(s_aCmds));
1501 AssertLogRelRC(rc);
1502}
1503
1504#endif /* VBOX_WITH_DEBUGGER */
1505
Note: See TracBrowser for help on using the repository browser.

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