VirtualBox

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

Last change on this file since 25414 was 24738, checked in by vboxsync, 15 years ago

VMReq.cpp: Made VMR3ReqProcessU re-entrant.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use