VirtualBox

source: vbox/trunk/src/VBox/VMM/include/VMInternal.h@ 93554

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

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 18.1 KB
Line 
1/* $Id: VMInternal.h 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * VM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-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#ifndef VMM_INCLUDED_SRC_include_VMInternal_h
19#define VMM_INCLUDED_SRC_include_VMInternal_h
20#ifndef RT_WITHOUT_PRAGMA_ONCE
21# pragma once
22#endif
23
24#include <VBox/cdefs.h>
25#include <VBox/vmm/vmapi.h>
26#include <iprt/assert.h>
27#include <iprt/critsect.h>
28#include <setjmp.h>
29
30
31
32/** @defgroup grp_vm_int Internals
33 * @ingroup grp_vm
34 * @internal
35 * @{
36 */
37
38
39/**
40 * VM state change callback.
41 */
42typedef struct VMATSTATE
43{
44 /** Pointer to the next one. */
45 struct VMATSTATE *pNext;
46 /** Pointer to the callback. */
47 PFNVMATSTATE pfnAtState;
48 /** The user argument. */
49 void *pvUser;
50} VMATSTATE;
51/** Pointer to a VM state change callback. */
52typedef VMATSTATE *PVMATSTATE;
53
54
55/**
56 * VM error callback.
57 */
58typedef struct VMATERROR
59{
60 /** Pointer to the next one. */
61 struct VMATERROR *pNext;
62 /** Pointer to the callback. */
63 PFNVMATERROR pfnAtError;
64 /** The user argument. */
65 void *pvUser;
66} VMATERROR;
67/** Pointer to a VM error callback. */
68typedef VMATERROR *PVMATERROR;
69
70
71/**
72 * Chunk of memory allocated off the hypervisor heap in which
73 * we copy the error details.
74 */
75typedef struct VMERROR
76{
77 /** The size of the chunk. */
78 uint32_t cbAllocated;
79 /** The current offset into the chunk.
80 * We start by putting the filename and function immediately
81 * after the end of the buffer. */
82 uint32_t off;
83 /** Offset from the start of this structure to the file name. */
84 uint32_t offFile;
85 /** The line number. */
86 uint32_t iLine;
87 /** Offset from the start of this structure to the function name. */
88 uint32_t offFunction;
89 /** Offset from the start of this structure to the formatted message text. */
90 uint32_t offMessage;
91 /** The VBox status code. */
92 int32_t rc;
93} VMERROR, *PVMERROR;
94
95
96/**
97 * VM runtime error callback.
98 */
99typedef struct VMATRUNTIMEERROR
100{
101 /** Pointer to the next one. */
102 struct VMATRUNTIMEERROR *pNext;
103 /** Pointer to the callback. */
104 PFNVMATRUNTIMEERROR pfnAtRuntimeError;
105 /** The user argument. */
106 void *pvUser;
107} VMATRUNTIMEERROR;
108/** Pointer to a VM error callback. */
109typedef VMATRUNTIMEERROR *PVMATRUNTIMEERROR;
110
111
112/**
113 * Chunk of memory allocated off the hypervisor heap in which
114 * we copy the runtime error details.
115 */
116typedef struct VMRUNTIMEERROR
117{
118 /** The size of the chunk. */
119 uint32_t cbAllocated;
120 /** The current offset into the chunk.
121 * We start by putting the error ID immediately
122 * after the end of the buffer. */
123 uint32_t off;
124 /** Offset from the start of this structure to the error ID. */
125 uint32_t offErrorId;
126 /** Offset from the start of this structure to the formatted message text. */
127 uint32_t offMessage;
128 /** Error flags. */
129 uint32_t fFlags;
130} VMRUNTIMEERROR, *PVMRUNTIMEERROR;
131
132/** The halt method. */
133typedef enum
134{
135 /** The usual invalid value. */
136 VMHALTMETHOD_INVALID = 0,
137 /** Use the method used during bootstrapping. */
138 VMHALTMETHOD_BOOTSTRAP,
139 /** Use the default method. */
140 VMHALTMETHOD_DEFAULT,
141 /** The old spin/yield/block method. */
142 VMHALTMETHOD_OLD,
143 /** The first go at a block/spin method. */
144 VMHALTMETHOD_1,
145 /** The first go at a more global approach. */
146 VMHALTMETHOD_GLOBAL_1,
147 /** The end of valid methods. (not inclusive of course) */
148 VMHALTMETHOD_END,
149 /** The usual 32-bit max value. */
150 VMHALTMETHOD_32BIT_HACK = 0x7fffffff
151} VMHALTMETHOD;
152
153
154/**
155 * VM Internal Data (part of the VM structure).
156 *
157 * @todo Move this and all related things to VMM. The VM component was, to some
158 * extent at least, a bad ad hoc design which should all have been put in
159 * VMM. @see pg_vm.
160 */
161typedef struct VMINT
162{
163 /** VM Error Message. */
164 R3PTRTYPE(PVMERROR) pErrorR3;
165 /** VM Runtime Error Message. */
166 R3PTRTYPE(PVMRUNTIMEERROR) pRuntimeErrorR3;
167 /** The VM was/is-being teleported and has not yet been fully resumed. */
168 bool fTeleportedAndNotFullyResumedYet;
169 /** The VM should power off instead of reset. */
170 bool fPowerOffInsteadOfReset;
171 /** Reset counter (soft + hard). */
172 uint32_t cResets;
173 /** Hard reset counter. */
174 uint32_t cHardResets;
175 /** Soft reset counter. */
176 uint32_t cSoftResets;
177} VMINT;
178/** Pointer to the VM Internal Data (part of the VM structure). */
179typedef VMINT *PVMINT;
180
181
182#ifdef IN_RING3
183
184/**
185 * VM internal data kept in the UVM.
186 */
187typedef struct VMINTUSERPERVM
188{
189 /** Head of the standard request queue. Atomic. */
190 volatile PVMREQ pNormalReqs;
191 /** Head of the priority request queue. Atomic. */
192 volatile PVMREQ pPriorityReqs;
193 /** The last index used during alloc/free. */
194 volatile uint32_t iReqFree;
195 /** Number of free request packets. */
196 volatile uint32_t cReqFree;
197 /** Array of pointers to lists of free request packets. Atomic. */
198 volatile PVMREQ apReqFree[16 - (HC_ARCH_BITS == 32 ? 5 : 4)];
199
200 /** The reference count of the UVM handle. */
201 volatile uint32_t cUvmRefs;
202
203 /** Number of active EMTs. */
204 volatile uint32_t cActiveEmts;
205
206# ifdef VBOX_WITH_STATISTICS
207# if HC_ARCH_BITS == 32
208 uint32_t uPadding;
209# endif
210 /** Number of VMR3ReqAlloc returning a new packet. */
211 STAMCOUNTER StatReqAllocNew;
212 /** Number of VMR3ReqAlloc causing races. */
213 STAMCOUNTER StatReqAllocRaces;
214 /** Number of VMR3ReqAlloc returning a recycled packet. */
215 STAMCOUNTER StatReqAllocRecycled;
216 /** Number of VMR3ReqFree calls. */
217 STAMCOUNTER StatReqFree;
218 /** Number of times the request was actually freed. */
219 STAMCOUNTER StatReqFreeOverflow;
220 /** Number of requests served. */
221 STAMCOUNTER StatReqProcessed;
222 /** Number of times there are more than one request and the others needed to be
223 * pushed back onto the list. */
224 STAMCOUNTER StatReqMoreThan1;
225 /** Number of times we've raced someone when pushing the other requests back
226 * onto the list. */
227 STAMCOUNTER StatReqPushBackRaces;
228# endif
229
230 /** Pointer to the support library session.
231 * Mainly for creation and destruction. */
232 PSUPDRVSESSION pSession;
233
234 /** Force EMT to terminate. */
235 bool volatile fTerminateEMT;
236
237 /** Critical section for pAtState and enmPrevVMState. */
238 RTCRITSECT AtStateCritSect;
239 /** List of registered state change callbacks. */
240 PVMATSTATE pAtState;
241 /** List of registered state change callbacks. */
242 PVMATSTATE *ppAtStateNext;
243 /** The previous VM state.
244 * This is mainly used for the 'Resetting' state, but may come in handy later
245 * and when debugging. */
246 VMSTATE enmPrevVMState;
247
248 /** Reason for the most recent suspend operation. */
249 VMSUSPENDREASON enmSuspendReason;
250 /** Reason for the most recent operation. */
251 VMRESUMEREASON enmResumeReason;
252
253 /** Critical section for pAtError and pAtRuntimeError. */
254 RTCRITSECT AtErrorCritSect;
255
256 /** List of registered error callbacks. */
257 PVMATERROR pAtError;
258 /** List of registered error callbacks. */
259 PVMATERROR *ppAtErrorNext;
260 /** The error message count.
261 * This is incremented every time an error is raised. */
262 uint32_t volatile cErrors;
263
264 /** The runtime error message count.
265 * This is incremented every time a runtime error is raised. */
266 uint32_t volatile cRuntimeErrors;
267 /** List of registered error callbacks. */
268 PVMATRUNTIMEERROR pAtRuntimeError;
269 /** List of registered error callbacks. */
270 PVMATRUNTIMEERROR *ppAtRuntimeErrorNext;
271
272 /** @name Generic Halt data
273 * @{
274 */
275 /** The current halt method.
276 * Can be selected by CFGM option 'VM/HaltMethod'. */
277 VMHALTMETHOD enmHaltMethod;
278 /** The index into g_aHaltMethods of the current halt method. */
279 uint32_t volatile iHaltMethod;
280 /** @} */
281
282 /** @todo Do NOT add new members here or reuse the current, we need to store the config for
283 * each halt method separately because we're racing on SMP guest rigs. */
284 union
285 {
286 /**
287 * Method 1 & 2 - Block whenever possible, and when lagging behind
288 * switch to spinning with regular blocking every 5-200ms (defaults)
289 * depending on the accumulated lag. The blocking interval is adjusted
290 * with the average oversleeping of the last 64 times.
291 *
292 * The difference between 1 and 2 is that we use native absolute
293 * time APIs for the blocking instead of the millisecond based IPRT
294 * interface.
295 */
296 struct
297 {
298 /** The max interval without blocking (when spinning). */
299 uint32_t u32MinBlockIntervalCfg;
300 /** The minimum interval between blocking (when spinning). */
301 uint32_t u32MaxBlockIntervalCfg;
302 /** The value to divide the current lag by to get the raw blocking interval (when spinning). */
303 uint32_t u32LagBlockIntervalDivisorCfg;
304 /** When to start spinning (lag / nano secs). */
305 uint32_t u32StartSpinningCfg;
306 /** When to stop spinning (lag / nano secs). */
307 uint32_t u32StopSpinningCfg;
308 } Method12;
309
310 /**
311 * The GVMM manages halted and waiting EMTs.
312 */
313 struct
314 {
315 /** The threshold between spinning and blocking. */
316 uint32_t cNsSpinBlockThresholdCfg;
317 } Global1;
318 } Halt;
319
320 /** Pointer to the DBGC instance data. */
321 void *pvDBGC;
322
323 /** TLS index for the VMINTUSERPERVMCPU pointer. */
324 RTTLS idxTLS;
325
326 /** The VM name. (Set after the config constructure has been called.) */
327 char *pszName;
328 /** The VM UUID. (Set after the config constructure has been called.) */
329 RTUUID Uuid;
330} VMINTUSERPERVM;
331# ifdef VBOX_WITH_STATISTICS
332AssertCompileMemberAlignment(VMINTUSERPERVM, StatReqAllocNew, 8);
333# endif
334
335/** Pointer to the VM internal data kept in the UVM. */
336typedef VMINTUSERPERVM *PVMINTUSERPERVM;
337
338
339/**
340 * VMCPU internal data kept in the UVM.
341 *
342 * Almost a copy of VMINTUSERPERVM. Separate data properly later on.
343 */
344typedef struct VMINTUSERPERVMCPU
345{
346 /** Head of the normal request queue. Atomic. */
347 volatile PVMREQ pNormalReqs;
348 /** Head of the priority request queue. Atomic. */
349 volatile PVMREQ pPriorityReqs;
350
351 /** The handle to the EMT thread. */
352 RTTHREAD ThreadEMT;
353 /** The native of the EMT thread. */
354 RTNATIVETHREAD NativeThreadEMT;
355 /** Wait event semaphore. */
356 RTSEMEVENT EventSemWait;
357 /** Wait/Idle indicator. */
358 bool volatile fWait;
359 /** Set if we've been thru vmR3Destroy and decremented the active EMT count
360 * already. */
361 bool volatile fBeenThruVmDestroy;
362 /** Align the next bit. */
363 bool afAlignment[HC_ARCH_BITS == 32 ? 2 : 6];
364
365 /** @name Generic Halt data
366 * @{
367 */
368 /** The average time (ns) between two halts in the last second. (updated once per second) */
369 uint32_t HaltInterval;
370 /** The average halt frequency for the last second. (updated once per second) */
371 uint32_t HaltFrequency;
372 /** The number of halts in the current period. */
373 uint32_t cHalts;
374 uint32_t padding; /**< alignment padding. */
375 /** When we started counting halts in cHalts (RTTimeNanoTS). */
376 uint64_t u64HaltsStartTS;
377 /** @} */
378
379 /** Union containing data and config for the different halt algorithms. */
380 union
381 {
382 /**
383 * Method 1 & 2 - Block whenever possible, and when lagging behind
384 * switch to spinning with regular blocking every 5-200ms (defaults)
385 * depending on the accumulated lag. The blocking interval is adjusted
386 * with the average oversleeping of the last 64 times.
387 *
388 * The difference between 1 and 2 is that we use native absolute
389 * time APIs for the blocking instead of the millisecond based IPRT
390 * interface.
391 */
392 struct
393 {
394 /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
395 uint32_t cBlocks;
396 /** Align the next member. */
397 uint32_t u32Alignment;
398 /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
399 uint64_t cNSBlockedTooLongAvg;
400 /** Total time spend oversleeping when blocking. */
401 uint64_t cNSBlockedTooLong;
402 /** Total time spent blocking. */
403 uint64_t cNSBlocked;
404 /** The timestamp (RTTimeNanoTS) of the last block. */
405 uint64_t u64LastBlockTS;
406
407 /** When we started spinning relentlessly in order to catch up some of the oversleeping.
408 * This is 0 when we're not spinning. */
409 uint64_t u64StartSpinTS;
410 } Method12;
411
412# if 0
413 /**
414 * Method 3 & 4 - Same as method 1 & 2 respectivly, except that we
415 * sprinkle it with yields.
416 */
417 struct
418 {
419 /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
420 uint32_t cBlocks;
421 /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
422 uint64_t cBlockedTooLongNSAvg;
423 /** Total time spend oversleeping when blocking. */
424 uint64_t cBlockedTooLongNS;
425 /** Total time spent blocking. */
426 uint64_t cBlockedNS;
427 /** The timestamp (RTTimeNanoTS) of the last block. */
428 uint64_t u64LastBlockTS;
429
430 /** How many times we've yielded while cBlockedNS and cBlockedTooLongNS has been accumulating. */
431 uint32_t cYields;
432 /** Avg. time spend oversleeping when yielding. */
433 uint32_t cYieldTooLongNSAvg;
434 /** Total time spend oversleeping when yielding. */
435 uint64_t cYieldTooLongNS;
436 /** Total time spent yielding. */
437 uint64_t cYieldedNS;
438 /** The timestamp (RTTimeNanoTS) of the last block. */
439 uint64_t u64LastYieldTS;
440
441 /** When we started spinning relentlessly in order to catch up some of the oversleeping. */
442 uint64_t u64StartSpinTS;
443 } Method34;
444# endif
445 } Halt;
446
447 /** Profiling the halted state; yielding vs blocking.
448 * @{ */
449 STAMPROFILE StatHaltYield;
450 STAMPROFILE StatHaltBlock;
451 STAMPROFILE StatHaltBlockOverslept;
452 STAMPROFILE StatHaltBlockInsomnia;
453 STAMPROFILE StatHaltBlockOnTime;
454 STAMPROFILE StatHaltTimers;
455 STAMPROFILE StatHaltPoll;
456 /** @} */
457} VMINTUSERPERVMCPU;
458AssertCompileMemberAlignment(VMINTUSERPERVMCPU, u64HaltsStartTS, 8);
459AssertCompileMemberAlignment(VMINTUSERPERVMCPU, Halt.Method12.cNSBlockedTooLongAvg, 8);
460AssertCompileMemberAlignment(VMINTUSERPERVMCPU, StatHaltYield, 8);
461
462/** Pointer to the VM internal data kept in the UVM. */
463typedef VMINTUSERPERVMCPU *PVMINTUSERPERVMCPU;
464
465#endif /* IN_RING3 */
466
467RT_C_DECLS_BEGIN
468
469DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArg);
470int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod);
471DECLCALLBACK(int) vmR3Destroy(PVM pVM);
472DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);
473void vmSetErrorCopy(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
474DECLCALLBACK(int) vmR3SetRuntimeError(PVM pVM, uint32_t fFlags, const char *pszErrorId, char *pszMessage);
475DECLCALLBACK(int) vmR3SetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa);
476void vmSetRuntimeErrorCopy(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va);
477void vmR3SetTerminated(PVM pVM);
478
479RT_C_DECLS_END
480
481
482/** @} */
483
484#endif /* !VMM_INCLUDED_SRC_include_VMInternal_h */
485
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