Changeset 80641 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Sep 6, 2019 8:09:16 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 133172
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 1 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/Makefile.kmk
r80335 r80641 484 484 VMMR0/HMVMXR0.cpp \ 485 485 VMMR0/HMSVMR0.cpp \ 486 VMMR0/IOMR0.cpp \ 486 487 VMMR0/PDMR0Device.cpp \ 487 488 VMMR0/PDMR0Driver.cpp \ -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
r80089 r80641 1158 1158 IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_ins_op,OP_SIZE,_addr,ADDR_SIZE), bool, fIoChecked) 1159 1159 { 1160 PVM 1160 PVMCC pVM = pVCpu->CTX_SUFF(pVM); 1161 1161 VBOXSTRICTRC rcStrict; 1162 1162 … … 1250 1250 IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_rep_ins_op,OP_SIZE,_addr,ADDR_SIZE), bool, fIoChecked) 1251 1251 { 1252 PVM pVM = pVCpu->CTX_SUFF(pVM);1252 PVMCC pVM = pVCpu->CTX_SUFF(pVM); 1253 1253 1254 1254 IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_ES | CPUMCTX_EXTRN_TR); … … 1467 1467 IEM_CIMPL_DEF_2(RT_CONCAT4(iemCImpl_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg, bool, fIoChecked) 1468 1468 { 1469 PVM 1469 PVMCC pVM = pVCpu->CTX_SUFF(pVM); 1470 1470 VBOXSTRICTRC rcStrict; 1471 1471 … … 1540 1540 IEM_CIMPL_DEF_2(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg, bool, fIoChecked) 1541 1541 { 1542 PVM pVM = pVCpu->CTX_SUFF(pVM);1542 PVMCC pVM = pVCpu->CTX_SUFF(pVM); 1543 1543 1544 1544 /* -
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r80333 r80641 75 75 * @param cbValue The size of the register to read in bytes. 1, 2 or 4 bytes. 76 76 */ 77 VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)77 VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue) 78 78 { 79 79 Assert(pVCpu->iom.s.PendingIOPortWrite.cbValue == 0); … … 81 81 /** @todo should initialize *pu32Value here because it can happen that some 82 82 * handle is buggy and doesn't handle all cases. */ 83 /* Take the IOM lock before performing any device I/O. */ 83 84 /* For lookups we need to share lock IOM. */ 84 85 int rc2 = IOM_LOCK_SHARED(pVM); 85 86 #ifndef IN_RING3 … … 88 89 #endif 89 90 AssertRC(rc2); 91 92 /* 93 * Get the entry for the current context. 94 */ 95 CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, Port, &pVCpu->iom.s.idxIoPortLastRead); 96 if (pRegEntry) 97 { 98 #ifdef VBOX_WITH_STATISTICS 99 PIOMIOPORTSTATSENTRY pStats = iomIoPortGetStats(pVM, pRegEntry); 100 #endif 101 102 /* 103 * Found an entry, get the data so we can leave the IOM lock. 104 */ 105 PFNIOMIOPORTIN pfnInCallback = pRegEntry->pfnInCallback; 106 PPDMDEVINS pDevIns = pRegEntry->pDevIns; 107 #ifndef IN_RING3 108 if ( pfnInCallback 109 && pDevIns 110 && pRegEntry->cPorts > 0) 111 { /* likely */ } 112 else 113 { 114 STAM_COUNTER_INC(&pStats->InRZToR3); 115 IOM_UNLOCK_SHARED(pVM); 116 return VINF_IOM_R3_IOPORT_READ; 117 } 118 #endif 119 void *pvUser = pRegEntry->pvUser; 120 IOM_UNLOCK_SHARED(pVM); 121 AssertPtr(pDevIns); 122 AssertPtr(pfnInCallback); 123 124 /* 125 * Call the device. 126 */ 127 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ); 128 if (rcStrict == VINF_SUCCESS) 129 { 130 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a); 131 rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue); 132 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a); 133 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 134 135 if (rcStrict == VINF_SUCCESS) 136 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In)); 137 #ifndef IN_RING3 138 else if (rcStrict == VINF_IOM_R3_IOPORT_READ) 139 STAM_COUNTER_INC(&pStats->InRZToR3); 140 #endif 141 else if (rcStrict == VERR_IOM_IOPORT_UNUSED) 142 { 143 /* make return value */ 144 rcStrict = VINF_SUCCESS; 145 switch (cbValue) 146 { 147 case 1: *(uint8_t *)pu32Value = 0xff; break; 148 case 2: *(uint16_t *)pu32Value = 0xffff; break; 149 case 4: *(uint32_t *)pu32Value = UINT32_C(0xffffffff); break; 150 default: 151 AssertMsgFailedReturn(("Invalid I/O port size %d. Port=%d\n", cbValue, Port), VERR_IOM_INVALID_IOPORT_SIZE); 152 } 153 } 154 Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=%Rrc\n", Port, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict))); 155 } 156 else 157 STAM_COUNTER_INC(&pStats->InRZToR3); 158 return rcStrict; 159 } 160 161 /* 162 * Old code 163 * Old code 164 * Old code 165 */ 90 166 91 167 #ifdef VBOX_WITH_STATISTICS … … 242 318 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 243 319 */ 244 VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort,320 VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortReadString(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uPort, 245 321 void *pvDst, uint32_t *pcTransfers, unsigned cb) 246 322 { 247 323 Assert(pVCpu->iom.s.PendingIOPortWrite.cbValue == 0); 248 324 249 /* Take the IOM lock before performing any device I/O. */325 /* For lookups we need to share lock IOM. */ 250 326 int rc2 = IOM_LOCK_SHARED(pVM); 251 327 #ifndef IN_RING3 … … 257 333 const uint32_t cRequestedTransfers = *pcTransfers; 258 334 Assert(cRequestedTransfers > 0); 335 336 /* 337 * Get the entry for the current context. 338 */ 339 CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, uPort, &pVCpu->iom.s.idxIoPortLastReadStr); 340 if (pRegEntry) 341 { 342 #ifdef VBOX_WITH_STATISTICS 343 PIOMIOPORTSTATSENTRY pStats = iomIoPortGetStats(pVM, pRegEntry); 344 #endif 345 346 /* 347 * Found an entry, get the data so we can leave the IOM lock. 348 */ 349 PFNIOMIOPORTINSTRING pfnInStrCallback = pRegEntry->pfnInStrCallback; 350 PFNIOMIOPORTIN pfnInCallback = pRegEntry->pfnInCallback; 351 PPDMDEVINS pDevIns = pRegEntry->pDevIns; 352 #ifndef IN_RING3 353 if ( pfnInCallback 354 && pDevIns 355 && pRegEntry->cPorts > 0) 356 { /* likely */ } 357 else 358 { 359 STAM_COUNTER_INC(&pStats->InRZToR3); 360 IOM_UNLOCK_SHARED(pVM); 361 return VINF_IOM_R3_IOPORT_READ; 362 } 363 #endif 364 void *pvUser = pRegEntry->pvUser; 365 IOM_UNLOCK_SHARED(pVM); 366 AssertPtr(pDevIns); 367 AssertPtr(pfnInCallback); 368 369 /* 370 * Call the device. 371 */ 372 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ); 373 if (rcStrict == VINF_SUCCESS) 374 { 375 /* 376 * First using the string I/O callback. 377 */ 378 if (pfnInStrCallback) 379 { 380 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a); 381 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb); 382 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a); 383 } 384 385 /* 386 * Then doing the single I/O fallback. 387 */ 388 if ( *pcTransfers > 0 389 && rcStrict == VINF_SUCCESS) 390 { 391 pvDst = (uint8_t *)pvDst + (cRequestedTransfers - *pcTransfers) * cb; 392 do 393 { 394 uint32_t u32Value = 0; 395 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a); 396 rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb); 397 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a); 398 if (rcStrict == VERR_IOM_IOPORT_UNUSED) 399 { 400 u32Value = UINT32_MAX; 401 rcStrict = VINF_SUCCESS; 402 } 403 if (IOM_SUCCESS(rcStrict)) 404 { 405 switch (cb) 406 { 407 case 4: *(uint32_t *)pvDst = u32Value; pvDst = (uint8_t *)pvDst + 4; break; 408 case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break; 409 case 1: *(uint8_t *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break; 410 default: AssertFailed(); 411 } 412 *pcTransfers -= 1; 413 } 414 } while ( *pcTransfers > 0 415 && rcStrict == VINF_SUCCESS); 416 } 417 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 418 419 #ifdef VBOX_WITH_STATISTICS 420 if (rcStrict == VINF_SUCCESS && pStats) 421 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In)); 422 # ifndef IN_RING3 423 else if (rcStrict == VINF_IOM_R3_IOPORT_READ && pStats) 424 STAM_COUNTER_INC(&pStats->InRZToR3); 425 # endif 426 #endif 427 Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n", 428 uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict))); 429 } 430 #ifndef IN_RING3 431 else 432 STAM_COUNTER_INC(&pStats->InRZToR3); 433 #endif 434 return rcStrict; 435 } 436 437 /* 438 * Old code 439 * Old code 440 * Old code 441 */ 259 442 260 443 #ifdef VBOX_WITH_STATISTICS … … 458 641 * @param cbValue The size of the register to read in bytes. 1, 2 or 4 bytes. 459 642 */ 460 VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue)643 VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVMCC pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue) 461 644 { 462 645 #ifndef IN_RING3 … … 464 647 #endif 465 648 466 /* Take the IOM lock before performing any device I/O. */649 /* For lookups we need to share lock IOM. */ 467 650 int rc2 = IOM_LOCK_SHARED(pVM); 468 651 #ifndef IN_RING3 … … 472 655 AssertRC(rc2); 473 656 474 /** @todo bird: When I get time, I'll remove the RC/R0 trees and link the RC/R0 475 * entries to the ring-3 node. */ 657 /* 658 * Get the entry for the current context. 659 */ 660 CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, Port, &pVCpu->iom.s.idxIoPortLastWrite); 661 if (pRegEntry) 662 { 663 #ifdef VBOX_WITH_STATISTICS 664 PIOMIOPORTSTATSENTRY pStats = iomIoPortGetStats(pVM, pRegEntry); 665 #endif 666 667 /* 668 * Found an entry, get the data so we can leave the IOM lock. 669 */ 670 PFNIOMIOPORTOUT pfnOutCallback = pRegEntry->pfnOutCallback; 671 PPDMDEVINS pDevIns = pRegEntry->pDevIns; 672 #ifndef IN_RING3 673 if ( pfnOutCallback 674 && pDevIns 675 && pRegEntry->cPorts > 0) 676 { /* likely */ } 677 else 678 { 679 IOM_UNLOCK_SHARED(pVM); 680 STAM_COUNTER_INC(&pStats->OutRZToR3); 681 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue); 682 } 683 #endif 684 void *pvUser = pRegEntry->pvUser; 685 IOM_UNLOCK_SHARED(pVM); 686 AssertPtr(pDevIns); 687 AssertPtr(pfnOutCallback); 688 689 /* 690 * Call the device. 691 */ 692 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE); 693 if (rcStrict == VINF_SUCCESS) 694 { 695 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a); 696 rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue); 697 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a); 698 699 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 700 701 #ifdef VBOX_WITH_STATISTICS 702 if (rcStrict == VINF_SUCCESS) 703 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out)); 704 #endif 705 Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d rc=%Rrc\n", Port, u32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict))); 706 } 707 #ifndef IN_RING3 708 if (rcStrict == VINF_IOM_R3_IOPORT_WRITE) 709 { 710 STAM_COUNTER_INC(&pStats->OutRZToR3); 711 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue); 712 } 713 #endif 714 return rcStrict; 715 } 716 717 /* 718 * Old code 719 * Old code 720 * Old code 721 */ 722 476 723 #ifdef VBOX_WITH_STATISTICS 477 724 /* … … 611 858 * @param cb Size of the transfer unit (1, 2 or 4 bytes). 612 859 */ 613 VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc,860 VMM_INT_DECL(VBOXSTRICTRC) IOMIOPortWriteString(PVMCC pVM, PVMCPU pVCpu, RTIOPORT uPort, void const *pvSrc, 614 861 uint32_t *pcTransfers, unsigned cb) 615 862 { … … 627 874 const uint32_t cRequestedTransfers = *pcTransfers; 628 875 Assert(cRequestedTransfers > 0); 876 877 /* 878 * Get the entry for the current context. 879 */ 880 CTX_SUFF(PIOMIOPORTENTRY) pRegEntry = iomIoPortGetEntry(pVM, uPort, &pVCpu->iom.s.idxIoPortLastWriteStr); 881 if (pRegEntry) 882 { 883 #ifdef VBOX_WITH_STATISTICS 884 PIOMIOPORTSTATSENTRY pStats = iomIoPortGetStats(pVM, pRegEntry); 885 #endif 886 887 /* 888 * Found an entry, get the data so we can leave the IOM lock. 889 */ 890 PFNIOMIOPORTOUTSTRING pfnOutStrCallback = pRegEntry->pfnOutStrCallback; 891 PFNIOMIOPORTOUT pfnOutCallback = pRegEntry->pfnOutCallback; 892 PPDMDEVINS pDevIns = pRegEntry->pDevIns; 893 #ifndef IN_RING3 894 if ( pfnOutCallback 895 && pDevIns 896 && pRegEntry->cPorts > 0) 897 { /* likely */ } 898 else 899 { 900 IOM_UNLOCK_SHARED(pVM); 901 STAM_COUNTER_INC(&pStats->OutRZToR3); 902 return VINF_IOM_R3_IOPORT_WRITE; 903 } 904 #endif 905 void *pvUser = pRegEntry->pvUser; 906 IOM_UNLOCK_SHARED(pVM); 907 AssertPtr(pDevIns); 908 AssertPtr(pfnOutCallback); 909 910 /* 911 * Call the device. 912 */ 913 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE); 914 if (rcStrict == VINF_SUCCESS) 915 { 916 /* 917 * First using string I/O if possible. 918 */ 919 if (pfnOutStrCallback) 920 { 921 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a); 922 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb); 923 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a); 924 } 925 926 /* 927 * Then doing the single I/O fallback. 928 */ 929 if ( *pcTransfers > 0 930 && rcStrict == VINF_SUCCESS) 931 { 932 pvSrc = (uint8_t *)pvSrc + (cRequestedTransfers - *pcTransfers) * cb; 933 do 934 { 935 uint32_t u32Value; 936 switch (cb) 937 { 938 case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break; 939 case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break; 940 case 1: u32Value = *(uint8_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 1; break; 941 default: AssertFailed(); u32Value = UINT32_MAX; 942 } 943 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a); 944 rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb); 945 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a); 946 if (IOM_SUCCESS(rcStrict)) 947 *pcTransfers -= 1; 948 } while ( *pcTransfers > 0 949 && rcStrict == VINF_SUCCESS); 950 } 951 952 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo)); 953 954 #ifdef VBOX_WITH_STATISTICS 955 if (rcStrict == VINF_SUCCESS) 956 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out)); 957 # ifndef IN_RING3 958 else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE) 959 STAM_COUNTER_INC(&pStats->OutRZToR3); 960 # endif 961 #endif 962 Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n", 963 uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict))); 964 } 965 #ifndef IN_RING3 966 else 967 STAM_COUNTER_INC(&pStats->OutRZToR3); 968 #endif 969 return rcStrict; 970 } 971 972 /* 973 * Old code. 974 * Old code. 975 * Old code. 976 */ 629 977 630 978 #ifdef VBOX_WITH_STATISTICS -
trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
r80531 r80641 54 54 #include <VBox/vmm/gmm.h> 55 55 #include "GVMMR0Internal.h" 56 #include <VBox/vmm/iom.h> 56 57 #include <VBox/vmm/pdm.h> 57 #include <VBox/vmm/vmcc.h>58 #include <VBox/vmm/vmcpuset.h>59 58 #include <VBox/vmm/vmm.h> 60 59 #ifdef VBOX_WITH_NEM_R0 61 60 # include <VBox/vmm/nem.h> 62 61 #endif 62 #include <VBox/vmm/vmcpuset.h> 63 #include <VBox/vmm/vmcc.h> 63 64 #include <VBox/param.h> 64 65 #include <VBox/err.h> … … 903 904 GMMR0InitPerVMData(pGVM); 904 905 PDMR0InitPerVMData(pGVM); 906 IOMR0InitPerVMData(pGVM); 905 907 pGVM->gvmm.s.VMMemObj = hVMMemObj; 906 908 … … 1294 1296 #endif 1295 1297 PDMR0CleanupVM(pGVM); 1298 IOMR0CleanupVM(pGVM); 1296 1299 1297 1300 AssertCompile(NIL_RTTHREADCTXHOOK == (RTTHREADCTXHOOK)0); /* Depends on zero initialized memory working for NIL at the moment. */ -
trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp
r80548 r80641 195 195 void *pvUser) 196 196 { 197 RT_NOREF(pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser); 198 return VERR_NOT_IMPLEMENTED; 197 PDMDEV_ASSERT_DEVINS(pDevIns); 198 LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: hIoPorts=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p\n", 199 pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser)); 200 PGVM pGVM = pDevIns->Internal.s.pGVM; 201 VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT); 202 VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE); 203 204 int rc = IOMR0IoPortSetUpContext(pGVM, pDevIns, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser); 205 206 LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc)); 207 return rc; 199 208 } 200 209 -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r80587 r80641 23 23 #include <VBox/vmm/vmm.h> 24 24 #include <VBox/sup.h> 25 #include <VBox/vmm/iom.h> 25 26 #include <VBox/vmm/trpm.h> 26 27 #include <VBox/vmm/cpum.h> … … 2198 2199 2199 2200 /* 2201 * IOM requests. 2202 */ 2203 case VMMR0_DO_IOM_GROW_IO_PORTS: 2204 { 2205 if (pReqHdr || idCpu != 0) 2206 return VERR_INVALID_PARAMETER; 2207 rc = IOMR0IoPortGrowRegistrationTables(pGVM, u64Arg); 2208 VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING); 2209 break; 2210 } 2211 2212 case VMMR0_DO_IOM_GROW_IO_PORT_STATS: 2213 { 2214 if (pReqHdr || idCpu != 0) 2215 return VERR_INVALID_PARAMETER; 2216 rc = IOMR0IoPortGrowStatisticsTable(pGVM, u64Arg); 2217 VMM_CHECK_SMAP_CHECK2(pGVM, RT_NOTHING); 2218 break; 2219 } 2220 2221 /* 2200 2222 * For profiling. 2201 2223 */ … … 2296 2318 2297 2319 case VMMR0_DO_PDM_DEVICE_CREATE: 2320 case VMMR0_DO_IOM_GROW_IO_PORTS: 2321 case VMMR0_DO_IOM_GROW_IO_PORT_STATS: 2298 2322 { 2299 2323 PGVMCPU pGVCpu = &pGVM->aCpus[idCpu]; -
trunk/src/VBox/VMM/VMMR3/IOM.cpp
r80531 r80641 230 230 STAM_REG(pVM, &pVM->iom.s.StatRZInstOther, STAMTYPE_COUNTER, "/IOM/RZ-MMIOHandler/Inst/Other", STAMUNIT_OCCURENCES, "Other instructions counter."); 231 231 STAM_REG(pVM, &pVM->iom.s.StatR3MMIOHandler, STAMTYPE_COUNTER, "/IOM/R3-MMIOHandler", STAMUNIT_OCCURENCES, "Number of calls to iomR3MmioHandler."); 232 #if 0 /* unused */ 232 233 STAM_REG(pVM, &pVM->iom.s.StatInstIn, STAMTYPE_COUNTER, "/IOM/IOWork/In", STAMUNIT_OCCURENCES, "Counter of any IN instructions."); 233 234 STAM_REG(pVM, &pVM->iom.s.StatInstOut, STAMTYPE_COUNTER, "/IOM/IOWork/Out", STAMUNIT_OCCURENCES, "Counter of any OUT instructions."); 234 235 STAM_REG(pVM, &pVM->iom.s.StatInstIns, STAMTYPE_COUNTER, "/IOM/IOWork/Ins", STAMUNIT_OCCURENCES, "Counter of any INS instructions."); 235 236 STAM_REG(pVM, &pVM->iom.s.StatInstOuts, STAMTYPE_COUNTER, "/IOM/IOWork/Outs", STAMUNIT_OCCURENCES, "Counter of any OUTS instructions."); 237 #endif 236 238 } 237 239 } … … 413 415 return VINF_SUCCESS; 414 416 } 417 418 419 /** 420 * Worker for PDMDEVHLPR3::pfnIoPortCreateEx. 421 */ 422 VMMR3_INT_DECL(int) IOMR3IoPortCreate(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev, 423 uint32_t iPciRegion, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn, 424 PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, RTR3PTR pvUser, 425 const char *pszDesc, PIOMIOPORTHANDLE phIoPorts) 426 { 427 /* 428 * Validate input. 429 */ 430 AssertPtrReturn(phIoPorts, VERR_INVALID_POINTER); 431 *phIoPorts = UINT32_MAX; 432 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); 433 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE); 434 435 AssertPtrReturn(pDevIns, VERR_INVALID_POINTER); 436 437 AssertMsgReturn(cPorts > 0 && cPorts <= _8K, ("cPorts=%s\n", cPorts), VERR_OUT_OF_RANGE); 438 AssertReturn(!fFlags, VERR_INVALID_FLAGS); 439 440 AssertReturn(pfnOut || pfnIn || pfnOutStr || pfnInStr, VERR_INVALID_PARAMETER); 441 AssertPtrNullReturn(pfnOut, VERR_INVALID_POINTER); 442 AssertPtrNullReturn(pfnIn, VERR_INVALID_POINTER); 443 AssertPtrNullReturn(pfnOutStr, VERR_INVALID_POINTER); 444 AssertPtrNullReturn(pfnInStr, VERR_INVALID_POINTER); 445 AssertPtrReturn(pszDesc, VERR_INVALID_POINTER); 446 AssertReturn(*pszDesc != '\0', VERR_INVALID_POINTER); 447 AssertReturn(strlen(pszDesc) < 128, VERR_INVALID_POINTER); 448 449 /* 450 * Ensure that we've got table space for it. 451 */ 452 #ifndef VBOX_WITH_STATISTICS 453 uint16_t const idxStats = UINT16_MAX; 454 #else 455 uint32_t const idxStats = pVM->iom.s.cIoPortStats; 456 uint32_t const cNewIoPortStats = idxStats + cPorts; 457 AssertReturn(cNewIoPortStats <= _64K, VERR_IOM_TOO_MANY_IOPORT_REGISTRATIONS); 458 if (cNewIoPortStats > pVM->iom.s.cIoPortStatsAllocation) 459 { 460 int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORT_STATS, cNewIoPortStats, NULL); 461 AssertLogRelRCReturn(rc, rc); 462 AssertReturn(idxStats == pVM->iom.s.cIoPortStats, VERR_IOM_IOPORT_IPE_1); 463 AssertReturn(cNewIoPortStats <= pVM->iom.s.cIoPortStatsAllocation, VERR_IOM_IOPORT_IPE_2); 464 } 465 #endif 466 467 uint32_t idx = pVM->iom.s.cIoPortRegs; 468 if (idx >= pVM->iom.s.cIoPortAlloc) 469 { 470 int rc = VMMR3CallR0Emt(pVM, pVM->apCpusR3[0], VMMR0_DO_IOM_GROW_IO_PORTS, pVM->iom.s.cIoPortAlloc + 1, NULL); 471 AssertLogRelRCReturn(rc, rc); 472 AssertReturn(idx == pVM->iom.s.cIoPortRegs, VERR_IOM_IOPORT_IPE_1); 473 AssertReturn(idx < pVM->iom.s.cIoPortAlloc, VERR_IOM_IOPORT_IPE_2); 474 } 475 476 /* 477 * Enter it. 478 */ 479 pVM->iom.s.paIoPortRegs[idx].pvUser = pvUser; 480 pVM->iom.s.paIoPortRegs[idx].pDevIns = pDevIns; 481 pVM->iom.s.paIoPortRegs[idx].pfnOutCallback = pfnOut ? pfnOut : iomR3IOPortDummyOut; 482 pVM->iom.s.paIoPortRegs[idx].pfnInCallback = pfnIn ? pfnIn : iomR3IOPortDummyIn; 483 pVM->iom.s.paIoPortRegs[idx].pfnOutStrCallback = pfnOutStr ? pfnOutStr : iomR3IOPortDummyOutStr; 484 pVM->iom.s.paIoPortRegs[idx].pfnInStrCallback = pfnInStr ? pfnInStr : iomR3IOPortDummyInStr; 485 pVM->iom.s.paIoPortRegs[idx].pszDesc = pszDesc; 486 pVM->iom.s.paIoPortRegs[idx].pPciDev = pPciDev; 487 pVM->iom.s.paIoPortRegs[idx].iPciRegion = iPciRegion; 488 pVM->iom.s.paIoPortRegs[idx].cPorts = cPorts; 489 pVM->iom.s.paIoPortRegs[idx].uPort = UINT16_MAX; 490 pVM->iom.s.paIoPortRegs[idx].idxStats = (uint16_t)idxStats; 491 pVM->iom.s.paIoPortRegs[idx].fMapped = false; 492 pVM->iom.s.paIoPortRegs[idx].idxSelf = idx; 493 494 pVM->iom.s.cIoPortRegs = idx + 1; 495 *phIoPorts = idx; 496 return VINF_SUCCESS; 497 } 498 499 500 /** 501 * Worker for PDMDEVHLPR3::pfnIoPortMap. 502 */ 503 VMMR3_INT_DECL(int) IOMR3IoPortMap(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT uPort) 504 { 505 /* 506 * Validate input and state. 507 */ 508 AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE); 509 AssertReturn(hIoPorts < pVM->iom.s.cIoPortRegs, VERR_IOM_INVALID_IOPORT_HANDLE); 510 PIOMIOPORTENTRYR3 const pRegEntry = &pVM->iom.s.paIoPortRegs[hIoPorts]; 511 AssertReturn(pRegEntry->pDevIns == pDevIns, VERR_IOM_INVALID_IOPORT_HANDLE); 512 513 RTIOPORT const cPorts = pRegEntry->cPorts; 514 AssertMsgReturn(cPorts > 0 && cPorts <= _8K, ("cPorts=%s\n", cPorts), VERR_IOM_IOPORT_IPE_1); 515 AssertReturn((uint32_t)uPort + cPorts <= _64K, VERR_OUT_OF_RANGE); 516 RTIOPORT const uLastPort = uPort + cPorts - 1; 517 518 /* 519 * Do the mapping. 520 */ 521 int rc = VINF_SUCCESS; 522 IOM_LOCK_EXCL(pVM); 523 524 if (!pRegEntry->fMapped) 525 { 526 uint32_t const cEntries = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iom.s.cIoPortRegs); 527 Assert(pVM->iom.s.cIoPortLookupEntries == cEntries); 528 529 PIOMIOPORTLOOKUPENTRY paEntries = pVM->iom.s.paIoPortLookup; 530 PIOMIOPORTLOOKUPENTRY pEntry; 531 if (cEntries > 0) 532 { 533 uint32_t iFirst = 0; 534 uint32_t iEnd = cEntries; 535 uint32_t i = cEntries / 2; 536 for (;;) 537 { 538 pEntry = &paEntries[i]; 539 if (pEntry->uLastPort < uPort) 540 { 541 i += 1; 542 if (i < iEnd) 543 iFirst = i; 544 else 545 { 546 /* Insert after the entry we just considered: */ 547 pEntry += 1; 548 if (iEnd < cEntries) 549 memmove(pEntry + 1, pEntry, sizeof(*pEntry) * (cEntries - iEnd)); 550 break; 551 } 552 } 553 else if (pEntry->uFirstPort > uLastPort) 554 { 555 if (i > iFirst) 556 iEnd = i; 557 else 558 { 559 /* Insert at the entry we just considered: */ 560 if (iEnd < cEntries) 561 memmove(pEntry + 1, pEntry, sizeof(*pEntry) * (cEntries - iEnd)); 562 break; 563 } 564 } 565 else 566 { 567 /* Oops! We've got a conflict. */ 568 AssertLogRelMsgFailed(("%u..%u (%s) conflicts with existing mapping %u..%u (%s)\n", 569 uPort, uLastPort, pRegEntry->pszDesc, 570 pEntry->uFirstPort, pEntry->uLastPort, pVM->iom.s.paIoPortRegs[pEntry->idx].pszDesc)); 571 IOM_UNLOCK_EXCL(pVM); 572 return VERR_IOM_IOPORT_RANGE_CONFLICT; 573 } 574 575 i = iFirst + (iEnd - iFirst) / 2; 576 } 577 } 578 else 579 pEntry = paEntries; 580 581 /* 582 * Fill in the entry and bump the table size. 583 */ 584 pEntry->idx = hIoPorts; 585 pEntry->uFirstPort = uPort; 586 pEntry->uLastPort = uLastPort; 587 pVM->iom.s.cIoPortLookupEntries = cEntries + 1; 588 589 pRegEntry->uPort = uPort; 590 pRegEntry->fMapped = true; 591 592 #ifdef VBOX_STRICT 593 /* 594 * Assert table sanity. 595 */ 596 AssertMsg(paEntries[0].uLastPort >= paEntries[0].uFirstPort, ("%#x %#x\n", paEntries[0].uLastPort, paEntries[0].uFirstPort)); 597 AssertMsg(paEntries[0].idx < pVM->iom.s.cIoPortRegs, ("%#x %#x\n", paEntries[0].idx, pVM->iom.s.cIoPortRegs)); 598 599 RTIOPORT uPortPrev = paEntries[0].uLastPort; 600 for (size_t i = 1; i <= cEntries; i++) 601 { 602 AssertMsg(paEntries[i].uLastPort >= paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, paEntries[i].uLastPort, paEntries[i].uFirstPort)); 603 AssertMsg(paEntries[i].idx < pVM->iom.s.cIoPortRegs, ("%u: %#x %#x\n", i, paEntries[i].idx, pVM->iom.s.cIoPortRegs)); 604 AssertMsg(uPortPrev < paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, uPortPrev, paEntries[i].uFirstPort)); 605 uPortPrev = paEntries[i].uLastPort; 606 } 607 #endif 608 } 609 else 610 { 611 AssertFailed(); 612 rc = VERR_IOM_IOPORTS_ALREADY_MAPPED; 613 } 614 615 IOM_UNLOCK_EXCL(pVM); 616 return rc; 617 } 618 619 620 /** 621 * Worker for PDMDEVHLPR3::pfnIoPortUnmap. 622 */ 623 VMMR3_INT_DECL(int) IOMR3IoPortUnmap(PVM pVM, PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts) 624 { 625 /* 626 * Validate input and state. 627 */ 628 AssertPtrReturn(pDevIns, VERR_INVALID_HANDLE); 629 AssertReturn(hIoPorts < pVM->iom.s.cIoPortRegs, VERR_IOM_INVALID_IOPORT_HANDLE); 630 PIOMIOPORTENTRYR3 const pRegEntry = &pVM->iom.s.paIoPortRegs[hIoPorts]; 631 AssertReturn(pRegEntry->pDevIns == pDevIns, VERR_IOM_INVALID_IOPORT_HANDLE); 632 633 /* 634 * Do the mapping. 635 */ 636 int rc; 637 IOM_LOCK_EXCL(pVM); 638 639 if (pRegEntry->fMapped) 640 { 641 RTIOPORT const uPort = pRegEntry->uPort; 642 RTIOPORT const uLastPort = uPort + pRegEntry->cPorts - 1; 643 uint32_t const cEntries = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iom.s.cIoPortRegs); 644 Assert(pVM->iom.s.cIoPortLookupEntries == cEntries); 645 Assert(cEntries > 0); 646 647 PIOMIOPORTLOOKUPENTRY paEntries = pVM->iom.s.paIoPortLookup; 648 uint32_t iFirst = 0; 649 uint32_t iEnd = cEntries; 650 uint32_t i = cEntries / 2; 651 for (;;) 652 { 653 PIOMIOPORTLOOKUPENTRY pEntry = &paEntries[i]; 654 if (pEntry->uLastPort < uPort) 655 { 656 i += 1; 657 if (i < iEnd) 658 iFirst = i; 659 else 660 { 661 rc = VERR_IOM_IOPORT_IPE_1; 662 AssertLogRelMsgFailedBreak(("%u..%u (%s) not found!\n", uPort, uLastPort, pRegEntry->pszDesc)); 663 } 664 } 665 else if (pEntry->uFirstPort > uLastPort) 666 { 667 if (i > iFirst) 668 iEnd = i; 669 else 670 { 671 rc = VERR_IOM_IOPORT_IPE_1; 672 AssertLogRelMsgFailedBreak(("%u..%u (%s) not found!\n", uPort, uLastPort, pRegEntry->pszDesc)); 673 } 674 } 675 else if (pEntry->idx == hIoPorts) 676 { 677 Assert(pEntry->uFirstPort == uPort); 678 Assert(pEntry->uLastPort == uLastPort); 679 if (i + 1 < cEntries) 680 memmove(pEntry, pEntry + 1, sizeof(*pEntry) * (cEntries - i - 1)); 681 pVM->iom.s.cIoPortLookupEntries = cEntries - 1; 682 pRegEntry->uPort = UINT16_MAX; 683 pRegEntry->fMapped = false; 684 rc = VINF_SUCCESS; 685 break; 686 } 687 else 688 { 689 AssertLogRelMsgFailed(("Lookig for %u..%u (%s), found %u..%u (%s) instead!\n", 690 uPort, uLastPort, pRegEntry->pszDesc, 691 pEntry->uFirstPort, pEntry->uLastPort, pVM->iom.s.paIoPortRegs[pEntry->idx].pszDesc)); 692 rc = VERR_IOM_IOPORT_IPE_1; 693 break; 694 } 695 696 i = iFirst + (iEnd - iFirst) / 2; 697 } 698 699 #ifdef VBOX_STRICT 700 /* 701 * Assert table sanity. 702 */ 703 AssertMsg(paEntries[0].uLastPort >= paEntries[0].uFirstPort, ("%#x %#x\n", paEntries[0].uLastPort, paEntries[0].uFirstPort)); 704 AssertMsg(paEntries[0].idx < pVM->iom.s.cIoPortRegs, ("%#x %#x\n", paEntries[0].idx, pVM->iom.s.cIoPortRegs)); 705 706 RTIOPORT uPortPrev = paEntries[0].uLastPort; 707 for (i = 1; i <= cEntries; i++) 708 { 709 AssertMsg(paEntries[i].uLastPort >= paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, paEntries[i].uLastPort, paEntries[i].uFirstPort)); 710 AssertMsg(paEntries[i].idx < pVM->iom.s.cIoPortRegs, ("%u: %#x %#x\n", i, paEntries[i].idx, pVM->iom.s.cIoPortRegs)); 711 AssertMsg(uPortPrev < paEntries[i].uFirstPort, ("%u: %#x %#x\n", i, uPortPrev, paEntries[i].uFirstPort)); 712 uPortPrev = paEntries[i].uLastPort; 713 } 714 #endif 715 } 716 else 717 { 718 AssertFailed(); 719 rc = VERR_IOM_IOPORTS_NOT_MAPPED; 720 } 721 722 IOM_UNLOCK_EXCL(pVM); 723 return rc; 724 } 725 415 726 416 727 #ifdef VBOX_WITH_STATISTICS -
trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
r80531 r80641 104 104 RTR3PTR pvUser, const char *pszDesc, PIOMIOPORTHANDLE phIoPorts) 105 105 { 106 RT_NOREF(pDevIns, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, phIoPorts); 107 return VERR_NOT_IMPLEMENTED; 106 PDMDEV_ASSERT_DEVINS(pDevIns); 107 LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: cPorts=%#x fFlags=%#x pPciDev=%p iPciRegion=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p pszDesc=%p:{%s} phIoPorts=%p\n", 108 pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr, 109 pvUser, pszDesc, pszDesc, phIoPorts)); 110 PVM pVM = pDevIns->Internal.s.pVMR3; 111 VM_ASSERT_EMT0_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); 112 VM_ASSERT_STATE_RETURN(pVM, VMSTATE_CREATING, VERR_VM_INVALID_VM_STATE); 113 114 int rc = IOMR3IoPortCreate(pVM, pDevIns, cPorts, fFlags, pPciDev, iPciRegion, 115 pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser, pszDesc, phIoPorts); 116 117 LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n", 118 pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts)); 119 return rc; 108 120 } 109 121 … … 112 124 static DECLCALLBACK(int) pdmR3DevHlp_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port) 113 125 { 114 RT_NOREF(pDevIns, hIoPorts, Port); 115 return VERR_NOT_IMPLEMENTED; 126 PDMDEV_ASSERT_DEVINS(pDevIns); 127 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port)); 128 PVM pVM = pDevIns->Internal.s.pVMR3; 129 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); 130 131 int rc = IOMR3IoPortMap(pVM, pDevIns, hIoPorts, Port); 132 133 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc)); 134 return rc; 116 135 } 117 136 … … 120 139 static DECLCALLBACK(int) pdmR3DevHlp_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts) 121 140 { 122 RT_NOREF(pDevIns, hIoPorts); 123 return VERR_NOT_IMPLEMENTED; 141 PDMDEV_ASSERT_DEVINS(pDevIns); 142 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts)); 143 PVM pVM = pDevIns->Internal.s.pVMR3; 144 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT); 145 146 int rc = IOMR3IoPortUnmap(pVM, pDevIns, hIoPorts); 147 148 LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc)); 149 return rc; 124 150 } 125 151 … … 129 155 { 130 156 PDMDEV_ASSERT_DEVINS(pDevIns); 131 LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p p 32_tszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,157 LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance, 132 158 Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc)); 133 159 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3); -
trunk/src/VBox/VMM/include/IOMInline.h
r80281 r80641 28 28 * @{ 29 29 */ 30 31 32 /** 33 * Gets the I/O port entry for the specified I/O port in the current context. 34 * 35 * @returns Pointer to I/O port entry. 36 * @returns NULL if no port registered. 37 * 38 * @param pVM The cross context VM structure. 39 * @param Port The I/O port lookup. 40 * @param pidxLastHint Pointer to IOMCPU::idxIoPortLastRead or 41 * IOMCPU::idxIoPortLastWrite. 42 * 43 * @note In ring-0 it is possible to get an uninitialized entry (pDevIns is 44 * NULL, cPorts is 0), in which case there should be ring-3 handlers 45 * for the entry. Use IOMIOPORTENTRYR0::idxSelf to get the ring-3 46 * entry. 47 */ 48 DECLINLINE(CTX_SUFF(PIOMIOPORTENTRY)) iomIoPortGetEntry(PVMCC pVM, RTIOPORT uPort, uint16_t *pidxLastHint) 49 { 50 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM)); 51 52 #ifdef IN_RING0 53 uint32_t iEnd = RT_MIN(pVM->iom.s.cIoPortLookupEntries, pVM->iomr0.s.cIoPortAlloc); 54 PIOMIOPORTLOOKUPENTRY paLookup = pVM->iomr0.s.paIoPortLookup; 55 #else 56 uint32_t iEnd = pVM->iom.s.cIoPortLookupEntries; 57 PIOMIOPORTLOOKUPENTRY paLookup = pVM->iom.s.paIoPortLookup; 58 #endif 59 if (iEnd > 0) 60 { 61 uint32_t iFirst = 0; 62 uint32_t i = *pidxLastHint; 63 if (i < iEnd) 64 { /* likely */ } 65 else 66 i = iEnd / 2; 67 for (;;) 68 { 69 PIOMIOPORTLOOKUPENTRY pCur = &paLookup[i]; 70 if (pCur->uFirstPort > uPort) 71 { 72 if (i > iFirst) 73 iEnd = i; 74 else 75 return NULL; 76 } 77 else if (pCur->uLastPort < uPort) 78 { 79 i += 1; 80 if (i < iEnd) 81 iFirst = i; 82 else 83 return NULL; 84 } 85 else 86 { 87 *pidxLastHint = (uint16_t)i; 88 89 /* 90 * Translate the 'idx' member into a pointer. 91 */ 92 size_t const idx = pCur->idx; 93 #ifdef IN_RING0 94 AssertMsg(idx < pVM->iom.s.cIoPortRegs && idx < pVM->iomr0.s.cIoPortAlloc, 95 ("%#zx vs %#x/%x (port %#x)\n", idx, pVM->iom.s.cIoPortRegs, pVM->iomr0.s.cIoPortMax, uPort)); 96 if (idx < pVM->iomr0.s.cIoPortAlloc) 97 return &pVM->iomr0.s.paIoPortRegs[idx]; 98 #else 99 if (idx < pVM->iom.s.cIoPortRegs) 100 return &pVM->iom.s.paIoPortRegs[idx]; 101 AssertMsgFailed(("%#zx vs %#x (port %#x)\n", idx, pVM->iom.s.cIoPortRegs, uPort)); 102 #endif 103 break; 104 } 105 106 i = iFirst + (iEnd - iFirst) / 2; 107 } 108 } 109 return NULL; 110 } 111 112 113 #ifdef VBOX_WITH_STATISTICS 114 /** 115 * Gets the I/O port statistics entry . 116 * 117 * @returns Pointer to stats. Instead of NULL, a pointer to IoPortDummyStats is 118 * returned, so the caller does not need to check for NULL. 119 * 120 * @param pVM The cross context VM structure. 121 * @param pRegEntry The I/O port entry to get stats for. 122 */ 123 DECLINLINE(PIOMIOPORTSTATSENTRY) iomIoPortGetStats(PVMCC pVM, CTX_SUFF(PIOMIOPORTENTRY) pRegEntry) 124 { 125 size_t idxStats = pRegEntry->idxStats; 126 # ifdef IN_RING0 127 if (idxStats < pVM->iomr0.s.cIoPortStatsAllocation) 128 return &pVM->iomr0.s.paIoPortStats[idxStats]; 129 # else 130 if (idxStats < pVM->iom.s.cIoPortStats) 131 return &pVM->iom.s.paIoPortStats[idxStats]; 132 # endif 133 return &pVM->iom.s.IoPortDummyStats; 134 } 135 #endif 136 30 137 31 138 /** -
trunk/src/VBox/VMM/include/IOMInternal.h
r80281 r80641 139 139 /** Pointer to I/O port statistics. */ 140 140 typedef IOMMMIOSTATS *PIOMMMIOSTATS; 141 142 /** 143 * I/O port lookup table entry. 144 */ 145 typedef struct IOMIOPORTLOOKUPENTRY 146 { 147 /** The first port in the range. */ 148 RTIOPORT uFirstPort; 149 /** The last port in the range (inclusive). */ 150 RTIOPORT uLastPort; 151 /** The registration handle/index. */ 152 uint16_t idx; 153 } IOMIOPORTLOOKUPENTRY; 154 /** Pointer to an I/O port lookup table entry. */ 155 typedef IOMIOPORTLOOKUPENTRY *PIOMIOPORTLOOKUPENTRY; 156 /** Pointer to a const I/O port lookup table entry. */ 157 typedef IOMIOPORTLOOKUPENTRY const *PCIOMIOPORTLOOKUPENTRY; 158 159 /** 160 * Ring-0 I/O port handle table entry. 161 */ 162 typedef struct IOMIOPORTENTRYR0 163 { 164 /** Pointer to user argument. */ 165 RTR0PTR pvUser; 166 /** Pointer to the associated device instance, NULL if entry not used. */ 167 R0PTRTYPE(PPDMDEVINS) pDevIns; 168 /** Pointer to OUT callback function. */ 169 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback; 170 /** Pointer to IN callback function. */ 171 R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback; 172 /** Pointer to string OUT callback function. */ 173 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback; 174 /** Pointer to string IN callback function. */ 175 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback; 176 /** The entry of the first statistics entry, UINT16_MAX if no stats. */ 177 uint16_t idxStats; 178 /** The number of ports covered by this entry, 0 if entry not used. */ 179 RTIOPORT cPorts; 180 /** Same as the handle index. */ 181 uint16_t idxSelf; 182 } IOMIOPORTENTRYR0; 183 /** Pointer to a ring-0 I/O port handle table entry. */ 184 typedef IOMIOPORTENTRYR0 *PIOMIOPORTENTRYR0; 185 /** Pointer to a const ring-0 I/O port handle table entry. */ 186 typedef IOMIOPORTENTRYR0 const *PCIOMIOPORTENTRYR0; 187 188 /** 189 * Ring-3 I/O port handle table entry. 190 */ 191 typedef struct IOMIOPORTENTRYR3 192 { 193 /** Pointer to user argument. */ 194 RTR3PTR pvUser; 195 /** Pointer to the associated device instance. */ 196 R3PTRTYPE(PPDMDEVINS) pDevIns; 197 /** Pointer to OUT callback function. */ 198 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback; 199 /** Pointer to IN callback function. */ 200 R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback; 201 /** Pointer to string OUT callback function. */ 202 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback; 203 /** Pointer to string IN callback function. */ 204 R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback; 205 /** Description / Name. For easing debugging. */ 206 R3PTRTYPE(const char *) pszDesc; 207 /** PCI device the registration is associated with. */ 208 R3PTRTYPE(PPDMPCIDEV) pPciDev; 209 /** The PCI device region (high 16-bit word) and subregion (low word), 210 * UINT32_MAX if not applicable. */ 211 uint32_t iPciRegion; 212 /** The number of ports covered by this entry. */ 213 RTIOPORT cPorts; 214 /** The current port mapping (duplicates lookup table). */ 215 RTIOPORT uPort; 216 /** The entry of the first statistics entry, UINT16_MAX if no stats. */ 217 uint16_t idxStats; 218 /** Set if mapped, clear if not. 219 * Only updated when critsect is held exclusively. */ 220 bool fMapped; 221 /** Same as the handle index. */ 222 uint16_t idxSelf; 223 } IOMIOPORTENTRYR3; 224 /** Pointer to a ring-3 I/O port handle table entry. */ 225 typedef IOMIOPORTENTRYR3 *PIOMIOPORTENTRYR3; 226 /** Pointer to a const ring-3 I/O port handle table entry. */ 227 typedef IOMIOPORTENTRYR3 const *PCIOMIOPORTENTRYR3; 228 229 /** 230 * I/O port statistics entry (one I/O port). 231 */ 232 typedef struct IOMIOPORTSTATSENTRY 233 { 234 /** Number of INs to this port from R3. */ 235 STAMCOUNTER InR3; 236 /** Profiling IN handler overhead in R3. */ 237 STAMPROFILE ProfInR3; 238 /** Number of OUTs to this port from R3. */ 239 STAMCOUNTER OutR3; 240 /** Profiling OUT handler overhead in R3. */ 241 STAMPROFILE ProfOutR3; 242 243 /** Number of INs to this port from R0/RC. */ 244 STAMCOUNTER InRZ; 245 /** Profiling IN handler overhead in R0/RC. */ 246 STAMPROFILE ProfInRZ; 247 /** Number of INs to this port from R0/RC which was serviced in R3. */ 248 STAMCOUNTER InRZToR3; 249 250 /** Number of OUTs to this port from R0/RC. */ 251 STAMCOUNTER OutRZ; 252 /** Profiling OUT handler overhead in R0/RC. */ 253 STAMPROFILE ProfOutRZ; 254 /** Number of OUTs to this port from R0/RC which was serviced in R3. */ 255 STAMCOUNTER OutRZToR3; 256 } IOMIOPORTSTATSENTRY; 257 /** Pointer to I/O port statistics entry. */ 258 typedef IOMIOPORTSTATSENTRY *PIOMIOPORTSTATSENTRY; 141 259 142 260 … … 281 399 /** 282 400 * The IOM trees. 401 * 283 402 * These are offset based the nodes and root must be in the same 284 403 * memory block in HC. The locations of IOM structure and the hypervisor heap … … 306 425 /** Pointer to the IOM trees. */ 307 426 typedef IOMTREES *PIOMTREES; 308 309 310 /**311 * Converts an IOM pointer into a VM pointer.312 * @returns Pointer to the VM structure the PGM is part of.313 * @param pIOM Pointer to IOM instance data.314 */315 #define IOM2VM(pIOM) ( (PVM)((char*)pIOM - pIOM->offVM) )316 317 /**318 * IOM Data (part of VM)319 */320 typedef struct IOM321 {322 /** Pointer to the trees - R3 ptr. */323 R3PTRTYPE(PIOMTREES) pTreesR3;324 /** Pointer to the trees - R0 ptr. */325 R0PTRTYPE(PIOMTREES) pTreesR0;326 327 /** MMIO physical access handler type. */328 PGMPHYSHANDLERTYPE hMmioHandlerType;329 uint32_t u32Padding;330 331 /** Lock serializing EMT access to IOM. */332 #ifdef IOM_WITH_CRIT_SECT_RW333 PDMCRITSECTRW CritSect;334 #else335 PDMCRITSECT CritSect;336 #endif337 338 /** @name I/O Port statistics.339 * @{ */340 STAMCOUNTER StatInstIn;341 STAMCOUNTER StatInstOut;342 STAMCOUNTER StatInstIns;343 STAMCOUNTER StatInstOuts;344 /** @} */345 346 /** @name MMIO statistics.347 * @{ */348 STAMPROFILE StatRZMMIOHandler;349 STAMCOUNTER StatRZMMIOFailures;350 351 STAMPROFILE StatRZInstMov;352 STAMPROFILE StatRZInstCmp;353 STAMPROFILE StatRZInstAnd;354 STAMPROFILE StatRZInstOr;355 STAMPROFILE StatRZInstXor;356 STAMPROFILE StatRZInstBt;357 STAMPROFILE StatRZInstTest;358 STAMPROFILE StatRZInstXchg;359 STAMPROFILE StatRZInstStos;360 STAMPROFILE StatRZInstLods;361 #ifdef IOM_WITH_MOVS_SUPPORT362 STAMPROFILEADV StatRZInstMovs;363 STAMPROFILE StatRZInstMovsToMMIO;364 STAMPROFILE StatRZInstMovsFromMMIO;365 STAMPROFILE StatRZInstMovsMMIO;366 #endif367 STAMCOUNTER StatRZInstOther;368 369 STAMCOUNTER StatRZMMIO1Byte;370 STAMCOUNTER StatRZMMIO2Bytes;371 STAMCOUNTER StatRZMMIO4Bytes;372 STAMCOUNTER StatRZMMIO8Bytes;373 374 STAMCOUNTER StatR3MMIOHandler;375 376 RTUINT cMovsMaxBytes;377 RTUINT cStosMaxBytes;378 /** @} */379 } IOM;380 /** Pointer to IOM instance data. */381 typedef IOM *PIOM;382 427 383 428 … … 433 478 * (Saves quite some time in rep outs/ins instruction emulation.) 434 479 * @{ */ 480 /** I/O port registration index for the last read operation. */ 481 uint16_t idxIoPortLastRead; 482 /** I/O port registration index for the last write operation. */ 483 uint16_t idxIoPortLastWrite; 484 /** I/O port registration index for the last read string operation. */ 485 uint16_t idxIoPortLastReadStr; 486 /** I/O port registration index for the last write string operation. */ 487 uint16_t idxIoPortLastWriteStr; 488 uint32_t u32Padding; 489 435 490 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3; 436 491 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3; … … 450 505 /** Pointer to IOM per virtual CPU instance data. */ 451 506 typedef IOMCPU *PIOMCPU; 507 508 509 /** 510 * IOM Data (part of VM) 511 */ 512 typedef struct IOM 513 { 514 /** Pointer to the trees - R3 ptr. */ 515 R3PTRTYPE(PIOMTREES) pTreesR3; 516 /** Pointer to the trees - R0 ptr. */ 517 R0PTRTYPE(PIOMTREES) pTreesR0; 518 519 /** MMIO physical access handler type. */ 520 PGMPHYSHANDLERTYPE hMmioHandlerType; 521 uint32_t u32Padding; 522 523 /** @name I/O ports 524 * @note The updating of these variables is done exclusively from EMT(0). 525 * @{ */ 526 /** Number of I/O port registrations. */ 527 uint32_t cIoPortRegs; 528 /** The size of the paIoPortsRegs allocation (in entries). */ 529 uint32_t cIoPortAlloc; 530 /** I/O port registration table for ring-3. 531 * There is a parallel table in ring-0, IOMR0PERVM::paIoPortRegs. */ 532 R3PTRTYPE(PIOMIOPORTENTRYR3) paIoPortRegs; 533 /** Number of entries in the lookup table. */ 534 uint32_t cIoPortLookupEntries; 535 uint32_t u32Padding1; 536 /** I/O port lookup table. */ 537 R3PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup; 538 539 /** The number of valid entries in paioPortStats. */ 540 uint32_t cIoPortStats; 541 /** The size of the paIoPortStats allocation (in entries). */ 542 uint32_t cIoPortStatsAllocation; 543 /** I/O port lookup table. */ 544 R3PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats; 545 /** Dummy stats entry so we don't need to check for NULL pointers so much. */ 546 IOMIOPORTSTATSENTRY IoPortDummyStats; 547 /** @} */ 548 549 550 /** Lock serializing EMT access to IOM. */ 551 #ifdef IOM_WITH_CRIT_SECT_RW 552 PDMCRITSECTRW CritSect; 553 #else 554 PDMCRITSECT CritSect; 555 #endif 556 557 #if 0 /* unused */ 558 /** @name I/O Port statistics. 559 * @{ */ 560 STAMCOUNTER StatInstIn; 561 STAMCOUNTER StatInstOut; 562 STAMCOUNTER StatInstIns; 563 STAMCOUNTER StatInstOuts; 564 /** @} */ 565 #endif 566 567 /** @name MMIO statistics. 568 * @{ */ 569 STAMPROFILE StatRZMMIOHandler; 570 STAMCOUNTER StatRZMMIOFailures; 571 572 STAMPROFILE StatRZInstMov; 573 STAMPROFILE StatRZInstCmp; 574 STAMPROFILE StatRZInstAnd; 575 STAMPROFILE StatRZInstOr; 576 STAMPROFILE StatRZInstXor; 577 STAMPROFILE StatRZInstBt; 578 STAMPROFILE StatRZInstTest; 579 STAMPROFILE StatRZInstXchg; 580 STAMPROFILE StatRZInstStos; 581 STAMPROFILE StatRZInstLods; 582 #ifdef IOM_WITH_MOVS_SUPPORT 583 STAMPROFILEADV StatRZInstMovs; 584 STAMPROFILE StatRZInstMovsToMMIO; 585 STAMPROFILE StatRZInstMovsFromMMIO; 586 STAMPROFILE StatRZInstMovsMMIO; 587 #endif 588 STAMCOUNTER StatRZInstOther; 589 590 STAMCOUNTER StatRZMMIO1Byte; 591 STAMCOUNTER StatRZMMIO2Bytes; 592 STAMCOUNTER StatRZMMIO4Bytes; 593 STAMCOUNTER StatRZMMIO8Bytes; 594 595 STAMCOUNTER StatR3MMIOHandler; 596 597 RTUINT cMovsMaxBytes; 598 RTUINT cStosMaxBytes; 599 /** @} */ 600 } IOM; 601 /** Pointer to IOM instance data. */ 602 typedef IOM *PIOM; 603 604 605 /** 606 * IOM data kept in the ring-0 GVM. 607 */ 608 typedef struct IOMR0PERVM 609 { 610 /** @name I/O ports 611 * @{ */ 612 /** The higest ring-0 I/O port registration plus one. */ 613 uint32_t cIoPortMax; 614 /** The size of the paIoPortsRegs allocation (in entries). */ 615 uint32_t cIoPortAlloc; 616 /** I/O port registration table for ring-0. 617 * There is a parallel table for ring-3, paIoPortRing3Regs. */ 618 R0PTRTYPE(PIOMIOPORTENTRYR0) paIoPortRegs; 619 /** I/O port lookup table. */ 620 R0PTRTYPE(PIOMIOPORTLOOKUPENTRY) paIoPortLookup; 621 /** I/O port registration table for ring-3. 622 * Also mapped to ring-3 as IOM::paIoPortRegs. */ 623 R0PTRTYPE(PIOMIOPORTENTRYR3) paIoPortRing3Regs; 624 /** Handle to the allocation backing both the ring-0 and ring-3 registration 625 * tables as well as the lookup table. */ 626 RTR0MEMOBJ hIoPortMemObj; 627 /** Handle to the ring-3 mapping of the lookup and ring-3 registration table. */ 628 RTR0MEMOBJ hIoPortMapObj; 629 #ifdef VBOX_WITH_STATISTICS 630 /** The size of the paIoPortStats allocation (in entries). */ 631 uint32_t cIoPortStatsAllocation; 632 /** I/O port lookup table. */ 633 R0PTRTYPE(PIOMIOPORTSTATSENTRY) paIoPortStats; 634 /** Handle to the allocation backing the I/O port statistics. */ 635 RTR0MEMOBJ hIoPortStatsMemObj; 636 /** Handle to the ring-3 mapping of the I/O port statistics. */ 637 RTR0MEMOBJ hIoPortStatsMapObj; 638 #endif 639 /** @} */ 640 } IOMR0PERVM; 452 641 453 642 -
trunk/src/VBox/VMM/include/NEMInternal.h
r80334 r80641 51 51 //# define NEM_WIN_USE_OUR_OWN_RUN_API /**< Applies to ring-3 code only. Useful for testing VID API. */ 52 52 # define NEM_WIN_WITH_RING0_RUNLOOP /**< Enables the ring-0 runloop. */ 53 # define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT /**< For quickly testing ring-3 API without messing with CFGM. */53 //# define NEM_WIN_USE_RING0_RUNLOOP_BY_DEFAULT /**< For quickly testing ring-3 API without messing with CFGM. */ 54 54 # if defined(NEM_WIN_USE_OUR_OWN_RUN_API) && !defined(NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS) 55 55 # error "NEM_WIN_USE_OUR_OWN_RUN_API requires NEM_WIN_USE_HYPERCALLS_FOR_REGISTERS"
Note:
See TracChangeset
for help on using the changeset viewer.