- Timestamp:
- Nov 18, 2019 8:31:38 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevHPET.cpp
r81961 r81963 230 230 uint64_t u64Period; 231 231 /** @} */ 232 233 STAMCOUNTER StatSetIrq; 234 STAMCOUNTER StatSetTimer; 232 235 } HPETTIMER; 233 236 AssertCompileMemberAlignment(HPETTIMER, u64Config, sizeof(uint64_t)); … … 263 266 /** @} */ 264 267 265 /** Global device lock. */266 PDMCRITSECT CritSect;267 268 268 /** Whether we emulate ICH9 HPET (different frequency & timer count). */ 269 269 bool fIch9; … … 271 271 uint8_t abPadding0[7]; 272 272 273 /** The handle of the MMIO region. */ 273 /** Global device lock. */ 274 PDMCRITSECT CritSect; 275 276 /** The handle of the MMIO region. */ 274 277 IOMMMIOHANDLE hMmio; 278 279 STAMCOUNTER StatCounterRead4Byte; 280 STAMCOUNTER StatCounterRead8Byte; 281 STAMCOUNTER StatCounterWriteLow; 282 STAMCOUNTER StatCounterWriteHigh; 275 283 } HPET; 276 284 /** Pointer to the shared HPET device state. */ … … 328 336 { 329 337 uint64_t u64Cfg = pHpetTimer->u64Config; 330 331 338 return ((u64Cfg & HPET_TN_SIZE_CAP) == 0) || ((u64Cfg & HPET_TN_32BIT) != 0); 332 339 } … … 344 351 DECLINLINE(uint64_t) nsToHpetTicks(PCHPET pThis, uint64_t u64Value) 345 352 { 353 //return ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, RT_MAX(pThis->u32Period, 1 /* no div/zero */)); 346 354 return ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, pThis->u32Period); 347 355 } … … 467 475 { 468 476 Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pThis, u64Diff))); 477 STAM_REL_COUNTER_INC(&pHpetTimer->StatSetTimer); 469 478 PDMDevHlpTimerSetNano(pDevIns, pHpetTimer->hTimer, hpetTicksToNs(pThis, u64Diff)); 470 479 } … … 496 505 RT_NOREF(pDevIns); 497 506 498 if ( iTimerNo >= HPET_CAP_GET_TIMERS(pThis->u32Capabilities) /* The second check is only to satisfy Parfait; */ 499 || iTimerNo >= RT_ELEMENTS(pThis->aTimers) ) /* in practice, the number of configured timers */ 500 { /* will always be <= aTimers elements. */ 507 uint32_t u32Value; 508 if ( iTimerNo < HPET_CAP_GET_TIMERS(pThis->u32Capabilities) 509 && iTimerNo < RT_ELEMENTS(pThis->aTimers) ) 510 { 511 PCHPETTIMER pHpetTimer = &pThis->aTimers[iTimerNo]; 512 switch (iTimerReg) 513 { 514 case HPET_TN_CFG: 515 u32Value = (uint32_t)pHpetTimer->u64Config; 516 Log(("read HPET_TN_CFG on %d: %#x\n", iTimerNo, u32Value)); 517 break; 518 519 case HPET_TN_CFG + 4: 520 u32Value = (uint32_t)(pHpetTimer->u64Config >> 32); 521 Log(("read HPET_TN_CFG+4 on %d: %#x\n", iTimerNo, u32Value)); 522 break; 523 524 case HPET_TN_CMP: 525 u32Value = (uint32_t)pHpetTimer->u64Cmp; 526 Log(("read HPET_TN_CMP on %d: %#x (%#llx)\n", pHpetTimer->idxTimer, u32Value, pHpetTimer->u64Cmp)); 527 break; 528 529 case HPET_TN_CMP + 4: 530 u32Value = (uint32_t)(pHpetTimer->u64Cmp >> 32); 531 Log(("read HPET_TN_CMP+4 on %d: %#x (%#llx)\n", pHpetTimer->idxTimer, u32Value, pHpetTimer->u64Cmp)); 532 break; 533 534 case HPET_TN_ROUTE: 535 u32Value = (uint32_t)(pHpetTimer->u64Fsb >> 32); /** @todo Looks wrong, but since it's not supported, who cares. */ 536 Log(("read HPET_TN_ROUTE on %d: %#x\n", iTimerNo, u32Value)); 537 break; 538 539 default: 540 { 541 LogRelMax(10, ("HPET: Invalid HPET register read %d on %d\n", iTimerReg, pHpetTimer->idxTimer)); 542 u32Value = 0; 543 break; 544 } 545 } 546 } 547 else 548 { 501 549 LogRelMax(10, ("HPET: Using timer above configured range: %d\n", iTimerNo)); 502 *pu32Value = 0; 503 return; 504 } 505 506 PCHPETTIMER pHpetTimer = &pThis->aTimers[iTimerNo]; 507 uint32_t u32Value; 508 switch (iTimerReg) 509 { 510 case HPET_TN_CFG: 511 u32Value = (uint32_t)pHpetTimer->u64Config; 512 Log(("read HPET_TN_CFG on %d: %#x\n", iTimerNo, u32Value)); 513 break; 514 515 case HPET_TN_CFG + 4: 516 u32Value = (uint32_t)(pHpetTimer->u64Config >> 32); 517 Log(("read HPET_TN_CFG+4 on %d: %#x\n", iTimerNo, u32Value)); 518 break; 519 520 case HPET_TN_CMP: 521 u32Value = (uint32_t)pHpetTimer->u64Cmp; 522 Log(("read HPET_TN_CMP on %d: %#x (%#llx)\n", pHpetTimer->idxTimer, u32Value, pHpetTimer->u64Cmp)); 523 break; 524 525 case HPET_TN_CMP + 4: 526 u32Value = (uint32_t)(pHpetTimer->u64Cmp >> 32); 527 Log(("read HPET_TN_CMP+4 on %d: %#x (%#llx)\n", pHpetTimer->idxTimer, u32Value, pHpetTimer->u64Cmp)); 528 break; 529 530 case HPET_TN_ROUTE: 531 u32Value = (uint32_t)(pHpetTimer->u64Fsb >> 32); /** @todo Looks wrong, but since it's not supported, who cares. */ 532 Log(("read HPET_TN_ROUTE on %d: %#x\n", iTimerNo, u32Value)); 533 break; 534 535 default: 536 { 537 LogRelMax(10, ("HPET: Invalid HPET register read %d on %d\n", iTimerReg, pHpetTimer->idxTimer)); 538 u32Value = 0; 539 break; 540 } 550 u32Value = 0; 541 551 } 542 552 *pu32Value = u32Value; … … 716 726 case HPET_COUNTER + 4: 717 727 { 728 STAM_REL_COUNTER_INC(&pThis->StatCounterRead4Byte); 718 729 DEVHPET_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_MMIO_READ); 719 730 … … 728 739 /** @todo is it correct? */ 729 740 u32Value = (idxReg == HPET_COUNTER) ? (uint32_t)u64Ticks : (uint32_t)(u64Ticks >> 32); 730 Log(("read HPET_COUNTER: %s part value %x (%#llx)\n", 731 (idxReg == HPET_COUNTER) ? "low" : "high", u32Value, u64Ticks)); 741 Log(("read HPET_COUNTER: %s part value %x (%#llx)\n", (idxReg == HPET_COUNTER) ? "low" : "high", u32Value, u64Ticks)); 732 742 break; 733 743 } … … 874 884 case HPET_COUNTER: 875 885 { 886 STAM_REL_COUNTER_INC(&pThis->StatCounterWriteLow); 876 887 DEVHPET_LOCK_RETURN(pDevIns, pThis, VINF_IOM_R3_MMIO_WRITE); 877 888 pThis->u64HpetCounter = RT_MAKE_U64(u32NewValue, RT_HI_U32(pThis->u64HpetCounter)); … … 883 894 case HPET_COUNTER + 4: 884 895 { 896 STAM_REL_COUNTER_INC(&pThis->StatCounterWriteHigh); 885 897 DEVHPET_LOCK_RETURN(pDevIns, pThis, VINF_IOM_R3_MMIO_WRITE); 886 898 pThis->u64HpetCounter = RT_MAKE_U64(RT_LO_U32(pThis->u64HpetCounter), u32NewValue); … … 943 955 /* When reading HPET counter we must read it in a single read, 944 956 to avoid unexpected time jumps on 32-bit overflow. */ 957 STAM_REL_COUNTER_INC(&pThis->StatCounterRead8Byte); 945 958 DEVHPET_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_MMIO_READ); 946 959 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) … … 1084 1097 AssertReturnVoid(pThisCC); 1085 1098 pThisCC->pHpetHlp->pfnSetIrq(pDevIns, irq, PDM_IRQ_LEVEL_FLIP_FLOP); 1099 STAM_REL_COUNTER_INC(&pHpetTimer->StatSetIrq); 1086 1100 } 1087 1101 else … … 1119 1133 { 1120 1134 Log4(("HPET: periodic: next in %llu\n", hpetTicksToNs(pThis, u64Diff))); 1121 PDMDevHlpTimerSetNano(pDevIns, pHpetTimer->hTimer, hpetTicksToNs(pThis, u64Diff));1135 STAM_REL_COUNTER_INC(&pHpetTimer->StatSetTimer); 1122 1136 } 1123 1137 else … … 1466 1480 1467 1481 /* 1468 * Register SSM state and info item.1482 * Register SSM state, info item and statistics. 1469 1483 */ 1470 1484 rc = PDMDevHlpSSMRegister3(pDevIns, HPET_SAVED_STATE_VERSION, sizeof(*pThis), hpetR3LiveExec, hpetR3SaveExec, hpetR3LoadExec); … … 1472 1486 1473 1487 PDMDevHlpDBGFInfoRegister(pDevIns, "hpet", "Display HPET status. (no arguments)", hpetR3Info); 1488 1489 /* Statistics: */ 1490 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCounterRead4Byte, STAMTYPE_COUNTER, 1491 "CounterRead4Byte", STAMUNIT_OCCURENCES, "HPET_COUNTER 32-bit reads"); 1492 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCounterRead8Byte, STAMTYPE_COUNTER, 1493 "CounterRead8Byte", STAMUNIT_OCCURENCES, "HPET_COUNTER 64-bit reads"); 1494 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCounterWriteLow, STAMTYPE_COUNTER, 1495 "CounterWriteLow", STAMUNIT_OCCURENCES, "Low HPET_COUNTER writes"); 1496 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatCounterWriteHigh, STAMTYPE_COUNTER, 1497 "CounterWriteHigh", STAMUNIT_OCCURENCES, "High HPET_COUNTER writes"); 1498 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++) 1499 { 1500 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aTimers[i].StatSetIrq, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, 1501 STAMUNIT_OCCURENCES, "Number of times the IRQ has been set.", "timer%u/SetIrq", i); 1502 PDMDevHlpSTAMRegisterF(pDevIns, &pThis->aTimers[i].StatSetTimer, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, 1503 STAMUNIT_OCCURENCES, "Number of times the timer has be programmed.", "timer%u/SetTimer", i); 1504 } 1474 1505 1475 1506 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.