VirtualBox

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

Last change on this file since 80239 was 80191, checked in by vboxsync, 5 years ago

VMM/r3: Refactored VMCPU enumeration in preparation that aCpus will be replaced with a pointer array. Removed two raw-mode offset members from the CPUM and CPUMCPU sub-structures. bugref:9217 bugref:9517

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: IEMR3.cpp 80191 2019-08-08 00:36:57Z vboxsync $ */
2/** @file
3 * IEM - Interpreted Execution Manager.
4 */
5
6/*
7 * Copyright (C) 2011-2019 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 VBOX_BUGREF_9217_PART_I
23#define LOG_GROUP LOG_GROUP_EM
24#include <VBox/vmm/iem.h>
25#include <VBox/vmm/cpum.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/asm-amd64-x86.h>
32#include <iprt/assert.h>
33
34static const char *iemGetTargetCpuName(uint32_t enmTargetCpu)
35{
36 switch (enmTargetCpu)
37 {
38#define CASE_RET_STR(enmValue) case enmValue: return #enmValue + (sizeof("IEMTARGETCPU_") - 1)
39 CASE_RET_STR(IEMTARGETCPU_8086);
40 CASE_RET_STR(IEMTARGETCPU_V20);
41 CASE_RET_STR(IEMTARGETCPU_186);
42 CASE_RET_STR(IEMTARGETCPU_286);
43 CASE_RET_STR(IEMTARGETCPU_386);
44 CASE_RET_STR(IEMTARGETCPU_486);
45 CASE_RET_STR(IEMTARGETCPU_PENTIUM);
46 CASE_RET_STR(IEMTARGETCPU_PPRO);
47 CASE_RET_STR(IEMTARGETCPU_CURRENT);
48#undef CASE_RET_STR
49 default: return "Unknown";
50 }
51}
52
53/**
54 * Initializes the interpreted execution manager.
55 *
56 * This must be called after CPUM as we're quering information from CPUM about
57 * the guest and host CPUs.
58 *
59 * @returns VBox status code.
60 * @param pVM The cross context VM structure.
61 */
62VMMR3DECL(int) IEMR3Init(PVM pVM)
63{
64 uint64_t const uInitialTlbRevision = UINT64_C(0) - (IEMTLB_REVISION_INCR * 200U);
65 uint64_t const uInitialTlbPhysRev = UINT64_C(0) - (IEMTLB_PHYS_REV_INCR * 100U);
66
67 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
68 {
69 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
70
71 pVCpu->iem.s.CodeTlb.uTlbRevision = pVCpu->iem.s.DataTlb.uTlbRevision = uInitialTlbRevision;
72 pVCpu->iem.s.CodeTlb.uTlbPhysRev = pVCpu->iem.s.DataTlb.uTlbPhysRev = uInitialTlbPhysRev;
73
74 STAMR3RegisterF(pVM, &pVCpu->iem.s.cInstructions, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
75 "Instructions interpreted", "/IEM/CPU%u/cInstructions", idCpu);
76 STAMR3RegisterF(pVM, &pVCpu->iem.s.cLongJumps, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
77 "Number of longjmp calls", "/IEM/CPU%u/cLongJumps", idCpu);
78 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPotentialExits, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
79 "Potential exits", "/IEM/CPU%u/cPotentialExits", idCpu);
80 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetAspectNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
81 "VERR_IEM_ASPECT_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetAspectNotImplemented", idCpu);
82 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInstrNotImplemented, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
83 "VERR_IEM_INSTR_NOT_IMPLEMENTED", "/IEM/CPU%u/cRetInstrNotImplemented", idCpu);
84 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetInfStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
85 "Informational statuses returned", "/IEM/CPU%u/cRetInfStatuses", idCpu);
86 STAMR3RegisterF(pVM, &pVCpu->iem.s.cRetErrStatuses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
87 "Error statuses returned", "/IEM/CPU%u/cRetErrStatuses", idCpu);
88 STAMR3RegisterF(pVM, &pVCpu->iem.s.cbWritten, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
89 "Approx bytes written", "/IEM/CPU%u/cbWritten", idCpu);
90 STAMR3RegisterF(pVM, &pVCpu->iem.s.cPendingCommit, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
91 "Times RC/R0 had to postpone instruction committing to ring-3", "/IEM/CPU%u/cPendingCommit", idCpu);
92
93#ifdef VBOX_WITH_STATISTICS
94 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
95 "Code TLB hits", "/IEM/CPU%u/CodeTlb-Hits", idCpu);
96 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbHits, STAMTYPE_U64_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
97 "Data TLB hits", "/IEM/CPU%u/DataTlb-Hits", idCpu);
98#endif
99 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbMisses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
100 "Code TLB misses", "/IEM/CPU%u/CodeTlb-Misses", idCpu);
101 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
102 "Code TLB revision", "/IEM/CPU%u/CodeTlb-Revision", idCpu);
103 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.CodeTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
104 "Code TLB physical revision", "/IEM/CPU%u/CodeTlb-PhysRev", idCpu);
105 STAMR3RegisterF(pVM, &pVCpu->iem.s.CodeTlb.cTlbSlowReadPath, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
106 "Code TLB slow read path", "/IEM/CPU%u/CodeTlb-SlowReads", idCpu);
107
108 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.cTlbMisses, STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
109 "Data TLB misses", "/IEM/CPU%u/DataTlb-Misses", idCpu);
110 STAMR3RegisterF(pVM, &pVCpu->iem.s.DataTlb.uTlbRevision, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
111 "Data TLB revision", "/IEM/CPU%u/DataTlb-Revision", idCpu);
112 STAMR3RegisterF(pVM, (void *)&pVCpu->iem.s.DataTlb.uTlbPhysRev, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE,
113 "Data TLB physical revision", "/IEM/CPU%u/DataTlb-PhysRev", idCpu);
114
115#if defined(VBOX_WITH_STATISTICS) && !defined(DOXYGEN_RUNNING)
116 /* Allocate instruction statistics and register them. */
117 pVCpu->iem.s.pStatsR3 = (PIEMINSTRSTATS)MMR3HeapAllocZ(pVM, MM_TAG_IEM, sizeof(IEMINSTRSTATS));
118 AssertLogRelReturn(pVCpu->iem.s.pStatsR3, VERR_NO_MEMORY);
119 int rc = MMHyperAlloc(pVM, sizeof(IEMINSTRSTATS), sizeof(uint64_t), MM_TAG_IEM, (void **)&pVCpu->iem.s.pStatsCCR3);
120 AssertLogRelRCReturn(rc, rc);
121 pVCpu->iem.s.pStatsR0 = MMHyperR3ToR0(pVM, pVCpu->iem.s.pStatsCCR3);
122# define IEM_DO_INSTR_STAT(a_Name, a_szDesc) \
123 STAMR3RegisterF(pVM, &pVCpu->iem.s.pStatsCCR3->a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
124 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-RZ/" #a_Name, idCpu); \
125 STAMR3RegisterF(pVM, &pVCpu->iem.s.pStatsR3->a_Name, STAMTYPE_U32_RESET, STAMVISIBILITY_USED, \
126 STAMUNIT_COUNT, a_szDesc, "/IEM/CPU%u/instr-R3/" #a_Name, idCpu);
127# include "IEMInstructionStatisticsTmpl.h"
128# undef IEM_DO_INSTR_STAT
129#endif
130
131 /*
132 * Host and guest CPU information.
133 */
134 if (idCpu == 0)
135 {
136 pVCpu->iem.s.enmCpuVendor = CPUMGetGuestCpuVendor(pVM);
137 pVCpu->iem.s.enmHostCpuVendor = CPUMGetHostCpuVendor(pVM);
138#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
139 switch (pVM->cpum.ro.GuestFeatures.enmMicroarch)
140 {
141 case kCpumMicroarch_Intel_8086: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_8086; break;
142 case kCpumMicroarch_Intel_80186: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_186; break;
143 case kCpumMicroarch_Intel_80286: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_286; break;
144 case kCpumMicroarch_Intel_80386: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_386; break;
145 case kCpumMicroarch_Intel_80486: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_486; break;
146 case kCpumMicroarch_Intel_P5: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PENTIUM; break;
147 case kCpumMicroarch_Intel_P6: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_PPRO; break;
148 case kCpumMicroarch_NEC_V20: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
149 case kCpumMicroarch_NEC_V30: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_V20; break;
150 default: pVCpu->iem.s.uTargetCpu = IEMTARGETCPU_CURRENT; break;
151 }
152 LogRel(("IEM: TargetCpu=%s, Microarch=%s\n", iemGetTargetCpuName(pVCpu->iem.s.uTargetCpu), CPUMR3MicroarchName(pVM->cpum.ro.GuestFeatures.enmMicroarch)));
153#endif
154 }
155 else
156 {
157 pVCpu->iem.s.enmCpuVendor = pVM->apCpusR3[0]->iem.s.enmCpuVendor;
158 pVCpu->iem.s.enmHostCpuVendor = pVM->apCpusR3[0]->iem.s.enmHostCpuVendor;
159#if IEM_CFG_TARGET_CPU == IEMTARGETCPU_DYNAMIC
160 pVCpu->iem.s.uTargetCpu = pVM->apCpusR3[0]->iem.s.uTargetCpu;
161#endif
162 }
163
164 /*
165 * Mark all buffers free.
166 */
167 uint32_t iMemMap = RT_ELEMENTS(pVCpu->iem.s.aMemMappings);
168 while (iMemMap-- > 0)
169 pVCpu->iem.s.aMemMappings[iMemMap].fAccess = IEM_ACCESS_INVALID;
170 }
171
172#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
173 /*
174 * Register the per-VM VMX APIC-access page handler type.
175 */
176 if (pVM->cpum.ro.GuestFeatures.fVmx)
177 {
178 PVMCPU pVCpu0 = pVM->apCpusR3[0];
179 int rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_ALL, iemVmxApicAccessPageHandler,
180 NULL /* pszModR0 */,
181 "iemVmxApicAccessPageHandler", NULL /* pszPfHandlerR0 */,
182 NULL /* pszModRC */,
183 NULL /* pszHandlerRC */, NULL /* pszPfHandlerRC */,
184 "VMX APIC-access page", &pVCpu0->iem.s.hVmxApicAccessPage);
185 AssertLogRelRCReturn(rc, rc);
186 }
187#endif
188
189 return VINF_SUCCESS;
190}
191
192
193VMMR3DECL(int) IEMR3Term(PVM pVM)
194{
195 NOREF(pVM);
196#if defined(VBOX_WITH_STATISTICS) && !defined(DOXYGEN_RUNNING)
197 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
198 {
199 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
200 MMR3HeapFree(pVCpu->iem.s.pStatsR3);
201 pVCpu->iem.s.pStatsR3 = NULL;
202 }
203#endif
204 return VINF_SUCCESS;
205}
206
207
208VMMR3DECL(void) IEMR3Relocate(PVM pVM)
209{
210 RT_NOREF(pVM);
211}
212
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