~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/VMM/include/TMInternal.h

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

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