VirtualBox

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

Last change on this file since 94800 was 94800, checked in by vboxsync, 3 years ago

VMM/IEM,PGM: TLB work, esp. on the data one. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1/* $Id: IEMR3.cpp 94800 2022-05-03 21:49:43Z vboxsync $ */
2/** @file
3 * IEM - Interpreted Execution Manager.
4 */
5
6/*
7 * Copyright (C) 2011-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_EM
23#include <VBox/vmm/iem.h>
24#include <VBox/vmm/cpum.h>
25#include <VBox/vmm/dbgf.h>
26#include <VBox/vmm/mm.h>
27#include "IEMInternal.h"
28#include <VBox/vmm/vm.h>
29#include <VBox/err.h>
30
31#include <iprt/assert.h>
32#include <iprt/getopt.h>
33#include <iprt/string.h>
34
35
36/*********************************************************************************************************************************
37* Internal Functions *
38*********************************************************************************************************************************/
39static FNDBGFINFOARGVINT iemR3InfoITlb;
40static FNDBGFINFOARGVINT iemR3InfoDTlb;
41
42
43static const char *iemGetTargetCpuName(uint32_t enmTargetCpu)
44{
45 switch (enmTargetCpu)
46 {
47#define CASE_RET_STR(enmValue) case enmValue: return #enmValue + (sizeof("IEMTARGETCPU_") - 1)
48 CASE_RET_STR(IEMTARGETCPU_8086);
49 CASE_RET_STR(IEMTARGETCPU_V20);
50 CASE_RET_STR(IEMTARGETCPU_186);
51 CASE_RET_STR(IEMTARGETCPU_286);
52 CASE_RET_STR(IEMTARGETCPU_386);
53 CASE_RET_STR(IEMTARGETCPU_486);
54 CASE_RET_STR(IEMTARGETCPU_PENTIUM);
55 CASE_RET_STR(IEMTARGETCPU_PPRO);
56 CASE_RET_STR(IEMTARGETCPU_CURRENT);
57#undef CASE_RET_STR
58 default: return "Unknown";
59 }
60}
61
62
63/**
64 * Initializes the interpreted execution manager.
65 *
66 * This must be called after CPUM as we're quering information from CPUM about
67 * the guest and host CPUs.
68 *
69 * @returns VBox status code.
70 * @param pVM The cross context VM structure.
71 */
72VMMR3DECL(int) IEMR3Init(PVM pVM)
73{
74 uint64_t const uInitialTlbRevision = UINT64_C(0) - (IEMTLB_REVISION_INCR * 200U);
75 uint64_t const uInitialTlbPhysRev = UINT64_C(0) - (IEMTLB_PHYS_REV_INCR * 100U);
76
77 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
78 {
79 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
80 AssertCompile(sizeof(pVCpu->iem.s) <= sizeof(pVCpu->iem.padding)); /* (tstVMStruct can't do it's job w/o instruction stats) */
81
82 pVCpu->iem.s.CodeTlb.uTlbRevision = pVCpu->iem.s.DataTlb.uTlbRevision = uInitialTlbRevision;
83 pVCpu->iem.s.CodeTlb.uTlbPhysRev = pVCpu->iem.s.DataTlb.uTlbPhysRev = uInitialTlbPhysRev;
84
85 STAMR3RegisterF(pVM, &pVCpu->iem.s.cInstructions, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
86 "Instructions interpreted", "/IEM/CPU%u/cInstructions", idCpu);
87 STAMR3RegisterF(pVM, &pVCpu->iem.s.cLongJumps, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
88 "Number of longjmp calls", "/IEM/CPU%u/cLongJumps", idCpu);
89 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPotentialExits, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
90 "Potential exits", "/IEM/CPU%u/cPotentialExits", idCpu);
91 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetAspectNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
92 "VERR_IEM_ASPECT_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetAspectNotImplemented", idCpu);
93 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInstrNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
94 "VERR_IEM_INSTR_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetInstrNotImplemented", idCpu);
95 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInfStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
96 "Informational statuses returned", "/IEM/CPU%u/cRetInfStatuses", idCpu);
97 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetErrStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
98 "Error statuses returned", "/IEM/CPU%u/cRetErrStatuses", idCpu);
99 STAMR3RegisterF(pVM, &pVCpu->iem.s.cbWritten, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
100 "Approx bytes written", "/IEM/CPU%u/cbWritten", idCpu);
101 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPendingCommit, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
102 "Times RC/R0 had to postpone instruction committing to ring-3", "/IEM/CPU%u/cPendingCommit", idCpu);
103
104#ifdef VBOX_WITH_STATISTICS
105 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
106 "Code TLB hits", "/IEM/CPU%u/CodeTlb-Hits", idCpu);
107 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
108 "Data TLB hits", "/IEM/CPU%u/DataTlb-Hits", idCpu);
109#endif
110 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbMisses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
111 "Code TLB misses", "/IEM/CPU%u/CodeTlb-Misses", idCpu);
112 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
113 "Code TLB revision", "/IEM/CPU%u/CodeTlb-Revision", idCpu);
114 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.CodeTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
115 "Code TLB physical revision", "/IEM/CPU%u/CodeTlb-PhysRev", idCpu);
116 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbSlowReadPath, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
117 "Code TLB slow read path", "/IEM/CPU%u/CodeTlb-SlowReads", idCpu);
118
119 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbMisses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
120 "Data TLB misses", "/IEM/CPU%u/DataTlb-Misses", idCpu);
121 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
122 "Data TLB revision", "/IEM/CPU%u/DataTlb-Revision", idCpu);
123 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.DataTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
124 "Data TLB physical revision", "/IEM/CPU%u/DataTlb-PhysRev", idCpu);
125
126#if defined(VBOX_WITH_STATISTICS) && !defined(DOXYGEN_RUNNING)
127 /* Instruction statistics: */
128# define IEM_DO_INSTR_STAT(a_Name, a_szDesc) \
129 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatsRZ.a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
130 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-RZ/" #a_Name, idCpu); \
131 STAMR3RegisterF(pVM, &pVCpu->iem.s.StatsR3.a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
132 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-R3/" #a_Name, idCpu);
133# include "IEMInstructionStatisticsTmpl.h"
134# undef IEM_DO_INSTR_STAT
135#endif
136
137 /*
138 * Host and guest CPU information.
139 */
140 if (idCpu == 0)
141 {
142 pVCpu->iem.s.enmCpuVendor = CPUMGetGuestCpuVendor(pVM);
143 pVCpu->iem.s.enmHostCpuVendor = CPUMGetHostCpuVendor(pVM);
144#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
145 switch (pVM->cpum.ro.GuestFeatures.enmMicroarch)
146 {
147 case kCpumMicroarch_Intel_8086: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_8086; break;
148 case kCpumMicroarch_Intel_80186: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_186; break;
149 case kCpumMicroarch_Intel_80286: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_286; break;
150 case kCpumMicroarch_Intel_80386: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_386; break;
151 case kCpumMicroarch_Intel_80486: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_486; break;
152 case kCpumMicroarch_Intel_P5: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PENTIUM; break;
153 case kCpumMicroarch_Intel_P6: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PPRO; break;
154 case kCpumMicroarch_NEC_V20: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
155 case kCpumMicroarch_NEC_V30: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
156 default: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT; break;
157 }
158 LogRel(("IEM: TargetCpu=%s, Microarch=%s\n", iemGetTargetCpuName(pVCpu->iem.s.uTargetCpu), CPUMR3MicroarchName(pVM->cpum.ro.GuestFeatures.enmMicroarch)));
159#endif
160 }
161 else
162 {
163 pVCpu->iem.s.enmCpuVendor = pVM->apCpusR3[0]->iem.s.enmCpuVendor;
164 pVCpu->iem.s.enmHostCpuVendor = pVM->apCpusR3[0]->iem.s.enmHostCpuVendor;
165#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
166 pVCpu->iem.s.uTargetCpu = pVM->apCpusR3[0]->iem.s.uTargetCpu;
167#endif
168 }
169
170 /*
171 * Mark all buffers free.
172 */
173 uint32_t iMemMap = RT_ELEMENTS(pVCpu->iem.s.aMemMappings);
174 while (iMemMap-- > 0)
175 pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
176 }
177
178#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
179 /*
180 * Register the per-VM VMX APIC-access page handler type.
181 */
182 if (pVM->cpum.ro.GuestFeatures.fVmx)
183 {
184 int rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_ALL, 0 /*fFlags*/,
185 iemVmxApicAccessPageHandler,
186 "VMX APIC-access page", &pVM->iem.s.hVmxApicAccessPage);
187 AssertLogRelRCReturn(rc, rc);
188 }
189#endif
190
191 DBGFR3InfoRegisterInternalArgv(pVM, "itlb", "IEM instruction TLB", iemR3InfoITlb, DBGFINFO_FLAGS_RUN_ON_EMT);
192 DBGFR3InfoRegisterInternalArgv(pVM, "dtlb", "IEM instruction TLB", iemR3InfoDTlb, DBGFINFO_FLAGS_RUN_ON_EMT);
193
194 return VINF_SUCCESS;
195}
196
197
198VMMR3DECL(int) IEMR3Term(PVM pVM)
199{
200 NOREF(pVM);
201 return VINF_SUCCESS;
202}
203
204
205VMMR3DECL(void) IEMR3Relocate(PVM pVM)
206{
207 RT_NOREF(pVM);
208}
209
210
211/** Worker for iemR3InfoTlbPrintSlots and iemR3InfoTlbPrintAddress. */
212static void iemR3InfoTlbPrintHeader(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, bool *pfHeader)
213{
214 if (*pfHeader)
215 return;
216 pHlp->pfnPrintf(pHlp, "%cTLB for CPU %u:\n", &pVCpu->iem.s.CodeTlb == pTlb ? 'I' : 'D', pVCpu->idCpu);
217 *pfHeader = true;
218}
219
220
221/** Worker for iemR3InfoTlbPrintSlots and iemR3InfoTlbPrintAddress. */
222static void iemR3InfoTlbPrintSlot(PCDBGFINFOHLP pHlp, IEMTLB const *pTlb, IEMTLBENTRY const *pTlbe, uint32_t uSlot)
223{
224 pHlp->pfnPrintf(pHlp, "%02x: %s %#018RX64 -> %RGp / %p / %#05x %s%s%s%s/%s%s%s/%s %s\n",
225 uSlot,
226 (pTlbe->uTag & IEMTLB_REVISION_MASK) == pTlb->uTlbRevision ? "valid "
227 : (pTlbe->uTag & IEMTLB_REVISION_MASK) == 0 ? "empty "
228 : "expired",
229 (pTlbe->uTag & ~IEMTLB_REVISION_MASK) << X86_PAGE_SHIFT,
230 pTlbe->GCPhys, pTlbe->pbMappingR3,
231 (uint32_t)pTlbe->fFlagsAndPhysRev & ~(uint32_t)IEMTLBE_F_PHYS_REV,
232 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_EXEC ? "NX" : " X",
233 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_WRITE ? "RO" : "RW",
234 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_ACCESSED ? "-" : "A",
235 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PT_NO_DIRTY ? "-" : "D",
236 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_WRITE ? "-" : "w",
237 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_NO_READ ? "-" : "r",
238 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PG_UNASSIGNED ? "U" : "-",
239 pTlbe->fFlagsAndPhysRev & IEMTLBE_F_NO_MAPPINGR3 ? "S" : "M",
240 (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == pTlb->uTlbPhysRev ? "phys-valid"
241 : (pTlbe->fFlagsAndPhysRev & IEMTLBE_F_PHYS_REV) == 0 ? "phys-empty" : "phys-expired");
242}
243
244
245/** Displays one or more TLB slots. */
246static void iemR3InfoTlbPrintSlots(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb,
247 uint32_t uSlot, uint32_t cSlots, bool *pfHeader)
248{
249 if (uSlot < RT_ELEMENTS(pTlb->aEntries))
250 {
251 if (cSlots > RT_ELEMENTS(pTlb->aEntries))
252 {
253 pHlp->pfnPrintf(pHlp, "error: Too many slots given: %u, adjusting it down to the max (%u)\n",
254 cSlots, RT_ELEMENTS(pTlb->aEntries));
255 cSlots = RT_ELEMENTS(pTlb->aEntries);
256 }
257
258 iemR3InfoTlbPrintHeader(pVCpu, pHlp, pTlb, pfHeader);
259 while (cSlots-- > 0)
260 {
261 IEMTLBENTRY const Tlbe = pTlb->aEntries[uSlot];
262 iemR3InfoTlbPrintSlot(pHlp, pTlb, &Tlbe, uSlot);
263 uSlot = (uSlot + 1) % RT_ELEMENTS(pTlb->aEntries);
264 }
265 }
266 else
267 pHlp->pfnPrintf(pHlp, "error: TLB slot is out of range: %u (%#x), max %u (%#x)\n",
268 uSlot, uSlot, RT_ELEMENTS(pTlb->aEntries) - 1, RT_ELEMENTS(pTlb->aEntries) - 1);
269}
270
271
272/** Displays the TLB slot for the given address. */
273static void iemR3InfoTlbPrintAddress(PVMCPU pVCpu, PCDBGFINFOHLP pHlp, IEMTLB const *pTlb,
274 uint64_t uAddress, bool *pfHeader)
275{
276 iemR3InfoTlbPrintHeader(pVCpu, pHlp, pTlb, pfHeader);
277
278 uint64_t const uTag = (uAddress << 16) >> (X86_PAGE_SHIFT + 16);
279 uint32_t const uSlot = (uint8_t)uTag;
280 IEMTLBENTRY const Tlbe = pTlb->aEntries[uSlot];
281 pHlp->pfnPrintf(pHlp, "Address %#RX64 -> slot %#x - %s\n", uAddress, uSlot,
282 Tlbe.uTag == (uTag | pTlb->uTlbRevision) ? "match"
283 : (Tlbe.uTag & ~IEMTLB_REVISION_MASK) == uTag ? "expired" : "mismatch");
284 iemR3InfoTlbPrintSlot(pHlp, pTlb, &Tlbe, uSlot);
285}
286
287
288/** Common worker for iemR3InfoDTlb and iemR3InfoITlb. */
289static void iemR3InfoTlbCommon(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs, bool fITlb)
290{
291 /*
292 * This is entirely argument driven.
293 */
294 static RTGETOPTDEF const s_aOptions[] =
295 {
296 { "--cpu", 'c', RTGETOPT_REQ_UINT32 },
297 { "--vcpu", 'c', RTGETOPT_REQ_UINT32 },
298 { "all", 'A', RTGETOPT_REQ_NOTHING },
299 { "--all", 'A', RTGETOPT_REQ_NOTHING },
300 { "--address", 'a', RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX },
301 { "--range", 'r', RTGETOPT_REQ_UINT32_PAIR | RTGETOPT_FLAG_HEX },
302 { "--slot", 's', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX },
303 };
304
305 char szDefault[] = "-A";
306 char *papszDefaults[2] = { szDefault, NULL };
307 if (cArgs == 0)
308 {
309 cArgs = 1;
310 papszArgs = papszDefaults;
311 }
312
313 RTGETOPTSTATE State;
314 int rc = RTGetOptInit(&State, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 0 /*iFirst*/, 0 /*fFlags*/);
315 AssertRCReturnVoid(rc);
316
317 bool fNeedHeader = true;
318 bool fAddressMode = true;
319 PVMCPU pVCpu = VMMGetCpu(pVM);
320 if (!pVCpu)
321 pVCpu = VMMGetCpuById(pVM, 0);
322
323 RTGETOPTUNION ValueUnion;
324 while ((rc = RTGetOpt(&State, &ValueUnion)) != 0)
325 {
326 switch (rc)
327 {
328 case 'c':
329 if (ValueUnion.u32 >= pVM->cCpus)
330 pHlp->pfnPrintf(pHlp, "error: Invalid CPU ID: %u\n", ValueUnion.u32);
331 else if (!pVCpu || pVCpu->idCpu != ValueUnion.u32)
332 {
333 pVCpu = VMMGetCpuById(pVM, ValueUnion.u32);
334 fNeedHeader = true;
335 }
336 break;
337
338 case 'a':
339 iemR3InfoTlbPrintAddress(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
340 ValueUnion.u64, &fNeedHeader);
341 fAddressMode = true;
342 break;
343
344 case 'A':
345 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
346 0, RT_ELEMENTS(pVCpu->iem.s.CodeTlb.aEntries), &fNeedHeader);
347 break;
348
349 case 'r':
350 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
351 ValueUnion.PairU32.uFirst, ValueUnion.PairU32.uSecond, &fNeedHeader);
352 fAddressMode = false;
353 break;
354
355 case 's':
356 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
357 ValueUnion.u32, 1, &fNeedHeader);
358 fAddressMode = false;
359 break;
360
361 case VINF_GETOPT_NOT_OPTION:
362 if (fAddressMode)
363 {
364 uint64_t uAddr;
365 rc = RTStrToUInt64Full(ValueUnion.psz, 16, &uAddr);
366 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG)
367 iemR3InfoTlbPrintAddress(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
368 uAddr, &fNeedHeader);
369 else
370 pHlp->pfnPrintf(pHlp, "error: Invalid or malformed guest address '%s': %Rrc\n", ValueUnion.psz, rc);
371 }
372 else
373 {
374 uint32_t uSlot;
375 rc = RTStrToUInt32Full(ValueUnion.psz, 16, &uSlot);
376 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG)
377 iemR3InfoTlbPrintSlots(pVCpu, pHlp, fITlb ? &pVCpu->iem.s.CodeTlb : &pVCpu->iem.s.DataTlb,
378 uSlot, 1, &fNeedHeader);
379 else
380 pHlp->pfnPrintf(pHlp, "error: Invalid or malformed TLB slot number '%s': %Rrc\n", ValueUnion.psz, rc);
381 }
382 break;
383
384 case 'h':
385 pHlp->pfnPrintf(pHlp,
386 "Usage: info %ctlb [options]\n"
387 "\n"
388 "Options:\n"
389 " -c<n>, --cpu=<n>, --vcpu=<n>\n"
390 " Selects the CPU which TLBs we're looking at. Default: Caller / 0\n"
391 " -A, --all, all\n"
392 " Display all the TLB entries (default if no other args).\n"
393 " -a<virt>, --address=<virt>\n"
394 " Shows the TLB entry for the specified guest virtual address.\n"
395 " -r<slot:count>, --range=<slot:count>\n"
396 " Shows the TLB entries for the specified slot range.\n"
397 " -s<slot>,--slot=<slot>\n"
398 " Shows the given TLB slot.\n"
399 "\n"
400 "Non-options are interpreted according to the last -a, -r or -s option,\n"
401 "defaulting to addresses if not preceeded by any of those options.\n"
402 , fITlb ? 'i' : 'd');
403 return;
404
405 default:
406 pHlp->pfnGetOptError(pHlp, rc, &ValueUnion, &State);
407 return;
408 }
409 }
410}
411
412
413/**
414 * @callback_method_impl{FNDBGFINFOARGVINT, itlb}
415 */
416static DECLCALLBACK(void) iemR3InfoITlb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
417{
418 return iemR3InfoTlbCommon(pVM, pHlp, cArgs, papszArgs, true /*fITlb*/);
419}
420
421
422/**
423 * @callback_method_impl{FNDBGFINFOARGVINT, dtlb}
424 */
425static DECLCALLBACK(void) iemR3InfoDTlb(PVM pVM, PCDBGFINFOHLP pHlp, int cArgs, char **papszArgs)
426{
427 return iemR3InfoTlbCommon(pVM, pHlp, cArgs, papszArgs, false /*fITlb*/);
428}
429
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