Changeset 37497 in vbox
- Timestamp:
- Jun 16, 2011 2:34:03 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevHPET.cpp
r37466 r37497 5 5 6 6 /* 7 * Copyright (C) 2009-201 0Oracle Corporation7 * Copyright (C) 2009-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 21 #define LOG_GROUP LOG_GROUP_DEV_HPET 22 22 #include <VBox/vmm/pdmdev.h> 23 #include <VBox/vmm/stam.h> 23 24 #include <VBox/log.h> 24 #include <VBox/vmm/stam.h>25 25 #include <iprt/assert.h> 26 26 #include <iprt/asm-math.h> … … 55 55 * 10000000 femtoseconds == 10ns 56 56 */ 57 #define HPET_CLK_PERIOD 10000000UL57 #define HPET_CLK_PERIOD UINT32_C(10000000) 58 58 59 59 /* 60 60 * 69841279 femtoseconds == 69.84 ns (1 / 14.31818MHz) 61 61 */ 62 #define HPET_CLK_PERIOD_ICH9 69841279UL62 #define HPET_CLK_PERIOD_ICH9 UINT32_C(69841279) 63 63 64 64 /* … … 111 111 #define HPET_SAVED_STATE_VERSION 2 112 112 113 /* Empty saved state */113 /** Empty saved state */ 114 114 #define HPET_SAVED_STATE_VERSION_EMPTY 1 115 115 … … 136 136 RCPTRTYPE(struct HpetState *) pHpetRC; 137 137 138 /* Timer number. */139 uint8_t u8TimerNumber;140 /* Wrap. */138 /** Timer index. */ 139 uint8_t idxTimer; 140 /** Wrap. */ 141 141 uint8_t u8Wrap; 142 /* Alignment. */142 /** Alignment. */ 143 143 uint32_t alignment0; 144 /* Memory-mapped, software visible timer registers. */ 145 /* Configuration/capabilities. */ 144 145 /** @name Memory-mapped, software visible timer registers. 146 * @{ */ 147 /** Configuration/capabilities. */ 146 148 uint64_t u64Config; 147 /* comparator. */149 /** Comparator. */ 148 150 uint64_t u64Cmp; 149 /* FSB route, not supported now. */151 /** FSB route, not supported now. */ 150 152 uint64_t u64Fsb; 151 152 /* Hidden register state. */ 153 /* Last value written to comparator. */ 153 /** @} */ 154 155 /** @name Hidden register state. 156 * @{ */ 157 /** Last value written to comparator. */ 154 158 uint64_t u64Period; 159 /** @} */ 155 160 } HpetTimer; 161 AssertCompileMemberAlignment(HpetTimer, u64Config, sizeof(uint64_t)); 156 162 157 163 typedef struct HpetState … … 199 205 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 200 206 201 /* 202 * We shall declare MMIO accessors as extern "C" to avoid name mangling 203 * and let them be found during R0/RC module init. 204 * Maybe PDMBOTHCBDECL macro shall have extern "C" part in it. 205 */ 206 207 RT_C_DECLS_BEGIN 208 PDMBOTHCBDECL(int) hpetMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb); 209 PDMBOTHCBDECL(int) hpetMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb); 210 RT_C_DECLS_END 211 212 213 /* 214 * Temporary control to disable locking if problems found 215 */ 216 static const bool fHpetLocking = true; 217 207 208 /** @todo Use macros so we can get the source position. */ 218 209 DECLINLINE(int) hpetLock(HpetState* pThis, int rcBusy) 219 210 { 220 if (!fHpetLocking)221 return VINF_SUCCESS;222 223 211 return PDMCritSectEnter(&pThis->csLock, rcBusy); 224 212 } … … 226 214 DECLINLINE(void) hpetUnlock(HpetState* pThis) 227 215 { 228 if (!fHpetLocking)229 return;230 231 216 PDMCritSectLeave(&pThis->csLock); 232 217 } 233 218 234 DECLINLINE(bool) hpet32bitTimer(HpetTimer *p Timer)235 { 236 uint64_t u64Cfg = p Timer->u64Config;219 DECLINLINE(bool) hpet32bitTimer(HpetTimer *pHpetTimer) 220 { 221 uint64_t u64Cfg = pHpetTimer->u64Config; 237 222 238 223 return ((u64Cfg & HPET_TN_SIZE_CAP) == 0) || ((u64Cfg & HPET_TN_32BIT) != 0); 239 224 } 240 225 241 DECLINLINE(uint64_t) hpetInvalidValue(HpetTimer *p Timer)242 { 243 return hpet32bitTimer(p Timer) ? ~0U : ~0ULL;226 DECLINLINE(uint64_t) hpetInvalidValue(HpetTimer *pHpetTimer) 227 { 228 return hpet32bitTimer(pHpetTimer) ? UINT32_MAX : UINT64_MAX; 244 229 } 245 230 … … 270 255 * with the same speed. 271 256 */ 272 return nsToHpetTicks(pThis, TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer)) + 273 pThis->u64HpetOffset); 257 return nsToHpetTicks(pThis, 258 TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer)) 259 + pThis->u64HpetOffset); 274 260 } 275 261 … … 297 283 } 298 284 299 DECLINLINE(uint64_t) hpetComputeDiff(HpetTimer * pTimer,285 DECLINLINE(uint64_t) hpetComputeDiff(HpetTimer *pHpetTimer, 300 286 uint64_t u64Now) 301 287 { 302 288 303 if (hpet32bitTimer(p Timer))289 if (hpet32bitTimer(pHpetTimer)) 304 290 { 305 291 uint32_t u32Diff; 306 292 307 u32Diff = (uint32_t)p Timer->u64Cmp - (uint32_t)u64Now;293 u32Diff = (uint32_t)pHpetTimer->u64Cmp - (uint32_t)u64Now; 308 294 u32Diff = ((int32_t)u32Diff > 0) ? u32Diff : (uint32_t)0; 309 295 return (uint64_t)u32Diff; … … 313 299 uint64_t u64Diff; 314 300 315 u64Diff = p Timer->u64Cmp - u64Now;301 u64Diff = pHpetTimer->u64Cmp - u64Now; 316 302 u64Diff = ((int64_t)u64Diff > 0) ? u64Diff : (uint64_t)0; 317 303 return u64Diff; … … 320 306 321 307 322 static void hpetAdjustComparator(HpetTimer* pTimer, 323 uint64_t u64Now) 324 { 325 uint64_t u64Period = pTimer->u64Period; 326 if ( (pTimer->u64Config & HPET_TN_PERIODIC) 327 && (u64Period != 0)) 308 static void hpetAdjustComparator(HpetTimer *pHpetTimer, uint64_t u64Now) 309 { 310 uint64_t u64Period = pHpetTimer->u64Period; 311 if ( (pHpetTimer->u64Config & HPET_TN_PERIODIC) 312 && u64Period != 0) 328 313 { 329 314 /* While loop is suboptimal */ 330 if (hpet32bitTimer(p Timer))315 if (hpet32bitTimer(pHpetTimer)) 331 316 { 332 while (hpetTimeAfter32(u64Now, p Timer->u64Cmp))333 p Timer->u64Cmp = (uint32_t)(pTimer->u64Cmp + u64Period);317 while (hpetTimeAfter32(u64Now, pHpetTimer->u64Cmp)) 318 pHpetTimer->u64Cmp = (uint32_t)(pHpetTimer->u64Cmp + u64Period); 334 319 } 335 320 else 336 321 { 337 while (hpetTimeAfter64(u64Now, p Timer->u64Cmp))338 p Timer->u64Cmp += u64Period;322 while (hpetTimeAfter64(u64Now, pHpetTimer->u64Cmp)) 323 pHpetTimer->u64Cmp += u64Period; 339 324 } 340 325 } 341 326 } 342 327 343 static void hpetProgramTimer(HpetTimer *pTimer) 344 { 328 static void hpetProgramTimer(HpetTimer *pHpetTimer) 329 { 330 uint64_t u64Ticks = hpetGetTicks(pHpetTimer->CTX_SUFF(pHpet)); 345 331 uint64_t u64Diff; 346 332 uint32_t u32TillWrap; 347 uint64_t u64Ticks = hpetGetTicks(pTimer->CTX_SUFF(pHpet));348 333 349 334 /* no wrapping on new timers */ 350 p Timer->u8Wrap = 0;351 352 hpetAdjustComparator(p Timer, u64Ticks);353 354 u64Diff = hpetComputeDiff(p Timer, u64Ticks);335 pHpetTimer->u8Wrap = 0; 336 337 hpetAdjustComparator(pHpetTimer, u64Ticks); 338 339 u64Diff = hpetComputeDiff(pHpetTimer, u64Ticks); 355 340 356 341 /* … … 358 343 * counter wraps in addition to an interrupt with comparator match. 359 344 */ 360 if ( hpet32bitTimer(p Timer)361 && !(p Timer->u64Config & HPET_TN_PERIODIC))345 if ( hpet32bitTimer(pHpetTimer) 346 && !(pHpetTimer->u64Config & HPET_TN_PERIODIC)) 362 347 { 363 348 u32TillWrap = 0xffffffff - (uint32_t)u64Ticks + 1; … … 365 350 { 366 351 Log(("wrap on timer %d: till=%u ticks=%lld diff64=%lld\n", 367 p Timer->u8TimerNumber, u32TillWrap, u64Ticks, u64Diff));352 pHpetTimer->idxTimer, u32TillWrap, u64Ticks, u64Diff)); 368 353 u64Diff = u32TillWrap; 369 p Timer->u8Wrap = 1;354 pHpetTimer->u8Wrap = 1; 370 355 } 371 356 } … … 378 363 #endif 379 364 380 Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(p Timer->CTX_SUFF(pHpet), u64Diff)));381 382 TMTimerSetNano(p Timer->CTX_SUFF(pTimer), hpetTicksToNs(pTimer->CTX_SUFF(pHpet), u64Diff));383 } 384 385 static uint32_t getTimerIrq(struct HpetTimer *p Timer)365 Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff))); 366 367 TMTimerSetNano(pHpetTimer->CTX_SUFF(pTimer), hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff)); 368 } 369 370 static uint32_t getTimerIrq(struct HpetTimer *pHpetTimer) 386 371 { 387 372 /* … … 393 378 * to the different ICs. 394 379 */ 395 if ( (p Timer->u8TimerNumber <= 1)396 && (p Timer->CTX_SUFF(pHpet)->u64HpetConfig & HPET_CFG_LEGACY))397 return (p Timer->u8TimerNumber == 0) ? 0 : 8;398 399 return (p Timer->u64Config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;380 if ( (pHpetTimer->idxTimer <= 1) 381 && (pHpetTimer->CTX_SUFF(pHpet)->u64HpetConfig & HPET_CFG_LEGACY)) 382 return (pHpetTimer->idxTimer == 0) ? 0 : 8; 383 384 return (pHpetTimer->u64Config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT; 400 385 } 401 386 … … 405 390 uint32_t *pValue) 406 391 { 407 HpetTimer *pTimer;408 409 392 if (iTimerNo >= HPET_NUM_TIMERS) 410 393 { … … 413 396 } 414 397 415 pTimer = &pThis->aTimers[iTimerNo]; 416 398 HpetTimer *pHpetTimer = &pThis->aTimers[iTimerNo]; 417 399 switch (iTimerReg) 418 400 { 419 401 case HPET_TN_CFG: 420 Log(("read HPET_TN_CFG on %d\n", p Timer->u8TimerNumber));421 *pValue = (uint32_t)(p Timer->u64Config);402 Log(("read HPET_TN_CFG on %d\n", pHpetTimer->idxTimer)); 403 *pValue = (uint32_t)(pHpetTimer->u64Config); 422 404 break; 423 405 case HPET_TN_CFG + 4: 424 Log(("read HPET_TN_CFG+4 on %d\n", p Timer->u8TimerNumber));425 *pValue = (uint32_t)(p Timer->u64Config >> 32);406 Log(("read HPET_TN_CFG+4 on %d\n", pHpetTimer->idxTimer)); 407 *pValue = (uint32_t)(pHpetTimer->u64Config >> 32); 426 408 break; 427 409 case HPET_TN_CMP: 428 Log(("read HPET_TN_CMP on %d, cmp=%llx\n", p Timer->u8TimerNumber, pTimer->u64Cmp));429 *pValue = (uint32_t)(p Timer->u64Cmp);410 Log(("read HPET_TN_CMP on %d, cmp=%llx\n", pHpetTimer->idxTimer, pHpetTimer->u64Cmp)); 411 *pValue = (uint32_t)(pHpetTimer->u64Cmp); 430 412 break; 431 413 case HPET_TN_CMP + 4: 432 Log(("read HPET_TN_CMP+4 on %d, cmp=%llx\n", p Timer->u8TimerNumber, pTimer->u64Cmp));433 *pValue = (uint32_t)(p Timer->u64Cmp >> 32);414 Log(("read HPET_TN_CMP+4 on %d, cmp=%llx\n", pHpetTimer->idxTimer, pHpetTimer->u64Cmp)); 415 *pValue = (uint32_t)(pHpetTimer->u64Cmp >> 32); 434 416 break; 435 417 case HPET_TN_ROUTE: 436 Log(("read HPET_TN_ROUTE on %d\n", p Timer->u8TimerNumber));437 *pValue = (uint32_t)(p Timer->u64Fsb >> 32);418 Log(("read HPET_TN_ROUTE on %d\n", pHpetTimer->idxTimer)); 419 *pValue = (uint32_t)(pHpetTimer->u64Fsb >> 32); 438 420 break; 439 421 default: 440 LogRel(("invalid HPET register read %d on %d\n", iTimerReg, p Timer->u8TimerNumber));422 LogRel(("invalid HPET register read %d on %d\n", iTimerReg, pHpetTimer->idxTimer)); 441 423 *pValue = 0; 442 424 break; … … 493 475 } 494 476 495 static int hpetTimerRegWrite32(HpetState *pThis,477 static int hpetTimerRegWrite32(HpetState *pThis, 496 478 uint32_t iTimerNo, 497 479 uint32_t iTimerReg, 498 480 uint32_t iNewValue) 499 481 { 500 HpetTimer * pTimer;501 uint64_t iOldValue = 0;502 482 uint32_t u32Temp; 503 483 int rc; … … 508 488 return VINF_SUCCESS; 509 489 } 510 pTimer = &pThis->aTimers[iTimerNo]; 511 490 491 HpetTimer *pHpetTimer = &pThis->aTimers[iTimerNo]; 512 492 rc = hpetTimerRegRead32(pThis, iTimerNo, iTimerReg, &u32Temp); 513 493 if (RT_FAILURE(rc)) 514 494 return rc; 515 iOldValue = u32Temp;495 uint64_t iOldValue = u32Temp; 516 496 517 497 switch (iTimerReg) … … 523 503 Log(("write HPET_TN_CFG: %d: %x\n", iTimerNo, iNewValue)); 524 504 525 if ((p Timer->u64Config & HPET_TN_PERIODIC_CAP) != 0)505 if ((pHpetTimer->u64Config & HPET_TN_PERIODIC_CAP) != 0) 526 506 u64Mask |= HPET_TN_PERIODIC; 527 507 528 if ((p Timer->u64Config & HPET_TN_SIZE_CAP) != 0)508 if ((pHpetTimer->u64Config & HPET_TN_SIZE_CAP) != 0) 529 509 u64Mask |= HPET_TN_32BIT; 530 510 else … … 534 514 { 535 515 Log(("setting timer %d to 32-bit mode\n", iTimerNo)); 536 p Timer->u64Cmp = (uint32_t)pTimer->u64Cmp;537 p Timer->u64Period = (uint32_t)pTimer->u64Period;516 pHpetTimer->u64Cmp = (uint32_t)pHpetTimer->u64Cmp; 517 pHpetTimer->u64Period = (uint32_t)pHpetTimer->u64Period; 538 518 } 539 519 if ((iNewValue & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_LEVEL) … … 542 522 AssertFailed(); 543 523 } 544 /* *We only care about lower 32-bits so far */545 p Timer->u64Config =546 hpetUpdateMasked(iNewValue, iOldValue, u64Mask);547 break;548 } 524 /* We only care about lower 32-bits so far */ 525 pHpetTimer->u64Config = hpetUpdateMasked(iNewValue, iOldValue, u64Mask); 526 break; 527 } 528 549 529 case HPET_TN_CFG + 4: /* Interrupt capabilities */ 550 530 { … … 552 532 break; 553 533 } 534 554 535 case HPET_TN_CMP: /* lower bits of comparator register */ 555 536 { 556 537 Log(("write HPET_TN_CMP on %d: %x\n", iTimerNo, iNewValue)); 557 if (p Timer->u64Config & HPET_TN_PERIODIC)538 if (pHpetTimer->u64Config & HPET_TN_PERIODIC) 558 539 { 559 iNewValue &= hpetInvalidValue(p Timer) >> 1;560 p Timer->u64Period = (pTimer->u64Period & 0xffffffff00000000ULL)561 | iNewValue;540 iNewValue &= hpetInvalidValue(pHpetTimer) >> 1; 541 pHpetTimer->u64Period = (pHpetTimer->u64Period & UINT64_C(0xffffffff00000000)) 542 | iNewValue; 562 543 } 563 544 564 p Timer->u64Cmp = (pTimer->u64Cmp & 0xffffffff00000000ULL)565 | iNewValue;566 567 p Timer->u64Config &= ~HPET_TN_SETVAL;568 Log2(("after HPET_TN_CMP cmp=%llx per=%llx\n", p Timer->u64Cmp, pTimer->u64Period));545 pHpetTimer->u64Cmp = (pHpetTimer->u64Cmp & UINT64_C(0xffffffff00000000)) 546 | iNewValue; 547 548 pHpetTimer->u64Config &= ~HPET_TN_SETVAL; 549 Log2(("after HPET_TN_CMP cmp=%llx per=%llx\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period)); 569 550 570 551 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) 571 hpetProgramTimer(pTimer); 572 break; 573 } 552 hpetProgramTimer(pHpetTimer); 553 break; 554 } 555 574 556 case HPET_TN_CMP + 4: /* upper bits of comparator register */ 575 557 { 576 558 Log(("write HPET_TN_CMP + 4 on %d: %x\n", iTimerNo, iNewValue)); 577 if (hpet32bitTimer(p Timer))559 if (hpet32bitTimer(pHpetTimer)) 578 560 break; 579 561 580 if (pTimer->u64Config & HPET_TN_PERIODIC) 581 { 582 pTimer->u64Period = (pTimer->u64Period & UINT64_C(0xffffffff)) 583 | ((uint64_t)iNewValue << 32); 584 } 585 586 pTimer->u64Cmp = (pTimer->u64Cmp & UINT64_C(0xffffffff)) 587 | ((uint64_t)iNewValue << 32); 588 589 Log2(("after HPET_TN_CMP+4 cmp=%llx per=%llx\n", pTimer->u64Cmp, pTimer->u64Period)); 590 591 pTimer->u64Config &= ~HPET_TN_SETVAL; 562 if (pHpetTimer->u64Config & HPET_TN_PERIODIC) 563 pHpetTimer->u64Period = (pHpetTimer->u64Period & UINT64_C(0xffffffff)) 564 | ((uint64_t)iNewValue << 32); 565 566 pHpetTimer->u64Cmp = (pHpetTimer->u64Cmp & UINT64_C(0xffffffff)) 567 | ((uint64_t)iNewValue << 32); 568 569 Log2(("after HPET_TN_CMP+4 cmp=%llx per=%llx\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period)); 570 571 pHpetTimer->u64Config &= ~HPET_TN_SETVAL; 592 572 593 573 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) 594 hpetProgramTimer(pTimer); 595 break; 596 } 574 hpetProgramTimer(pHpetTimer); 575 break; 576 } 577 597 578 case HPET_TN_ROUTE: 598 579 { … … 600 581 break; 601 582 } 583 602 584 case HPET_TN_ROUTE + 4: 603 585 { … … 605 587 break; 606 588 } 589 607 590 default: 608 591 { … … 612 595 } 613 596 } 597 614 598 return VINF_SUCCESS; 615 599 } … … 643 627 break; 644 628 } 629 645 630 case HPET_CFG: 646 631 { 647 uint32_t i, iOldValue; 648 649 Log(("write HPET_CFG: %x\n", iNewValue)); 650 651 iOldValue = (uint32_t)(pThis->u64HpetConfig); 632 uint32_t const iOldValue = (uint32_t)(pThis->u64HpetConfig); 633 Log(("write HPET_CFG: %x (old %x)\n", iNewValue, iOldValue)); 652 634 653 635 /* … … 656 638 */ 657 639 if (hpetBitJustSet(iOldValue, iNewValue, HPET_CFG_LEGACY)) 658 {659 640 rc = hpetLegacyMode(pThis, true); 660 }661 641 else if (hpetBitJustCleared(iOldValue, iNewValue, HPET_CFG_LEGACY)) 662 {663 642 rc = hpetLegacyMode(pThis, false); 664 }665 643 if (rc != VINF_SUCCESS) 666 644 return rc; … … 671 649 /* Enable main counter and interrupt generation. */ 672 650 pThis->u64HpetOffset = hpetTicksToNs(pThis, pThis->u64HpetCounter) 673 - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer));674 for ( i = 0; i < HPET_NUM_TIMERS; i++)651 - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer)); 652 for (uint32_t i = 0; i < HPET_NUM_TIMERS; i++) 675 653 if (pThis->aTimers[i].u64Cmp != hpetInvalidValue(&pThis->aTimers[i])) 676 654 hpetProgramTimer(&pThis->aTimers[i]); … … 680 658 /* Halt main counter and disable interrupt generation. */ 681 659 pThis->u64HpetCounter = hpetGetTicks(pThis); 682 for ( i = 0; i < HPET_NUM_TIMERS; i++)660 for (uint32_t i = 0; i < HPET_NUM_TIMERS; i++) 683 661 TMTimerStop(pThis->aTimers[i].CTX_SUFF(pTimer)); 684 662 } 685 663 break; 686 664 } 665 687 666 case HPET_CFG + 4: 688 667 { … … 690 669 pThis->u64HpetConfig = hpetUpdateMasked((uint64_t)iNewValue << 32, 691 670 pThis->u64HpetConfig, 692 0xffffffff00000000ULL); 693 break; 694 } 671 UINT64_C(0xffffffff00000000)); 672 break; 673 } 674 695 675 case HPET_STATUS: 696 676 { … … 700 680 break; 701 681 } 682 702 683 case HPET_STATUS + 4: 703 684 { … … 707 688 break; 708 689 } 690 709 691 case HPET_COUNTER: 710 692 { 711 pThis->u64HpetCounter = (pThis->u64HpetCounter & 0xffffffff00000000ULL) | iNewValue;693 pThis->u64HpetCounter = (pThis->u64HpetCounter & UINT64_C(0xffffffff00000000)) | iNewValue; 712 694 Log(("write HPET_COUNTER: %#x -> %llx\n", 713 695 iNewValue, pThis->u64HpetCounter)); 714 696 break; 715 697 } 698 716 699 case HPET_COUNTER + 4: 717 700 { 718 pThis->u64HpetCounter = (pThis->u64HpetCounter & 0xffffffffULL)719 | (((uint64_t)iNewValue) << 32);701 pThis->u64HpetCounter = (pThis->u64HpetCounter & UINT64_C(0xffffffff)) 702 | (((uint64_t)iNewValue) << 32); 720 703 Log(("write HPET_COUNTER + 4: %#x -> %llx\n", 721 704 iNewValue, pThis->u64HpetCounter)); 722 705 break; 723 706 } 707 724 708 default: 725 709 LogRel(("invalid HPET config write: %x\n", iIndex)); … … 829 813 unsigned cb) 830 814 { 831 HpetState *pThis= PDMINS_2_DATA(pDevIns, HpetState*);832 int rc= VINF_SUCCESS;833 uint32_t iIndex = (uint32_t)(GCPhysAddr - HPET_BASE);815 HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState*); 816 int rc = VINF_SUCCESS; 817 uint32_t iIndex = (uint32_t)(GCPhysAddr - HPET_BASE); 834 818 835 819 LogFlow(("hpetMMIOWrite (%d): %llx (%x) <- %x\n", … … 858 842 break; 859 843 } 844 860 845 case 8: 861 846 { 862 union863 {864 uint32_t u32[2];865 uint64_t u64;866 } value;867 868 847 /* Unaligned accesses not allowed */ 869 848 if (iIndex % 8 != 0) … … 873 852 break; 874 853 } 854 855 856 // for 8-byte accesses we just split them, happens under lock anyway 857 union 858 { 859 uint32_t u32[2]; 860 uint64_t u64; 861 } value; 875 862 value.u64 = *(uint64_t*)pv; 876 // for 8-byte accesses we just split them, happens under lock anyway877 863 if (iIndex >= 0x100 && iIndex < 0x400) 878 864 { … … 881 867 882 868 rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg, value.u32[0]); 883 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 884 break; 885 rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg + 4, value.u32[1]); 869 if (RT_LIKELY(rc == VINF_SUCCESS)) 870 rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg + 4, value.u32[1]); 886 871 } 887 872 else 888 873 { 889 874 rc = hpetConfigRegWrite32(pThis, iIndex, value.u32[0]); 890 if (RT_UNLIKELY(rc != VINF_SUCCESS)) 891 break; 892 rc = hpetConfigRegWrite32(pThis, iIndex+4, value.u32[1]); 875 if (RT_LIKELY(rc == VINF_SUCCESS)) 876 rc = hpetConfigRegWrite32(pThis, iIndex+4, value.u32[1]); 893 877 } 894 878 break; … … 898 882 AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */ 899 883 rc = VERR_INTERNAL_ERROR; 884 break; 900 885 } 901 886 902 887 hpetUnlock(pThis); 903 904 888 return rc; 905 889 } … … 907 891 #ifdef IN_RING3 908 892 909 static int hpetSaveTimer(HpetTimer *pTimer, 910 PSSMHANDLE pSSM) 911 { 912 TMR3TimerSave(pTimer->pTimerR3, pSSM); 913 SSMR3PutU8 (pSSM, pTimer->u8Wrap); 914 SSMR3PutU64 (pSSM, pTimer->u64Config); 915 SSMR3PutU64 (pSSM, pTimer->u64Cmp); 916 SSMR3PutU64 (pSSM, pTimer->u64Fsb); 917 SSMR3PutU64 (pSSM, pTimer->u64Period); 918 919 return VINF_SUCCESS; 920 } 921 922 static int hpetLoadTimer(HpetTimer *pTimer, 923 PSSMHANDLE pSSM) 924 { 925 TMR3TimerLoad(pTimer->pTimerR3, pSSM); 926 SSMR3GetU8(pSSM, &pTimer->u8Wrap); 927 SSMR3GetU64(pSSM, &pTimer->u64Config); 928 SSMR3GetU64(pSSM, &pTimer->u64Cmp); 929 SSMR3GetU64(pSSM, &pTimer->u64Fsb); 930 SSMR3GetU64(pSSM, &pTimer->u64Period); 931 932 return VINF_SUCCESS; 893 /** @todo move the saved state stuff down before the timer. */ 894 895 static int hpetSaveTimer(HpetTimer *pHpetTimer, PSSMHANDLE pSSM) 896 { 897 TMR3TimerSave(pHpetTimer->pTimerR3, pSSM); 898 SSMR3PutU8(pSSM, pHpetTimer->u8Wrap); 899 SSMR3PutU64(pSSM, pHpetTimer->u64Config); 900 SSMR3PutU64(pSSM, pHpetTimer->u64Cmp); 901 SSMR3PutU64(pSSM, pHpetTimer->u64Fsb); 902 return SSMR3PutU64(pSSM, pHpetTimer->u64Period); 903 } 904 905 static int hpetLoadTimer(HpetTimer *pHpetTimer, PSSMHANDLE pSSM) 906 { 907 TMR3TimerLoad(pHpetTimer->pTimerR3, pSSM); 908 SSMR3GetU8(pSSM, &pHpetTimer->u8Wrap); 909 SSMR3GetU64(pSSM, &pHpetTimer->u64Config); 910 SSMR3GetU64(pSSM, &pHpetTimer->u64Cmp); 911 SSMR3GetU64(pSSM, &pHpetTimer->u64Fsb); 912 return SSMR3GetU64(pSSM, &pHpetTimer->u64Period); 933 913 } 934 914 … … 992 972 { 993 973 HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *); 994 uint32_t iTimer;995 int rc;996 974 997 975 if (uVersion == HPET_SAVED_STATE_VERSION_EMPTY) … … 1003 981 uint8_t u8NumTimers; 1004 982 1005 rc = SSMR3GetU8(pSSM, &u8NumTimers); AssertRCReturn(rc, rc); 983 int rc = SSMR3GetU8(pSSM, &u8NumTimers); 984 AssertRCReturn(rc, rc); 1006 985 if (u8NumTimers != HPET_NUM_TIMERS) 1007 986 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - wrong number of timers: saved=%#x config=%#x"), u8NumTimers, HPET_NUM_TIMERS); … … 1010 989 return VINF_SUCCESS; 1011 990 1012 for ( iTimer = 0; iTimer < HPET_NUM_TIMERS; iTimer++)991 for (uint32_t iTimer = 0; iTimer < HPET_NUM_TIMERS; iTimer++) 1013 992 { 1014 993 rc = hpetLoadTimer(&pThis->aTimers[iTimer], pSSM); … … 1025 1004 } 1026 1005 1027 static void hpetIrqUpdate(struct HpetTimer *p Timer)1028 { 1029 uint32_t irq = getTimerIrq(pTimer);1030 HpetState * pThis = pTimer->CTX_SUFF(pHpet);1006 static void hpetIrqUpdate(struct HpetTimer *pHpetTimer) 1007 { 1008 uint32_t irq = getTimerIrq(pHpetTimer); 1009 HpetState *pThis = pHpetTimer->CTX_SUFF(pHpet); 1031 1010 1032 1011 /** @todo: is it correct? */ 1033 if ( !!(p Timer->u64Config & HPET_TN_ENABLE)1012 if ( !!(pHpetTimer->u64Config & HPET_TN_ENABLE) 1034 1013 && !!(pThis->u64HpetConfig & HPET_CFG_ENABLE)) 1035 1014 { … … 1037 1016 1038 1017 /* ISR bits are only set in level-triggered mode */ 1039 if ((p Timer->u64Config & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_LEVEL)1040 pThis->u64Isr |= (uint64_t)(1 << p Timer->u8TimerNumber);1018 if ((pHpetTimer->u64Config & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_LEVEL) 1019 pThis->u64Isr |= (uint64_t)(1 << pHpetTimer->idxTimer); 1041 1020 1042 1021 /* We trigger flip/flop in edge-triggered mode and do nothing in level-triggered mode yet */ 1043 if ((p Timer->u64Config & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_EDGE)1022 if ((pHpetTimer->u64Config & HPET_TN_INT_TYPE) == HPET_TIMER_TYPE_EDGE) 1044 1023 pThis->pHpetHlpR3->pfnSetIrq(pThis->CTX_SUFF(pDevIns), irq, PDM_IRQ_LEVEL_FLIP_FLOP); 1045 1024 else … … 1056 1035 * @param pvUser Pointer to the HPET timer state. 1057 1036 */ 1058 static DECLCALLBACK(void) hpetTimer(PPDMDEVINS pDevIns, 1059 PTMTIMER pTmTimer, 1060 void * pvUser) 1037 static DECLCALLBACK(void) hpetTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 1061 1038 { 1062 1039 HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *); 1063 HpetTimer *p Timer= (HpetTimer *)pvUser;1064 uint64_t u64Period = p Timer->u64Period;1065 uint64_t u64CurTick = hpetGetTicks(pThis); /** @todo this should be done AFTER locking the HPET. */1040 HpetTimer *pHpetTimer = (HpetTimer *)pvUser; 1041 uint64_t u64Period = pHpetTimer->u64Period; 1042 uint64_t u64CurTick = hpetGetTicks(pThis); 1066 1043 uint64_t u64Diff; 1067 int rc;1068 1069 if (pTimer == NULL)1070 return;1071 1044 1072 1045 /* Lock in R3 must either block or succeed */ 1073 rc = hpetLock(pThis, VERR_IGNORED); 1074 1046 int rc = hpetLock(pThis, VERR_IGNORED); 1075 1047 AssertLogRelRCReturnVoid(rc); 1076 1048 1077 if ((p Timer->u64Config & HPET_TN_PERIODIC) && (u64Period != 0))1078 { 1079 hpetAdjustComparator(p Timer, u64CurTick);1080 1081 u64Diff = hpetComputeDiff(p Timer, u64CurTick);1082 1083 Log4(("HPET: periodical: next in %ll d\n",hpetTicksToNs(pThis, u64Diff)));1084 TMTimerSetNano(pT mTimer, hpetTicksToNs(pThis, u64Diff));1085 } 1086 else if ( hpet32bitTimer(p Timer)1087 && !(p Timer->u64Config & HPET_TN_PERIODIC))1088 { 1089 if (p Timer->u8Wrap)1090 { 1091 u64Diff = hpetComputeDiff(p Timer, u64CurTick);1092 TMTimerSetNano(pT mTimer, hpetTicksToNs(pThis, u64Diff));1093 p Timer->u8Wrap = 0;1049 if ((pHpetTimer->u64Config & HPET_TN_PERIODIC) && (u64Period != 0)) 1050 { 1051 hpetAdjustComparator(pHpetTimer, u64CurTick); 1052 1053 u64Diff = hpetComputeDiff(pHpetTimer, u64CurTick); 1054 1055 Log4(("HPET: periodical: next in %llu\n", hpetTicksToNs(pThis, u64Diff))); 1056 TMTimerSetNano(pTimer, hpetTicksToNs(pThis, u64Diff)); 1057 } 1058 else if ( hpet32bitTimer(pHpetTimer) 1059 && !(pHpetTimer->u64Config & HPET_TN_PERIODIC)) 1060 { 1061 if (pHpetTimer->u8Wrap) 1062 { 1063 u64Diff = hpetComputeDiff(pHpetTimer, u64CurTick); 1064 TMTimerSetNano(pTimer, hpetTicksToNs(pThis, u64Diff)); 1065 pHpetTimer->u8Wrap = 0; 1094 1066 } 1095 1067 } 1096 1068 1097 1069 /* Should it really be under lock, does it really matter? */ 1098 hpetIrqUpdate(p Timer);1070 hpetIrqUpdate(pHpetTimer); 1099 1071 1100 1072 hpetUnlock(pThis); … … 1142 1114 for (i = 0; i < HPET_NUM_TIMERS; i++) 1143 1115 { 1144 HpetTimer *p Timer = &pThis->aTimers[i];1145 p Timer->u8TimerNumber = i;1116 HpetTimer *pHpetTimer = &pThis->aTimers[i]; 1117 pHpetTimer->idxTimer = i; 1146 1118 /* capable of periodic operations and 64-bits */ 1147 1119 if (pThis->fIch9) 1148 pTimer->u64Config = (i == 0) ? 1149 (HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP) 1150 : 1151 0; 1120 pHpetTimer->u64Config = (i == 0) 1121 ? (HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP) 1122 : 0; 1152 1123 else 1153 p Timer->u64Config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;1124 pHpetTimer->u64Config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP; 1154 1125 1155 1126 /* We can do all IRQs */ 1156 1127 uint32_t u32RoutingCap = 0xffffffff; 1157 p Timer->u64Config |= ((uint64_t)u32RoutingCap) << 32;1158 p Timer->u64Period = 0ULL;1159 p Timer->u8Wrap= 0;1160 p Timer->u64Cmp = hpetInvalidValue(pTimer);1161 } 1162 pThis->u64HpetCounter = 0 ULL;1163 pThis->u64HpetOffset = 0ULL;1128 pHpetTimer->u64Config |= ((uint64_t)u32RoutingCap) << 32; 1129 pHpetTimer->u64Period = 0; 1130 pHpetTimer->u8Wrap = 0; 1131 pHpetTimer->u64Cmp = hpetInvalidValue(pHpetTimer); 1132 } 1133 pThis->u64HpetCounter = 0; 1134 pThis->u64HpetOffset = 0; 1164 1135 1165 1136 uint32_t u32Vendor = 0x8086; … … 1189 1160 1190 1161 pThis->pDevInsR3 = pDevIns; 1191 pThis->pDevInsR0 1192 pThis->pDevInsRC 1162 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1163 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1193 1164 1194 1165 for (unsigned i = 0; i < HPET_NUM_TIMERS; i++) 1195 1166 { 1196 HpetTimer *p Timer = &pThis->aTimers[i];1197 1198 p Timer->pHpetR3 = pThis;1199 p Timer->pHpetR0 = PDMINS_2_DATA_R0PTR(pDevIns);1200 p Timer->pHpetRC = PDMINS_2_DATA_RCPTR(pDevIns);1201 1202 int rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hpetTimer, p Timer,1203 TMTIMER_FLAGS_ DEFAULT_CRIT_SECT, "HPET Timer",1167 HpetTimer *pHpetTimer = &pThis->aTimers[i]; 1168 1169 pHpetTimer->pHpetR3 = pThis; 1170 pHpetTimer->pHpetR0 = PDMINS_2_DATA_R0PTR(pDevIns); 1171 pHpetTimer->pHpetRC = PDMINS_2_DATA_RCPTR(pDevIns); 1172 1173 int rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hpetTimer, pHpetTimer, 1174 TMTIMER_FLAGS_NO_CRIT_SECT, "HPET Timer", 1204 1175 &pThis->aTimers[i].pTimerR3); 1205 1176 if (RT_FAILURE(rc)) … … 1207 1178 pThis->aTimers[i].pTimerRC = TMTimerRCPtr(pThis->aTimers[i].pTimerR3); 1208 1179 pThis->aTimers[i].pTimerR0 = TMTimerR0Ptr(pThis->aTimers[i].pTimerR3); 1180 TMR3TimerSetCritSect(pThis->aTimers[i].pTimerR3, &pThis->csLock); 1209 1181 } 1210 1182 … … 1223 1195 static DECLCALLBACK(void) hpetInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) 1224 1196 { 1225 HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *); 1226 int i; 1197 HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *); 1227 1198 1228 1199 pHlp->pfnPrintf(pHlp, … … 1236 1207 pHlp->pfnPrintf(pHlp, 1237 1208 "Timers:\n"); 1238 for ( i = 0; i < HPET_NUM_TIMERS; i++)1209 for (unsigned i = 0; i < HPET_NUM_TIMERS; i++) 1239 1210 { 1240 1211 pHlp->pfnPrintf(pHlp, " %d: comparator=%016RX64 period(hidden)=%016RX64 cfg=%016RX64\n", 1241 pThis->aTimers[i]. u8TimerNumber,1212 pThis->aTimers[i].idxTimer, 1242 1213 pThis->aTimers[i].u64Cmp, 1243 1214 pThis->aTimers[i].u64Period, … … 1254 1225 HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *); 1255 1226 int rc; 1256 bool fRCEnabled = false;1257 bool fR0Enabled = false;1258 bool fIch9 = false;1259 PDMHPETREG HpetReg;1260 1227 1261 1228 /* Only one HPET device now, as we use fixed MMIO region. */ … … 1272 1239 1273 1240 /* Query configuration. */ 1241 bool fRCEnabled; 1274 1242 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fRCEnabled, true); 1275 1243 if (RT_FAILURE(rc)) … … 1277 1245 N_("Configuration error: Querying \"GCEnabled\" as a bool failed")); 1278 1246 1247 bool fR0Enabled; 1279 1248 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true); 1280 1249 if (RT_FAILURE(rc)) 1281 1250 return PDMDEV_SET_ERROR(pDevIns, rc, 1282 1251 N_("Configuration error: failed to read R0Enabled as boolean")); 1252 1253 bool fIch9; 1283 1254 rc = CFGMR3QueryBoolDef(pCfg, "ICH9", &fIch9, false); 1284 1255 if (RT_FAILURE(rc)) … … 1287 1258 1288 1259 /* Initialize the device state */ 1289 memset(pThis, 0, sizeof(*pThis));1290 1291 1260 pThis->fIch9 = (uint8_t)fIch9; 1292 1261 … … 1302 1271 * Register the HPET and get helpers. 1303 1272 */ 1304 HpetReg.u32Version = PDM_HPETREG_VERSION; 1273 PDMHPETREG HpetReg; 1274 HpetReg.u32Version = PDM_HPETREG_VERSION; 1305 1275 rc = PDMDevHlpHPETRegister(pDevIns, &HpetReg, &pThis->pHpetHlpR3); 1306 if (RT_FAILURE(rc)) 1307 { 1308 AssertMsgRC(rc, ("Cannot HPETRegister: %Rrc\n", rc)); 1309 return rc; 1310 } 1276 AssertRCReturn(rc, rc); 1311 1277 1312 1278 /* … … 1343 1309 } 1344 1310 } 1311 1345 1312 if (fR0Enabled) 1346 1313 { … … 1428 1395 1429 1396 #endif /* IN_RING3 */ 1430 1431 #endif /* VBOX_DEVICE_STRUCT_TESTCASE */ 1397 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */ 1398
Note:
See TracChangeset
for help on using the changeset viewer.