VirtualBox

source: vbox/trunk/src/VBox/VMM/include/EMInternal.h@ 97441

Last change on this file since 97441 was 97178, checked in by vboxsync, 2 years ago

VMM/CPUM,EM,HM,IEM,++: Moved VMCPU_FF_INHIBIT_INTERRUPTS and VMCPU_FF_BLOCK_NMIS to CPUMCTX::fInhibit. Moved ldtr and tr up to the CPUMCTXCORE area in hope for better cache alignment of rip, rflags and crX register fields. bugref:9941

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: EMInternal.h 97178 2022-10-17 21:06:03Z vboxsync $ */
2/** @file
3 * EM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2022 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#ifndef VMM_INCLUDED_SRC_include_EMInternal_h
29#define VMM_INCLUDED_SRC_include_EMInternal_h
30#ifndef RT_WITHOUT_PRAGMA_ONCE
31# pragma once
32#endif
33
34#include <VBox/cdefs.h>
35#include <VBox/types.h>
36#include <VBox/vmm/em.h>
37#include <VBox/vmm/stam.h>
38#include <VBox/dis.h>
39#include <VBox/vmm/pdmcritsect.h>
40#include <iprt/avl.h>
41#include <iprt/setjmp-without-sigmask.h>
42
43RT_C_DECLS_BEGIN
44
45
46/** @defgroup grp_em_int Internal
47 * @ingroup grp_em
48 * @internal
49 * @{
50 */
51
52/** The saved state version. */
53#define EM_SAVED_STATE_VERSION 5
54#define EM_SAVED_STATE_VERSION_PRE_IEM 4
55#define EM_SAVED_STATE_VERSION_PRE_MWAIT 3
56#define EM_SAVED_STATE_VERSION_PRE_SMP 2
57
58
59/** @name MWait state flags.
60 * @{
61 */
62/** MWait activated. */
63#define EMMWAIT_FLAG_ACTIVE RT_BIT(0)
64/** MWait will continue when an interrupt is pending even when IF=0. */
65#define EMMWAIT_FLAG_BREAKIRQIF0 RT_BIT(1)
66/** Monitor instruction was executed previously. */
67#define EMMWAIT_FLAG_MONITOR_ACTIVE RT_BIT(2)
68/** @} */
69
70/** EM time slice in ms; used for capping execution time. */
71#define EM_TIME_SLICE 100
72
73/**
74 * Cli node structure
75 */
76typedef struct CLISTAT
77{
78 /** The key is the cli address. */
79 AVLGCPTRNODECORE Core;
80#if HC_ARCH_BITS == 32 && !defined(RT_OS_WINDOWS)
81 /** Padding. */
82 uint32_t u32Padding;
83#endif
84 /** Occurrences. */
85 STAMCOUNTER Counter;
86} CLISTAT, *PCLISTAT;
87#ifdef IN_RING3
88AssertCompileMemberAlignment(CLISTAT, Counter, 8);
89#endif
90
91
92/**
93 * Exit history entry.
94 *
95 * @remarks We could perhaps trim this down a little bit by assuming uFlatPC
96 * only needs 48 bits (currently true but will change) and stuffing
97 * the flags+type in the available 16 bits made available. The
98 * timestamp could likewise be shortened to accomodate the index, or
99 * we might skip the index entirely. However, since we will have to
100 * deal with 56-bit wide PC address before long, there's not point.
101 *
102 * On the upside, there are unused bits in both uFlagsAndType and the
103 * idxSlot fields if needed for anything.
104 */
105typedef struct EMEXITENTRY
106{
107 /** The flat PC (CS:EIP/RIP) address of the exit.
108 * UINT64_MAX if not available. */
109 uint64_t uFlatPC;
110 /** The EMEXIT_MAKE_FLAGS_AND_TYPE */
111 uint32_t uFlagsAndType;
112 /** The index into the exit slot hash table.
113 * UINT32_MAX if too many collisions and not entered into it. */
114 uint32_t idxSlot;
115 /** The TSC timestamp of the exit.
116 * This is 0 if not timestamped. */
117 uint64_t uTimestamp;
118} EMEXITENTRY;
119/** Pointer to an exit history entry. */
120typedef EMEXITENTRY *PEMEXITENTRY;
121/** Pointer to a const exit history entry. */
122typedef EMEXITENTRY const *PCEMEXITENTRY;
123
124
125/**
126 * EM VM Instance data.
127 */
128typedef struct EM
129{
130 /** Whether IEM executes everything. */
131 bool fIemExecutesAll;
132 /** Whether a triple fault triggers a guru. */
133 bool fGuruOnTripleFault;
134 /** Alignment padding. */
135 bool afPadding[2];
136
137 /** Id of the VCPU that last executed code in the recompiler. */
138 VMCPUID idLastRemCpu;
139} EM;
140/** Pointer to EM VM instance data. */
141typedef EM *PEM;
142
143
144/**
145 * EM VMCPU Instance data.
146 */
147typedef struct EMCPU
148{
149 /** Execution Manager State. */
150 EMSTATE volatile enmState;
151
152 /** The state prior to the suspending of the VM. */
153 EMSTATE enmPrevState;
154
155 /** Set if hypercall instruction VMMCALL (AMD) & VMCALL (Intel) are enabled.
156 * GIM sets this and the execution managers queries it. Not saved, as GIM
157 * takes care of that bit too. */
158 bool fHypercallEnabled;
159
160 /** Explicit padding. */
161 uint8_t abPadding0[3];
162
163 /** The number of instructions we've executed in IEM since switching to the
164 * EMSTATE_IEM_THEN_REM state. */
165 uint32_t cIemThenRemInstructions;
166
167 /** Start of the current time slice in ms. */
168 uint64_t u64TimeSliceStart;
169 /** Start of the current time slice in thread execution time (ms). */
170 uint64_t u64TimeSliceStartExec;
171 /** Current time slice value. */
172 uint64_t u64TimeSliceExec;
173
174 /** Pending ring-3 I/O port access (VINF_EM_PENDING_R3_IOPORT_READ / VINF_EM_PENDING_R3_IOPORT_WRITE). */
175 struct
176 {
177 RTIOPORT uPort; /**< The I/O port number.*/
178 uint8_t cbValue; /**< The value size in bytes. Zero when not pending. */
179 uint8_t cbInstr; /**< The instruction length. */
180 uint32_t uValue; /**< The value to write. */
181 } PendingIoPortAccess;
182
183 /** MWait halt state. */
184 struct
185 {
186 uint32_t fWait; /**< Type of mwait; see EMMWAIT_FLAG_*. */
187 uint32_t u32Padding;
188 RTGCPTR uMWaitRAX; /**< MWAIT hints. */
189 RTGCPTR uMWaitRCX; /**< MWAIT extensions. */
190 RTGCPTR uMonitorRAX; /**< Monitored address. */
191 RTGCPTR uMonitorRCX; /**< Monitor extension. */
192 RTGCPTR uMonitorRDX; /**< Monitor hint. */
193 } MWait;
194
195#if 0
196 /** Make sure the jmp_buf is at a 32-byte boundrary. */
197 uint64_t au64Padding1[4];
198#endif
199 union
200 {
201 /** Padding used in the other rings.
202 * This must be larger than jmp_buf on any supported platform. */
203 char achPaddingFatalLongJump[256];
204#ifdef IN_RING3
205 /** Long buffer jump for fatal VM errors.
206 * It will jump to before the outer EM loop is entered. */
207 jmp_buf FatalLongJump;
208#endif
209 } u;
210
211 /** For saving stack space, the disassembler state is allocated here instead of
212 * on the stack. */
213 DISCPUSTATE DisState;
214
215 /** @name Execution profiling.
216 * @{ */
217 STAMPROFILE StatForcedActions;
218 STAMPROFILE StatHalted;
219 STAMPROFILEADV StatCapped;
220 STAMPROFILEADV StatHMEntry;
221 STAMPROFILE StatHMExec;
222 STAMPROFILE StatIEMEmu;
223 STAMPROFILE StatIEMThenREM;
224 STAMPROFILEADV StatNEMEntry;
225 STAMPROFILE StatNEMExec;
226 STAMPROFILE StatREMEmu;
227 STAMPROFILE StatREMExec;
228 STAMPROFILE StatREMSync;
229 STAMPROFILEADV StatREMTotal;
230 STAMPROFILE StatRAWExec;
231 STAMPROFILEADV StatRAWEntry;
232 STAMPROFILEADV StatRAWTail;
233 STAMPROFILEADV StatRAWTotal;
234 STAMPROFILEADV StatTotal;
235 /** @} */
236
237 /** R3: Profiling of emR3RawExecuteIOInstruction. */
238 STAMPROFILE StatIOEmu;
239 STAMCOUNTER StatIoRestarted;
240 STAMCOUNTER StatIoIem;
241 /** R3: Profiling of emR3RawPrivileged. */
242 STAMPROFILE StatPrivEmu;
243 /** R3: Number of times emR3HmExecute is called. */
244 STAMCOUNTER StatHMExecuteCalled;
245 /** R3: Number of times emR3NEMExecute is called. */
246 STAMCOUNTER StatNEMExecuteCalled;
247
248 /** Align the next member at a 32-byte boundrary. */
249 uint64_t au64Padding2[1+2];
250
251 /** Exit history table (6KB). */
252 EMEXITENTRY aExitHistory[256];
253 /** Where to store the next exit history entry.
254 * Since aExitHistory is 256 items longs, we'll just increment this and
255 * mask it when using it. That help the readers detect whether we've
256 * wrapped around or not. */
257 uint64_t iNextExit;
258
259 /** Index into aExitRecords set by EMHistoryExec when returning to ring-3.
260 * This is UINT16_MAX if not armed. */
261 uint16_t volatile idxContinueExitRec;
262 /** Whether exit optimizations are enabled or not (in general). */
263 bool fExitOptimizationEnabled : 1;
264 /** Whether exit optimizations are enabled for ring-0 (in general). */
265 bool fExitOptimizationEnabledR0 : 1;
266 /** Whether exit optimizations are enabled for ring-0 when preemption is disabled. */
267 bool fExitOptimizationEnabledR0PreemptDisabled : 1;
268 /** Explicit padding. */
269 bool fPadding2;
270 /** Max number of instructions to execute. */
271 uint16_t cHistoryExecMaxInstructions;
272 /** Min number of instructions to execute while probing. */
273 uint16_t cHistoryProbeMinInstructions;
274 /** Max number of instructions to execute without an exit before giving up probe. */
275 uint16_t cHistoryProbeMaxInstructionsWithoutExit;
276 uint16_t uPadding3;
277 /** Number of exit records in use. */
278 uint32_t cExitRecordUsed;
279 /** Profiling the EMHistoryExec when executing (not probing). */
280 STAMPROFILE StatHistoryExec;
281 /** Number of saved exits. */
282 STAMCOUNTER StatHistoryExecSavedExits;
283 /** Number of instructions executed by EMHistoryExec. */
284 STAMCOUNTER StatHistoryExecInstructions;
285 uint64_t uPadding4;
286 /** Number of instructions executed by EMHistoryExec when probing. */
287 STAMCOUNTER StatHistoryProbeInstructions;
288 /** Number of times probing resulted in EMEXITACTION_NORMAL_PROBED. */
289 STAMCOUNTER StatHistoryProbedNormal;
290 /** Number of times probing resulted in EMEXITACTION_EXEC_WITH_MAX. */
291 STAMCOUNTER StatHistoryProbedExecWithMax;
292 /** Number of times probing resulted in ring-3 continuation. */
293 STAMCOUNTER StatHistoryProbedToRing3;
294 /** Profiling the EMHistoryExec when probing.*/
295 STAMPROFILE StatHistoryProbe;
296 /** Hit statistics for each lookup step. */
297 STAMCOUNTER aStatHistoryRecHits[16];
298 /** Type change statistics for each lookup step. */
299 STAMCOUNTER aStatHistoryRecTypeChanged[16];
300 /** Replacement statistics for each lookup step. */
301 STAMCOUNTER aStatHistoryRecReplaced[16];
302 /** New record statistics for each lookup step. */
303 STAMCOUNTER aStatHistoryRecNew[16];
304
305 /** Exit records (32KB). (Aligned on 32 byte boundrary.) */
306 EMEXITREC aExitRecords[1024];
307} EMCPU;
308/** Pointer to EM VM instance data. */
309typedef EMCPU *PEMCPU;
310
311/** @} */
312
313int emR3InitDbg(PVM pVM);
314
315int emR3HmExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
316VBOXSTRICTRC emR3NemExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
317int emR3RawExecute(PVM pVM, PVMCPU pVCpu, bool *pfFFDone);
318
319EMSTATE emR3Reschedule(PVM pVM, PVMCPU pVCpu);
320int emR3ForcedActions(PVM pVM, PVMCPU pVCpu, int rc);
321VBOXSTRICTRC emR3HighPriorityPostForcedActions(PVM pVM, PVMCPU pVCpu, VBOXSTRICTRC rc);
322
323int emR3RawResumeHyper(PVM pVM, PVMCPU pVCpu);
324int emR3RawStep(PVM pVM, PVMCPU pVCpu);
325
326VBOXSTRICTRC emR3NemSingleInstruction(PVM pVM, PVMCPU pVCpu, uint32_t fFlags);
327
328int emR3SingleStepExecRem(PVM pVM, PVMCPU pVCpu, uint32_t cIterations);
329
330bool emR3IsExecutionAllowed(PVM pVM, PVMCPU pVCpu);
331
332VBOXSTRICTRC emR3ExecutePendingIoPortWrite(PVM pVM, PVMCPU pVCpu);
333VBOXSTRICTRC emR3ExecutePendingIoPortRead(PVM pVM, PVMCPU pVCpu);
334VBOXSTRICTRC emR3ExecuteSplitLockInstruction(PVM pVM, PVMCPU pVCpu);
335
336RT_C_DECLS_END
337
338#endif /* !VMM_INCLUDED_SRC_include_EMInternal_h */
339
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