VirtualBox

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

Last change on this file since 105428 was 105428, checked in by vboxsync, 6 months ago

VMM/IEM: More 'info dtlb/itlb' details. [build fix] bugref:10727

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

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