Changeset 37508 in vbox for trunk/src/VBox
- Timestamp:
- Jun 16, 2011 5:23:02 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevHPET.cpp
r37507 r37508 129 129 #define DEVHPET_UNLOCK(a_pThis) \ 130 130 do { PDMCritSectLeave(&(a_pThis)->csLock); } while (0) 131 132 133 /** 134 * Acquires the TM lock and HPET lock, returns on failure. 135 */ 136 #define DEVHPET_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \ 137 do { \ 138 int rcLock = TMTimerLock((a_pThis)->aTimers[0].CTX_SUFF(pTimer), (a_rcBusy)); \ 139 if (rcLock != VINF_SUCCESS) \ 140 return rcLock; \ 141 rcLock = PDMCritSectEnter(&(a_pThis)->csLock, (a_rcBusy)); \ 142 if (rcLock != VINF_SUCCESS) \ 143 { \ 144 TMTimerUnlock((a_pThis)->aTimers[0].CTX_SUFF(pTimer)); \ 145 return rcLock; \ 146 } \ 147 } while (0) 148 149 150 /** 151 * Releases the HPET lock and TM lock. 152 */ 153 #define DEVHPET_UNLOCK_BOTH(a_pThis) \ 154 do { \ 155 PDMCritSectLeave(&(a_pThis)->csLock); \ 156 TMTimerUnlock((a_pThis)->aTimers[0].CTX_SUFF(pTimer)); \ 157 } while (0) 131 158 132 159 … … 338 365 static void hpetProgramTimer(HpetTimer *pHpetTimer) 339 366 { 340 uint64_t u64Ticks = hpetGetTicks(pHpetTimer->CTX_SUFF(pHpet));341 uint64_t u64Diff;342 uint32_t u32TillWrap;343 344 367 /* no wrapping on new timers */ 345 368 pHpetTimer->u8Wrap = 0; 346 369 370 uint64_t u64Ticks = hpetGetTicks(pHpetTimer->CTX_SUFF(pHpet)); 347 371 hpetAdjustComparator(pHpetTimer, u64Ticks); 348 372 349 u 64Diff = hpetComputeDiff(pHpetTimer, u64Ticks);373 uint64_t u64Diff = hpetComputeDiff(pHpetTimer, u64Ticks); 350 374 351 375 /* … … 356 380 && !(pHpetTimer->u64Config & HPET_TN_PERIODIC)) 357 381 { 358 u 32TillWrap = 0xffffffff - (uint32_t)u64Ticks + 1;382 uint32_t u32TillWrap = 0xffffffff - (uint32_t)u64Ticks + 1; 359 383 if (u32TillWrap < (uint32_t)u64Diff) 360 384 { … … 366 390 } 367 391 368 /* Avoid killing VM with interrupts */ 369 #if 1 370 /* @todo: HACK, rethink, may have negative impact on the guest */ 392 /* 393 * HACK ALERT! Avoid killing VM with interrupts. 394 */ 395 #if 1 /** @todo: HACK, rethink, may have negative impact on the guest */ 371 396 if (u64Diff == 0) 372 397 u64Diff = 100000; /* 1 millisecond */ … … 374 399 375 400 Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff))); 376 377 401 TMTimerSetNano(pHpetTimer->CTX_SUFF(pTimer), hpetTicksToNs(pHpetTimer->CTX_SUFF(pHpet), u64Diff)); 378 402 } … … 395 419 static int hpetTimerRegRead32(HpetState const *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t *pu32Value) 396 420 { 421 Assert(PDMCritSectIsOwner(&pThis->csLock)); 422 397 423 if (iTimerNo >= HPET_NUM_TIMERS) 398 424 { … … 455 481 * @param idxReg The register being written to. 456 482 * @param u32NewValue The value being written. 483 * 484 * @remarks The caller should not hold the device lock, unless it also holds 485 * the TM lock. 457 486 */ 458 487 static int hpetTimerRegWrite32(HpetState *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t u32NewValue) 459 488 { 489 Assert(!PDMCritSectIsOwner(&pThis->csLock) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer))); 490 460 491 if (iTimerNo >= HPET_NUM_TIMERS) 461 492 { … … 469 500 case HPET_TN_CFG: 470 501 { 502 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 471 503 Log(("write HPET_TN_CFG: %d: %x\n", iTimerNo, u32NewValue)); 472 504 uint64_t const iOldValue = (uint32_t)pHpetTimer->u64Config; … … 495 527 /* We only care about lower 32-bits so far */ 496 528 pHpetTimer->u64Config = hpetUpdateMasked(u32NewValue, iOldValue, u64Mask); 529 DEVHPET_UNLOCK(pThis); 497 530 break; 498 531 } … … 506 539 case HPET_TN_CMP: /* lower bits of comparator register */ 507 540 { 508 Log(("write HPET_TN_CMP on %d: %x\n", iTimerNo, u32NewValue)); 541 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 542 Log(("write HPET_TN_CMP on %d: %#x\n", iTimerNo, u32NewValue)); 543 509 544 if (pHpetTimer->u64Config & HPET_TN_PERIODIC) 510 545 { … … 515 550 516 551 pHpetTimer->u64Cmp = (pHpetTimer->u64Cmp & UINT64_C(0xffffffff00000000)) 517 | u32NewValue; 552 | u32NewValue; /** @todo RT_MAKE_U64 */ 518 553 519 554 pHpetTimer->u64Config &= ~HPET_TN_SETVAL; 520 Log2(("after HPET_TN_CMP cmp=% llx per=%llx\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period));555 Log2(("after HPET_TN_CMP cmp=%#llx per=%#llx\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period)); 521 556 522 557 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) 523 558 hpetProgramTimer(pHpetTimer); 559 DEVHPET_UNLOCK_BOTH(pThis); 524 560 break; 525 561 } … … 527 563 case HPET_TN_CMP + 4: /* upper bits of comparator register */ 528 564 { 529 Log(("write HPET_TN_CMP + 4 on %d: %x\n", iTimerNo, u32NewValue)); 530 if (hpet32bitTimer(pHpetTimer)) 531 break; 532 533 if (pHpetTimer->u64Config & HPET_TN_PERIODIC) 534 pHpetTimer->u64Period = RT_MAKE_U64(pHpetTimer->u64Period, u32NewValue); 535 pHpetTimer->u64Cmp = RT_MAKE_U64(pHpetTimer->u64Cmp, u32NewValue); 536 537 Log2(("after HPET_TN_CMP+4 cmp=%llx per=%llx tmr=%d\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period, iTimerNo)); 538 539 pHpetTimer->u64Config &= ~HPET_TN_SETVAL; 540 541 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) 542 hpetProgramTimer(pHpetTimer); 565 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 566 Log(("write HPET_TN_CMP + 4 on %d: %#x\n", iTimerNo, u32NewValue)); 567 if (!hpet32bitTimer(pHpetTimer)) 568 { 569 if (pHpetTimer->u64Config & HPET_TN_PERIODIC) 570 pHpetTimer->u64Period = RT_MAKE_U64(pHpetTimer->u64Period, u32NewValue); 571 pHpetTimer->u64Cmp = RT_MAKE_U64(pHpetTimer->u64Cmp, u32NewValue); 572 573 Log2(("after HPET_TN_CMP+4 cmp=%llx per=%llx tmr=%d\n", pHpetTimer->u64Cmp, pHpetTimer->u64Period, iTimerNo)); 574 575 pHpetTimer->u64Config &= ~HPET_TN_SETVAL; 576 577 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) 578 hpetProgramTimer(pHpetTimer); 579 } 580 DEVHPET_UNLOCK_BOTH(pThis); 543 581 break; 544 582 } … … 558 596 default: 559 597 { 560 LogRel(("invalid timer register write: %d\n", iTimerReg)); 561 AssertFailed(); 598 static unsigned s_cOccurences = 0; 599 if (s_cOccurences++ < 10) 600 LogRel(("invalid timer register write: %d\n", iTimerReg)); 562 601 break; 563 602 } … … 578 617 * @param idxReg The register to read. 579 618 * @param pu32Value Where to return the register value. 580 */ 581 static int hpetConfigRegRead32(HpetState const *pThis, uint32_t idxReg, uint32_t *pu32Value) 582 { 619 * 620 * @remarks The caller must not own the device lock if HPET_COUNTER is read. 621 */ 622 static int hpetConfigRegRead32(HpetState *pThis, uint32_t idxReg, uint32_t *pu32Value) 623 { 624 Assert(!PDMCritSectIsOwner(&pThis->csLock) || (idxReg != HPET_COUNTER && idxReg != HPET_COUNTER + 4)); 625 583 626 uint32_t u32Value; 584 627 switch (idxReg) 585 628 { 586 629 case HPET_ID: 630 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 587 631 u32Value = (uint32_t)pThis->u64Capabilities; 632 DEVHPET_UNLOCK(pThis); 588 633 Log(("read HPET_ID: %#x\n", u32Value)); 589 634 break; 590 635 591 636 case HPET_PERIOD: 637 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 592 638 u32Value = (uint32_t)(pThis->u64Capabilities >> 32); 639 DEVHPET_UNLOCK(pThis); 593 640 Log(("read HPET_PERIOD: %#x\n", u32Value)); 594 641 break; 595 642 596 643 case HPET_CFG: 644 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 597 645 u32Value = (uint32_t)pThis->u64HpetConfig; 646 DEVHPET_UNLOCK(pThis); 598 647 Log(("read HPET_CFG: %#x\n", u32Value)); 599 648 break; 600 649 601 650 case HPET_CFG + 4: 651 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 602 652 u32Value = (uint32_t)(pThis->u64HpetConfig >> 32); 653 DEVHPET_UNLOCK(pThis); 603 654 Log(("read of HPET_CFG + 4: %#x\n", u32Value)); 604 655 break; … … 607 658 case HPET_COUNTER + 4: 608 659 { 660 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 661 609 662 uint64_t u64Ticks; 610 663 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) … … 612 665 else 613 666 u64Ticks = pThis->u64HpetCounter; 667 668 DEVHPET_UNLOCK_BOTH(pThis); 669 614 670 /** @todo is it correct? */ 615 671 u32Value = (idxReg == HPET_COUNTER) ? (uint32_t)u64Ticks : (uint32_t)(u64Ticks >> 32); … … 620 676 621 677 case HPET_STATUS: 622 Log(("read HPET_STATUS\n"));678 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 623 679 u32Value = (uint32_t)pThis->u64Isr; 680 DEVHPET_UNLOCK(pThis); 681 Log(("read HPET_STATUS: %#x\n", u32Value)); 624 682 break; 625 683 … … 643 701 * @param idxReg The register being written to. 644 702 * @param u32NewValue The value being written. 703 * 704 * @remarks The caller should not hold the device lock, unless it also holds 705 * the TM lock. 645 706 */ 646 707 static int hpetConfigRegWrite32(HpetState *pThis, uint32_t idxReg, uint32_t u32NewValue) 647 708 { 709 Assert(!PDMCritSectIsOwner(&pThis->csLock) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer))); 710 648 711 int rc = VINF_SUCCESS; 649 712 switch (idxReg) … … 658 721 case HPET_CFG: 659 722 { 723 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 660 724 uint32_t const iOldValue = (uint32_t)(pThis->u64HpetConfig); 661 725 Log(("write HPET_CFG: %x (old %x)\n", u32NewValue, iOldValue)); … … 671 735 rc = pThis->pHpetHlpR3->pfnSetLegacyMode(pThis->pDevInsR3, RT_BOOL(u32NewValue & HPET_CFG_LEGACY)); 672 736 if (rc != VINF_SUCCESS) 673 break;674 737 #else 675 738 rc = VINF_IOM_HC_MMIO_WRITE; 676 break;677 739 #endif 740 { 741 DEVHPET_UNLOCK_BOTH(pThis); 742 break; 743 } 678 744 } 679 745 … … 697 763 TMTimerStop(pThis->aTimers[i].CTX_SUFF(pTimer)); 698 764 } 765 766 DEVHPET_UNLOCK_BOTH(pThis); 699 767 break; 700 768 } … … 702 770 case HPET_CFG + 4: 703 771 { 704 /** @todo why do we let the guest write to the high bits but not 705 * read them? */ 772 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 706 773 pThis->u64HpetConfig = hpetUpdateMasked((uint64_t)u32NewValue << 32, 707 774 pThis->u64HpetConfig, 708 775 UINT64_C(0xffffffff00000000)); 709 776 Log(("write HPET_CFG + 4: %x -> %#llx\n", u32NewValue, pThis->u64HpetConfig)); 777 DEVHPET_UNLOCK(pThis); 710 778 break; 711 779 } … … 713 781 case HPET_STATUS: 714 782 { 783 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 715 784 /* Clear ISR for all set bits in u32NewValue, see p. 14 of the HPET spec. */ 716 785 pThis->u64Isr &= ~((uint64_t)u32NewValue); 717 786 Log(("write HPET_STATUS: %x -> ISR=%#llx\n", u32NewValue, pThis->u64Isr)); 787 DEVHPET_UNLOCK(pThis); 718 788 break; 719 789 } … … 733 803 case HPET_COUNTER: 734 804 { 805 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 735 806 pThis->u64HpetCounter = RT_MAKE_U64(u32NewValue, pThis->u64HpetCounter); 736 807 Log(("write HPET_COUNTER: %#x -> %llx\n", u32NewValue, pThis->u64HpetCounter)); 808 DEVHPET_UNLOCK(pThis); 737 809 break; 738 810 } … … 740 812 case HPET_COUNTER + 4: 741 813 { 814 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 742 815 pThis->u64HpetCounter = RT_MAKE_U64(pThis->u64HpetCounter, u32NewValue); 743 816 Log(("write HPET_COUNTER + 4: %#x -> %llx\n", u32NewValue, pThis->u64HpetCounter)); 817 DEVHPET_UNLOCK(pThis); 744 818 break; 745 819 } 746 820 747 821 default: 748 LogRel(("invalid HPET config write: %x\n", idxReg)); 749 break; 822 { 823 static unsigned s_cOccurences = 0; 824 if (s_cOccurences++ < 10) 825 LogRel(("invalid HPET config write: %x\n", idxReg)); 826 break; 827 } 750 828 } 751 829 … … 766 844 767 845 LogFlow(("hpetMMIORead (%d): %llx (%x)\n", cb, (uint64_t)GCPhysAddr, idxReg)); 768 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ);769 846 770 847 int rc = VINF_SUCCESS; … … 773 850 case 4: 774 851 if (idxReg >= 0x100 && idxReg < 0x400) 852 { 853 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 775 854 rc = hpetTimerRegRead32(pThis, 776 855 (idxReg - 0x100) / 0x20, 777 856 (idxReg - 0x100) % 0x20, 778 857 (uint32_t *)pv); 858 DEVHPET_UNLOCK(pThis); 859 } 779 860 else 780 861 rc = hpetConfigRegRead32(pThis, idxReg, (uint32_t *)pv); … … 797 878 /* When reading HPET counter we must read it in a single read, 798 879 to avoid unexpected time jumps on 32-bit overflow. */ 799 pValue->u = (pThis->u64HpetConfig & HPET_CFG_ENABLE) != 0 800 ? hpetGetTicks(pThis) 801 : pThis->u64HpetCounter; 802 rc = VINF_SUCCESS; 803 } 804 else if (idxReg >= 0x100 && idxReg < 0x400) 805 { 806 uint32_t iTimer = (idxReg - 0x100) / 0x20; 807 uint32_t iTimerReg = (idxReg - 0x100) % 0x20; 808 rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg, &pValue->s.Lo); 809 if (rc == VINF_SUCCESS) 810 rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg + 4, &pValue->s.Hi); 880 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 881 if (pThis->u64HpetConfig & HPET_CFG_ENABLE) 882 pValue->u = hpetGetTicks(pThis); 883 else 884 pValue->u = pThis->u64HpetCounter; 885 DEVHPET_UNLOCK_BOTH(pThis); 811 886 } 812 887 else 813 888 { 814 /* for most 8-byte accesses we just split them, happens under lock anyway. */ 815 rc = hpetConfigRegRead32(pThis, idxReg, &pValue->s.Lo); 816 if (rc == VINF_SUCCESS) 817 rc = hpetConfigRegRead32(pThis, idxReg + 4, &pValue->s.Hi); 889 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_READ); 890 if (idxReg >= 0x100 && idxReg < 0x400) 891 { 892 uint32_t iTimer = (idxReg - 0x100) / 0x20; 893 uint32_t iTimerReg = (idxReg - 0x100) % 0x20; 894 rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg, &pValue->s.Lo); 895 if (rc == VINF_SUCCESS) 896 rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg + 4, &pValue->s.Hi); 897 } 898 else 899 { 900 /* for most 8-byte accesses we just split them, happens under lock anyway. */ 901 rc = hpetConfigRegRead32(pThis, idxReg, &pValue->s.Lo); 902 if (rc == VINF_SUCCESS) 903 rc = hpetConfigRegRead32(pThis, idxReg + 4, &pValue->s.Hi); 904 } 905 DEVHPET_UNLOCK(pThis); 818 906 } 819 907 break; … … 831 919 } 832 920 833 DEVHPET_UNLOCK(pThis);834 921 return rc; 835 922 } … … 845 932 LogFlow(("hpetMMIOWrite: cb=%u reg=%03x (%RGp) val=%llx\n", 846 933 cb, idxReg, GCPhysAddr, cb == 4 ? *(uint32_t *)pv : cb == 8 ? *(uint64_t *)pv : 0xdeadbeef)); 847 848 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE);849 934 850 935 int rc; … … 871 956 872 957 /* Split the access and rely on the locking to prevent trouble. */ 958 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_MMIO_WRITE); 873 959 RTUINT64U uValue; 874 960 uValue.u = *(uint64_t const *)pv; … … 888 974 rc = hpetConfigRegWrite32(pThis, idxReg + 4, uValue.s.Hi); 889 975 } 976 DEVHPET_UNLOCK_BOTH(pThis); 890 977 break; 891 978 } … … 903 990 } 904 991 905 DEVHPET_UNLOCK(pThis);906 992 return rc; 907 993 }
Note:
See TracChangeset
for help on using the changeset viewer.