VirtualBox

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

Last change on this file since 22997 was 22986, checked in by vboxsync, 15 years ago

VMM: Removed the AtReset callbacks. Rewrote the AtState registration and deregistration to no involve EMT (doens't matter really as they are usually called on EMT anyway, but it simplifies the code quite a bit.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 15.7 KB
Line 
1/* $Id: VMInternal.h 22986 2009-09-14 06:36:15Z 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 /** Set by VMR3SuspendNoSave; cleared by VMR3Resume; signals the VM is in an
169 * inconsistent state and saving is not allowed. */
170 bool fPreventSaveState;
171} VMINT;
172/** Pointer to the VM Internal Data (part of the VM structure). */
173typedef VMINT *PVMINT;
174
175
176/**
177 * VM internal data kept in the UVM.
178 */
179typedef struct VMINTUSERPERVM
180{
181 /** Head of the request queue. Atomic. */
182 volatile PVMREQ pReqs;
183 /** The last index used during alloc/free. */
184 volatile uint32_t iReqFree;
185 /** Number of free request packets. */
186 volatile uint32_t cReqFree;
187 /** Array of pointers to lists of free request packets. Atomic. */
188 volatile PVMREQ apReqFree[9];
189
190#ifdef VBOX_WITH_STATISTICS
191 /** Number of VMR3ReqAlloc returning a new packet. */
192 STAMCOUNTER StatReqAllocNew;
193 /** Number of VMR3ReqAlloc causing races. */
194 STAMCOUNTER StatReqAllocRaces;
195 /** Number of VMR3ReqAlloc returning a recycled packet. */
196 STAMCOUNTER StatReqAllocRecycled;
197 /** Number of VMR3ReqFree calls. */
198 STAMCOUNTER StatReqFree;
199 /** Number of times the request was actually freed. */
200 STAMCOUNTER StatReqFreeOverflow;
201#endif
202
203 /** Pointer to the support library session.
204 * Mainly for creation and destruction. */
205 PSUPDRVSESSION pSession;
206
207 /** Force EMT to terminate. */
208 bool volatile fTerminateEMT;
209 /** If set the EMT does the final VM cleanup when it exits.
210 * If clear the VMR3Destroy() caller does so. */
211 bool fEMTDoesTheCleanup;
212
213 /** Critical section for pAtState. */
214 RTCRITSECT AtStateCritSect;
215 /** List of registered state change callbacks. */
216 PVMATSTATE pAtState;
217 /** List of registered state change callbacks. */
218 PVMATSTATE *ppAtStateNext;
219
220 /** Critical section for pAtError and pAtRuntimeError. */
221 RTCRITSECT AtErrorCritSect;
222
223 /** List of registered error callbacks. */
224 PVMATERROR pAtError;
225 /** List of registered error callbacks. */
226 PVMATERROR *ppAtErrorNext;
227
228 /** List of registered error callbacks. */
229 PVMATRUNTIMEERROR pAtRuntimeError;
230 /** List of registered error callbacks. */
231 PVMATRUNTIMEERROR *ppAtRuntimeErrorNext;
232
233 /** @name Generic Halt data
234 * @{
235 */
236 /** The current halt method.
237 * Can be selected by CFGM option 'VM/HaltMethod'. */
238 VMHALTMETHOD enmHaltMethod;
239 /** The index into g_aHaltMethods of the current halt method. */
240 uint32_t volatile iHaltMethod;
241 /** @} */
242
243 /** @todo Do NOT add new members here or resue the current, we need to store the config for
244 * each halt method seperately because we're racing on SMP guest rigs. */
245 union
246 {
247 /**
248 * Method 1 & 2 - Block whenever possible, and when lagging behind
249 * switch to spinning with regular blocking every 5-200ms (defaults)
250 * depending on the accumulated lag. The blocking interval is adjusted
251 * with the average oversleeping of the last 64 times.
252 *
253 * The difference between 1 and 2 is that we use native absolute
254 * time APIs for the blocking instead of the millisecond based IPRT
255 * interface.
256 */
257 struct
258 {
259 /** The max interval without blocking (when spinning). */
260 uint32_t u32MinBlockIntervalCfg;
261 /** The minimum interval between blocking (when spinning). */
262 uint32_t u32MaxBlockIntervalCfg;
263 /** The value to divide the current lag by to get the raw blocking interval (when spinning). */
264 uint32_t u32LagBlockIntervalDivisorCfg;
265 /** When to start spinning (lag / nano secs). */
266 uint32_t u32StartSpinningCfg;
267 /** When to stop spinning (lag / nano secs). */
268 uint32_t u32StopSpinningCfg;
269 } Method12;
270 } Halt;
271
272 /** Pointer to the DBGC instance data. */
273 void *pvDBGC;
274
275 /** TLS index for the VMINTUSERPERVMCPU pointer. */
276 RTTLS idxTLS;
277} VMINTUSERPERVM;
278
279/** Pointer to the VM internal data kept in the UVM. */
280typedef VMINTUSERPERVM *PVMINTUSERPERVM;
281
282
283/**
284 * VMCPU internal data kept in the UVM.
285 *
286 * Almost a copy of VMINTUSERPERVM. Separate data properly later on.
287 */
288typedef struct VMINTUSERPERVMCPU
289{
290 /** Head of the request queue. Atomic. */
291 volatile PVMREQ pReqs;
292
293 /** The handle to the EMT thread. */
294 RTTHREAD ThreadEMT;
295 /** The native of the EMT thread. */
296 RTNATIVETHREAD NativeThreadEMT;
297 /** Wait event semaphore. */
298 RTSEMEVENT EventSemWait;
299 /** Wait/Idle indicator. */
300 bool volatile fWait;
301 /** Force EMT to terminate. */
302 bool volatile fTerminateEMT;
303 /** If set the EMT does the final VM cleanup when it exits.
304 * If clear the VMR3Destroy() caller does so. */
305 bool fEMTDoesTheCleanup;
306 /** Align the next bit. */
307 bool afAlignment[5];
308
309 /** @name Generic Halt data
310 * @{
311 */
312 /** The average time (ns) between two halts in the last second. (updated once per second) */
313 uint32_t HaltInterval;
314 /** The average halt frequency for the last second. (updated once per second) */
315 uint32_t HaltFrequency;
316 /** The number of halts in the current period. */
317 uint32_t cHalts;
318 uint32_t padding; /**< alignment padding. */
319 /** When we started counting halts in cHalts (RTTimeNanoTS). */
320 uint64_t u64HaltsStartTS;
321 /** @} */
322
323 /** Union containing data and config for the different halt algorithms. */
324 union
325 {
326 /**
327 * Method 1 & 2 - Block whenever possible, and when lagging behind
328 * switch to spinning with regular blocking every 5-200ms (defaults)
329 * depending on the accumulated lag. The blocking interval is adjusted
330 * with the average oversleeping of the last 64 times.
331 *
332 * The difference between 1 and 2 is that we use native absolute
333 * time APIs for the blocking instead of the millisecond based IPRT
334 * interface.
335 */
336 struct
337 {
338 /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
339 uint32_t cBlocks;
340 /** Align the next member. */
341 uint32_t u32Alignment;
342 /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
343 uint64_t cNSBlockedTooLongAvg;
344 /** Total time spend oversleeping when blocking. */
345 uint64_t cNSBlockedTooLong;
346 /** Total time spent blocking. */
347 uint64_t cNSBlocked;
348 /** The timestamp (RTTimeNanoTS) of the last block. */
349 uint64_t u64LastBlockTS;
350
351 /** When we started spinning relentlessly in order to catch up some of the oversleeping.
352 * This is 0 when we're not spinning. */
353 uint64_t u64StartSpinTS;
354 } Method12;
355
356#if 0
357 /**
358 * Method 3 & 4 - Same as method 1 & 2 respectivly, except that we
359 * sprinkle it with yields.
360 */
361 struct
362 {
363 /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
364 uint32_t cBlocks;
365 /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
366 uint64_t cBlockedTooLongNSAvg;
367 /** Total time spend oversleeping when blocking. */
368 uint64_t cBlockedTooLongNS;
369 /** Total time spent blocking. */
370 uint64_t cBlockedNS;
371 /** The timestamp (RTTimeNanoTS) of the last block. */
372 uint64_t u64LastBlockTS;
373
374 /** How many times we've yielded while cBlockedNS and cBlockedTooLongNS has been accumulating. */
375 uint32_t cYields;
376 /** Avg. time spend oversleeping when yielding. */
377 uint32_t cYieldTooLongNSAvg;
378 /** Total time spend oversleeping when yielding. */
379 uint64_t cYieldTooLongNS;
380 /** Total time spent yielding. */
381 uint64_t cYieldedNS;
382 /** The timestamp (RTTimeNanoTS) of the last block. */
383 uint64_t u64LastYieldTS;
384
385 /** When we started spinning relentlessly in order to catch up some of the oversleeping. */
386 uint64_t u64StartSpinTS;
387 } Method34;
388#endif
389 } Halt;
390
391 /** Profiling the halted state; yielding vs blocking.
392 * @{ */
393 STAMPROFILE StatHaltYield;
394 STAMPROFILE StatHaltBlock;
395 STAMPROFILE StatHaltTimers;
396 STAMPROFILE StatHaltPoll;
397 /** @} */
398} VMINTUSERPERVMCPU;
399#ifdef IN_RING3
400AssertCompileMemberAlignment(VMINTUSERPERVMCPU, u64HaltsStartTS, 8);
401AssertCompileMemberAlignment(VMINTUSERPERVMCPU, Halt.Method12.cNSBlockedTooLongAvg, 8);
402AssertCompileMemberAlignment(VMINTUSERPERVMCPU, StatHaltYield, 8);
403#endif
404
405/** Pointer to the VM internal data kept in the UVM. */
406typedef VMINTUSERPERVMCPU *PVMINTUSERPERVMCPU;
407
408RT_C_DECLS_BEGIN
409
410DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArg);
411int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod);
412DECLCALLBACK(int) vmR3Destroy(PVM pVM);
413DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);
414void vmSetErrorCopy(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
415DECLCALLBACK(int) vmR3SetRuntimeError(PVM pVM, uint32_t fFlags, const char *pszErrorId, char *pszMessage);
416DECLCALLBACK(int) vmR3SetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list *pVa);
417void vmSetRuntimeErrorCopy(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va);
418void vmR3DestroyFinalBitFromEMT(PUVM pUVM);
419void vmR3SetState(PVM pVM, VMSTATE enmStateNew);
420
421RT_C_DECLS_END
422
423
424/** @} */
425
426#endif
427
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