Changeset 90503 in vbox for trunk/src/VBox/Devices/VMMDev
- Timestamp:
- Aug 3, 2021 9:22:13 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 146107
- Location:
- trunk/src/VBox/Devices/VMMDev
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/VMMDev/VMMDevState.h
r90467 r90503 261 261 uint32_t StatMemBalloonChunks; 262 262 263 /** @name Testing264 * @{ */265 /** Set if testing is enabled. */266 bool fTestingEnabled;267 /** Set if testing the MMIO testing range is enabled. */268 bool fTestingMMIO;269 /** Alignment padding. */270 bool afPadding9[HC_ARCH_BITS == 32 ? 2 : 6];271 #if !defined(VBOX_WITHOUT_TESTING_FEATURES) || defined(DOXYGEN_RUNNING)272 /** The high timestamp value. */273 uint32_t u32TestingHighTimestamp;274 /** The current testing command (VMMDEV_TESTING_CMD_XXX). */275 uint32_t u32TestingCmd;276 /** The testing data offset (command specific). */277 uint32_t offTestingData;278 /** For buffering the what comes in over the testing data port. */279 union280 {281 char padding[1024];282 283 /** VMMDEV_TESTING_CMD_INIT, VMMDEV_TESTING_CMD_SUB_NEW,284 * VMMDEV_TESTING_CMD_FAILED. */285 struct286 {287 char sz[1024];288 } String, Init, SubNew, Failed;289 290 /** VMMDEV_TESTING_CMD_TERM, VMMDEV_TESTING_CMD_SUB_DONE. */291 struct292 {293 uint32_t c;294 } Error, Term, SubDone;295 296 /** VMMDEV_TESTING_CMD_VALUE. */297 struct298 {299 RTUINT64U u64Value;300 uint32_t u32Unit;301 char szName[1024 - 8 - 4];302 } Value;303 304 /** The read back register (VMMDEV_TESTING_MMIO_OFF_READBACK,305 * VMMDEV_TESTING_MMIO_OFF_READBACK_R3). */306 uint8_t abReadBack[VMMDEV_TESTING_READBACK_SIZE];307 } TestingData;308 /** The locking testing control dword. */309 union310 {311 /** Plain view. */312 uint32_t u32;313 struct314 {315 /** Number of microseconds to hold the lock. Zero means disabled. */316 uint32_t cUsHold : 14;317 /** Number of microseconds to wait before retaking the lock again. */318 uint32_t cUsBetween : 14;319 /** Reserved MBZ. */320 uint32_t uReserved : 2;321 /** Pass VINF_SUCCESS as rcBusy if set. */322 uint32_t fMustSucceed : 1;323 /** Whether to poke EMTs before releasing it. */324 uint32_t fPokeBeforeRelease : 1;325 } s;326 } TestingLockControl;327 /** Alignment padding. */328 uint32_t uPadding10;329 /** Event semaphore that the locking thread blocks. */330 SUPSEMEVENT hTestingLockEvt;331 /** Handle for the I/O ports used by the testing component. */332 IOMIOPORTHANDLE hIoPortTesting;333 /** Handle for the MMIO region used by the testing component. */334 IOMMMIOHANDLE hMmioTesting;335 #endif /* !VBOX_WITHOUT_TESTING_FEATURES || DOXYGEN_RUNNING */336 /** @} */337 338 263 /** @name Heartbeat 339 264 * @{ */ … … 354 279 /** Timer for signalling a flatlined guest. */ 355 280 TMTIMERHANDLE hFlatlinedTimer; 281 /** @} */ 282 283 /** @name Testing 284 * @{ */ 285 /** Set if testing is enabled. */ 286 bool fTestingEnabled; 287 /** Set if testing the MMIO testing range is enabled. */ 288 bool fTestingMMIO; 289 /** Alignment padding. */ 290 bool afPadding9[2]; 291 #if !defined(VBOX_WITHOUT_TESTING_FEATURES) || defined(DOXYGEN_RUNNING) 292 /** The high timestamp value. */ 293 uint32_t u32TestingHighTimestamp; 294 /** The current testing command (VMMDEV_TESTING_CMD_XXX). */ 295 uint32_t u32TestingCmd; 296 /** The testing data offset (command specific). */ 297 uint32_t offTestingData; 298 /** For buffering the what comes in over the testing data port. */ 299 union 300 { 301 char padding[1024]; 302 303 /** VMMDEV_TESTING_CMD_INIT, VMMDEV_TESTING_CMD_SUB_NEW, 304 * VMMDEV_TESTING_CMD_FAILED. */ 305 struct 306 { 307 char sz[1024]; 308 } String, Init, SubNew, Failed; 309 310 /** VMMDEV_TESTING_CMD_TERM, VMMDEV_TESTING_CMD_SUB_DONE. */ 311 struct 312 { 313 uint32_t c; 314 } Error, Term, SubDone; 315 316 /** VMMDEV_TESTING_CMD_VALUE. */ 317 struct 318 { 319 RTUINT64U u64Value; 320 uint32_t u32Unit; 321 char szName[1024 - 8 - 4]; 322 } Value; 323 324 /** The read back register (VMMDEV_TESTING_MMIO_OFF_READBACK, 325 * VMMDEV_TESTING_MMIO_OFF_READBACK_R3). */ 326 uint8_t abReadBack[VMMDEV_TESTING_READBACK_SIZE]; 327 } TestingData; 328 /** The locking testing control dword. */ 329 union 330 { 331 /** Plain view. */ 332 uint64_t u64; 333 /** Plain 32-bit view. */ 334 uint32_t au32[2]; 335 struct 336 { 337 /** bits 15:0: Number of microseconds to hold the lock. */ 338 uint32_t cUsHold : 16; 339 /** bits 31:16: Number of microseconds to wait before retaking the lock again. */ 340 uint32_t cUsBetween : 16; 341 /** bits 51:32: Kilo (1024) ticks the EMT should hold the lock for. */ 342 uint32_t cKiloTicksEmtHold : 20; 343 /** bits 57:52: Reserved MBZ. */ 344 uint32_t uReserved : 6; 345 /** bit 58: Thread takes lock in shared mode when set, exclusive when clear. */ 346 uint32_t fThreadShared : 1; 347 /** bit 59: EMT takes lock in shared mode when set, exclusive when clear. */ 348 uint32_t fEmtShared : 1; 349 /** bit 60: Use read/write critical section instead of regular. */ 350 uint32_t fReadWriteSection : 1; 351 /** bit 61: EMT passes VINF_SUCCESS as rcBusy if set. */ 352 uint32_t fMustSucceed : 1; 353 /** bit 62: Thread pokes EMTs before releasing it when set. */ 354 uint32_t fPokeBeforeRelease : 1; 355 /** bit 63: Enabled/disabled. */ 356 uint32_t fEnabled : 1; 357 } s; 358 } TestingLockControl; 359 /** Event semaphore that the locking thread blocks. */ 360 SUPSEMEVENT hTestingLockEvt; 361 # if HC_ARCH_BITS == 32 362 uint32_t uPadding10; 363 # endif 364 /** Handle for the I/O ports used by the testing component. */ 365 IOMIOPORTHANDLE hIoPortTesting; 366 /** Handle for the MMIO region used by the testing component. */ 367 IOMMMIOHANDLE hMmioTesting; 368 /** Read write critical section of lock testing. */ 369 PDMCRITSECTRW CritSectRw; 370 #endif /* !VBOX_WITHOUT_TESTING_FEATURES || DOXYGEN_RUNNING */ 356 371 /** @} */ 357 372 -
trunk/src/VBox/Devices/VMMDev/VMMDevTesting.cpp
r90467 r90503 38 38 # include <VBox/vmm/vmcc.h> 39 39 #endif 40 #include <VBox/AssertGuest.h> 40 41 41 42 #include "VMMDevState.h" … … 592 593 * Configure the locking contention test. 593 594 */ 594 case VMMDEV_TESTING_IOPORT_LOCKED - VMMDEV_TESTING_IOPORT_BASE: 595 case VMMDEV_TESTING_IOPORT_LOCKED_HI - VMMDEV_TESTING_IOPORT_BASE: 596 case VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE: 595 597 switch (cb) 596 598 { 597 599 case 4: 600 { 601 bool const fReadWriteSection = pThis->TestingLockControl.s.fReadWriteSection; 602 int rc; 603 #ifndef IN_RING3 604 if (!pThis->TestingLockControl.s.fMustSucceed) 605 { 606 if (!fReadWriteSection) 607 rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE); 608 else 609 rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_IOM_R3_IOPORT_WRITE); 610 if (rc != VINF_SUCCESS) 611 return rc; 612 } 613 else 614 #endif 615 { 616 if (!fReadWriteSection) 617 rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS); 618 else 619 rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_SUCCESS); 620 AssertRCReturn(rc, rc); 621 } 622 623 if (offPort == VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE) 624 { 625 if (pThis->TestingLockControl.au32[0] != u32) 626 { 627 pThis->TestingLockControl.au32[0] = u32; 628 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTestingLockEvt); 629 } 630 } 631 else 632 { 633 u32 &= ~VMMDEV_TESTING_LOCKED_HI_MBZ_MASK; 634 if (pThis->TestingLockControl.au32[1] != u32) 635 { 636 pThis->TestingLockControl.au32[1] = u32; 637 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTestingLockEvt); 638 } 639 } 640 641 if (!fReadWriteSection) 642 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); 643 else 644 PDMDevHlpCritSectRwLeaveExcl(pDevIns, &pThis->CritSectRw); 645 return VINF_SUCCESS; 646 } 647 598 648 case 2: 599 649 case 1: 600 { 601 #ifndef IN_RING3 602 if (!pThis->TestingLockControl.s.fMustSucceed) 603 { 604 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_WRITE); 605 if (rc != VINF_SUCCESS) 606 return rc; 607 } 608 else 609 #endif 610 { 611 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS); 612 AssertRCReturn(rc, rc); 613 } 614 615 u32 &= ~VMMDEV_TESTING_LOCKED_MBZ_MASK; 616 if (pThis->TestingLockControl.u32 != u32) 617 { 618 pThis->TestingLockControl.u32 = u32; 619 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hTestingLockEvt); 620 } 621 622 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); 623 return VINF_SUCCESS; 624 } 650 ASSERT_GUEST_FAILED(); 651 break; 625 652 626 653 default: … … 711 738 * acquiring the lock of course. 712 739 */ 713 case VMMDEV_TESTING_IOPORT_LOCKED - VMMDEV_TESTING_IOPORT_BASE: 740 case VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE: 741 case VMMDEV_TESTING_IOPORT_LOCKED_HI - VMMDEV_TESTING_IOPORT_BASE: 714 742 switch (cb) 715 743 { … … 718 746 case 1: 719 747 { 748 /* 749 * Check configuration and enter the designation critical 750 * section in the specific fashion. 751 */ 752 bool const fReadWriteSection = pThis->TestingLockControl.s.fReadWriteSection; 753 bool const fEmtShared = pThis->TestingLockControl.s.fEmtShared; 754 int rc; 720 755 #ifndef IN_RING3 721 756 if (!pThis->TestingLockControl.s.fMustSucceed) 722 757 { 723 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_READ); 758 if (!fReadWriteSection) 759 rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_IOM_R3_IOPORT_READ); 760 else if (!fEmtShared) 761 rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_IOM_R3_IOPORT_READ); 762 else 763 rc = PDMDevHlpCritSectRwEnterShared(pDevIns, &pThis->CritSectRw, VINF_IOM_R3_IOPORT_READ); 724 764 if (rc != VINF_SUCCESS) 725 765 return rc; … … 728 768 #endif 729 769 { 730 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS); 770 if (!fReadWriteSection) 771 rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VINF_SUCCESS); 772 else if (!fEmtShared) 773 rc = PDMDevHlpCritSectRwEnterExcl(pDevIns, &pThis->CritSectRw, VINF_SUCCESS); 774 else 775 rc = PDMDevHlpCritSectRwEnterShared(pDevIns, &pThis->CritSectRw, VINF_SUCCESS); 731 776 AssertRCReturn(rc, rc); 732 777 } 733 778 734 *pu32 = pThis->TestingLockControl.u32; 735 736 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); 779 /* 780 * Grab return value and, if requested, hold for a while. 781 */ 782 *pu32 = pThis->TestingLockControl.au32[ offPort 783 - (VMMDEV_TESTING_IOPORT_LOCKED_LO - VMMDEV_TESTING_IOPORT_BASE)]; 784 uint64_t cTicks = (uint64_t)pThis->TestingLockControl.s.cKiloTicksEmtHold * _1K; 785 if (cTicks) 786 { 787 uint64_t const uStartTick = ASMReadTSC(); 788 do 789 { 790 ASMNopPause(); 791 ASMNopPause(); 792 } while (ASMReadTSC() - uStartTick < cTicks); 793 } 794 795 /* 796 * Leave. 797 */ 798 if (!fReadWriteSection) 799 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); 800 else if (!fEmtShared) 801 PDMDevHlpCritSectRwLeaveExcl(pDevIns, &pThis->CritSectRw); 802 else 803 PDMDevHlpCritSectRwLeaveShared(pDevIns, &pThis->CritSectRw); 737 804 return VINF_SUCCESS; 738 805 } … … 868 935 } 869 936 870 871 937 /* 872 938 * Register the I/O ports used for testing. … … 875 941 vmmdevTestingIoWrite, vmmdevTestingIoRead, "VMMDev Testing", NULL /*paExtDescs*/, 876 942 &pThis->hIoPortTesting); 943 AssertRCReturn(rc, rc); 944 945 /* 946 * Initialize the read/write critical section used for the locking tests. 947 */ 948 rc = PDMDevHlpCritSectRwInit(pDevIns, &pThis->CritSectRw, RT_SRC_POS, "VMMLockRW"); 877 949 AssertRCReturn(rc, rc); 878 950
Note:
See TracChangeset
for help on using the changeset viewer.