Changeset 36971 in vbox
- Timestamp:
- May 5, 2011 12:11:42 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevHPET.cpp
r36870 r36971 95 95 #define HPET_CFG_WRITE_MASK 0x3 96 96 97 #define HPET_TN_INT_TYPE (1 <<1)98 #define HPET_TN_ENABLE (1 <<2)99 #define HPET_TN_PERIODIC (1 <<3)100 #define HPET_TN_PERIODIC_CAP (1 <<4)101 #define HPET_TN_SIZE_CAP (1 <<5)102 #define HPET_TN_SETVAL (1 <<6)103 #define HPET_TN_32BIT (1 <<8)104 #define HPET_TN_INT_ROUTE_MASK 0x3e00105 #define HPET_TN_CFG_WRITE_MASK 0x3f4e97 #define HPET_TN_INT_TYPE RT_BIT_64(1) 98 #define HPET_TN_ENABLE RT_BIT_64(2) 99 #define HPET_TN_PERIODIC RT_BIT_64(3) 100 #define HPET_TN_PERIODIC_CAP RT_BIT_64(4) 101 #define HPET_TN_SIZE_CAP RT_BIT_64(5) 102 #define HPET_TN_SETVAL RT_BIT_64(6) 103 #define HPET_TN_32BIT RT_BIT_64(8) 104 #define HPET_TN_INT_ROUTE_MASK UINT64_C(0x3e00) 105 #define HPET_TN_CFG_WRITE_MASK UINT64_C(0x3e46) 106 106 #define HPET_TN_INT_ROUTE_SHIFT 9 107 107 #define HPET_TN_INT_ROUTE_CAP_SHIFT 32 … … 191 191 PDMCRITSECT csLock; 192 192 193 /* If we emulate ICH9 HPET (different frequency and counter rollover behavior 194 in 32-bit mode). */ 193 /* If we emulate ICH9 HPET (different frequency). */ 195 194 uint8_t fIch9; 196 195 uint8_t padding0[7]; … … 233 232 } 234 233 235 static uint32_t hpetTimeAfter32(uint64_t a, uint64_t b) 234 DECLINLINE(bool) hpet32bitTimer(HpetTimer *pTimer) 235 { 236 uint64_t u64Cfg = pTimer->u64Config; 237 238 return ((u64Cfg & HPET_TN_SIZE_CAP) == 0) || ((u64Cfg & HPET_TN_32BIT) != 0); 239 } 240 241 DECLINLINE(uint64_t) hpetInvalidValue(HpetTimer *pTimer) 242 { 243 return hpet32bitTimer(pTimer) ? ~0U : ~0ULL; 244 } 245 246 DECLINLINE(uint32_t) hpetTimeAfter32(uint64_t a, uint64_t b) 236 247 { 237 248 return ((int32_t)(b) - (int32_t)(a) <= 0); 238 249 } 239 250 240 static uint32_thpetTimeAfter64(uint64_t a, uint64_t b)251 DECLINLINE(uint32_t) hpetTimeAfter64(uint64_t a, uint64_t b) 241 252 { 242 253 return ((int64_t)(b) - (int64_t)(a) <= 0); 243 254 } 244 255 245 static uint64_thpetTicksToNs(HpetState* pThis, uint64_t value)256 DECLINLINE(uint64_t) hpetTicksToNs(HpetState* pThis, uint64_t value) 246 257 { 247 258 return (ASMMultU64ByU32DivByU32(value, (uint32_t)(pThis->u64Capabilities >> 32), FS_PER_NS)); 248 259 } 249 260 250 static uint64_tnsToHpetTicks(HpetState* pThis, uint64_t u64Value)261 DECLINLINE(uint64_t) nsToHpetTicks(HpetState* pThis, uint64_t u64Value) 251 262 { 252 263 return (ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, (uint32_t)(pThis->u64Capabilities >> 32))); 253 264 } 254 265 255 static uint64_thpetGetTicks(HpetState* pThis)266 DECLINLINE(uint64_t) hpetGetTicks(HpetState* pThis) 256 267 { 257 268 /* … … 263 274 } 264 275 265 static uint64_thpetUpdateMasked(uint64_t u64NewValue,266 uint64_t u64OldValue,267 uint64_t u64Mask)276 DECLINLINE(uint64_t) hpetUpdateMasked(uint64_t u64NewValue, 277 uint64_t u64OldValue, 278 uint64_t u64Mask) 268 279 { 269 280 u64NewValue &= u64Mask; … … 272 283 } 273 284 274 static boolhpetBitJustSet(uint64_t u64OldValue,275 uint64_t u64NewValue,276 uint64_t u64Mask)285 DECLINLINE(bool) hpetBitJustSet(uint64_t u64OldValue, 286 uint64_t u64NewValue, 287 uint64_t u64Mask) 277 288 { 278 289 return (!(u64OldValue & u64Mask) && !!(u64NewValue & u64Mask)); 279 290 } 280 291 281 static boolhpetBitJustCleared(uint64_t u64OldValue,282 uint64_t u64NewValue,283 uint64_t u64Mask)292 DECLINLINE(bool) hpetBitJustCleared(uint64_t u64OldValue, 293 uint64_t u64NewValue, 294 uint64_t u64Mask) 284 295 { 285 296 return (!!(u64OldValue & u64Mask) && !(u64NewValue & u64Mask)); … … 290 301 { 291 302 292 if ( pTimer->u64Config & HPET_TN_32BIT)303 if (hpet32bitTimer(pTimer)) 293 304 { 294 305 uint32_t u32Diff; … … 317 328 { 318 329 /* While loop is suboptimal */ 319 if ( pTimer->u64Config & HPET_TN_32BIT)330 if (hpet32bitTimer(pTimer)) 320 331 { 321 332 while (hpetTimeAfter32(u64Now, pTimer->u64Cmp)) … … 343 354 u64Diff = hpetComputeDiff(pTimer, u64Ticks); 344 355 345 /* HPET spec says in one-shot 32-bit mode, generate an interrupt when 356 /* 357 * HPET spec says in one-shot 32-bit mode, generate an interrupt when 346 358 * counter wraps in addition to an interrupt with comparator match. 347 *348 * ICH9 spec doesn't mention that, so we disable wraparound behavior for ICH9,349 * see public trac defect #8707.350 359 */ 351 if (!pTimer->CTX_SUFF(pHpet)->fIch9) 352 { 353 if ( (pTimer->u64Config & HPET_TN_32BIT) 354 && !(pTimer->u64Config & HPET_TN_PERIODIC)) 355 { 356 u32TillWrap = 0xffffffff - (uint32_t)u64Ticks; 357 if (u32TillWrap < (uint32_t)u64Diff) 358 { 359 u64Diff = u32TillWrap; 360 pTimer->u8Wrap = 1; 361 } 360 if ( hpet32bitTimer(pTimer) 361 && !(pTimer->u64Config & HPET_TN_PERIODIC)) 362 { 363 u32TillWrap = 0xffffffff - (uint32_t)u64Ticks + 1; 364 if (u32TillWrap < (uint32_t)u64Diff) 365 { 366 Log(("wrap on timer %d: till=%u ticks=%lld diff64=%lld\n", 367 pTimer->u8TimerNumber, u32TillWrap, u64Ticks, u64Diff)); 368 u64Diff = u32TillWrap; 369 pTimer->u8Wrap = 1; 362 370 } 363 371 } … … 388 396 && (pTimer->CTX_SUFF(pHpet)->u64HpetConfig & HPET_CFG_LEGACY)) 389 397 return (pTimer->u8TimerNumber == 0) ? 0 : 8; 390 398 391 399 return (pTimer->u64Config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT; 392 400 } … … 511 519 case HPET_TN_CFG: 512 520 { 521 uint64_t u64Mask = HPET_TN_CFG_WRITE_MASK; 522 513 523 Log(("write HPET_TN_CFG: %d: %x\n", iTimerNo, iNewValue)); 524 525 if ((pTimer->u64Config & HPET_TN_PERIODIC_CAP) != 0) 526 u64Mask |= HPET_TN_PERIODIC; 527 528 if ((pTimer->u64Config & HPET_TN_SIZE_CAP) != 0) 529 u64Mask |= HPET_TN_32BIT; 530 else 531 iNewValue &= ~HPET_TN_32BIT; 532 514 533 if ((iNewValue & HPET_TN_32BIT) != 0) 515 534 { 516 Log(("setting timer to 32-bit mode\n"));517 pTimer->u64Cmp = (uint32_t)pTimer->u64Cmp;535 Log(("setting timer %d to 32-bit mode\n", iTimerNo)); 536 pTimer->u64Cmp = (uint32_t)pTimer->u64Cmp; 518 537 pTimer->u64Period = (uint32_t)pTimer->u64Period; 519 538 } … … 525 544 /** We only care about lower 32-bits so far */ 526 545 pTimer->u64Config = 527 hpetUpdateMasked(iNewValue, iOldValue, HPET_TN_CFG_WRITE_MASK);546 hpetUpdateMasked(iNewValue, iOldValue, u64Mask); 528 547 break; 529 548 } … … 536 555 { 537 556 Log(("write HPET_TN_CMP on %d: %x\n", iTimerNo, iNewValue)); 538 if (pTimer->u64Config & HPET_TN_32BIT) 539 iNewValue = (uint32_t)iNewValue; 540 541 if (pTimer->u64Config & HPET_TN_SETVAL) 542 { 543 /* HPET_TN_SETVAL allows to adjust comparator w/o updating period, and it's cleared on access */ 544 if (pTimer->u64Config & HPET_TN_32BIT) 545 pTimer->u64Config &= ~HPET_TN_SETVAL; 546 } 547 else if (pTimer->u64Config & HPET_TN_PERIODIC) 548 { 549 iNewValue &= (pTimer->u64Config & HPET_TN_32BIT ? ~0U : ~0ULL) >> 1; 557 if (pTimer->u64Config & HPET_TN_PERIODIC) 558 { 559 iNewValue &= hpetInvalidValue(pTimer) >> 1; 550 560 pTimer->u64Period = (pTimer->u64Period & 0xffffffff00000000ULL) 551 561 | iNewValue; … … 555 565 | iNewValue; 556 566 567 pTimer->u64Config &= ~HPET_TN_SETVAL; 557 568 Log2(("after HPET_TN_CMP cmp=%llx per=%llx\n", pTimer->u64Cmp, pTimer->u64Period)); 558 569 … … 564 575 { 565 576 Log(("write HPET_TN_CMP + 4 on %d: %x\n", iTimerNo, iNewValue)); 566 if ( pTimer->u64Config & HPET_TN_32BIT)577 if (hpet32bitTimer(pTimer)) 567 578 break; 568 579 569 if (pTimer->u64Config & HPET_TN_SETVAL) 570 { 571 /* HPET_TN_SETVAL allows to adjust comparator w/o updating period, and it's cleared on access */ 572 pTimer->u64Config &= ~HPET_TN_SETVAL; 573 } 574 else if (pTimer->u64Config & HPET_TN_PERIODIC) 575 { 576 pTimer->u64Period = (pTimer->u64Period & 0xffffffffULL) 580 if (pTimer->u64Config & HPET_TN_PERIODIC) 581 { 582 pTimer->u64Period = (pTimer->u64Period & UINT64_C(0xffffffff)) 577 583 | ((uint64_t)iNewValue << 32); 578 584 } 579 585 580 pTimer->u64Cmp = (pTimer->u64Cmp & 0xffffffffULL)586 pTimer->u64Cmp = (pTimer->u64Cmp & UINT64_C(0xffffffff)) 581 587 | ((uint64_t)iNewValue << 32); 582 588 583 589 Log2(("after HPET_TN_CMP+4 cmp=%llx per=%llx\n", pTimer->u64Cmp, pTimer->u64Period)); 590 591 pTimer->u64Config &= ~HPET_TN_SETVAL; 584 592 585 593 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) … … 665 673 - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer)); 666 674 for (i = 0; i < HPET_NUM_TIMERS; i++) 667 if (pThis->aTimers[i].u64Cmp != ~0ULL)675 if (pThis->aTimers[i].u64Cmp != hpetInvalidValue(&pThis->aTimers[i])) 668 676 hpetProgramTimer(&pThis->aTimers[i]); 669 677 } … … 1076 1084 TMTimerSetNano(pTmTimer, hpetTicksToNs(pThis, u64Diff)); 1077 1085 } 1078 else if ( (pTimer->u64Config & HPET_TN_32BIT)1086 else if ( hpet32bitTimer(pTimer) 1079 1087 && !(pTimer->u64Config & HPET_TN_PERIODIC)) 1080 1088 { … … 1136 1144 HpetTimer *pTimer = &pThis->aTimers[i]; 1137 1145 pTimer->u8TimerNumber = i; 1138 pTimer->u64Cmp = ~0ULL;1139 1146 /* capable of periodic operations and 64-bits */ 1140 pTimer->u64Config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP; 1147 if (pThis->fIch9) 1148 pTimer->u64Config = (i == 0) ? 1149 (HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP) 1150 : 1151 0; 1152 else 1153 pTimer->u64Config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP; 1154 1141 1155 /* We can do all IRQs */ 1142 1156 uint32_t u32RoutingCap = 0xffffffff; … … 1144 1158 pTimer->u64Period = 0ULL; 1145 1159 pTimer->u8Wrap = 0; 1160 pTimer->u64Cmp = hpetInvalidValue(pTimer); 1146 1161 } 1147 1162 pThis->u64HpetCounter = 0ULL;
Note:
See TracChangeset
for help on using the changeset viewer.