VirtualBox

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

最後變更 在這個檔案從37517是 37517,由 vboxsync 提交於 14 年 前

TM: Simplified the virtual sync timers by requiring changes to be done while holding the virtual sync lock. This means we can skip all the pending states and move timers on and off the active list immediately, avoiding the problems with timers being on the pending-scheduling list. Also made u64VirtualSync keep track of the last time stamp all the time (when under the lock) and thus really making sure time does not jump backwards.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 31.0 KB
 
1/* $Id: TMInternal.h 37517 2011-06-16 19:24:00Z vboxsync $ */
2/** @file
3 * TM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 ___TMInternal_h
19#define ___TMInternal_h
20
21#include <VBox/cdefs.h>
22#include <VBox/types.h>
23#include <iprt/time.h>
24#include <iprt/timer.h>
25#include <iprt/assert.h>
26#include <VBox/vmm/stam.h>
27#include <VBox/vmm/pdmcritsect.h>
28
29RT_C_DECLS_BEGIN
30
31
32/** @defgroup grp_tm_int Internal
33 * @ingroup grp_tm
34 * @internal
35 * @{
36 */
37
38/** Frequency of the real clock. */
39#define TMCLOCK_FREQ_REAL UINT32_C(1000)
40/** Frequency of the virtual clock. */
41#define TMCLOCK_FREQ_VIRTUAL UINT32_C(1000000000)
42
43
44/**
45 * Timer type.
46 */
47typedef enum TMTIMERTYPE
48{
49 /** Device timer. */
50 TMTIMERTYPE_DEV = 1,
51 /** USB device timer. */
52 TMTIMERTYPE_USB,
53 /** Driver timer. */
54 TMTIMERTYPE_DRV,
55 /** Internal timer . */
56 TMTIMERTYPE_INTERNAL,
57 /** External timer. */
58 TMTIMERTYPE_EXTERNAL
59} TMTIMERTYPE;
60
61/**
62 * Timer state
63 */
64typedef enum TMTIMERSTATE
65{
66 /** Timer is stopped. */
67 TMTIMERSTATE_STOPPED = 1,
68 /** Timer is active. */
69 TMTIMERSTATE_ACTIVE,
70 /** Timer is expired, getting expire and unlinking. */
71 TMTIMERSTATE_EXPIRED_GET_UNLINK,
72 /** Timer is expired and is being delivered. */
73 TMTIMERSTATE_EXPIRED_DELIVER,
74
75 /** Timer is stopped but still in the active list.
76 * Currently in the ScheduleTimers list. */
77 TMTIMERSTATE_PENDING_STOP,
78 /** Timer is stopped but needs unlinking from the ScheduleTimers list.
79 * Currently in the ScheduleTimers list. */
80 TMTIMERSTATE_PENDING_STOP_SCHEDULE,
81 /** Timer is being modified and will soon be pending scheduling.
82 * Currently in the ScheduleTimers list. */
83 TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE,
84 /** Timer is pending scheduling.
85 * Currently in the ScheduleTimers list. */
86 TMTIMERSTATE_PENDING_SCHEDULE,
87 /** Timer is being modified and will soon be pending rescheduling.
88 * Currently in the ScheduleTimers list and the active list. */
89 TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE,
90 /** Timer is modified and is now pending rescheduling.
91 * Currently in the ScheduleTimers list and the active list. */
92 TMTIMERSTATE_PENDING_RESCHEDULE,
93 /** Timer is being destroyed. */
94 TMTIMERSTATE_DESTROY,
95 /** Timer is free. */
96 TMTIMERSTATE_FREE
97} TMTIMERSTATE;
98
99/** Predicate that returns true if the give state is pending scheduling or
100 * rescheduling of any kind. Will reference the argument more than once! */
101#define TMTIMERSTATE_IS_PENDING_SCHEDULING(enmState) \
102 ( (enmState) <= TMTIMERSTATE_PENDING_RESCHEDULE \
103 && (enmState) >= TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE)
104
105
106/**
107 * Internal representation of a timer.
108 *
109 * For correct serialization (without the use of semaphores and
110 * other blocking/slow constructs) certain rules applies to updating
111 * this structure:
112 * - For thread other than EMT only u64Expire, enmState and pScheduleNext*
113 * are changeable. Everything else is out of bounds.
114 * - Updating of u64Expire timer can only happen in the TMTIMERSTATE_STOPPED
115 * and TMTIMERSTATE_PENDING_RESCHEDULING_SET_EXPIRE states.
116 * - Timers in the TMTIMERSTATE_EXPIRED state are only accessible from EMT.
117 * - Actual destruction of a timer can only be done at scheduling time.
118 */
119typedef struct TMTIMER
120{
121 /** Expire time. */
122 volatile uint64_t u64Expire;
123 /** Clock to apply to u64Expire. */
124 TMCLOCK enmClock;
125 /** Timer callback type. */
126 TMTIMERTYPE enmType;
127 /** Type specific data. */
128 union
129 {
130 /** TMTIMERTYPE_DEV. */
131 struct
132 {
133 /** Callback. */
134 R3PTRTYPE(PFNTMTIMERDEV) pfnTimer;
135 /** Device instance. */
136 PPDMDEVINSR3 pDevIns;
137 } Dev;
138
139 /** TMTIMERTYPE_DEV. */
140 struct
141 {
142 /** Callback. */
143 R3PTRTYPE(PFNTMTIMERUSB) pfnTimer;
144 /** USB device instance. */
145 PPDMUSBINS pUsbIns;
146 } Usb;
147
148 /** TMTIMERTYPE_DRV. */
149 struct
150 {
151 /** Callback. */
152 R3PTRTYPE(PFNTMTIMERDRV) pfnTimer;
153 /** Device instance. */
154 R3PTRTYPE(PPDMDRVINS) pDrvIns;
155 } Drv;
156
157 /** TMTIMERTYPE_INTERNAL. */
158 struct
159 {
160 /** Callback. */
161 R3PTRTYPE(PFNTMTIMERINT) pfnTimer;
162 } Internal;
163
164 /** TMTIMERTYPE_EXTERNAL. */
165 struct
166 {
167 /** Callback. */
168 R3PTRTYPE(PFNTMTIMEREXT) pfnTimer;
169 } External;
170 } u;
171
172 /** Timer state. */
173 volatile TMTIMERSTATE enmState;
174 /** Timer relative offset to the next timer in the schedule list. */
175 int32_t volatile offScheduleNext;
176
177 /** Timer relative offset to the next timer in the chain. */
178 int32_t offNext;
179 /** Timer relative offset to the previous timer in the chain. */
180 int32_t offPrev;
181
182 /** Pointer to the VM the timer belongs to - R3 Ptr. */
183 PVMR3 pVMR3;
184 /** Pointer to the VM the timer belongs to - R0 Ptr. */
185 PVMR0 pVMR0;
186 /** Pointer to the VM the timer belongs to - RC Ptr. */
187 PVMRC pVMRC;
188 /** The timer frequency hint. This is 0 if not hint was given. */
189 uint32_t volatile uHzHint;
190
191 /** User argument. */
192 RTR3PTR pvUser;
193 /** The critical section associated with the lock. */
194 R3PTRTYPE(PPDMCRITSECT) pCritSect;
195
196 /** Pointer to the next timer in the list of created or free timers. (TM::pTimers or TM::pFree) */
197 PTMTIMERR3 pBigNext;
198 /** Pointer to the previous timer in the list of all created timers. (TM::pTimers) */
199 PTMTIMERR3 pBigPrev;
200 /** Pointer to the timer description. */
201 R3PTRTYPE(const char *) pszDesc;
202#if HC_ARCH_BITS == 32
203 uint32_t padding0; /**< pad structure to multiple of 8 bytes. */
204#endif
205} TMTIMER;
206AssertCompileMemberSize(TMTIMER, enmState, sizeof(uint32_t));
207
208
209/**
210 * Updates a timer state in the correct atomic manner.
211 */
212#if 1
213# define TM_SET_STATE(pTimer, state) \
214 ASMAtomicWriteU32((uint32_t volatile *)&(pTimer)->enmState, state)
215#else
216# define TM_SET_STATE(pTimer, state) \
217 do { \
218 uint32_t uOld1 = (pTimer)->enmState; \
219 Log(("%s: %p: %d -> %d\n", __FUNCTION__, (pTimer), (pTimer)->enmState, state)); \
220 uint32_t uOld2 = ASMAtomicXchgU32((uint32_t volatile *)&(pTimer)->enmState, state); \
221 Assert(uOld1 == uOld2); \
222 } while (0)
223#endif
224
225/**
226 * Tries to updates a timer state in the correct atomic manner.
227 */
228#if 1
229# define TM_TRY_SET_STATE(pTimer, StateNew, StateOld, fRc) \
230 (fRc) = ASMAtomicCmpXchgU32((uint32_t volatile *)&(pTimer)->enmState, StateNew, StateOld)
231#else
232# define TM_TRY_SET_STATE(pTimer, StateNew, StateOld, fRc) \
233 do { (fRc) = ASMAtomicCmpXchgU32((uint32_t volatile *)&(pTimer)->enmState, StateNew, StateOld); \
234 Log(("%s: %p: %d -> %d %RTbool\n", __FUNCTION__, (pTimer), StateOld, StateNew, fRc)); \
235 } while (0)
236#endif
237
238/** Get the previous timer. */
239#define TMTIMER_GET_PREV(pTimer) ((PTMTIMER)((pTimer)->offPrev ? (intptr_t)(pTimer) + (pTimer)->offPrev : 0))
240/** Get the next timer. */
241#define TMTIMER_GET_NEXT(pTimer) ((PTMTIMER)((pTimer)->offNext ? (intptr_t)(pTimer) + (pTimer)->offNext : 0))
242/** Set the previous timer link. */
243#define TMTIMER_SET_PREV(pTimer, pPrev) ((pTimer)->offPrev = (pPrev) ? (intptr_t)(pPrev) - (intptr_t)(pTimer) : 0)
244/** Set the next timer link. */
245#define TMTIMER_SET_NEXT(pTimer, pNext) ((pTimer)->offNext = (pNext) ? (intptr_t)(pNext) - (intptr_t)(pTimer) : 0)
246
247
248/**
249 * A timer queue.
250 *
251 * This is allocated on the hyper heap.
252 */
253typedef struct TMTIMERQUEUE
254{
255 /** The cached expire time for this queue.
256 * Updated by EMT when scheduling the queue or modifying the head timer.
257 * Assigned UINT64_MAX when there is no head timer. */
258 uint64_t u64Expire;
259 /** Doubly linked list of active timers.
260 *
261 * When no scheduling is pending, this list is will be ordered by expire time (ascending).
262 * Access is serialized by only letting the emulation thread (EMT) do changes.
263 *
264 * The offset is relative to the queue structure.
265 */
266 int32_t offActive;
267 /** List of timers pending scheduling of some kind.
268 *
269 * Timer stats allowed in the list are TMTIMERSTATE_PENDING_STOPPING,
270 * TMTIMERSTATE_PENDING_DESTRUCTION, TMTIMERSTATE_PENDING_STOPPING_DESTRUCTION,
271 * TMTIMERSTATE_PENDING_RESCHEDULING and TMTIMERSTATE_PENDING_SCHEDULE.
272 *
273 * The offset is relative to the queue structure.
274 */
275 int32_t volatile offSchedule;
276 /** The clock for this queue. */
277 TMCLOCK enmClock;
278 /** Pad the structure up to 32 bytes. */
279 uint32_t au32Padding[3];
280} TMTIMERQUEUE;
281
282/** Pointer to a timer queue. */
283typedef TMTIMERQUEUE *PTMTIMERQUEUE;
284
285/** Get the head of the active timer list. */
286#define TMTIMER_GET_HEAD(pQueue) ((PTMTIMER)((pQueue)->offActive ? (intptr_t)(pQueue) + (pQueue)->offActive : 0))
287/** Set the head of the active timer list. */
288#define TMTIMER_SET_HEAD(pQueue, pHead) ((pQueue)->offActive = pHead ? (intptr_t)pHead - (intptr_t)(pQueue) : 0)
289
290
291/**
292 * CPU load data set.
293 * Mainly used by tmR3CpuLoadTimer.
294 */
295typedef struct TMCPULOADSTATE
296{
297 /** The percent of the period spent executing guest code. */
298 uint8_t cPctExecuting;
299 /** The percent of the period spent halted. */
300 uint8_t cPctHalted;
301 /** The percent of the period spent on other things. */
302 uint8_t cPctOther;
303 /** Explicit alignment padding */
304 uint8_t au8Alignment[5];
305
306 /** Previous cNsTotal value. */
307 uint64_t cNsPrevTotal;
308 /** Previous cNsExecuting value. */
309 uint64_t cNsPrevExecuting;
310 /** Previous cNsHalted value. */
311 uint64_t cNsPrevHalted;
312} TMCPULOADSTATE;
313AssertCompileSizeAlignment(TMCPULOADSTATE, 8);
314AssertCompileMemberAlignment(TMCPULOADSTATE, cNsPrevTotal, 8);
315/** Pointer to a CPU load data set. */
316typedef TMCPULOADSTATE *PTMCPULOADSTATE;
317
318/**
319 * Converts a TM pointer into a VM pointer.
320 * @returns Pointer to the VM structure the TM is part of.
321 * @param pTM Pointer to TM instance data.
322 */
323#define TM2VM(pTM) ( (PVM)((char*)pTM - pTM->offVM) )
324
325
326/**
327 * TM VM Instance data.
328 * Changes to this must checked against the padding of the cfgm union in VM!
329 */
330typedef struct TM
331{
332 /** Offset to the VM structure.
333 * See TM2VM(). */
334 RTUINT offVM;
335
336 /** Set if we fully virtualize the TSC, i.e. intercept all rdtsc instructions.
337 * Config variable: TSCVirtualized (bool) */
338 bool fTSCVirtualized;
339 /** Set if we use the real TSC as time source or if we use the virtual clock.
340 * If fTSCVirtualized is set we maintain a offset to the TSC and pausing/resuming the
341 * ticking. fTSCVirtualized = false implies fTSCUseRealTSC = true.
342 * Config variable: TSCUseRealTSC (bool) */
343 bool fTSCUseRealTSC;
344 /** Flag indicating that the host TSC is suitable for use in AMD-V and VT-x mode.
345 * Config variable: MaybeUseOffsettedHostTSC (boolean) */
346 bool fMaybeUseOffsettedHostTSC;
347 /** Whether the TSC is tied to the execution of code.
348 * Config variable: TSCTiedToExecution (bool) */
349 bool fTSCTiedToExecution;
350 /** Modifier for fTSCTiedToExecution which pauses the TSC while halting if true.
351 * Config variable: TSCNotTiedToHalt (bool) */
352 bool fTSCNotTiedToHalt;
353 bool afAlignment0[2]; /**< alignment padding */
354 /** The ID of the virtual CPU that normally runs the timers. */
355 VMCPUID idTimerCpu;
356 /** The number of CPU clock ticks per second (TMCLOCK_TSC).
357 * Config variable: TSCTicksPerSecond (64-bit unsigned int)
358 * The config variable implies fTSCVirtualized = true and fTSCUseRealTSC = false. */
359 uint64_t cTSCTicksPerSecond;
360
361 /** Virtual time ticking enabled indicator (counter for each VCPU). (TMCLOCK_VIRTUAL) */
362 uint32_t volatile cVirtualTicking;
363 /** Virtual time is not running at 100%. */
364 bool fVirtualWarpDrive;
365 /** Virtual timer synchronous time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL_SYNC) */
366 bool volatile fVirtualSyncTicking;
367 /** Virtual timer synchronous time catch-up active. */
368 bool volatile fVirtualSyncCatchUp;
369 bool afAlignment1[5]; /**< alignment padding */
370 /** WarpDrive percentage.
371 * 100% is normal (fVirtualSyncNormal == true). When other than 100% we apply
372 * this percentage to the raw time source for the period it's been valid in,
373 * i.e. since u64VirtualWarpDriveStart. */
374 uint32_t u32VirtualWarpDrivePercentage;
375
376 /** The offset of the virtual clock relative to it's timesource.
377 * Only valid if fVirtualTicking is set. */
378 uint64_t u64VirtualOffset;
379 /** The guest virtual time when fVirtualTicking is cleared. */
380 uint64_t u64Virtual;
381 /** When the Warp drive was started or last adjusted.
382 * Only valid when fVirtualWarpDrive is set. */
383 uint64_t u64VirtualWarpDriveStart;
384 /** The previously returned nano TS.
385 * This handles TSC drift on SMP systems and expired interval.
386 * This is a valid range u64NanoTS to u64NanoTS + 1000000000 (ie. 1sec). */
387 uint64_t volatile u64VirtualRawPrev;
388 /** The ring-3 data structure for the RTTimeNanoTS workers used by tmVirtualGetRawNanoTS. */
389 RTTIMENANOTSDATAR3 VirtualGetRawDataR3;
390 /** The ring-0 data structure for the RTTimeNanoTS workers used by tmVirtualGetRawNanoTS. */
391 RTTIMENANOTSDATAR0 VirtualGetRawDataR0;
392 /** The ring-0 data structure for the RTTimeNanoTS workers used by tmVirtualGetRawNanoTS. */
393 RTTIMENANOTSDATARC VirtualGetRawDataRC;
394 /** Pointer to the ring-3 tmVirtualGetRawNanoTS worker function. */
395 R3PTRTYPE(PFNTIMENANOTSINTERNAL) pfnVirtualGetRawR3;
396 /** Pointer to the ring-3 tmVirtualGetRawNanoTS worker function. */
397 R0PTRTYPE(PFNTIMENANOTSINTERNAL) pfnVirtualGetRawR0;
398 /** Pointer to the ring-3 tmVirtualGetRawNanoTS worker function. */
399 RCPTRTYPE(PFNTIMENANOTSINTERNAL) pfnVirtualGetRawRC;
400 /** Alignment. */
401 RTRCPTR AlignmentRCPtr;
402 /** The guest virtual timer synchronous time when fVirtualSyncTicking is cleared.
403 * When fVirtualSyncTicking is set it holds the last time returned to
404 * the guest (while the lock was held). */
405 uint64_t volatile u64VirtualSync;
406 /** The offset of the timer synchronous virtual clock (TMCLOCK_VIRTUAL_SYNC) relative
407 * to the virtual clock (TMCLOCK_VIRTUAL).
408 * (This is accessed by the timer thread and must be updated atomically.) */
409 uint64_t volatile offVirtualSync;
410 /** The offset into offVirtualSync that's been irrevocably given up by failed catch-up attempts.
411 * Thus the current lag is offVirtualSync - offVirtualSyncGivenUp. */
412 uint64_t offVirtualSyncGivenUp;
413 /** The TMCLOCK_VIRTUAL at the previous TMVirtualGetSync call when catch-up is active. */
414 uint64_t volatile u64VirtualSyncCatchUpPrev;
415 /** The current catch-up percentage. */
416 uint32_t volatile u32VirtualSyncCatchUpPercentage;
417 /** How much slack when processing timers. */
418 uint32_t u32VirtualSyncScheduleSlack;
419 /** When to stop catch-up. */
420 uint64_t u64VirtualSyncCatchUpStopThreshold;
421 /** When to give up catch-up. */
422 uint64_t u64VirtualSyncCatchUpGiveUpThreshold;
423/** @def TM_MAX_CATCHUP_PERIODS
424 * The number of catchup rates. */
425#define TM_MAX_CATCHUP_PERIODS 10
426 /** The aggressiveness of the catch-up relative to how far we've lagged behind.
427 * The idea is to have increasing catch-up percentage as the lag increases. */
428 struct TMCATCHUPPERIOD
429 {
430 uint64_t u64Start; /**< When this period starts. (u64VirtualSyncOffset). */
431 uint32_t u32Percentage; /**< The catch-up percent to apply. */
432 uint32_t u32Alignment; /**< Structure alignment */
433 } aVirtualSyncCatchUpPeriods[TM_MAX_CATCHUP_PERIODS];
434
435 /** The current max timer Hz hint. */
436 uint32_t volatile uMaxHzHint;
437 /** Whether to recalulate the HzHint next time its queried. */
438 bool volatile fHzHintNeedsUpdating;
439 /** Alignment */
440 bool afAlignment2[3];
441 /** @cfgm{TM/HostHzMax, uint32_t, Hz, 0, UINT32_MAX, 20000}
442 * The max host Hz frequency hint returned by TMCalcHostTimerFrequency. */
443 uint32_t cHostHzMax;
444 /** @cfgm{TM/HostHzFudgeFactorTimerCpu, uint32_t, Hz, 0, UINT32_MAX, 111}
445 * The number of Hz TMCalcHostTimerFrequency adds for the timer CPU. */
446 uint32_t cPctHostHzFudgeFactorTimerCpu;
447 /** @cfgm{TM/HostHzFudgeFactorOtherCpu, uint32_t, Hz, 0, UINT32_MAX, 110}
448 * The number of Hz TMCalcHostTimerFrequency adds for the other CPUs. */
449 uint32_t cPctHostHzFudgeFactorOtherCpu;
450 /** @cfgm{TM/HostHzFudgeFactorCatchUp100, uint32_t, Hz, 0, UINT32_MAX, 300}
451 * The fudge factor (expressed in percent) that catch-up percentages below
452 * 100% is multiplied by. */
453 uint32_t cPctHostHzFudgeFactorCatchUp100;
454 /** @cfgm{TM/HostHzFudgeFactorCatchUp200, uint32_t, Hz, 0, UINT32_MAX, 250}
455 * The fudge factor (expressed in percent) that catch-up percentages
456 * 100%-199% is multiplied by. */
457 uint32_t cPctHostHzFudgeFactorCatchUp200;
458 /** @cfgm{TM/HostHzFudgeFactorCatchUp400, uint32_t, Hz, 0, UINT32_MAX, 200}
459 * The fudge factor (expressed in percent) that catch-up percentages
460 * 200%-399% is multiplied by. */
461 uint32_t cPctHostHzFudgeFactorCatchUp400;
462
463 /** The UTC offset in ns.
464 * This is *NOT* for converting UTC to local time. It is for converting real
465 * world UTC time to VM UTC time. This feature is indented for doing date
466 * testing of software and similar.
467 * @todo Implement warpdrive on UTC. */
468 int64_t offUTC;
469
470 /** Timer queues for the different clock types - R3 Ptr */
471 R3PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR3;
472 /** Timer queues for the different clock types - R0 Ptr */
473 R0PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR0;
474 /** Timer queues for the different clock types - RC Ptr */
475 RCPTRTYPE(PTMTIMERQUEUE) paTimerQueuesRC;
476
477 /** Pointer to our RC mapping of the GIP. */
478 RCPTRTYPE(void *) pvGIPRC;
479 /** Pointer to our R3 mapping of the GIP. */
480 R3PTRTYPE(void *) pvGIPR3;
481
482 /** Pointer to a singly linked list of free timers.
483 * This chain is using the TMTIMER::pBigNext members.
484 * Only accessible from the emulation thread. */
485 PTMTIMERR3 pFree;
486
487 /** Pointer to a doubly linked list of created timers.
488 * This chain is using the TMTIMER::pBigNext and TMTIMER::pBigPrev members.
489 * Only accessible from the emulation thread. */
490 PTMTIMERR3 pCreated;
491
492 /** The schedule timer timer handle (runtime timer).
493 * This timer will do frequent check on pending queue schedules and
494 * raise VM_FF_TIMER to pull EMTs attention to them.
495 */
496 R3PTRTYPE(PRTTIMER) pTimer;
497 /** Interval in milliseconds of the pTimer timer. */
498 uint32_t u32TimerMillies;
499
500 /** Indicates that queues are being run. */
501 bool volatile fRunningQueues;
502 /** Indicates that the virtual sync queue is being run. */
503 bool volatile fRunningVirtualSyncQueue;
504 /** Alignment */
505 bool afAlignment3[2];
506
507 /** Lock serializing access to the timer lists. */
508 PDMCRITSECT TimerCritSect;
509 /** Lock serializing access to the VirtualSync clock and the associated
510 * timer queue. */
511 PDMCRITSECT VirtualSyncLock;
512
513 /** CPU load state for all the virtual CPUs (tmR3CpuLoadTimer). */
514 TMCPULOADSTATE CpuLoad;
515
516 /** TMR3TimerQueuesDo
517 * @{ */
518 STAMPROFILE StatDoQueues;
519 STAMPROFILEADV aStatDoQueues[TMCLOCK_MAX];
520 /** @} */
521 /** tmSchedule
522 * @{ */
523 STAMPROFILE StatScheduleOneRZ;
524 STAMPROFILE StatScheduleOneR3;
525 STAMCOUNTER StatScheduleSetFF;
526 STAMCOUNTER StatPostponedR3;
527 STAMCOUNTER StatPostponedRZ;
528 /** @} */
529 /** Read the time
530 * @{ */
531 STAMCOUNTER StatVirtualGet;
532 STAMCOUNTER StatVirtualGetSetFF;
533 STAMCOUNTER StatVirtualSyncGet;
534 STAMCOUNTER StatVirtualSyncGetAdjLast;
535 STAMCOUNTER StatVirtualSyncGetELoop;
536 STAMCOUNTER StatVirtualSyncGetExpired;
537 STAMCOUNTER StatVirtualSyncGetLockless;
538 STAMCOUNTER StatVirtualSyncGetLocked;
539 STAMCOUNTER StatVirtualSyncGetSetFF;
540 STAMCOUNTER StatVirtualPause;
541 STAMCOUNTER StatVirtualResume;
542 /** @} */
543 /** TMTimerPoll
544 * @{ */
545 STAMCOUNTER StatPoll;
546 STAMCOUNTER StatPollAlreadySet;
547 STAMCOUNTER StatPollELoop;
548 STAMCOUNTER StatPollMiss;
549 STAMCOUNTER StatPollRunning;
550 STAMCOUNTER StatPollSimple;
551 STAMCOUNTER StatPollVirtual;
552 STAMCOUNTER StatPollVirtualSync;
553 /** @} */
554 /** TMTimerSet sans virtual sync timers.
555 * @{ */
556 STAMCOUNTER StatTimerSet;
557 STAMCOUNTER StatTimerSetOpt;
558 STAMPROFILE StatTimerSetRZ;
559 STAMPROFILE StatTimerSetR3;
560 STAMCOUNTER StatTimerSetStStopped;
561 STAMCOUNTER StatTimerSetStExpDeliver;
562 STAMCOUNTER StatTimerSetStActive;
563 STAMCOUNTER StatTimerSetStPendStop;
564 STAMCOUNTER StatTimerSetStPendStopSched;
565 STAMCOUNTER StatTimerSetStPendSched;
566 STAMCOUNTER StatTimerSetStPendResched;
567 STAMCOUNTER StatTimerSetStOther;
568 /** @} */
569 /** TMTimerSet on virtual sync timers.
570 * @{ */
571 STAMCOUNTER StatTimerSetVs;
572 STAMPROFILE StatTimerSetVsRZ;
573 STAMPROFILE StatTimerSetVsR3;
574 STAMCOUNTER StatTimerSetVsStStopped;
575 STAMCOUNTER StatTimerSetVsStExpDeliver;
576 STAMCOUNTER StatTimerSetVsStActive;
577 /** @} */
578 /** TMTimerSetRelative sans virtual sync timers
579 * @{ */
580 STAMCOUNTER StatTimerSetRelative;
581 STAMPROFILE StatTimerSetRelativeRZ;
582 STAMPROFILE StatTimerSetRelativeR3;
583 STAMCOUNTER StatTimerSetRelativeOpt;
584 STAMCOUNTER StatTimerSetRelativeStStopped;
585 STAMCOUNTER StatTimerSetRelativeStExpDeliver;
586 STAMCOUNTER StatTimerSetRelativeStActive;
587 STAMCOUNTER StatTimerSetRelativeStPendStop;
588 STAMCOUNTER StatTimerSetRelativeStPendStopSched;
589 STAMCOUNTER StatTimerSetRelativeStPendSched;
590 STAMCOUNTER StatTimerSetRelativeStPendResched;
591 STAMCOUNTER StatTimerSetRelativeStOther;
592 /** @} */
593 /** TMTimerSetRelative on virtual sync timers.
594 * @{ */
595 STAMCOUNTER StatTimerSetRelativeVs;
596 STAMPROFILE StatTimerSetRelativeVsRZ;
597 STAMPROFILE StatTimerSetRelativeVsR3;
598 STAMCOUNTER StatTimerSetRelativeVsStStopped;
599 STAMCOUNTER StatTimerSetRelativeVsStExpDeliver;
600 STAMCOUNTER StatTimerSetRelativeVsStActive;
601 /** @} */
602 /** TMTimerStop sans virtual sync.
603 * @{ */
604 STAMPROFILE StatTimerStopRZ;
605 STAMPROFILE StatTimerStopR3;
606 /** @} */
607 /** TMTimerStop on virtual sync timers.
608 * @{ */
609 STAMPROFILE StatTimerStopVsRZ;
610 STAMPROFILE StatTimerStopVsR3;
611 /** @} */
612 /** VirtualSync - Running and Catching Up
613 * @{ */
614 STAMCOUNTER StatVirtualSyncRun;
615 STAMCOUNTER StatVirtualSyncRunRestart;
616 STAMPROFILE StatVirtualSyncRunSlack;
617 STAMCOUNTER StatVirtualSyncRunStop;
618 STAMCOUNTER StatVirtualSyncRunStoppedAlready;
619 STAMCOUNTER StatVirtualSyncGiveUp;
620 STAMCOUNTER StatVirtualSyncGiveUpBeforeStarting;
621 STAMPROFILEADV StatVirtualSyncCatchup;
622 STAMCOUNTER aStatVirtualSyncCatchupInitial[TM_MAX_CATCHUP_PERIODS];
623 STAMCOUNTER aStatVirtualSyncCatchupAdjust[TM_MAX_CATCHUP_PERIODS];
624 /** @} */
625 /** TMR3VirtualSyncFF (non dedicated EMT). */
626 STAMPROFILE StatVirtualSyncFF;
627 /** The timer callback. */
628 STAMCOUNTER StatTimerCallbackSetFF;
629
630 /** Calls to TMCpuTickSet. */
631 STAMCOUNTER StatTSCSet;
632
633 /** @name Reasons for refusing TSC offsetting in TMCpuTickCanUseRealTSC.
634 * @{ */
635 STAMCOUNTER StatTSCNotFixed;
636 STAMCOUNTER StatTSCNotTicking;
637 STAMCOUNTER StatTSCCatchupLE010;
638 STAMCOUNTER StatTSCCatchupLE025;
639 STAMCOUNTER StatTSCCatchupLE100;
640 STAMCOUNTER StatTSCCatchupOther;
641 STAMCOUNTER StatTSCWarp;
642 STAMCOUNTER StatTSCUnderflow;
643 STAMCOUNTER StatTSCSyncNotTicking;
644 /** @} */
645} TM;
646/** Pointer to TM VM instance data. */
647typedef TM *PTM;
648
649/**
650 * TM VMCPU Instance data.
651 * Changes to this must checked against the padding of the tm union in VM!
652 */
653typedef struct TMCPU
654{
655 /** Offset to the VMCPU structure.
656 * See TMCPU2VM(). */
657 RTUINT offVMCPU;
658
659 /** CPU timestamp ticking enabled indicator (bool). (RDTSC) */
660 bool fTSCTicking;
661 bool afAlignment0[3]; /**< alignment padding */
662
663 /** The offset between the raw TSC source and the Guest TSC.
664 * Only valid if fTicking is set and and fTSCUseRealTSC is clear. */
665 uint64_t offTSCRawSrc;
666
667 /** The guest TSC when fTicking is cleared. */
668 uint64_t u64TSC;
669
670 /** The last seen TSC by the guest. */
671 uint64_t u64TSCLastSeen;
672
673#ifndef VBOX_WITHOUT_NS_ACCOUNTING
674 /** The nanosecond timestamp of the CPU start or resume.
675 * This is recalculated when the VM is started so that
676 * cNsTotal = RTTimeNanoTS() - u64NsTsStartCpu. */
677 uint64_t u64NsTsStartTotal;
678 /** The nanosecond timestamp of the last start-execute notification. */
679 uint64_t u64NsTsStartExecuting;
680 /** The nanosecond timestamp of the last start-halt notification. */
681 uint64_t u64NsTsStartHalting;
682 /** The cNsXXX generation. */
683 uint32_t volatile uTimesGen;
684 /** Explicit alignment padding. */
685 uint32_t u32Alignment;
686 /** The number of nanoseconds total run time.
687 * @remarks This is updated when cNsExecuting and cNsHalted are updated. */
688 uint64_t cNsTotal;
689 /** The number of nanoseconds spent executing. */
690 uint64_t cNsExecuting;
691 /** The number of nanoseconds being halted. */
692 uint64_t cNsHalted;
693 /** The number of nanoseconds spent on other things.
694 * @remarks This is updated when cNsExecuting and cNsHalted are updated. */
695 uint64_t cNsOther;
696 /** The number of halts. */
697 uint64_t cPeriodsHalted;
698 /** The number of guest execution runs. */
699 uint64_t cPeriodsExecuting;
700# if defined(VBOX_WITH_STATISTICS) || defined(VBOX_WITH_NS_ACCOUNTING_STATS)
701 /** Resettable version of cNsTotal. */
702 STAMCOUNTER StatNsTotal;
703 /** Resettable version of cNsExecuting. */
704 STAMPROFILE StatNsExecuting;
705 /** Long execution intervals. */
706 STAMPROFILE StatNsExecLong;
707 /** Short execution intervals . */
708 STAMPROFILE StatNsExecShort;
709 /** Tiny execution intervals . */
710 STAMPROFILE StatNsExecTiny;
711 /** Resettable version of cNsHalted. */
712 STAMPROFILE StatNsHalted;
713 /** Resettable version of cNsOther. */
714 STAMPROFILE StatNsOther;
715# endif
716
717 /** CPU load state for this virtual CPU (tmR3CpuLoadTimer). */
718 TMCPULOADSTATE CpuLoad;
719#endif
720} TMCPU;
721/** Pointer to TM VMCPU instance data. */
722typedef TMCPU *PTMCPU;
723
724#if 0 /* enable this to rule out locking bugs on single cpu guests. */
725# define tmTimerLock(pVM) VINF_SUCCESS
726# define tmTimerTryLock(pVM) VINF_SUCCESS
727# define tmTimerUnlock(pVM) ((void)0)
728# define tmVirtualSyncLock(pVM) VINF_SUCCESS
729# define tmVirtualSyncTryLock(pVM) VINF_SUCCESS
730# define tmVirtualSyncUnlock(pVM) ((void)0)
731# define TM_ASSERT_LOCK(pVM) VM_ASSERT_EMT(pVM)
732#else
733int tmTimerLock(PVM pVM);
734int tmTimerTryLock(PVM pVM);
735void tmTimerUnlock(PVM pVM);
736/** Checks that the caller owns the timer lock. */
737#define TM_ASSERT_LOCK(pVM) Assert(PDMCritSectIsOwner(&pVM->tm.s.TimerCritSect))
738int tmVirtualSyncLock(PVM pVM);
739int tmVirtualSyncTryLock(PVM pVM);
740void tmVirtualSyncUnlock(PVM pVM);
741#endif
742
743const char *tmTimerState(TMTIMERSTATE enmState);
744void tmTimerQueueSchedule(PVM pVM, PTMTIMERQUEUE pQueue);
745#ifdef VBOX_STRICT
746void tmTimerQueuesSanityChecks(PVM pVM, const char *pszWhere);
747#endif
748
749int tmCpuTickPause(PVM pVM, PVMCPU pVCpu);
750int tmCpuTickResume(PVM pVM, PVMCPU pVCpu);
751
752int tmVirtualPauseLocked(PVM pVM);
753int tmVirtualResumeLocked(PVM pVM);
754DECLEXPORT(void) tmVirtualNanoTSBad(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS);
755DECLEXPORT(uint64_t) tmVirtualNanoTSRediscover(PRTTIMENANOTSDATA pData);
756
757
758/** @} */
759
760RT_C_DECLS_END
761
762#endif
763
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette