VirtualBox

source: vbox/trunk/src/VBox/VMM/TMInternal.h@ 443

Last change on this file since 443 was 443, checked in by vboxsync, 18 years ago

Implemented Warp drive. This can be configured using the WarpDrivePercentage (2..20000) or the TMVirtualSetWarpDrive API.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 15.3 KB
Line 
1/* $Id: TMInternal.h 443 2007-01-30 21:53:52Z vboxsync $ */
2/** @file
3 * TM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22#ifndef __TMInternal_h__
23#define __TMInternal_h__
24
25#include <VBox/cdefs.h>
26#include <VBox/types.h>
27#include <iprt/timer.h>
28#include <VBox/stam.h>
29
30__BEGIN_DECLS
31
32
33/** @defgroup grp_tm_int Internal
34 * @ingroup grp_tm
35 * @internal
36 * @{
37 */
38
39/** Frequency of the real clock. */
40#define TMCLOCK_FREQ_REAL UINT32_C(1000)
41/** Frequency of the virtual clock. */
42#define TMCLOCK_FREQ_VIRTUAL UINT32_C(1000000000)
43
44
45/**
46 * Timer type.
47 */
48typedef enum TMTIMERTYPE
49{
50 /** Device timer. */
51 TMTIMERTYPE_DEV = 1,
52 /** Driver timer. */
53 TMTIMERTYPE_DRV,
54 /** Internal timer . */
55 TMTIMERTYPE_INTERNAL,
56 /** External timer. */
57 TMTIMERTYPE_EXTERNAL
58} TMTIMERTYPE;
59
60/**
61 * Timer state
62 */
63typedef enum TMTIMERSTATE
64{
65 /** Timer is stopped. */
66 TMTIMERSTATE_STOPPED = 1,
67 /** Timer is active. */
68 TMTIMERSTATE_ACTIVE,
69 /** Timer is expired, is being delivered. */
70 TMTIMERSTATE_EXPIRED,
71
72 /** Timer is stopped but still in the active list.
73 * Currently in the ScheduleTimers list. */
74 TMTIMERSTATE_PENDING_STOP,
75 /** Timer is stopped but needs unlinking from the ScheduleTimers list.
76 * Currently in the ScheduleTimers list. */
77 TMTIMERSTATE_PENDING_STOP_SCHEDULE,
78 /** Timer is being modified and will soon be pending scheduling.
79 * Currently in the ScheduleTimers list. */
80 TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE,
81 /** Timer is pending scheduling.
82 * Currently in the ScheduleTimers list. */
83 TMTIMERSTATE_PENDING_SCHEDULE,
84 /** Timer is being modified and will soon be pending rescheduling.
85 * Currently in the ScheduleTimers list and the active list. */
86 TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE,
87 /** Timer is modified and is now pending rescheduling.
88 * Currently in the ScheduleTimers list and the active list. */
89 TMTIMERSTATE_PENDING_RESCHEDULE,
90 /** Timer is destroyed but needs to be replaced from the
91 * active to the free list.
92 * Currently in the ScheduleTimers list and the active list. */
93 TMTIMERSTATE_PENDING_STOP_DESTROY,
94 /** Timer is destroyed but needs moving to the free list.
95 * Currently in the ScheduleTimers list. */
96 TMTIMERSTATE_PENDING_DESTROY,
97 /** Timer is free. */
98 TMTIMERSTATE_FREE
99} TMTIMERSTATE;
100
101
102/**
103 * Internal representation of a timer.
104 *
105 * For correct serialization (without the use of semaphores and
106 * other blocking/slow constructs) certain rules applies to updating
107 * this structure:
108 * - For thread other than EMT only u64Expire, enmState and pScheduleNext*
109 * are changeable. Everything else is out of bounds.
110 * - Updating of u64Expire timer can only happen in the TMTIMERSTATE_STOPPED
111 * and TMTIMERSTATE_PENDING_RESCHEDULING_SET_EXPIRE states.
112 * - Timers in the TMTIMERSTATE_EXPIRED state are only accessible from EMT.
113 * - Actual destruction of a timer can only be done at scheduling time.
114 */
115typedef struct TMTIMER
116{
117 /** Expire time. */
118 volatile uint64_t u64Expire;
119 /** Clock to apply to u64Expire. */
120 TMCLOCK enmClock;
121 /** Timer callback type. */
122 TMTIMERTYPE enmType;
123 /** Type specific data. */
124 union
125 {
126 /** TMTIMERTYPE_DEV. */
127 struct
128 {
129 /** Callback. */
130 R3PTRTYPE(PFNTMTIMERDEV) pfnTimer;
131 /** Device instance. */
132 R3PTRTYPE(PPDMDEVINS) pDevIns;
133 } Dev;
134
135 /** TMTIMERTYPE_DRV. */
136 struct
137 {
138 /** Callback. */
139 R3PTRTYPE(PFNTMTIMERDRV) pfnTimer;
140 /** Device instance. */
141 R3PTRTYPE(PPDMDRVINS) pDrvIns;
142 } Drv;
143
144 /** TMTIMERTYPE_INTERNAL. */
145 struct
146 {
147 /** Callback. */
148 R3PTRTYPE(PFNTMTIMERINT) pfnTimer;
149 /** User argument. */
150 R3PTRTYPE(void *) pvUser;
151 } Internal;
152
153 /** TMTIMERTYPE_EXTERNAL. */
154 struct
155 {
156 /** Callback. */
157 R3PTRTYPE(PFNTMTIMEREXT) pfnTimer;
158 /** User data. */
159 R3PTRTYPE(void *) pvUser;
160 } External;
161 } u;
162
163 /** Timer state. */
164 volatile TMTIMERSTATE enmState;
165 /** Timer relative offset to the next timer in the schedule list. */
166 int32_t offScheduleNext;
167
168 /** Timer relative offset to the next timer in the chain. */
169 int32_t offNext;
170 /** Timer relative offset to the previous timer in the chain. */
171 int32_t offPrev;
172
173 /** Pointer to the next timer in the list of created or free timers. (TM::pTimers or TM::pFree) */
174 PTMTIMERR3 pBigNext;
175 /** Pointer to the previous timer in the list of all created timers. (TM::pTimers) */
176 PTMTIMERR3 pBigPrev;
177 /** Pointer to the timer description. */
178 HCPTRTYPE(const char *) pszDesc;
179 /** Pointer to the VM the timer belongs to - R3 Ptr. */
180 PVMR3 pVMR3;
181 /** Pointer to the VM the timer belongs to - R0 Ptr. */
182 PVMR0 pVMR0;
183 /** Pointer to the VM the timer belongs to - GC Ptr. */
184 PVMGC pVMGC;
185#if HC_ARCH_BITS == 64 && GC_ARCH_BITS == 32
186 RTGCPTR padding0; /**< pad structure to multiple of 8 bytes. */
187#endif
188} TMTIMER;
189
190
191/**
192 * Updates a timer state in the correct atomic manner.
193 */
194#if 1
195# define TM_SET_STATE(pTimer, state) \
196 ASMAtomicXchgSize(&(pTimer)->enmState, state)
197#else
198# define TM_SET_STATE(pTimer, state) \
199 do { Log(("%s: %p: %d -> %d\n", __FUNCTION__, (pTimer), (pTimer)->enmState, state)); \
200 ASMAtomicXchgSize(&(pTimer)->enmState, state);\
201 } while (0)
202#endif
203
204/**
205 * Tries to updates a timer state in the correct atomic manner.
206 */
207#if 1
208# define TM_TRY_SET_STATE(pTimer, StateNew, StateOld, fRc) \
209 ASMAtomicCmpXchgSize(&(pTimer)->enmState, StateNew, StateOld, fRc)
210#else
211# define TM_TRY_SET_STATE(pTimer, StateNew, StateOld, fRc) \
212 do { ASMAtomicCmpXchgSize(&(pTimer)->enmState, StateNew, StateOld, fRc); \
213 Log(("%s: %p: %d -> %d %RTbool\n", __FUNCTION__, (pTimer), StateOld, StateNew, fRc)); \
214 } while (0)
215#endif
216
217/** Get the previous timer. */
218#define TMTIMER_GET_PREV(pTimer) ((PTMTIMER)((pTimer)->offPrev ? (intptr_t)(pTimer) + (pTimer)->offPrev : 0))
219/** Get the next timer. */
220#define TMTIMER_GET_NEXT(pTimer) ((PTMTIMER)((pTimer)->offNext ? (intptr_t)(pTimer) + (pTimer)->offNext : 0))
221/** Set the previous timer link. */
222#define TMTIMER_SET_PREV(pTimer, pPrev) ((pTimer)->offPrev = (pPrev) ? (intptr_t)(pPrev) - (intptr_t)(pTimer) : 0)
223/** Set the next timer link. */
224#define TMTIMER_SET_NEXT(pTimer, pNext) ((pTimer)->offNext = (pNext) ? (intptr_t)(pNext) - (intptr_t)(pTimer) : 0)
225
226
227/**
228 * A timer queue.
229 *
230 * This is allocated on the hyper heap.
231 */
232typedef struct TMTIMERQUEUE
233{
234 /** The cached expire time for this queue.
235 * Updated by EMT when scheduling the queue or modifying the head timer.
236 * Assigned UINT64_MAX when there is no head timer. */
237 uint64_t u64Expire;
238 /** Doubly linked list of active timers.
239 *
240 * When no scheduling is pending, this list is will be ordered by expire time (ascending).
241 * Access is serialized by only letting the emulation thread (EMT) do changes.
242 *
243 * The offset is relative to the queue structure.
244 */
245 int32_t offActive;
246 /** List of timers pending scheduling of some kind.
247 *
248 * Timer stats allowed in the list are TMTIMERSTATE_PENDING_STOPPING,
249 * TMTIMERSTATE_PENDING_DESTRUCTION, TMTIMERSTATE_PENDING_STOPPING_DESTRUCTION,
250 * TMTIMERSTATE_PENDING_RESCHEDULING and TMTIMERSTATE_PENDING_SCHEDULE.
251 *
252 * The offset is relative to the queue structure.
253 */
254 int32_t volatile offSchedule;
255 /** The clock for this queue. */
256 TMCLOCK enmClock;
257 /** Pad the structure up to 32 bytes. */
258 uint32_t au32Padding[3];
259} TMTIMERQUEUE;
260
261/** Pointer to a timer queue. */
262typedef TMTIMERQUEUE *PTMTIMERQUEUE;
263
264/** Get the head of the active timer list. */
265#define TMTIMER_GET_HEAD(pQueue) ((PTMTIMER)((pQueue)->offActive ? (intptr_t)(pQueue) + (pQueue)->offActive : 0))
266/** Set the head of the active timer list. */
267#define TMTIMER_SET_HEAD(pQueue, pHead) ((pQueue)->offActive = pHead ? (intptr_t)pHead - (intptr_t)(pQueue) : 0)
268
269
270/**
271 * Converts a TM pointer into a VM pointer.
272 * @returns Pointer to the VM structure the TM is part of.
273 * @param pTM Pointer to TM instance data.
274 */
275#define TM2VM(pTM) ( (PVM)((char*)pTM - pTM->offVM) )
276
277
278/**
279 * TM VM Instance data.
280 * Changes to this must checked against the padding of the cfgm union in VM!
281 */
282typedef struct TM
283{
284 /** Offset to the VM structure.
285 * See TM2VM(). */
286 RTUINT offVM;
287
288 /** CPU timestamp ticking enabled indicator (bool). (RDTSC) */
289 bool fTSCTicking;
290 /** The offset between the host TSC and the Guest TSC.
291 * Only valid if fTicking is set. */
292 uint64_t u64TSCOffset;
293 /** The guest TSC when fTicking is cleared. */
294 uint64_t u64TSC;
295 /** The number of CPU clock ticks per second (TMCLOCK_TSC).
296 * If GIP is available, g_pSUPGlobalInfoPage->u64CpuHz will be used instead. */
297 uint64_t cTSCTicksPerSecond;
298
299 /** Virtual time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL) */
300 bool fVirtualTicking;
301 /** Virtual time is not running at 100%. */
302 bool fVirtualWarpDrive;
303 /** Virtual timer synchronous time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL_SYNC) */
304 bool fVirtualSyncTicking;
305 /** Virtual timer synchronous time catch-up active. */
306 bool volatile fVirtualSyncCatchUp;
307 /** WarpDrive percentage.
308 * 100% is normal (fVirtualSyncNormal == true). When other than 100% we apply
309 * this percentage to the raw time source for the period it's been valid in,
310 * i.e. since u64VirtualWarpDriveStart. */
311 uint32_t u32VirtualWarpDrivePercentage;
312
313 /** The offset of the virtual clock relative to it's timesource.
314 * Only valid if fVirtualTicking is set. */
315 uint64_t u64VirtualOffset;
316 /** The guest virtual time when fVirtualTicking is cleared. */
317 uint64_t u64Virtual;
318 /** When the Warp drive was started or last adjusted.
319 * Only valid when fVirtualWarpDrive is set. */
320 uint64_t u64VirtualWarpDriveStart;
321
322 /** The offset of the virtual timer synchronous clock (TMCLOCK_VIRTUAL_SYNC) relative
323 * to the virtual clock. */
324 uint64_t volatile u64VirtualSyncOffset;
325 /** The TMCLOCK_VIRTUAL at the previous TMVirtualGetSync call when catch-up is active. */
326 uint64_t volatile u64VirtualSyncCatchUpPrev;
327 /** The guest virtual timer synchronous time when fVirtualSyncTicking is cleared. */
328 uint64_t u64VirtualSync;
329 /** How many percent faster the clock should advance when catch-up is active. */
330 uint32_t u32VirtualSyncCatchupPercentage;
331 /** When to stop catch-up. */
332 uint32_t u32VirtualSyncCatchupStopThreashold;
333 /** When to start catch-up. */
334 uint64_t u64VirtualSyncCatchupStartTreashold;
335 /** When to give up catch-up. */
336 uint64_t u64VirtualSyncCatchupGiveUpTreashold;
337
338 /** Timer queues for the different clock types - R3 Ptr */
339 R3PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR3;
340 /** Timer queues for the different clock types - R0 Ptr */
341 R0PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR0;
342 /** Timer queues for the different clock types - GC Ptr */
343 GCPTRTYPE(PTMTIMERQUEUE) paTimerQueuesGC;
344
345 /** Pointer to our GC mapping of the GIP. */
346 GCPTRTYPE(void *) pvGIPGC;
347 /** Pointer to our R3 mapping of the GIP. */
348 R3PTRTYPE(void *) pvGIPR3;
349
350 /** Pointer to a singly linked list of free timers.
351 * This chain is using the TMTIMER::pBigNext members.
352 * Only accessible from the emulation thread. */
353 PTMTIMERR3 pFree;
354
355 /** Pointer to a doubly linked list of created timers.
356 * This chain is using the TMTIMER::pBigNext and TMTIMER::pBigPrev members.
357 * Only accessible from the emulation thread. */
358 PTMTIMERR3 pCreated;
359
360 /** The schedulation timer timer handle (runtime timer).
361 * This timer will do freqent check on pending queue schedulations and
362 * raise VM_FF_TIMER to pull EMTs attention to them.
363 */
364 HCPTRTYPE(PRTTIMER) pTimer;
365 /** Interval in milliseconds of the pTimer timer. */
366 uint32_t u32TimerMillies;
367
368 /** Alignment padding to ensure that the statistics are 64-bit aligned when using GCC. */
369 uint32_t u32Padding;
370
371 /** TMR3TimerQueuesDo
372 * @{ */
373 STAMPROFILE StatDoQueues;
374 STAMPROFILEADV StatDoQueuesSchedule;
375 STAMPROFILEADV StatDoQueuesRun;
376 /** @} */
377 /** tmSchedule
378 * @{ */
379 STAMPROFILE StatScheduleOneGC;
380 STAMPROFILE StatScheduleOneR0;
381 STAMPROFILE StatScheduleOneR3;
382 STAMCOUNTER StatScheduleSetFF;
383 /** @} */
384 STAMCOUNTER StatVirtualGet;
385 STAMCOUNTER StatVirtualGetSync;
386 STAMCOUNTER StatVirtualPause;
387 STAMCOUNTER StatVirtualResume;
388 /** TMTimerPoll
389 * @{ */
390 STAMCOUNTER StatPollAlreadySet;
391 STAMCOUNTER StatPollVirtual;
392 STAMCOUNTER StatPollVirtualSync;
393 STAMCOUNTER StatPollMiss;
394 /** @} */
395 /** TMTimerSet
396 * @{ */
397 STAMPROFILE StatTimerSetGC;
398 STAMPROFILE StatTimerSetR0;
399 STAMPROFILE StatTimerSetR3;
400 /** @} */
401 /** TMTimerStop
402 * @{ */
403 STAMPROFILE StatTimerStopGC;
404 STAMPROFILE StatTimerStopR0;
405 STAMPROFILE StatTimerStopR3;
406 /** @} */
407 /**
408 * @{ */
409 STAMCOUNTER StatPostponedR3;
410 STAMCOUNTER StatPostponedR0;
411 STAMCOUNTER StatPostponedGC;
412 /** @} */
413 /** The timer callback. */
414 STAMCOUNTER StatTimerCallbackSetFF;
415
416} TM;
417/** Pointer to TM VM instance data. */
418typedef TM *PTM;
419
420
421const char *tmTimerState(TMTIMERSTATE enmState);
422void tmTimerQueueSchedule(PVM pVM, PTMTIMERQUEUE pQueue);
423#ifdef VBOX_STRICT
424void tmTimerQueuesSanityChecks(PVM pVM, const char *pszWhere);
425#endif
426
427/** @} */
428
429__END_DECLS
430
431#endif
432
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