Changeset 82311 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Dec 1, 2019 1:45:02 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135135
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r81383 r82311 142 142 143 143 /* 144 * Old code145 * Old code146 * Old code147 */148 149 #ifdef VBOX_WITH_STATISTICS150 /*151 * Get the statistics record.152 */153 PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead);154 if (!pStats || pStats->Core.Key != Port)155 {156 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);157 if (pStats)158 pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats;159 }160 #endif161 162 /*163 * Get handler for current context.164 */165 CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead);166 if ( !pRange167 || (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)168 {169 pRange = iomIOPortGetRange(pVM, Port);170 if (pRange)171 pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange;172 }173 MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);174 if (pRange)175 {176 /*177 * Found a range, get the data in case we leave the IOM lock.178 */179 PFNIOMIOPORTIN pfnInCallback = pRange->pfnInCallback;180 #ifndef IN_RING3181 if (pfnInCallback)182 { /* likely */ }183 else184 {185 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });186 IOM_UNLOCK_SHARED(pVM);187 return VINF_IOM_R3_IOPORT_READ;188 }189 #endif190 void *pvUser = pRange->pvUser;191 PPDMDEVINS pDevIns = pRange->pDevIns;192 IOM_UNLOCK_SHARED(pVM);193 194 /*195 * Call the device.196 */197 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);198 if (rcStrict == VINF_SUCCESS)199 { /* likely */ }200 else201 {202 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });203 return rcStrict;204 }205 #ifdef VBOX_WITH_STATISTICS206 if (pStats)207 {208 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);209 rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);210 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);211 }212 else213 #endif214 rcStrict = pfnInCallback(pDevIns, pvUser, Port, pu32Value, (unsigned)cbValue);215 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));216 217 #ifdef VBOX_WITH_STATISTICS218 if (rcStrict == VINF_SUCCESS && pStats)219 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));220 # ifndef IN_RING3221 else if (rcStrict == VINF_IOM_R3_IOPORT_READ && pStats)222 STAM_COUNTER_INC(&pStats->InRZToR3);223 # endif224 #endif225 if (rcStrict == VERR_IOM_IOPORT_UNUSED)226 {227 /* make return value */228 rcStrict = VINF_SUCCESS;229 switch (cbValue)230 {231 case 1: *(uint8_t *)pu32Value = 0xff; break;232 case 2: *(uint16_t *)pu32Value = 0xffff; break;233 case 4: *(uint32_t *)pu32Value = UINT32_C(0xffffffff); break;234 default:235 AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port));236 return VERR_IOM_INVALID_IOPORT_SIZE;237 }238 }239 Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=%Rrc\n", Port, *pu32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));240 return rcStrict;241 }242 243 #ifndef IN_RING3244 /*245 * Handler in ring-3?246 */247 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, Port);248 if (pRangeR3)249 {250 # ifdef VBOX_WITH_STATISTICS251 if (pStats)252 STAM_COUNTER_INC(&pStats->InRZToR3);253 # endif254 IOM_UNLOCK_SHARED(pVM);255 return VINF_IOM_R3_IOPORT_READ;256 }257 #endif258 259 /*260 144 * Ok, no handler for this port. 261 145 */ 262 #ifdef VBOX_WITH_STATISTICS 263 if (pStats) 264 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In)); 265 #endif 266 267 /* make return value */ 146 IOM_UNLOCK_SHARED(pVM); 268 147 switch (cbValue) 269 148 { … … 272 151 case 4: *(uint32_t *)pu32Value = UINT32_C(0xffffffff); break; 273 152 default: 274 AssertMsgFailed(("Invalid I/O port size %d. Port=%d\n", cbValue, Port)); 275 IOM_UNLOCK_SHARED(pVM); 276 return VERR_IOM_INVALID_IOPORT_SIZE; 153 AssertMsgFailedReturn(("Invalid I/O port size %d. Port=%d\n", cbValue, Port), VERR_IOM_INVALID_IOPORT_SIZE); 277 154 } 278 155 Log3(("IOMIOPortRead: Port=%RTiop *pu32=%08RX32 cb=%d rc=VINF_SUCCESS\n", Port, *pu32Value, cbValue)); 279 IOM_UNLOCK_SHARED(pVM);280 156 return VINF_SUCCESS; 281 157 } … … 421 297 422 298 /* 423 * Old code424 * Old code425 * Old code426 */427 428 #ifdef VBOX_WITH_STATISTICS429 /*430 * Get the statistics record.431 */432 PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead);433 if (!pStats || pStats->Core.Key != uPort)434 {435 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, uPort);436 if (pStats)437 pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats;438 }439 #endif440 441 /*442 * Get handler for current context.443 */444 CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead);445 if ( !pRange446 || (unsigned)uPort - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)447 {448 pRange = iomIOPortGetRange(pVM, uPort);449 if (pRange)450 pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange;451 }452 MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);453 if (pRange)454 {455 /*456 * Found a range.457 */458 PFNIOMIOPORTINSTRING pfnInStrCallback = pRange->pfnInStrCallback;459 PFNIOMIOPORTIN pfnInCallback = pRange->pfnInCallback;460 #ifndef IN_RING3461 if (pfnInStrCallback || pfnInCallback)462 { /* likely */ }463 else464 {465 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });466 IOM_UNLOCK_SHARED(pVM);467 return VINF_IOM_R3_IOPORT_READ;468 }469 #endif470 void *pvUser = pRange->pvUser;471 PPDMDEVINS pDevIns = pRange->pDevIns;472 IOM_UNLOCK_SHARED(pVM);473 474 /*475 * Call the device.476 */477 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_READ);478 if (rcStrict == VINF_SUCCESS)479 { /* likely */ }480 else481 {482 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); });483 return rcStrict;484 }485 486 /*487 * First using the string I/O callback.488 */489 if (pfnInStrCallback)490 {491 #ifdef VBOX_WITH_STATISTICS492 if (pStats)493 {494 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);495 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);496 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);497 }498 else499 #endif500 rcStrict = pfnInStrCallback(pDevIns, pvUser, uPort, (uint8_t *)pvDst, pcTransfers, cb);501 }502 503 /*504 * Then doing the single I/O fallback.505 */506 if ( *pcTransfers > 0507 && rcStrict == VINF_SUCCESS)508 {509 pvDst = (uint8_t *)pvDst + (cRequestedTransfers - *pcTransfers) * cb;510 do511 {512 uint32_t u32Value = 0;513 #ifdef VBOX_WITH_STATISTICS514 if (pStats)515 {516 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfIn), a);517 rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);518 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfIn), a);519 }520 else521 #endif522 rcStrict = pfnInCallback(pDevIns, pvUser, uPort, &u32Value, cb);523 if (rcStrict == VERR_IOM_IOPORT_UNUSED)524 {525 u32Value = UINT32_MAX;526 rcStrict = VINF_SUCCESS;527 }528 if (IOM_SUCCESS(rcStrict))529 {530 switch (cb)531 {532 case 4: *(uint32_t *)pvDst = u32Value; pvDst = (uint8_t *)pvDst + 4; break;533 case 2: *(uint16_t *)pvDst = (uint16_t)u32Value; pvDst = (uint8_t *)pvDst + 2; break;534 case 1: *(uint8_t *)pvDst = (uint8_t )u32Value; pvDst = (uint8_t *)pvDst + 1; break;535 default: AssertFailed();536 }537 *pcTransfers -= 1;538 }539 } while ( *pcTransfers > 0540 && rcStrict == VINF_SUCCESS);541 }542 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));543 544 #ifdef VBOX_WITH_STATISTICS545 if (rcStrict == VINF_SUCCESS && pStats)546 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));547 # ifndef IN_RING3548 else if (rcStrict == VINF_IOM_R3_IOPORT_READ && pStats)549 STAM_COUNTER_INC(&pStats->InRZToR3);550 # endif551 #endif552 Log3(("IOMIOPortReadStr: uPort=%RTiop pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=%Rrc\n",553 uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));554 return rcStrict;555 }556 557 #ifndef IN_RING3558 /*559 * Handler in ring-3?560 */561 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, uPort);562 if (pRangeR3)563 {564 # ifdef VBOX_WITH_STATISTICS565 if (pStats)566 STAM_COUNTER_INC(&pStats->InRZToR3);567 # endif568 IOM_UNLOCK_SHARED(pVM);569 return VINF_IOM_R3_IOPORT_READ;570 }571 #endif572 573 /*574 299 * Ok, no handler for this port. 575 300 */ 301 IOM_UNLOCK_SHARED(pVM); 576 302 *pcTransfers = 0; 577 303 memset(pvDst, 0xff, cRequestedTransfers * cb); 578 #ifdef VBOX_WITH_STATISTICS579 if (pStats)580 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(In));581 #endif582 304 Log3(("IOMIOPortReadStr: uPort=%RTiop (unused) pvDst=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n", 583 305 uPort, pvDst, pcTransfers, cRequestedTransfers, *pcTransfers, cb)); 584 IOM_UNLOCK_SHARED(pVM);585 306 return VINF_SUCCESS; 586 307 } … … 703 424 704 425 /* 705 * Old code706 * Old code707 * Old code708 */709 710 #ifdef VBOX_WITH_STATISTICS711 /*712 * Find the statistics record.713 */714 PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite);715 if (!pStats || pStats->Core.Key != Port)716 {717 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);718 if (pStats)719 pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;720 }721 #endif722 723 /*724 * Get handler for current context.725 */726 CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite);727 if ( !pRange728 || (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)729 {730 pRange = iomIOPortGetRange(pVM, Port);731 if (pRange)732 pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;733 }734 MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);735 if (pRange)736 {737 /*738 * Found a range.739 */740 PFNIOMIOPORTOUT pfnOutCallback = pRange->pfnOutCallback;741 #ifndef IN_RING3742 if (pfnOutCallback)743 { /* likely */ }744 else745 {746 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });747 IOM_UNLOCK_SHARED(pVM);748 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);749 }750 #endif751 void *pvUser = pRange->pvUser;752 PPDMDEVINS pDevIns = pRange->pDevIns;753 IOM_UNLOCK_SHARED(pVM);754 755 /*756 * Call the device.757 */758 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);759 if (rcStrict == VINF_SUCCESS)760 { /* likely */ }761 else762 {763 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });764 #ifndef IN_RING3765 if (RT_LIKELY(rcStrict == VINF_IOM_R3_IOPORT_WRITE))766 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);767 #endif768 return rcStrict;769 }770 #ifdef VBOX_WITH_STATISTICS771 if (pStats)772 {773 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);774 rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);775 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);776 }777 else778 #endif779 rcStrict = pfnOutCallback(pDevIns, pvUser, Port, u32Value, (unsigned)cbValue);780 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));781 782 #ifdef VBOX_WITH_STATISTICS783 if (rcStrict == VINF_SUCCESS && pStats)784 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));785 # ifndef IN_RING3786 else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE && pStats)787 STAM_COUNTER_INC(&pStats->OutRZToR3);788 # endif789 #endif790 Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d rc=%Rrc\n", Port, u32Value, cbValue, VBOXSTRICTRC_VAL(rcStrict)));791 #ifndef IN_RING3792 if (rcStrict == VINF_IOM_R3_IOPORT_WRITE)793 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);794 #endif795 return rcStrict;796 }797 798 #ifndef IN_RING3799 /*800 * Handler in ring-3?801 */802 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, Port);803 if (pRangeR3)804 {805 # ifdef VBOX_WITH_STATISTICS806 if (pStats)807 STAM_COUNTER_INC(&pStats->OutRZToR3);808 # endif809 IOM_UNLOCK_SHARED(pVM);810 return iomIOPortRing3WritePending(pVCpu, Port, u32Value, cbValue);811 }812 #endif813 814 /*815 426 * Ok, no handler for that port. 816 427 */ 817 #ifdef VBOX_WITH_STATISTICS 818 /* statistics. */ 819 if (pStats) 820 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out)); 821 #endif 428 IOM_UNLOCK_SHARED(pVM); 822 429 Log3(("IOMIOPortWrite: Port=%RTiop u32=%08RX32 cb=%d nop\n", Port, u32Value, cbValue)); 823 IOM_UNLOCK_SHARED(pVM);824 430 return VINF_SUCCESS; 825 431 } … … 961 567 962 568 /* 963 * Old code.964 * Old code.965 * Old code.966 */967 968 #ifdef VBOX_WITH_STATISTICS969 /*970 * Get the statistics record.971 */972 PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite);973 if (!pStats || pStats->Core.Key != uPort)974 {975 pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, uPort);976 if (pStats)977 pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;978 }979 #endif980 981 /*982 * Get handler for current context.983 */984 CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite);985 if ( !pRange986 || (unsigned)uPort - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)987 {988 pRange = iomIOPortGetRange(pVM, uPort);989 if (pRange)990 pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;991 }992 MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);993 if (pRange)994 {995 /*996 * Found a range.997 */998 PFNIOMIOPORTOUTSTRING pfnOutStrCallback = pRange->pfnOutStrCallback;999 PFNIOMIOPORTOUT pfnOutCallback = pRange->pfnOutCallback;1000 #ifndef IN_RING31001 if (pfnOutStrCallback || pfnOutCallback)1002 { /* likely */ }1003 else1004 {1005 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });1006 IOM_UNLOCK_SHARED(pVM);1007 return VINF_IOM_R3_IOPORT_WRITE;1008 }1009 #endif1010 void *pvUser = pRange->pvUser;1011 PPDMDEVINS pDevIns = pRange->pDevIns;1012 IOM_UNLOCK_SHARED(pVM);1013 1014 /*1015 * Call the device.1016 */1017 VBOXSTRICTRC rcStrict = PDMCritSectEnter(pDevIns->CTX_SUFF(pCritSectRo), VINF_IOM_R3_IOPORT_WRITE);1018 if (rcStrict == VINF_SUCCESS)1019 { /* likely */ }1020 else1021 {1022 STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->OutRZToR3); });1023 return rcStrict;1024 }1025 1026 /*1027 * First using string I/O if possible.1028 */1029 if (pfnOutStrCallback)1030 {1031 #ifdef VBOX_WITH_STATISTICS1032 if (pStats)1033 {1034 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);1035 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);1036 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);1037 }1038 else1039 #endif1040 rcStrict = pfnOutStrCallback(pDevIns, pvUser, uPort, (uint8_t const *)pvSrc, pcTransfers, cb);1041 }1042 1043 /*1044 * Then doing the single I/O fallback.1045 */1046 if ( *pcTransfers > 01047 && rcStrict == VINF_SUCCESS)1048 {1049 pvSrc = (uint8_t *)pvSrc + (cRequestedTransfers - *pcTransfers) * cb;1050 do1051 {1052 uint32_t u32Value;1053 switch (cb)1054 {1055 case 4: u32Value = *(uint32_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 4; break;1056 case 2: u32Value = *(uint16_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 2; break;1057 case 1: u32Value = *(uint8_t *)pvSrc; pvSrc = (uint8_t const *)pvSrc + 1; break;1058 default: AssertFailed(); u32Value = UINT32_MAX;1059 }1060 #ifdef VBOX_WITH_STATISTICS1061 if (pStats)1062 {1063 STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfOut), a);1064 rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);1065 STAM_PROFILE_STOP(&pStats->CTX_SUFF_Z(ProfOut), a);1066 }1067 else1068 #endif1069 rcStrict = pfnOutCallback(pDevIns, pvUser, uPort, u32Value, cb);1070 if (IOM_SUCCESS(rcStrict))1071 *pcTransfers -= 1;1072 } while ( *pcTransfers > 01073 && rcStrict == VINF_SUCCESS);1074 }1075 1076 PDMCritSectLeave(pDevIns->CTX_SUFF(pCritSectRo));1077 1078 #ifdef VBOX_WITH_STATISTICS1079 if (rcStrict == VINF_SUCCESS && pStats)1080 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));1081 # ifndef IN_RING31082 else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE && pStats)1083 STAM_COUNTER_INC(&pStats->OutRZToR3);1084 # endif1085 #endif1086 Log3(("IOMIOPortWriteStr: uPort=%RTiop pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rcStrict=%Rrc\n",1087 uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb, VBOXSTRICTRC_VAL(rcStrict)));1088 return rcStrict;1089 }1090 1091 #ifndef IN_RING31092 /*1093 * Handler in ring-3?1094 */1095 PIOMIOPORTRANGER3 pRangeR3 = iomIOPortGetRangeR3(pVM, uPort);1096 if (pRangeR3)1097 {1098 # ifdef VBOX_WITH_STATISTICS1099 if (pStats)1100 STAM_COUNTER_INC(&pStats->OutRZToR3);1101 # endif1102 IOM_UNLOCK_SHARED(pVM);1103 return VINF_IOM_R3_IOPORT_WRITE;1104 }1105 #endif1106 1107 /*1108 569 * Ok, no handler for this port. 1109 570 */ 571 IOM_UNLOCK_SHARED(pVM); 1110 572 *pcTransfers = 0; 1111 #ifdef VBOX_WITH_STATISTICS1112 if (pStats)1113 STAM_COUNTER_INC(&pStats->CTX_SUFF_Z(Out));1114 #endif1115 573 Log3(("IOMIOPortWriteStr: uPort=%RTiop (unused) pvSrc=%p pcTransfer=%p:{%#x->%#x} cb=%d rc=VINF_SUCCESS\n", 1116 574 uPort, pvSrc, pcTransfers, cRequestedTransfers, *pcTransfers, cb)); 1117 IOM_UNLOCK_SHARED(pVM);1118 575 return VINF_SUCCESS; 1119 576 } -
trunk/src/VBox/VMM/VMMR3/IOM.cpp
r81983 r82311 134 134 *********************************************************************************************************************************/ 135 135 static void iomR3FlushCache(PVM pVM); 136 #if 0137 static DECLCALLBACK(int) iomR3RelocateIOPortCallback(PAVLROIOPORTNODECORE pNode, void *pvUser);138 static DECLCALLBACK(int) iomR3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser);139 #endif140 static FNIOMIOPORTIN iomR3IOPortDummyIn;141 static FNIOMIOPORTOUT iomR3IOPortDummyOut;142 static FNIOMIOPORTINSTRING iomR3IOPortDummyInStr;143 static FNIOMIOPORTOUTSTRING iomR3IOPortDummyOutStr;144 136 145 137 #ifdef VBOX_WITH_STATISTICS … … 302 294 { 303 295 PVMCPU pVCpu = pVM->apCpusR3[idCpu]; 304 pVCpu->iom.s.pRangeLastReadR0 = NIL_RTR0PTR;305 pVCpu->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR;306 pVCpu->iom.s.pStatsLastReadR0 = NIL_RTR0PTR;307 pVCpu->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR;308 296 pVCpu->iom.s.pMMIORangeLastR0 = NIL_RTR0PTR; 309 297 pVCpu->iom.s.pMMIOStatsLastR0 = NIL_RTR0PTR; 310 298 311 pVCpu->iom.s.pRangeLastReadR3 = NULL;312 pVCpu->iom.s.pRangeLastWriteR3 = NULL;313 pVCpu->iom.s.pStatsLastReadR3 = NULL;314 pVCpu->iom.s.pStatsLastWriteR3 = NULL;315 299 pVCpu->iom.s.pMMIORangeLastR3 = NULL; 316 300 pVCpu->iom.s.pMMIOStatsLastR3 = NULL; … … 344 328 VMMR3_INT_DECL(void) IOMR3Relocate(PVM pVM, RTGCINTPTR offDelta) 345 329 { 346 #if 0347 LogFlow(("IOMR3Relocate: offDelta=%d\n", offDelta));348 349 /*350 * Apply relocations to the GC callbacks.351 */352 pVM->iom.s.pTreesRC = MMHyperR3ToRC(pVM, pVM->iom.s.pTreesR3);353 RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeRC, true, iomR3RelocateIOPortCallback, &offDelta);354 RTAvlroGCPhysDoWithAll(&pVM->iom.s.pTreesR3->MMIOTree, true, iomR3RelocateMMIOCallback, &offDelta);355 356 /*357 * Reset the raw-mode cache (don't bother relocating it).358 */359 VMCPUID idCpu = pVM->cCpus;360 while (idCpu-- > 0)361 {362 PVMCPU pVCpu = pVM->apCpusR3[idCpu];363 pVCpu->iom.s.pRangeLastReadRC = NIL_RTRCPTR;364 pVCpu->iom.s.pRangeLastWriteRC = NIL_RTRCPTR;365 pVCpu->iom.s.pStatsLastReadRC = NIL_RTRCPTR;366 pVCpu->iom.s.pStatsLastWriteRC = NIL_RTRCPTR;367 pVCpu->iom.s.pMMIORangeLastRC = NIL_RTRCPTR;368 pVCpu->iom.s.pMMIOStatsLastRC = NIL_RTRCPTR;369 }370 #else371 330 RT_NOREF(pVM, offDelta); 372 #endif 373 } 374 375 #if 0 376 377 /** 378 * Callback function for relocating a I/O port range. 379 * 380 * @returns 0 (continue enum) 381 * @param pNode Pointer to a IOMIOPORTRANGERC node. 382 * @param pvUser Pointer to the offDelta. This is a pointer to the delta since we're 383 * not certain the delta will fit in a void pointer for all possible configs. 384 */ 385 static DECLCALLBACK(int) iomR3RelocateIOPortCallback(PAVLROIOPORTNODECORE pNode, void *pvUser) 386 { 387 PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)pNode; 388 RTGCINTPTR offDelta = *(PRTGCINTPTR)pvUser; 389 390 Assert(pRange->pDevIns); 391 pRange->pDevIns += offDelta; 392 if (pRange->pfnOutCallback) 393 pRange->pfnOutCallback += offDelta; 394 if (pRange->pfnInCallback) 395 pRange->pfnInCallback += offDelta; 396 if (pRange->pfnOutStrCallback) 397 pRange->pfnOutStrCallback += offDelta; 398 if (pRange->pfnInStrCallback) 399 pRange->pfnInStrCallback += offDelta; 400 if (pRange->pvUser > _64K) 401 pRange->pvUser += offDelta; 402 return 0; 403 } 404 405 406 /** 407 * Callback function for relocating a MMIO range. 408 * 409 * @returns 0 (continue enum) 410 * @param pNode Pointer to a IOMMMIORANGE node. 411 * @param pvUser Pointer to the offDelta. This is a pointer to the delta since we're 412 * not certain the delta will fit in a void pointer for all possible configs. 413 */ 414 static DECLCALLBACK(int) iomR3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser) 415 { 416 PIOMMMIORANGE pRange = (PIOMMMIORANGE)pNode; 417 RTGCINTPTR offDelta = *(PRTGCINTPTR)pvUser; 418 419 if (pRange->pDevInsRC) 420 pRange->pDevInsRC += offDelta; 421 if (pRange->pfnWriteCallbackRC) 422 pRange->pfnWriteCallbackRC += offDelta; 423 if (pRange->pfnReadCallbackRC) 424 pRange->pfnReadCallbackRC += offDelta; 425 if (pRange->pfnFillCallbackRC) 426 pRange->pfnFillCallbackRC += offDelta; 427 if (pRange->pvUserRC > _64K) 428 pRange->pvUserRC += offDelta; 429 430 return 0; 431 } 432 433 #endif 331 } 434 332 435 333 /** … … 454 352 455 353 #ifdef VBOX_WITH_STATISTICS 456 457 /**458 * Create the statistics node for an I/O port.459 *460 * @returns Pointer to new stats node.461 *462 * @param pVM The cross context VM structure.463 * @param Port Port.464 * @param pszDesc Description.465 */466 static PIOMIOPORTSTATS iomR3IOPortStatsCreate(PVM pVM, RTIOPORT Port, const char *pszDesc)467 {468 IOM_LOCK_EXCL(pVM);469 470 /* check if it already exists. */471 PIOMIOPORTSTATS pPort = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.pTreesR3->IOPortStatTree, Port);472 if (pPort)473 {474 IOM_UNLOCK_EXCL(pVM);475 return pPort;476 }477 478 /* allocate stats node. */479 int rc = MMHyperAlloc(pVM, sizeof(*pPort), 0, MM_TAG_IOM_STATS, (void **)&pPort);480 AssertRC(rc);481 if (RT_SUCCESS(rc))482 {483 /* insert into the tree. */484 pPort->Core.Key = Port;485 if (RTAvloIOPortInsert(&pVM->iom.s.pTreesR3->IOPortStatTree, &pPort->Core))486 {487 IOM_UNLOCK_EXCL(pVM);488 489 /* put a name on common ports. */490 if (!pszDesc)491 pszDesc = iomR3IOPortGetStandardName(Port);492 493 /* register the statistics counters. */494 rc = STAMR3RegisterF(pVM, &pPort->InR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/Ports/%04x-In-R3", Port); AssertRC(rc);495 rc = STAMR3RegisterF(pVM, &pPort->OutR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/Ports/%04x-Out-R3", Port); AssertRC(rc);496 rc = STAMR3RegisterF(pVM, &pPort->InRZ, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/Ports/%04x-In-RZ", Port); AssertRC(rc);497 rc = STAMR3RegisterF(pVM, &pPort->OutRZ, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/Ports/%04x-Out-RZ", Port); AssertRC(rc);498 rc = STAMR3RegisterF(pVM, &pPort->InRZToR3, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/Ports/%04x-In-RZtoR3", Port); AssertRC(rc);499 rc = STAMR3RegisterF(pVM, &pPort->OutRZToR3,STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES, pszDesc, "/IOM/Ports/%04x-Out-RZtoR3", Port); AssertRC(rc);500 501 /* Profiling */502 rc = STAMR3RegisterF(pVM, &pPort->ProfInR3, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-In-R3/Prof", Port); AssertRC(rc);503 rc = STAMR3RegisterF(pVM, &pPort->ProfOutR3,STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-Out-R3/Prof", Port); AssertRC(rc);504 rc = STAMR3RegisterF(pVM, &pPort->ProfInRZ, STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-In-RZ/Prof", Port); AssertRC(rc);505 rc = STAMR3RegisterF(pVM, &pPort->ProfOutRZ,STAMTYPE_PROFILE, STAMVISIBILITY_USED, STAMUNIT_TICKS_PER_CALL, pszDesc,"/IOM/Ports/%04x-Out-RZ/Prof", Port); AssertRC(rc);506 507 return pPort;508 }509 510 AssertMsgFailed(("what! Port=%d\n", Port));511 MMHyperFree(pVM, pPort);512 }513 IOM_UNLOCK_EXCL(pVM);514 return NULL;515 }516 517 354 518 355 /** … … 566 403 567 404 #endif /* VBOX_WITH_STATISTICS */ 568 569 /**570 * Registers a I/O port ring-3 handler.571 *572 * This API is called by PDM on behalf of a device. Devices must first register573 * ring-3 ranges before any GC and R0 ranges can be registered using IOMR3IOPortRegisterRC()574 * and IOMR3IOPortRegisterR0().575 *576 *577 * @returns VBox status code.578 *579 * @param pVM The cross context VM structure.580 * @param pDevIns PDM device instance owning the port range.581 * @param PortStart First port number in the range.582 * @param cPorts Number of ports to register.583 * @param pvUser User argument for the callbacks.584 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in R3.585 * @param pfnInCallback Pointer to function which is gonna handle IN operations in R3.586 * @param pfnOutStrCallback Pointer to function which is gonna handle string OUT operations in R3.587 * @param pfnInStrCallback Pointer to function which is gonna handle string IN operations in R3.588 * @param pszDesc Pointer to description string. This must not be freed.589 */590 VMMR3_INT_DECL(int) IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTHCPTR pvUser,591 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,592 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, const char *pszDesc)593 {594 LogFlow(("IOMR3IOPortRegisterR3: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RHv pfnOutCallback=%#x pfnInCallback=%#x pfnOutStrCallback=%#x pfnInStrCallback=%#x pszDesc=%s\n",595 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));596 597 /*598 * Validate input.599 */600 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart601 || (RTUINT)PortStart + cPorts > 0x10000)602 {603 AssertMsgFailed(("Invalid port range %#x-%#x (inclusive)! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));604 return VERR_IOM_INVALID_IOPORT_RANGE;605 }606 if (!pfnOutCallback && !pfnInCallback)607 {608 AssertMsgFailed(("no handlers specfied for %#x-%#x (inclusive)! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));609 return VERR_INVALID_PARAMETER;610 }611 if (!pfnOutCallback)612 pfnOutCallback = iomR3IOPortDummyOut;613 if (!pfnInCallback)614 pfnInCallback = iomR3IOPortDummyIn;615 if (!pfnOutStrCallback)616 pfnOutStrCallback = iomR3IOPortDummyOutStr;617 if (!pfnInStrCallback)618 pfnInStrCallback = iomR3IOPortDummyInStr;619 620 /* Flush the IO port lookup cache */621 iomR3FlushCache(pVM);622 623 /*624 * Allocate new range record and initialize it.625 */626 PIOMIOPORTRANGER3 pRange;627 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);628 if (RT_SUCCESS(rc))629 {630 pRange->Core.Key = PortStart;631 pRange->Core.KeyLast = PortStart + (cPorts - 1);632 pRange->Port = PortStart;633 pRange->cPorts = cPorts;634 pRange->pvUser = pvUser;635 pRange->pDevIns = pDevIns;636 pRange->pfnOutCallback = pfnOutCallback;637 pRange->pfnInCallback = pfnInCallback;638 pRange->pfnOutStrCallback = pfnOutStrCallback;639 pRange->pfnInStrCallback = pfnInStrCallback;640 pRange->pszDesc = pszDesc;641 642 /*643 * Try Insert it.644 */645 IOM_LOCK_EXCL(pVM);646 if (RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR3, &pRange->Core))647 {648 #ifdef VBOX_WITH_STATISTICS649 for (unsigned iPort = 0; iPort < cPorts; iPort++)650 iomR3IOPortStatsCreate(pVM, PortStart + iPort, pszDesc);651 #endif652 IOM_UNLOCK_EXCL(pVM);653 return VINF_SUCCESS;654 }655 IOM_UNLOCK_EXCL(pVM);656 657 /* conflict. */658 DBGFR3Info(pVM->pUVM, "ioport", NULL, NULL);659 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));660 MMHyperFree(pVM, pRange);661 rc = VERR_IOM_IOPORT_RANGE_CONFLICT;662 }663 664 return rc;665 }666 667 668 #if 0669 /**670 * Registers a I/O port RC handler.671 *672 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges673 * using IOMIOPortRegisterR3() before calling this function.674 *675 *676 * @returns VBox status code.677 *678 * @param pVM The cross context VM structure.679 * @param pDevIns PDM device instance owning the port range.680 * @param PortStart First port number in the range.681 * @param cPorts Number of ports to register.682 * @param pvUser User argument for the callbacks.683 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in GC.684 * @param pfnInCallback Pointer to function which is gonna handle IN operations in GC.685 * @param pfnOutStrCallback Pointer to function which is gonna handle string OUT operations in GC.686 * @param pfnInStrCallback Pointer to function which is gonna handle string IN operations in GC.687 * @param pszDesc Pointer to description string. This must not be freed.688 */689 VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTRCPTR pvUser,690 RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback,691 RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, const char *pszDesc)692 {693 LogFlow(("IOMR3IOPortRegisterRC: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RRv pfnOutCallback=%RRv pfnInCallback=%RRv pfnOutStrCallback=%RRv pfnInStrCallback=%RRv pszDesc=%s\n",694 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));695 AssertReturn(VM_IS_RAW_MODE_ENABLED(pVM), VERR_IOM_HM_IPE);696 697 /*698 * Validate input.699 */700 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart701 || (RTUINT)PortStart + cPorts > 0x10000)702 {703 AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));704 return VERR_IOM_INVALID_IOPORT_RANGE;705 }706 RTIOPORT PortLast = PortStart + (cPorts - 1);707 if (!pfnOutCallback && !pfnInCallback)708 {709 AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc));710 return VERR_INVALID_PARAMETER;711 }712 713 IOM_LOCK_EXCL(pVM);714 715 /*716 * Validate that there are ring-3 ranges for the ports.717 */718 RTIOPORT Port = PortStart;719 while (Port <= PortLast && Port >= PortStart)720 {721 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);722 if (!pRange)723 {724 AssertMsgFailed(("No R3! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));725 IOM_UNLOCK_EXCL(pVM);726 return VERR_IOM_NO_R3_IOPORT_RANGE;727 }728 #ifndef IOM_NO_PDMINS_CHECKS729 if (pRange->pDevIns != pDevIns)730 {731 AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));732 IOM_UNLOCK_EXCL(pVM);733 return VERR_IOM_NOT_IOPORT_RANGE_OWNER;734 }735 #endif736 Port = pRange->Core.KeyLast + 1;737 }738 739 /* Flush the IO port lookup cache */740 iomR3FlushCache(pVM);741 742 /*743 * Allocate new range record and initialize it.744 */745 PIOMIOPORTRANGERC pRange;746 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);747 if (RT_SUCCESS(rc))748 {749 pRange->Core.Key = PortStart;750 pRange->Core.KeyLast = PortLast;751 pRange->Port = PortStart;752 pRange->cPorts = cPorts;753 pRange->pvUser = pvUser;754 pRange->pfnOutCallback = pfnOutCallback;755 pRange->pfnInCallback = pfnInCallback;756 pRange->pfnOutStrCallback = pfnOutStrCallback;757 pRange->pfnInStrCallback = pfnInStrCallback;758 pRange->pDevIns = pDevIns->pDevInsForRC;759 pRange->pszDesc = pszDesc;760 761 /*762 * Insert it.763 */764 if (RTAvlroIOPortInsert(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeRC, &pRange->Core))765 {766 IOM_UNLOCK_EXCL(pVM);767 return VINF_SUCCESS;768 }769 770 /* conflict. */771 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));772 MMHyperFree(pVM, pRange);773 rc = VERR_IOM_IOPORT_RANGE_CONFLICT;774 }775 IOM_UNLOCK_EXCL(pVM);776 return rc;777 }778 #endif779 780 781 /**782 * Registers a Port IO R0 handler.783 *784 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges785 * using IOMR3IOPortRegisterR3() before calling this function.786 *787 *788 * @returns VBox status code.789 *790 * @param pVM The cross context VM structure.791 * @param pDevIns PDM device instance owning the port range.792 * @param PortStart First port number in the range.793 * @param cPorts Number of ports to register.794 * @param pvUser User argument for the callbacks.795 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in GC.796 * @param pfnInCallback Pointer to function which is gonna handle IN operations in GC.797 * @param pfnOutStrCallback Pointer to function which is gonna handle OUT operations in GC.798 * @param pfnInStrCallback Pointer to function which is gonna handle IN operations in GC.799 * @param pszDesc Pointer to description string. This must not be freed.800 */801 VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser,802 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,803 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,804 const char *pszDesc)805 {806 LogFlow(("IOMR3IOPortRegisterR0: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%RHv pfnOutCallback=%RHv pfnInCallback=%RHv pfnOutStrCallback=%RHv pfnInStrCallback=%RHv pszDesc=%s\n",807 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));808 809 /*810 * Validate input.811 */812 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart813 || (RTUINT)PortStart + cPorts > 0x10000)814 {815 AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));816 return VERR_IOM_INVALID_IOPORT_RANGE;817 }818 RTIOPORT PortLast = PortStart + (cPorts - 1);819 if (!pfnOutCallback && !pfnInCallback)820 {821 AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc));822 return VERR_INVALID_PARAMETER;823 }824 825 IOM_LOCK_EXCL(pVM);826 827 /*828 * Validate that there are ring-3 ranges for the ports.829 */830 RTIOPORT Port = PortStart;831 while (Port <= PortLast && Port >= PortStart)832 {833 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);834 if (!pRange)835 {836 AssertMsgFailed(("No R3! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));837 IOM_UNLOCK_EXCL(pVM);838 return VERR_IOM_NO_R3_IOPORT_RANGE;839 }840 #ifndef IOM_NO_PDMINS_CHECKS841 if (pRange->pDevIns != pDevIns)842 {843 AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));844 IOM_UNLOCK_EXCL(pVM);845 return VERR_IOM_NOT_IOPORT_RANGE_OWNER;846 }847 #endif848 Port = pRange->Core.KeyLast + 1;849 }850 851 /* Flush the IO port lookup cache */852 iomR3FlushCache(pVM);853 854 /*855 * Allocate new range record and initialize it.856 */857 PIOMIOPORTRANGER0 pRange;858 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);859 if (RT_SUCCESS(rc))860 {861 pRange->Core.Key = PortStart;862 pRange->Core.KeyLast = PortLast;863 pRange->Port = PortStart;864 pRange->cPorts = cPorts;865 pRange->pvUser = pvUser;866 pRange->pfnOutCallback = pfnOutCallback;867 pRange->pfnInCallback = pfnInCallback;868 pRange->pfnOutStrCallback = pfnOutStrCallback;869 pRange->pfnInStrCallback = pfnInStrCallback;870 pRange->pDevIns = PDMDEVINS_2_R0PTR(pDevIns);871 pRange->pszDesc = pszDesc;872 873 /*874 * Insert it.875 */876 if (RTAvlroIOPortInsert(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR0, &pRange->Core))877 {878 IOM_UNLOCK_EXCL(pVM);879 return VINF_SUCCESS;880 }881 882 /* conflict. */883 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));884 MMHyperFree(pVM, pRange);885 rc = VERR_IOM_IOPORT_RANGE_CONFLICT;886 }887 IOM_UNLOCK_EXCL(pVM);888 return rc;889 }890 891 892 /**893 * Deregisters a I/O Port range.894 *895 * The specified range must be registered using IOMR3IOPortRegister previous to896 * this call. The range does can be a smaller part of the range specified to897 * IOMR3IOPortRegister, but it can never be larger.898 *899 * This function will remove GC, R0 and R3 context port handlers for this range.900 *901 * @returns VBox status code.902 *903 * @param pVM The cross context VM structure.904 * @param pDevIns The device instance associated with the range.905 * @param PortStart First port number in the range.906 * @param cPorts Number of ports to remove starting at PortStart.907 *908 * @remark This function mainly for PCI PnP Config and will not do909 * all the checks you might expect it to do.910 */911 VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts)912 {913 LogFlow(("IOMR3IOPortDeregister: pDevIns=%p PortStart=%#x cPorts=%#x\n", pDevIns, PortStart, cPorts));914 915 /*916 * Validate input.917 */918 if ( (RTUINT)PortStart + cPorts < (RTUINT)PortStart919 || (RTUINT)PortStart + cPorts > 0x10000)920 {921 AssertMsgFailed(("Invalid port range %#x-%#x!\n", PortStart, (unsigned)PortStart + cPorts - 1));922 return VERR_IOM_INVALID_IOPORT_RANGE;923 }924 925 IOM_LOCK_EXCL(pVM);926 927 /* Flush the IO port lookup cache */928 iomR3FlushCache(pVM);929 930 /*931 * Check ownership.932 */933 RTIOPORT PortLast = PortStart + (cPorts - 1);934 RTIOPORT Port = PortStart;935 while (Port <= PortLast && Port >= PortStart)936 {937 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeR3, Port);938 if (pRange)939 {940 Assert(Port <= pRange->Core.KeyLast);941 #ifndef IOM_NO_PDMINS_CHECKS942 if (pRange->pDevIns != pDevIns)943 {944 AssertMsgFailed(("Removal of ports in range %#x-%#x rejected because not owner of %#x-%#x (%s)\n",945 PortStart, PortLast, pRange->Core.Key, pRange->Core.KeyLast, pRange->pszDesc));946 IOM_UNLOCK_EXCL(pVM);947 return VERR_IOM_NOT_IOPORT_RANGE_OWNER;948 }949 #else /* IOM_NO_PDMINS_CHECKS */950 RT_NOREF_PV(pDevIns);951 #endif /* IOM_NO_PDMINS_CHECKS */952 Port = pRange->Core.KeyLast;953 }954 Port++;955 }956 957 #if 0958 /*959 * Remove any RC ranges first.960 */961 int rc = VINF_SUCCESS;962 Port = PortStart;963 while (Port <= PortLast && Port >= PortStart)964 {965 /*966 * Try find range.967 */968 PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeRC, Port);969 if (pRange)970 {971 if ( pRange->Core.Key == Port972 && pRange->Core.KeyLast <= PortLast)973 {974 /*975 * Kick out the entire range.976 */977 void *pv = RTAvlroIOPortRemove(&pVM->iom.s.pTreesR3->IOPortTreeRC, Port);978 Assert(pv == (void *)pRange); NOREF(pv);979 Port += pRange->cPorts;980 MMHyperFree(pVM, pRange);981 }982 else if (pRange->Core.Key == Port)983 {984 /*985 * Cut of the head of the range, done.986 */987 pRange->cPorts -= Port - pRange->Port;988 pRange->Core.Key = Port;989 pRange->Port = Port;990 break;991 }992 else if (pRange->Core.KeyLast <= PortLast)993 {994 /*995 * Just cut of the tail.996 */997 unsigned c = pRange->Core.KeyLast - Port + 1;998 pRange->Core.KeyLast -= c;999 pRange->cPorts -= c;1000 Port += c;1001 }1002 else1003 {1004 /*1005 * Split the range, done.1006 */1007 Assert(pRange->Core.KeyLast > PortLast && pRange->Core.Key < Port);1008 /* create tail. */1009 PIOMIOPORTRANGERC pRangeNew;1010 int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew);1011 if (RT_FAILURE(rc2))1012 {1013 IOM_UNLOCK_EXCL(pVM);1014 return rc2;1015 }1016 *pRangeNew = *pRange;1017 pRangeNew->Core.Key = PortLast;1018 pRangeNew->Port = PortLast;1019 pRangeNew->cPorts = pRangeNew->Core.KeyLast - PortLast + 1;1020 1021 LogFlow(("IOMR3IOPortDeregister (rc): split the range; new %x\n", pRangeNew->Core.Key));1022 1023 /* adjust head */1024 pRange->Core.KeyLast = Port - 1;1025 pRange->cPorts = Port - pRange->Port;1026 1027 /* insert */1028 if (!RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeRC, &pRangeNew->Core))1029 {1030 AssertMsgFailed(("This cannot happen!\n"));1031 MMHyperFree(pVM, pRangeNew);1032 rc = VERR_IOM_IOPORT_IPE_1;1033 }1034 break;1035 }1036 }1037 else /* next port */1038 Port++;1039 } /* for all ports - RC. */1040 #else1041 int rc = VINF_SUCCESS;1042 #endif1043 1044 /*1045 * Remove any R0 ranges.1046 */1047 Port = PortStart;1048 while (Port <= PortLast && Port >= PortStart)1049 {1050 /*1051 * Try find range.1052 */1053 PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeR0, Port);1054 if (pRange)1055 {1056 if ( pRange->Core.Key == Port1057 && pRange->Core.KeyLast <= PortLast)1058 {1059 /*1060 * Kick out the entire range.1061 */1062 void *pv = RTAvlroIOPortRemove(&pVM->iom.s.pTreesR3->IOPortTreeR0, Port);1063 Assert(pv == (void *)pRange); NOREF(pv);1064 Port += pRange->cPorts;1065 MMHyperFree(pVM, pRange);1066 }1067 else if (pRange->Core.Key == Port)1068 {1069 /*1070 * Cut of the head of the range, done.1071 */1072 pRange->cPorts -= Port - pRange->Port;1073 pRange->Core.Key = Port;1074 pRange->Port = Port;1075 break;1076 }1077 else if (pRange->Core.KeyLast <= PortLast)1078 {1079 /*1080 * Just cut of the tail.1081 */1082 unsigned c = pRange->Core.KeyLast - Port + 1;1083 pRange->Core.KeyLast -= c;1084 pRange->cPorts -= c;1085 Port += c;1086 }1087 else1088 {1089 /*1090 * Split the range, done.1091 */1092 Assert(pRange->Core.KeyLast > PortLast && pRange->Core.Key < Port);1093 /* create tail. */1094 PIOMIOPORTRANGER0 pRangeNew;1095 int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew);1096 if (RT_FAILURE(rc2))1097 {1098 IOM_UNLOCK_EXCL(pVM);1099 return rc2;1100 }1101 *pRangeNew = *pRange;1102 pRangeNew->Core.Key = PortLast;1103 pRangeNew->Port = PortLast;1104 pRangeNew->cPorts = pRangeNew->Core.KeyLast - PortLast + 1;1105 1106 LogFlow(("IOMR3IOPortDeregister (r0): split the range; new %x\n", pRangeNew->Core.Key));1107 1108 /* adjust head */1109 pRange->Core.KeyLast = Port - 1;1110 pRange->cPorts = Port - pRange->Port;1111 1112 /* insert */1113 if (!RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR0, &pRangeNew->Core))1114 {1115 AssertMsgFailed(("This cannot happen!\n"));1116 MMHyperFree(pVM, pRangeNew);1117 rc = VERR_IOM_IOPORT_IPE_1;1118 }1119 break;1120 }1121 }1122 else /* next port */1123 Port++;1124 } /* for all ports - R0. */1125 1126 /*1127 * And the same procedure for ring-3 ranges.1128 */1129 Port = PortStart;1130 while (Port <= PortLast && Port >= PortStart)1131 {1132 /*1133 * Try find range.1134 */1135 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.pTreesR3->IOPortTreeR3, Port);1136 if (pRange)1137 {1138 if ( pRange->Core.Key == Port1139 && pRange->Core.KeyLast <= PortLast)1140 {1141 /*1142 * Kick out the entire range.1143 */1144 void *pv = RTAvlroIOPortRemove(&pVM->iom.s.pTreesR3->IOPortTreeR3, Port);1145 Assert(pv == (void *)pRange); NOREF(pv);1146 Port += pRange->cPorts;1147 MMHyperFree(pVM, pRange);1148 }1149 else if (pRange->Core.Key == Port)1150 {1151 /*1152 * Cut of the head of the range, done.1153 */1154 pRange->cPorts -= Port - pRange->Port;1155 pRange->Core.Key = Port;1156 pRange->Port = Port;1157 break;1158 }1159 else if (pRange->Core.KeyLast <= PortLast)1160 {1161 /*1162 * Just cut of the tail.1163 */1164 unsigned c = pRange->Core.KeyLast - Port + 1;1165 pRange->Core.KeyLast -= c;1166 pRange->cPorts -= c;1167 Port += c;1168 }1169 else1170 {1171 /*1172 * Split the range, done.1173 */1174 Assert(pRange->Core.KeyLast > PortLast && pRange->Core.Key < Port);1175 /* create tail. */1176 PIOMIOPORTRANGER3 pRangeNew;1177 int rc2 = MMHyperAlloc(pVM, sizeof(*pRangeNew), 0, MM_TAG_IOM, (void **)&pRangeNew);1178 if (RT_FAILURE(rc2))1179 {1180 IOM_UNLOCK_EXCL(pVM);1181 return rc2;1182 }1183 *pRangeNew = *pRange;1184 pRangeNew->Core.Key = PortLast;1185 pRangeNew->Port = PortLast;1186 pRangeNew->cPorts = pRangeNew->Core.KeyLast - PortLast + 1;1187 1188 LogFlow(("IOMR3IOPortDeregister (r3): split the range; new %x\n", pRangeNew->Core.Key));1189 1190 /* adjust head */1191 pRange->Core.KeyLast = Port - 1;1192 pRange->cPorts = Port - pRange->Port;1193 1194 /* insert */1195 if (!RTAvlroIOPortInsert(&pVM->iom.s.pTreesR3->IOPortTreeR3, &pRangeNew->Core))1196 {1197 AssertMsgFailed(("This cannot happen!\n"));1198 MMHyperFree(pVM, pRangeNew);1199 rc = VERR_IOM_IOPORT_IPE_1;1200 }1201 break;1202 }1203 }1204 else /* next port */1205 Port++;1206 } /* for all ports - ring-3. */1207 1208 /* done */1209 IOM_UNLOCK_EXCL(pVM);1210 return rc;1211 }1212 1213 1214 /**1215 * Dummy Port I/O Handler for IN operations.1216 *1217 * @returns VBox status code.1218 *1219 * @param pDevIns The device instance.1220 * @param pvUser User argument.1221 * @param Port Port number used for the IN operation.1222 * @param pu32 Where to store the result.1223 * @param cb Number of bytes read.1224 */1225 static DECLCALLBACK(int) iomR3IOPortDummyIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)1226 {1227 NOREF(pDevIns); NOREF(pvUser); NOREF(Port);1228 switch (cb)1229 {1230 case 1: *pu32 = 0xff; break;1231 case 2: *pu32 = 0xffff; break;1232 case 4: *pu32 = UINT32_C(0xffffffff); break;1233 default:1234 AssertReleaseMsgFailed(("cb=%d\n", cb));1235 return VERR_IOM_IOPORT_IPE_2;1236 }1237 return VINF_SUCCESS;1238 }1239 1240 1241 /**1242 * @callback_method_impl{FNIOMIOPORTINSTRING,1243 * Dummy Port I/O Handler for string IN operations.}1244 */1245 static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t *pbDst,1246 uint32_t *pcTransfer, unsigned cb)1247 {1248 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pbDst); NOREF(pcTransfer); NOREF(cb);1249 return VINF_SUCCESS;1250 }1251 1252 1253 /**1254 * Dummy Port I/O Handler for OUT operations.1255 *1256 * @returns VBox status code.1257 *1258 * @param pDevIns The device instance.1259 * @param pvUser User argument.1260 * @param Port Port number used for the OUT operation.1261 * @param u32 The value to output.1262 * @param cb The value size in bytes.1263 */1264 static DECLCALLBACK(int) iomR3IOPortDummyOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)1265 {1266 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(u32); NOREF(cb);1267 return VINF_SUCCESS;1268 }1269 1270 1271 /**1272 * @callback_method_impl{FNIOMIOPORTOUTSTRING,1273 * Dummy Port I/O Handler for string OUT operations.}1274 */1275 static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint8_t const *pbSrc,1276 uint32_t *pcTransfer, unsigned cb)1277 {1278 NOREF(pDevIns); NOREF(pvUser); NOREF(Port); NOREF(pbSrc); NOREF(pcTransfer); NOREF(cb);1279 return VINF_SUCCESS;1280 }1281 1282 1283 405 1284 406 /** -
trunk/src/VBox/VMM/VMMR3/IOMR3IoPort.cpp
r82277 r82311 592 592 593 593 /** 594 * Display a single I/O port ring-3 range.595 *596 * @returns 0597 * @param pNode Pointer to I/O port HC range.598 * @param pvUser Pointer to info output callback structure.599 */600 static DECLCALLBACK(int) iomR3IOPortInfoOneR3(PAVLROIOPORTNODECORE pNode, void *pvUser)601 {602 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)pNode;603 PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;604 pHlp->pfnPrintf(pHlp,605 "%04x-%04x %p %p %p %p %s\n",606 pRange->Core.Key,607 pRange->Core.KeyLast,608 pRange->pDevIns,609 pRange->pfnInCallback,610 pRange->pfnOutCallback,611 pRange->pvUser,612 pRange->pszDesc);613 return 0;614 }615 616 617 /**618 594 * Display all registered I/O port ranges. 619 595 * … … 624 600 DECLCALLBACK(void) iomR3IoPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs) 625 601 { 602 RT_NOREF(pszArgs); 603 626 604 /* No locking needed here as registerations are only happening during VMSTATE_CREATING. */ 627 605 pHlp->pfnPrintf(pHlp, … … 648 626 paRegs[i].idxSelf, pszRing, paRegs[i].cPorts, paRegs[i].pszDesc); 649 627 } 650 651 /* Legacy registration: */ 652 NOREF(pszArgs); 653 pHlp->pfnPrintf(pHlp, 654 "I/O Port R3 ranges (pVM=%p)\n" 655 "Range %.*s %.*s %.*s %.*s Description\n", 656 pVM, 657 sizeof(RTHCPTR) * 2, "pDevIns ", 658 sizeof(RTHCPTR) * 2, "In ", 659 sizeof(RTHCPTR) * 2, "Out ", 660 sizeof(RTHCPTR) * 2, "pvUser "); 661 IOM_LOCK_SHARED(pVM); 662 RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeR3, true, iomR3IOPortInfoOneR3, (void *)pHlp); 663 IOM_UNLOCK_SHARED(pVM); 664 665 pHlp->pfnPrintf(pHlp, 666 "I/O Port R0 ranges (pVM=%p)\n" 667 "Range %.*s %.*s %.*s %.*s Description\n", 668 pVM, 669 sizeof(RTHCPTR) * 2, "pDevIns ", 670 sizeof(RTHCPTR) * 2, "In ", 671 sizeof(RTHCPTR) * 2, "Out ", 672 sizeof(RTHCPTR) * 2, "pvUser "); 673 IOM_LOCK_SHARED(pVM); 674 RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeR0, true, iomR3IOPortInfoOneR3, (void *)pHlp); 675 IOM_UNLOCK_SHARED(pVM); 676 } 677 628 } 629 -
trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
r82224 r82311 139 139 LogFlow(("pdmR3DevHlp_IoPortGetMappingAddress: caller='%s'/%d: returns %#RX32\n", pDevIns->pReg->szName, pDevIns->iInstance, uAddress)); 140 140 return uAddress; 141 }142 143 144 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegister} */145 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTHCPTR pvUser, PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,146 PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)147 {148 PDMDEV_ASSERT_DEVINS(pDevIns);149 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,150 Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc, pszDesc));151 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);152 153 #if 0 /** @todo needs a real string cache for this */154 if (pDevIns->iInstance > 0)155 {156 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);157 if (pszDesc2)158 pszDesc = pszDesc2;159 }160 #endif161 162 int rc = IOMR3IOPortRegisterR3(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser,163 pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);164 165 LogFlow(("pdmR3DevHlp_IOPortRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));166 return rc;167 }168 169 170 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegisterRC} */171 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterRC(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTRCPTR pvUser,172 const char *pszOut, const char *pszIn,173 const char *pszOutStr, const char *pszInStr, const char *pszDesc)174 {175 PDMDEV_ASSERT_DEVINS(pDevIns);176 Assert(pDevIns->pReg->pszRCMod[0]);177 Assert(pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC);178 LogFlow(("pdmR3DevHlp_IOPortRegisterRC: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,179 Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));180 181 #if 0182 /*183 * Resolve the functions (one of the can be NULL).184 */185 PVM pVM = pDevIns->Internal.s.pVMR3;186 VM_ASSERT_EMT(pVM);187 int rc = VINF_SUCCESS;188 if ( pDevIns->pReg->pszRCMod[0]189 && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_RC)190 && VM_IS_RAW_MODE_ENABLED(pVM))191 {192 RTRCPTR RCPtrIn = NIL_RTRCPTR;193 if (pszIn)194 {195 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszIn, &RCPtrIn);196 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pReg->pszRCMod, pszIn));197 }198 RTRCPTR RCPtrOut = NIL_RTRCPTR;199 if (pszOut && RT_SUCCESS(rc))200 {201 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszOut, &RCPtrOut);202 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pReg->pszRCMod, pszOut));203 }204 RTRCPTR RCPtrInStr = NIL_RTRCPTR;205 if (pszInStr && RT_SUCCESS(rc))206 {207 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszInStr, &RCPtrInStr);208 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pReg->pszRCMod, pszInStr));209 }210 RTRCPTR RCPtrOutStr = NIL_RTRCPTR;211 if (pszOutStr && RT_SUCCESS(rc))212 {213 rc = pdmR3DevGetSymbolRCLazy(pDevIns, pszOutStr, &RCPtrOutStr);214 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pReg->pszRCMod, pszOutStr));215 }216 217 if (RT_SUCCESS(rc))218 {219 #if 0 /** @todo needs a real string cache for this */220 if (pDevIns->iInstance > 0)221 {222 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);223 if (pszDesc2)224 pszDesc = pszDesc2;225 }226 #endif227 228 rc = IOMR3IOPortRegisterRC(pVM, pDevIns, Port, cPorts, pvUser, RCPtrOut, RCPtrIn, RCPtrOutStr, RCPtrInStr, pszDesc);229 }230 }231 else if (VM_IS_RAW_MODE_ENABLED(pVM))232 {233 AssertMsgFailed(("No RC module for this driver!\n"));234 rc = VERR_INVALID_PARAMETER;235 }236 #else237 RT_NOREF(pDevIns, Port, cPorts, pvUser, pszOut, pszIn, pszOutStr, pszInStr, pszDesc);238 int rc = VINF_SUCCESS;239 #endif240 241 LogFlow(("pdmR3DevHlp_IOPortRegisterRC: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));242 return rc;243 }244 245 246 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortRegisterR0} */247 static DECLCALLBACK(int) pdmR3DevHlp_IOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTR0PTR pvUser,248 const char *pszOut, const char *pszIn,249 const char *pszOutStr, const char *pszInStr, const char *pszDesc)250 {251 PDMDEV_ASSERT_DEVINS(pDevIns);252 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);253 LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: Port=%#x cPorts=%#x pvUser=%p pszOut=%p:{%s} pszIn=%p:{%s} pszOutStr=%p:{%s} pszInStr=%p:{%s} pszDesc=%p:{%s}\n", pDevIns->pReg->szName, pDevIns->iInstance,254 Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));255 256 /*257 * Resolve the functions (one of the can be NULL).258 */259 int rc = VINF_SUCCESS;260 if ( pDevIns->pReg->pszR0Mod[0]261 && (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0))262 {263 R0PTRTYPE(PFNIOMIOPORTIN) pfnR0PtrIn = 0;264 if (pszIn)265 {266 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszIn, &pfnR0PtrIn);267 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszIn)\n", pDevIns->pReg->pszR0Mod, pszIn));268 }269 R0PTRTYPE(PFNIOMIOPORTOUT) pfnR0PtrOut = 0;270 if (pszOut && RT_SUCCESS(rc))271 {272 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszOut, &pfnR0PtrOut);273 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOut)\n", pDevIns->pReg->pszR0Mod, pszOut));274 }275 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnR0PtrInStr = 0;276 if (pszInStr && RT_SUCCESS(rc))277 {278 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszInStr, &pfnR0PtrInStr);279 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszInStr)\n", pDevIns->pReg->pszR0Mod, pszInStr));280 }281 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnR0PtrOutStr = 0;282 if (pszOutStr && RT_SUCCESS(rc))283 {284 rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pszOutStr, &pfnR0PtrOutStr);285 AssertMsgRC(rc, ("Failed to resolve %s.%s (pszOutStr)\n", pDevIns->pReg->pszR0Mod, pszOutStr));286 }287 288 if (RT_SUCCESS(rc))289 {290 #if 0 /** @todo needs a real string cache for this */291 if (pDevIns->iInstance > 0)292 {293 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);294 if (pszDesc2)295 pszDesc = pszDesc2;296 }297 #endif298 299 rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);300 }301 }302 else303 {304 AssertMsgFailed(("No R0 module for this driver!\n"));305 rc = VERR_INVALID_PARAMETER;306 }307 308 LogFlow(("pdmR3DevHlp_IOPortRegisterR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));309 return rc;310 }311 312 313 /** @interface_method_impl{PDMDEVHLPR3,pfnIOPortDeregister} */314 static DECLCALLBACK(int) pdmR3DevHlp_IOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts)315 {316 PDMDEV_ASSERT_DEVINS(pDevIns);317 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);318 LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: Port=%#x cPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance,319 Port, cPorts));320 321 int rc = IOMR3IOPortDeregister(pDevIns->Internal.s.pVMR3, pDevIns, Port, cPorts);322 323 LogFlow(("pdmR3DevHlp_IOPortDeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));324 return rc;325 141 } 326 142 … … 697 513 698 514 LogFlow(("pdmR3DevHlp_Mmio2ChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc)); 699 return rc;700 }701 702 703 /**704 * @copydoc PDMDEVHLPR3::pfnMMIO2Register705 */706 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2Register(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cb,707 uint32_t fFlags, void **ppv, const char *pszDesc)708 {709 PDMDEV_ASSERT_DEVINS(pDevIns);710 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);711 LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: pPciDev=%p (%#x) iRegion=%#x cb=%#RGp fFlags=%RX32 ppv=%p pszDescp=%p:{%s}\n",712 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion,713 cb, fFlags, ppv, pszDesc, pszDesc));714 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);715 716 /** @todo PGMR3PhysMMIO2Register mangles the description, move it here and717 * use a real string cache. */718 int rc = PGMR3PhysMMIO2Register(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,719 cb, fFlags, pszDesc, ppv, NULL);720 721 LogFlow(("pdmR3DevHlp_MMIO2Register: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));722 return rc;723 }724 725 726 /**727 * @copydoc PDMDEVHLPR3::pfnMMIOExDeregister728 */729 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExDeregister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion)730 {731 PDMDEV_ASSERT_DEVINS(pDevIns);732 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);733 LogFlow(("pdmR3DevHlp_MMIOExDeregister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x\n",734 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion));735 736 AssertReturn(iRegion <= UINT8_MAX || iRegion == UINT32_MAX, VERR_INVALID_PARAMETER);737 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);738 739 int rc = PGMR3PhysMMIOExDeregister(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254,740 iRegion, NIL_PGMMMIO2HANDLE);741 742 LogFlow(("pdmR3DevHlp_MMIOExDeregister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));743 return rc;744 }745 746 747 /**748 * @copydoc PDMDEVHLPR3::pfnMMIOExMap749 */750 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS GCPhys)751 {752 PDMDEV_ASSERT_DEVINS(pDevIns);753 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);754 LogFlow(("pdmR3DevHlp_MMIOExMap: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x GCPhys=%#RGp\n",755 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, GCPhys));756 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);757 758 int rc = PGMR3PhysMMIOExMap(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,759 NIL_PGMMMIO2HANDLE, GCPhys);760 761 LogFlow(("pdmR3DevHlp_MMIOExMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));762 return rc;763 }764 765 766 /**767 * @copydoc PDMDEVHLPR3::pfnMMIOExUnmap768 */769 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS GCPhys)770 {771 PDMDEV_ASSERT_DEVINS(pDevIns);772 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);773 LogFlow(("pdmR3DevHlp_MMIOExUnmap: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x GCPhys=%#RGp\n",774 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, GCPhys));775 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);776 777 int rc = PGMR3PhysMMIOExUnmap(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,778 NIL_PGMMMIO2HANDLE, GCPhys);779 780 LogFlow(("pdmR3DevHlp_MMIOExUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));781 return rc;782 }783 784 785 /**786 * @copydoc PDMDEVHLPR3::pfnMMIOExReduce787 */788 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExReduce(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS cbRegion)789 {790 PDMDEV_ASSERT_DEVINS(pDevIns);791 VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);792 LogFlow(("pdmR3DevHlp_MMIOExReduce: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x cbRegion=%RGp\n",793 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, cbRegion));794 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 != NULL, VERR_INVALID_PARAMETER);795 796 int rc = PGMR3PhysMMIOExReduce(pDevIns->Internal.s.pVMR3, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,797 NIL_PGMMMIO2HANDLE, cbRegion);798 799 LogFlow(("pdmR3DevHlp_MMIOExReduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));800 return rc;801 }802 803 804 /**805 * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2806 */807 static DECLCALLBACK(int) pdmR3DevHlp_MMHyperMapMMIO2(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS off,808 RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr)809 {810 PDMDEV_ASSERT_DEVINS(pDevIns);811 #ifndef PGM_WITHOUT_MAPPINGS812 PVM pVM = pDevIns->Internal.s.pVMR3;813 VM_ASSERT_EMT(pVM);814 LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x off=%RGp cb=%RGp pszDesc=%p:{%s} pRCPtr=%p\n",815 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, off, cb, pszDesc, pszDesc, pRCPtr));816 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);817 818 if (pDevIns->iInstance > 0)819 {820 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);821 if (pszDesc2)822 pszDesc = pszDesc2;823 }824 825 int rc = MMR3HyperMapMMIO2(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, off, cb, pszDesc, pRCPtr);826 827 #else828 RT_NOREF(pDevIns, pPciDev, iRegion, off, cb, pszDesc, pRCPtr);829 AssertFailed();830 int rc = VERR_RAW_MODE_NOT_SUPPORTED;831 #endif832 LogFlow(("pdmR3DevHlp_MMHyperMapMMIO2: caller='%s'/%d: returns %Rrc *pRCPtr=%RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pRCPtr));833 return rc;834 }835 836 837 /**838 * @copydoc PDMDEVHLPR3::pfnMMIO2MapKernel839 */840 static DECLCALLBACK(int) pdmR3DevHlp_MMIO2MapKernel(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion, RTGCPHYS off,841 RTGCPHYS cb,const char *pszDesc, PRTR0PTR pR0Ptr)842 {843 PDMDEV_ASSERT_DEVINS(pDevIns);844 PVM pVM = pDevIns->Internal.s.pVMR3;845 VM_ASSERT_EMT(pVM);846 LogFlow(("pdmR3DevHlp_MMIO2MapKernel: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x off=%RGp cb=%RGp pszDesc=%p:{%s} pR0Ptr=%p\n",847 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, off, cb, pszDesc, pszDesc, pR0Ptr));848 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);849 850 if (pDevIns->iInstance > 0)851 {852 char *pszDesc2 = MMR3HeapAPrintf(pVM, MM_TAG_PDM_DEVICE_DESC, "%s [%u]", pszDesc, pDevIns->iInstance);853 if (pszDesc2)854 pszDesc = pszDesc2;855 }856 857 int rc = PGMR3PhysMMIO2MapKernel(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion, off, cb, pszDesc, pR0Ptr);858 859 LogFlow(("pdmR3DevHlp_MMIO2MapKernel: caller='%s'/%d: returns %Rrc *pR0Ptr=%RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pR0Ptr));860 return rc;861 }862 863 864 /**865 * @copydoc PDMDEVHLPR3::pfnMMIOExChangeRegionNo866 */867 static DECLCALLBACK(int) pdmR3DevHlp_MMIOExChangeRegionNo(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,868 uint32_t iNewRegion)869 {870 PDMDEV_ASSERT_DEVINS(pDevIns);871 PVM pVM = pDevIns->Internal.s.pVMR3;872 VM_ASSERT_EMT(pVM);873 LogFlow(("pdmR3DevHlp_MMIOExChangeRegionNo: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%#x iNewRegion=%#x\n",874 pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iRegion, iNewRegion));875 AssertReturn(!pPciDev || pPciDev->Int.s.pDevInsR3 == pDevIns, VERR_INVALID_PARAMETER);876 877 int rc = PGMR3PhysMMIOExChangeRegionNo(pVM, pDevIns, pPciDev ? pPciDev->Int.s.idxDevCfg : 254, iRegion,878 NIL_PGMMMIO2HANDLE, iNewRegion);879 880 LogFlow(("pdmR3DevHlp_MMIOExChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));881 515 return rc; 882 516 } … … 2096 1730 } 2097 1731 1732 /* This flag is required now. */ 1733 AssertLogRelMsgReturn(fFlags & PDMPCIDEV_IORGN_F_NEW_STYLE, 1734 ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags), 1735 VERR_INVALID_FLAGS); 1736 2098 1737 /* 2099 1738 * We're currently restricted to page aligned MMIO regions. … … 4345 3984 pdmR3DevHlp_IoPortUnmap, 4346 3985 pdmR3DevHlp_IoPortGetMappingAddress, 4347 pdmR3DevHlp_IOPortRegister,4348 pdmR3DevHlp_IOPortRegisterRC,4349 pdmR3DevHlp_IOPortRegisterR0,4350 pdmR3DevHlp_IOPortDeregister,4351 3986 pdmR3DevHlp_MmioCreateEx, 4352 3987 pdmR3DevHlp_MmioMap, … … 4365 4000 pdmR3DevHlp_Mmio2GetMappingAddress, 4366 4001 pdmR3DevHlp_Mmio2ChangeRegionNo, 4367 pdmR3DevHlp_MMIO2Register,4368 pdmR3DevHlp_MMIOExDeregister,4369 pdmR3DevHlp_MMIOExMap,4370 pdmR3DevHlp_MMIOExUnmap,4371 pdmR3DevHlp_MMIOExReduce,4372 pdmR3DevHlp_MMHyperMapMMIO2,4373 pdmR3DevHlp_MMIO2MapKernel,4374 4002 pdmR3DevHlp_ROMRegister, 4375 4003 pdmR3DevHlp_ROMProtectShadow, … … 4658 4286 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly, 4659 4287 pdmR3DevHlp_PhysBulkReleasePageMappingLocks, 4660 pdmR3DevHlp_MMIOExChangeRegionNo,4661 4288 0, 4662 4289 0, … … 4843 4470 pdmR3DevHlp_IoPortUnmap, 4844 4471 pdmR3DevHlp_IoPortGetMappingAddress, 4845 pdmR3DevHlp_IOPortRegister,4846 pdmR3DevHlp_IOPortRegisterRC,4847 pdmR3DevHlp_IOPortRegisterR0,4848 pdmR3DevHlp_IOPortDeregister,4849 4472 pdmR3DevHlp_MmioCreateEx, 4850 4473 pdmR3DevHlp_MmioMap, … … 4863 4486 pdmR3DevHlp_Mmio2GetMappingAddress, 4864 4487 pdmR3DevHlp_Mmio2ChangeRegionNo, 4865 pdmR3DevHlp_MMIO2Register,4866 pdmR3DevHlp_MMIOExDeregister,4867 pdmR3DevHlp_MMIOExMap,4868 pdmR3DevHlp_MMIOExUnmap,4869 pdmR3DevHlp_MMIOExReduce,4870 pdmR3DevHlp_MMHyperMapMMIO2,4871 pdmR3DevHlp_MMIO2MapKernel,4872 4488 pdmR3DevHlp_ROMRegister, 4873 4489 pdmR3DevHlp_ROMProtectShadow, … … 5156 4772 pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly, 5157 4773 pdmR3DevHlp_PhysBulkReleasePageMappingLocks, 5158 pdmR3DevHlp_MMIOExChangeRegionNo,5159 4774 0, 5160 4775 0, -
trunk/src/VBox/VMM/include/IOMInline.h
r81333 r82311 257 257 258 258 /** 259 * Gets the I/O port range for the specified I/O port in the current context.260 *261 * @returns Pointer to I/O port range.262 * @returns NULL if no port registered.263 *264 * @param pVM The cross context VM structure.265 * @param Port The I/O port lookup.266 */267 DECLINLINE(CTX_SUFF(PIOMIOPORTRANGE)) iomIOPortGetRange(PVM pVM, RTIOPORT Port)268 {269 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));270 return (CTX_SUFF(PIOMIOPORTRANGE))RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->CTX_SUFF(IOPortTree), Port);271 }272 273 274 /**275 * Gets the I/O port range for the specified I/O port in the HC.276 *277 * @returns Pointer to I/O port range.278 * @returns NULL if no port registered.279 *280 * @param pVM The cross context VM structure.281 * @param Port The I/O port to lookup.282 */283 DECLINLINE(PIOMIOPORTRANGER3) iomIOPortGetRangeR3(PVM pVM, RTIOPORT Port)284 {285 Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));286 return (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortTreeR3, Port);287 }288 289 290 /**291 259 * Gets the MMIO range for the specified physical address in the current context. 292 260 * -
trunk/src/VBox/VMM/include/IOMInternal.h
r81463 r82311 407 407 408 408 /** 409 * I/O port range descriptor, R3 version.410 */411 typedef struct IOMIOPORTRANGER3412 {413 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */414 AVLROIOPORTNODECORE Core;415 #if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)416 uint32_t u32Alignment; /**< The sizeof(Core) differs. */417 #endif418 /** Start I/O port address. */419 RTIOPORT Port;420 /** Size of the range. */421 uint16_t cPorts;422 /** Pointer to user argument. */423 RTR3PTR pvUser;424 /** Pointer to the associated device instance. */425 R3PTRTYPE(PPDMDEVINS) pDevIns;426 /** Pointer to OUT callback function. */427 R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;428 /** Pointer to IN callback function. */429 R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;430 /** Pointer to string OUT callback function. */431 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;432 /** Pointer to string IN callback function. */433 R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;434 /** Description / Name. For easing debugging. */435 R3PTRTYPE(const char *) pszDesc;436 } IOMIOPORTRANGER3;437 /** Pointer to I/O port range descriptor, R3 version. */438 typedef IOMIOPORTRANGER3 *PIOMIOPORTRANGER3;439 440 /**441 * I/O port range descriptor, R0 version.442 */443 typedef struct IOMIOPORTRANGER0444 {445 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */446 AVLROIOPORTNODECORE Core;447 #if HC_ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)448 uint32_t u32Alignment; /**< The sizeof(Core) differs. */449 #endif450 /** Start I/O port address. */451 RTIOPORT Port;452 /** Size of the range. */453 uint16_t cPorts;454 /** Pointer to user argument. */455 RTR0PTR pvUser;456 /** Pointer to the associated device instance. */457 R0PTRTYPE(PPDMDEVINS) pDevIns;458 /** Pointer to OUT callback function. */459 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;460 /** Pointer to IN callback function. */461 R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback;462 /** Pointer to string OUT callback function. */463 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;464 /** Pointer to string IN callback function. */465 R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;466 /** Description / Name. For easing debugging. */467 R3PTRTYPE(const char *) pszDesc;468 } IOMIOPORTRANGER0;469 /** Pointer to I/O port range descriptor, R0 version. */470 typedef IOMIOPORTRANGER0 *PIOMIOPORTRANGER0;471 472 /**473 * I/O port range descriptor, RC version.474 */475 typedef struct IOMIOPORTRANGERC476 {477 /** Avl node core with Port as Key and Port + cPorts - 1 as KeyLast. */478 AVLROIOPORTNODECORE Core;479 /** Start I/O port address. */480 RTIOPORT Port;481 /** Size of the range. */482 uint16_t cPorts;483 /** Pointer to user argument. */484 RTRCPTR pvUser;485 /** Pointer to the associated device instance. */486 RCPTRTYPE(PPDMDEVINS) pDevIns;487 /** Pointer to OUT callback function. */488 RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback;489 /** Pointer to IN callback function. */490 RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback;491 /** Pointer to string OUT callback function. */492 RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback;493 /** Pointer to string IN callback function. */494 RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback;495 #if HC_ARCH_BITS == 64496 RTRCPTR RCPtrAlignment; /**< pszDesc is 8 byte aligned. */497 #endif498 /** Description / Name. For easing debugging. */499 R3PTRTYPE(const char *) pszDesc;500 } IOMIOPORTRANGERC;501 /** Pointer to I/O port range descriptor, RC version. */502 typedef IOMIOPORTRANGERC *PIOMIOPORTRANGERC;503 504 505 /**506 * I/O port statistics. (one I/O port)507 *508 * This is a simple way of making on demand statistics, however it's a509 * bit free with the hypervisor heap memory.510 */511 typedef struct IOMIOPORTSTATS512 {513 /** Avl node core with the port as Key. */514 AVLOIOPORTNODECORE Core;515 #if HC_ARCH_BITS != 64 || !defined(RT_OS_WINDOWS)516 uint32_t u32Alignment; /**< The sizeof(Core) differs. */517 #endif518 /** Number of INs to this port from R3. */519 STAMCOUNTER InR3;520 /** Profiling IN handler overhead in R3. */521 STAMPROFILE ProfInR3;522 /** Number of OUTs to this port from R3. */523 STAMCOUNTER OutR3;524 /** Profiling OUT handler overhead in R3. */525 STAMPROFILE ProfOutR3;526 527 /** Number of INs to this port from R0/RC. */528 STAMCOUNTER InRZ;529 /** Profiling IN handler overhead in R0/RC. */530 STAMPROFILE ProfInRZ;531 /** Number of INs to this port from R0/RC which was serviced in R3. */532 STAMCOUNTER InRZToR3;533 534 /** Number of OUTs to this port from R0/RC. */535 STAMCOUNTER OutRZ;536 /** Profiling OUT handler overhead in R0/RC. */537 STAMPROFILE ProfOutRZ;538 /** Number of OUTs to this port from R0/RC which was serviced in R3. */539 STAMCOUNTER OutRZToR3;540 } IOMIOPORTSTATS;541 AssertCompileMemberAlignment(IOMIOPORTSTATS, InR3, 8);542 /** Pointer to I/O port statistics. */543 typedef IOMIOPORTSTATS *PIOMIOPORTSTATS;544 545 546 /**547 409 * The IOM trees. 548 410 * … … 553 415 typedef struct IOMTREES 554 416 { 555 /** Tree containing I/O port range descriptors registered for HC (IOMIOPORTRANGEHC). */556 AVLROIOPORTTREE IOPortTreeR3;557 /** Tree containing I/O port range descriptors registered for R0 (IOMIOPORTRANGER0). */558 AVLROIOPORTTREE IOPortTreeR0;559 #if 0560 /** Tree containing I/O port range descriptors registered for RC (IOMIOPORTRANGERC). */561 AVLROIOPORTTREE IOPortTreeRC;562 #endif563 564 417 /** Tree containing the MMIO range descriptors (IOMMMIORANGE). */ 565 418 AVLROGCPHYSTREE MMIOTree; 566 567 /** Tree containing I/O port statistics (IOMIOPORTSTATS). */568 AVLOIOPORTTREE IOPortStatTree;569 419 /** Tree containing MMIO statistics (IOMMMIOSTATS). */ 570 420 AVLOGCPHYSTREE MmioStatTree; … … 639 489 uint16_t u16Padding; 640 490 641 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastReadR3;642 R3PTRTYPE(PIOMIOPORTRANGER3) pRangeLastWriteR3;643 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR3;644 R3PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR3;645 491 R3PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR3; 646 492 R3PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR3; 647 493 648 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastReadR0;649 R0PTRTYPE(PIOMIOPORTRANGER0) pRangeLastWriteR0;650 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastReadR0;651 R0PTRTYPE(PIOMIOPORTSTATS) pStatsLastWriteR0;652 494 R0PTRTYPE(PIOMMMIORANGE) pMMIORangeLastR0; 653 495 R0PTRTYPE(PIOMMMIOSTATS) pMMIOStatsLastR0;
Note:
See TracChangeset
for help on using the changeset viewer.