Changeset 87792 in vbox for trunk/src/VBox/VMM/include
- Timestamp:
- Feb 18, 2021 6:38:24 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142852
- Location:
- trunk/src/VBox/VMM/include
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/include/TMInline.h
r87774 r87792 23 23 24 24 25 DECLINLINE(PTMTIMER) tmTimerQueueGetHead(PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueueShared) 26 { 27 #ifdef IN_RING3 28 RT_NOREF(pQueueShared); 29 uint32_t const idx = pQueueCC->idxActive; 30 #else 31 uint32_t const idx = pQueueShared->idxActive; 32 #endif 33 if (idx < pQueueCC->cTimersAlloc) 34 return &pQueueCC->paTimers[idx]; 35 return NULL; 36 } 37 38 39 DECLINLINE(void) tmTimerQueueSetHead(PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueueShared, PTMTIMER pHead) 40 { 41 uint32_t idx; 42 if (pHead) 43 { 44 idx = (uint32_t)(pHead - &pQueueCC->paTimers[0]); 45 AssertMsgStmt(idx < pQueueCC->cTimersAlloc, 46 ("idx=%u (%s) cTimersAlloc=%u\n", idx, pHead->szName, pQueueCC->cTimersAlloc), 47 idx = UINT32_MAX); 48 } 49 else 50 idx = UINT32_MAX; 51 #ifndef IN_RING3 52 pQueueShared->idxActive = idx; 53 #else 54 pQueueCC->idxActive = idx; 55 RT_NOREF(pQueueShared); 56 #endif 57 } 58 59 60 /** 61 * Get the previous timer - translates TMTIMER::idxPrev. 62 */ 63 DECLINLINE(PTMTIMER) tmTimerGetPrev(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer) 64 { 65 uint32_t const idxPrev = pTimer->idxPrev; 66 Assert(idxPrev); 67 if (idxPrev < pQueueCC->cTimersAlloc) 68 return &pQueueCC->paTimers[idxPrev]; 69 Assert(idxPrev == UINT32_MAX); 70 return NULL; 71 } 72 73 74 /** 75 * Get the next timer - translates TMTIMER::idxNext. 76 */ 77 DECLINLINE(PTMTIMER) tmTimerGetNext(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer) 78 { 79 uint32_t const idxNext = pTimer->idxNext; 80 Assert(idxNext); 81 if (idxNext < pQueueCC->cTimersAlloc) 82 return &pQueueCC->paTimers[idxNext]; 83 Assert(idxNext == UINT32_MAX); 84 return NULL; 85 } 86 87 88 /** 89 * Set the previous timer link (TMTIMER::idxPrev). 90 */ 91 DECLINLINE(void) tmTimerSetPrev(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer, PTMTIMER pPrev) 92 { 93 uint32_t idxPrev; 94 if (pPrev) 95 { 96 idxPrev = (uint32_t)(pPrev - &pQueueCC->paTimers[0]); 97 Assert(idxPrev); 98 AssertMsgStmt(idxPrev < pQueueCC->cTimersAlloc, 99 ("idxPrev=%u (%s) cTimersAlloc=%u\n", idxPrev, pPrev->szName, pQueueCC->cTimersAlloc), 100 idxPrev = UINT32_MAX); 101 } 102 else 103 idxPrev = UINT32_MAX; 104 pTimer->idxPrev = idxPrev; 105 } 106 107 108 /** 109 * Set the next timer link (TMTIMER::idxNext). 110 */ 111 DECLINLINE(void) tmTimerSetNext(PTMTIMERQUEUECC pQueueCC, PTMTIMER pTimer, PTMTIMER pNext) 112 { 113 uint32_t idxNext; 114 if (pNext) 115 { 116 idxNext = (uint32_t)(pNext - &pQueueCC->paTimers[0]); 117 Assert(idxNext); 118 AssertMsgStmt(idxNext < pQueueCC->cTimersAlloc, 119 ("idxNext=%u (%s) cTimersAlloc=%u\n", idxNext, pNext->szName, pQueueCC->cTimersAlloc), 120 idxNext = UINT32_MAX); 121 } 122 else 123 idxNext = UINT32_MAX; 124 pTimer->idxNext = idxNext; 125 } 126 127 25 128 /** 26 129 * Used to unlink a timer from the active list. 27 130 * 28 131 * @param pVM The cross context VM structure. 29 * @param pQueue The timer queue. 132 * @param pQueueCC The context specific queue data (same as @a pQueue for 133 * ring-3). 134 * @param pQueue The shared timer queue data. 30 135 * @param pTimer The timer that needs linking. 31 136 * 32 137 * @remarks Called while owning the relevant queue lock. 33 138 */ 34 DECL_FORCE_INLINE(void) tmTimerQueueUnlinkActive(PVMCC pVM, PTMTIMERQUEUE pQueue, PTMTIMER pTimer)139 DECL_FORCE_INLINE(void) tmTimerQueueUnlinkActive(PVMCC pVM, PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueue, PTMTIMER pTimer) 35 140 { 36 141 #ifdef VBOX_STRICT … … 42 147 RT_NOREF(pVM); 43 148 44 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer);45 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer);149 const PTMTIMER pPrev = tmTimerGetPrev(pQueueCC, pTimer); 150 const PTMTIMER pNext = tmTimerGetNext(pQueueCC, pTimer); 46 151 if (pPrev) 47 TMTIMER_SET_NEXT(pPrev, pNext);48 else 49 { 50 TMTIMER_SET_HEAD(pQueue, pNext);152 tmTimerSetNext(pQueueCC, pPrev, pNext); 153 else 154 { 155 tmTimerQueueSetHead(pQueueCC, pQueue, pNext); 51 156 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 52 157 DBGFTRACE_U64_TAG(pVM, pQueue->u64Expire, "tmTimerQueueUnlinkActive"); 53 158 } 54 159 if (pNext) 55 TMTIMER_SET_PREV(pNext, pPrev);56 pTimer-> offNext = 0;57 pTimer-> offPrev = 0;160 tmTimerSetPrev(pQueueCC, pNext, pPrev); 161 pTimer->idxNext = UINT32_MAX; 162 pTimer->idxPrev = UINT32_MAX; 58 163 } 59 164 … … 70 175 #ifdef IN_RING3 71 176 # define TMTIMER_HANDLE_TO_PTR_RETURN_EX(a_pVM, a_hTimer, a_rcRet, a_pTimerVar) do { \ 72 RT_NOREF(a_pVM); \ 73 (a_pTimerVar) = (PTMTIMER)hTimer; \ 74 AssertPtrReturn((a_pTimerVar), a_rcRet); \ 177 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 178 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 179 AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \ 180 \ 181 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 182 AssertReturn(idxQueue < (a_pVM)->tm.s.aTimerQueues[idxQueue].cTimersAlloc, a_rcRet); \ 183 \ 184 (a_pTimerVar) = &(a_pVM)->tm.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 75 185 AssertReturn((a_pTimerVar)->hSelf == a_hTimer, a_rcRet); \ 76 186 } while (0) 77 187 #else 78 188 # define TMTIMER_HANDLE_TO_PTR_RETURN_EX(a_pVM, a_hTimer, a_rcRet, a_pTimerVar) do { \ 79 (a_pTimerVar) = (PTMTIMER)MMHyperR3ToCC(pVM, (RTR3PTR)hTimer); \ 80 AssertPtrReturn((a_pTimerVar), a_rcRet); \ 189 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 190 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 191 AssertReturn(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues), a_rcRet); \ 192 AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \ 193 \ 194 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 195 AssertReturn(idxQueue < (a_pVM)->tmr0.s.aTimerQueues[idxQueue].cTimersAlloc, a_rcRet); \ 196 \ 197 (a_pTimerVar) = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 81 198 AssertReturn((a_pTimerVar)->hSelf == a_hTimer, a_rcRet); \ 82 199 Assert((a_pTimerVar)->fFlags & TMTIMER_FLAGS_RING0); \ 200 Assert(VM_IS_EMT(pVM)); \ 83 201 } while (0) 84 202 #endif … … 105 223 #ifdef IN_RING3 106 224 # define TMTIMER_HANDLE_TO_PTR_RETURN_VOID(a_pVM, a_hTimer, a_pTimerVar) do { \ 107 RT_NOREF(a_pVM); \ 108 (a_pTimerVar) = (PTMTIMER)hTimer; \ 109 AssertPtrReturnVoid((a_pTimerVar)); \ 225 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 226 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 227 AssertReturnVoid(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues)); \ 228 \ 229 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 230 AssertReturnVoid(idxQueue < (a_pVM)->tm.s.aTimerQueues[idxQueue].cTimersAlloc); \ 231 \ 232 (a_pTimerVar) = &(a_pVM)->tm.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 110 233 AssertReturnVoid((a_pTimerVar)->hSelf == a_hTimer); \ 111 234 } while (0) 112 235 #else 113 236 # define TMTIMER_HANDLE_TO_PTR_RETURN_VOID(a_pVM, a_hTimer, a_pTimerVar) do { \ 114 (a_pTimerVar) = (PTMTIMER)MMHyperR3ToCC(pVM, (RTR3PTR)hTimer); \ 115 AssertPtrReturnVoid((a_pTimerVar)); \ 237 uintptr_t const idxQueue = (uintptr_t)((a_hTimer) >> TMTIMERHANDLE_QUEUE_IDX_SHIFT) \ 238 & (uintptr_t)TMTIMERHANDLE_QUEUE_IDX_SMASK; \ 239 AssertReturnVoid(idxQueue < RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues)); \ 240 AssertCompile(RT_ELEMENTS((a_pVM)->tm.s.aTimerQueues) == RT_ELEMENTS((a_pVM)->tmr0.s.aTimerQueues)); \ 241 \ 242 uintptr_t const idxTimer = (uintptr_t)((a_hTimer) & TMTIMERHANDLE_TIMER_IDX_MASK); \ 243 AssertReturnVoid(idxQueue < (a_pVM)->tmr0.s.aTimerQueues[idxQueue].cTimersAlloc); \ 244 \ 245 (a_pTimerVar) = &(a_pVM)->tmr0.s.aTimerQueues[idxQueue].paTimers[idxTimer]; \ 116 246 AssertReturnVoid((a_pTimerVar)->hSelf == a_hTimer); \ 117 247 Assert((a_pTimerVar)->fFlags & TMTIMER_FLAGS_RING0); \ 248 Assert(VM_IS_EMT(pVM)); \ 118 249 } while (0) 119 250 #endif -
trunk/src/VBox/VMM/include/TMInternal.h
r87773 r87792 29 29 #include <VBox/vmm/stam.h> 30 30 #include <VBox/vmm/pdmcritsect.h> 31 #include <VBox/vmm/pdmcritsectrw.h> 31 32 32 33 RT_C_DECLS_BEGIN … … 50 51 typedef enum TMTIMERTYPE 51 52 { 53 /** Invalid zero value. */ 54 TMTIMERTYPE_INVALID = 0, 52 55 /** Device timer. */ 53 TMTIMERTYPE_DEV = 1,56 TMTIMERTYPE_DEV, 54 57 /** USB device timer. */ 55 58 TMTIMERTYPE_USB, … … 65 68 typedef enum TMTIMERSTATE 66 69 { 70 /** Invalid zero entry (used for table entry zero). */ 71 TMTIMERSTATE_INVALID = 0, 67 72 /** Timer is stopped. */ 68 TMTIMERSTATE_STOPPED = 1,73 TMTIMERSTATE_STOPPED, 69 74 /** Timer is active. */ 70 75 TMTIMERSTATE_ACTIVE, … … 104 109 && (enmState) >= TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE) 105 110 111 /** @name Timer handle value elements 112 * @{ */ 113 #define TMTIMERHANDLE_RANDOM_MASK UINT64_C(0xffffffffff000000) 114 #define TMTIMERHANDLE_QUEUE_IDX_SHIFT 16 115 #define TMTIMERHANDLE_QUEUE_IDX_MASK UINT64_C(0x0000000000ff0000) 116 #define TMTIMERHANDLE_QUEUE_IDX_SMASK UINT64_C(0x00000000000000ff) 117 #define TMTIMERHANDLE_TIMER_IDX_MASK UINT64_C(0x000000000000ffff) 118 /** @} */ 119 106 120 107 121 /** … … 166 180 /** Timer state. */ 167 181 volatile TMTIMERSTATE enmState; 168 /** T imer relative offset to thenext timer in the schedule list. */169 int32_t volatile offScheduleNext;170 171 /** T imer relative offset tothe next timer in the chain. */172 int32_t offNext;173 /** T imer relative offset tothe previous timer in the chain. */174 int32_t offPrev;182 /** The index of the next next timer in the schedule list. */ 183 int32_t volatile idxScheduleNext; 184 185 /** The index of the next timer in the chain. */ 186 uint32_t idxNext; 187 /** The index of the previous timer in the chain. */ 188 uint32_t idxPrev; 175 189 176 190 /** It's own handle value. */ … … 186 200 R3PTRTYPE(PPDMCRITSECT) pCritSect; 187 201 188 /** Pointer to the next timer in the list of created or free timers. (TM::pTimers or TM::pFree) */189 PTMTIMERR3 pBigNext;190 /** Pointer to the previous timer in the list of all created timers. (TM::pTimers) */191 PTMTIMERR3 pBigPrev;192 202 /** The timer name. */ 193 203 char szName[32]; … … 234 244 #endif 235 245 236 /** Get the previous timer. */ 237 #define TMTIMER_GET_PREV(pTimer) ((PTMTIMER)((pTimer)->offPrev ? (intptr_t)(pTimer) + (pTimer)->offPrev : 0)) 238 /** Get the next timer. */ 239 #define TMTIMER_GET_NEXT(pTimer) ((PTMTIMER)((pTimer)->offNext ? (intptr_t)(pTimer) + (pTimer)->offNext : 0)) 240 /** Set the previous timer link. */ 241 #define TMTIMER_SET_PREV(pTimer, pPrev) ((pTimer)->offPrev = (pPrev) ? (intptr_t)(pPrev) - (intptr_t)(pTimer) : 0) 242 /** Set the next timer link. */ 243 #define TMTIMER_SET_NEXT(pTimer, pNext) ((pTimer)->offNext = (pNext) ? (intptr_t)(pNext) - (intptr_t)(pTimer) : 0) 244 245 246 /** 247 * A timer queue. 248 * 249 * This is allocated on the hyper heap. 246 247 /** 248 * A timer queue, shared. 250 249 */ 251 250 typedef struct TMTIMERQUEUE 252 251 { 252 /** The ring-0 mapping of the timer table. */ 253 R3PTRTYPE(PTMTIMER) paTimers; 254 253 255 /** The cached expire time for this queue. 254 256 * Updated by EMT when scheduling the queue or modifying the head timer. … … 259 261 * When no scheduling is pending, this list is will be ordered by expire time (ascending). 260 262 * Access is serialized by only letting the emulation thread (EMT) do changes. 261 *262 * The offset is relative to the queue structure.263 263 */ 264 int32_t offActive;264 uint32_t idxActive; 265 265 /** List of timers pending scheduling of some kind. 266 266 * … … 268 268 * TMTIMERSTATE_PENDING_DESTRUCTION, TMTIMERSTATE_PENDING_STOPPING_DESTRUCTION, 269 269 * TMTIMERSTATE_PENDING_RESCHEDULING and TMTIMERSTATE_PENDING_SCHEDULE. 270 *271 * The offset is relative to the queue structure.272 270 */ 273 int32_t volatile offSchedule;271 uint32_t volatile idxSchedule; 274 272 /** The clock for this queue. */ 275 273 TMCLOCK enmClock; 276 /** Pad the structure up to 32 bytes. */ 277 uint32_t au32Padding[3]; 274 275 /** The size of the paTimers allocation (in entries). */ 276 uint32_t cTimersAlloc; 277 /** Number of free timer entries. */ 278 uint32_t cTimersFree; 279 /** Where to start looking for free timers. */ 280 uint32_t idxFreeHint; 281 /** The queue name. */ 282 char szName[16]; 283 /** Set if we've disabled growing. */ 284 bool fCannotGrow; 285 /** Align on 64-byte boundrary. */ 286 bool afAlignment[7]; 287 /** Lock serializing timer allocation and deallocation. */ 288 PDMCRITSECTRW AllocLock; 278 289 } TMTIMERQUEUE; 279 290 AssertCompileSizeAlignment(TMTIMERQUEUE, 64); 280 291 /** Pointer to a timer queue. */ 281 292 typedef TMTIMERQUEUE *PTMTIMERQUEUE; 282 293 283 /** Get the head of the active timer list. */ 284 #define TMTIMER_GET_HEAD(pQueue) ((PTMTIMER)((pQueue)->offActive ? (intptr_t)(pQueue) + (pQueue)->offActive : 0)) 285 /** Set the head of the active timer list. */ 286 #define TMTIMER_SET_HEAD(pQueue, pHead) ((pQueue)->offActive = pHead ? (intptr_t)pHead - (intptr_t)(pQueue) : 0) 294 /** 295 * A timer queue, ring-0 only bits. 296 */ 297 typedef struct TMTIMERQUEUER0 298 { 299 /** The size of the paTimers allocation (in entries). */ 300 uint32_t cTimersAlloc; 301 uint32_t uAlignment; 302 /** The ring-0 mapping of the timer table. */ 303 R0PTRTYPE(PTMTIMER) paTimers; 304 /** Handle to the timer table allocation. */ 305 RTR0MEMOBJ hMemObj; 306 /** Handle to the ring-3 mapping of the timer table. */ 307 RTR0MEMOBJ hMapObj; 308 } TMTIMERQUEUER0; 309 /** Pointer to the ring-0 timer queue data. */ 310 typedef TMTIMERQUEUER0 *PTMTIMERQUEUER0; 311 312 /** Pointer to the current context data for a timer queue. 313 * @note In ring-3 this is the same as the shared data. */ 314 #ifdef IN_RING3 315 typedef TMTIMERQUEUE *PTMTIMERQUEUECC; 316 #else 317 typedef TMTIMERQUEUER0 *PTMTIMERQUEUECC; 318 #endif 319 /** Helper macro for getting the current context queue point. */ 320 #ifdef IN_RING3 321 # define TM_GET_TIMER_QUEUE_CC(a_pVM, a_idxQueue, a_pQueueShared) (a_pQueueShared) 322 #else 323 # define TM_GET_TIMER_QUEUE_CC(a_pVM, a_idxQueue, a_pQueueShared) (&(a_pVM)->tmr0.s.aTimerQueues[a_idxQueue]) 324 #endif 287 325 288 326 … … 348 386 349 387 /** 350 * Converts a TM pointer into a VM pointer.351 * @returns Pointer to the VM structure the TM is part of.352 * @param pTM Pointer to TM instance data.353 */354 #define TM2VM(pTM) ( (PVM)((char*)pTM - pTM->offVM) )355 356 357 /**358 388 * TM VM Instance data. 359 389 * Changes to this must checked against the padding of the cfgm union in VM! … … 361 391 typedef struct TM 362 392 { 363 /** Offset to the VM structure.364 * See TM2VM(). */365 RTUINT offVM;366 367 393 /** The current TSC mode of the VM. 368 394 * Config variable: Mode (string). */ … … 370 396 /** The original TSC mode of the VM. */ 371 397 TMTSCMODE enmOriginalTSCMode; 372 /** Alignment padding. */373 uint32_t u32Alignment0;374 398 /** Whether the TSC is tied to the execution of code. 375 399 * Config variable: TSCTiedToExecution (bool) */ … … 513 537 R3PTRTYPE(char *) pszAlignment2b; 514 538 515 /** Timer queues for the different clock types - R3 Ptr */ 516 R3PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR3; 517 /** Timer queues for the different clock types - R0 Ptr */ 518 R0PTRTYPE(PTMTIMERQUEUE) paTimerQueuesR0; 519 /** Timer queues for the different clock types - RC Ptr */ 520 RCPTRTYPE(PTMTIMERQUEUE) paTimerQueuesRC; 539 /** Timer queues for the different clock types. */ 540 TMTIMERQUEUE aTimerQueues[TMCLOCK_MAX]; 521 541 522 542 /** Pointer to our RC mapping of the GIP. */ … … 524 544 /** Pointer to our R3 mapping of the GIP. */ 525 545 R3PTRTYPE(void *) pvGIPR3; 526 527 /** Pointer to a singly linked list of free timers.528 * This chain is using the TMTIMER::pBigNext members.529 * Only accessible from the emulation thread. */530 PTMTIMERR3 pFree;531 532 /** Pointer to a doubly linked list of created timers.533 * This chain is using the TMTIMER::pBigNext and TMTIMER::pBigPrev members.534 * Only accessible from the emulation thread. */535 PTMTIMERR3 pCreated;536 546 537 547 /** The schedule timer timer handle (runtime timer). … … 696 706 /** Pointer to TM VM instance data. */ 697 707 typedef TM *PTM; 708 698 709 699 710 /** … … 796 807 typedef TMCPU *PTMCPU; 797 808 809 810 /** 811 * TM data kept in the ring-0 GVM. 812 */ 813 typedef struct TMR0PERVM 814 { 815 /** Timer queues for the different clock types. */ 816 TMTIMERQUEUER0 aTimerQueues[TMCLOCK_MAX]; 817 } TMR0PERVM; 818 819 798 820 const char *tmTimerState(TMTIMERSTATE enmState); 799 void tmTimerQueueSchedule(PVMCC pVM, PTMTIMERQUEUE pQueue);821 void tmTimerQueueSchedule(PVMCC pVM, PTMTIMERQUEUECC pQueueCC, PTMTIMERQUEUE pQueue); 800 822 #ifdef VBOX_STRICT 801 void tmTimerQueuesSanityChecks(PVM pVM, const char *pszWhere);823 void tmTimerQueuesSanityChecks(PVMCC pVM, const char *pszWhere); 802 824 #endif 803 825
Note:
See TracChangeset
for help on using the changeset viewer.