Changeset 7726 in vbox
- Timestamp:
- Apr 3, 2008 2:52:04 PM (17 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/iom.h
r7725 r7726 196 196 typedef FNIOMMMIOFILL *PFNIOMMMIOFILL; 197 197 198 199 IOMDECL(int) IOMIOPortRegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTGCPTR pvUser,200 GCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, GCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback,201 GCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, GCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,202 const char *pszDesc);203 IOMDECL(int) IOMMMIORegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,204 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,205 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc);206 207 IOMDECL(int) IOMIOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser,208 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,209 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,210 const char *pszDesc);211 IOMDECL(int) IOMMMIORegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,212 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,213 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc);214 198 IOMDECL(int) IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue); 215 199 IOMDECL(int) IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue); … … 222 206 IOMDECL(int) IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu); 223 207 IOMDECL(int) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, uint32_t cbTransfer); 224 IOMDECL(void) IOMFlushCache(PVM pVM);225 208 IOMDECL(int) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue); 226 209 IOMDECL(int) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue); … … 252 235 R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStringCallback, R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStringCallback, 253 236 const char *pszDesc); 237 IOMR3DECL(int) IOMR3IOPortRegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTGCPTR pvUser, 238 GCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, GCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback, 239 GCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, GCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, 240 const char *pszDesc); 241 IOMR3DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser, 242 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback, 243 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, 244 const char *pszDesc); 245 IOMR3DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts); 246 254 247 IOMR3DECL(int) IOMR3MMIORegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser, 255 248 R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback, 256 249 R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc); 257 IOMR3DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts); 250 IOMR3DECL(int) IOMR3MMIORegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser, 251 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback, 252 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc); 253 IOMR3DECL(int) IOMR3MMIORegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser, 254 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback, 255 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc); 258 256 IOMR3DECL(int) IOMR3MMIODeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange); 259 257 /** @} */ -
trunk/src/VBox/VMM/IOM.cpp
r7603 r7726 67 67 * Internal Functions * 68 68 *******************************************************************************/ 69 static void iomR3FlushCache(PVM pVM); 69 70 static DECLCALLBACK(int) iomr3RelocateIOPortCallback(PAVLROIOPORTNODECORE pNode, void *pvUser); 70 71 static DECLCALLBACK(int) iomr3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser); 71 72 static DECLCALLBACK(void) iomR3IOPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 72 73 static DECLCALLBACK(void) iomR3MMIOInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 73 static DECLCALLBACK(int) 74 static DECLCALLBACK(int) 74 static DECLCALLBACK(int) iomR3IOPortDummyIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb); 75 static DECLCALLBACK(int) iomR3IOPortDummyOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb); 75 76 static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, unsigned *pcTransfer, unsigned cb); 76 77 static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, unsigned *pcTransfer, unsigned cb); … … 144 145 145 146 /* Redundant, but just in case we change something in the future */ 146 IOMFlushCache(pVM);147 iomR3FlushCache(pVM); 147 148 148 149 LogFlow(("IOMR3Init: returns %Vrc\n", rc)); … … 152 153 153 154 /** 155 * Flushes the IOM port & statistics lookup cache 156 * 157 * @param pVM The VM. 158 */ 159 static void iomR3FlushCache(PVM pVM) 160 { 161 /* 162 * Caching of port and statistics (saves some time in rep outs/ins instruction emulation) 163 */ 164 pVM->iom.s.pRangeLastReadGC = 0; 165 pVM->iom.s.pRangeLastWriteGC = 0; 166 pVM->iom.s.pStatsLastReadGC = 0; 167 pVM->iom.s.pStatsLastWriteGC = 0; 168 169 pVM->iom.s.pRangeLastReadR3 = 0; 170 pVM->iom.s.pRangeLastWriteR3 = 0; 171 pVM->iom.s.pStatsLastReadR3 = 0; 172 pVM->iom.s.pStatsLastWriteR3 = 0; 173 174 pVM->iom.s.pRangeLastReadR0 = 0; 175 pVM->iom.s.pRangeLastWriteR0 = 0; 176 pVM->iom.s.pStatsLastReadR0 = 0; 177 pVM->iom.s.pStatsLastWriteR0 = 0; 178 } 179 180 181 /** 154 182 * The VM is being reset. 155 183 * … … 158 186 IOMR3DECL(void) IOMR3Reset(PVM pVM) 159 187 { 160 IOMFlushCache(pVM);188 iomR3FlushCache(pVM); 161 189 } 162 190 … … 491 519 * 492 520 * This API is called by PDM on behalf of a device. Devices must first register 493 * ring-3 ranges before any GC and R0 ranges can be registerd using IOM IOPortRegisterGC()494 * and IOM IOPortRegisterR0().521 * ring-3 ranges before any GC and R0 ranges can be registerd using IOMR3IOPortRegisterGC() 522 * and IOMR3IOPortRegisterR0(). 495 523 * 496 524 * … … 539 567 540 568 /* Flush the IO port lookup cache */ 541 IOMFlushCache(pVM);569 iomR3FlushCache(pVM); 542 570 543 571 /* … … 584 612 585 613 /** 614 * Registers a Port IO GC handler. 615 * 616 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges 617 * using IOMIOPortRegisterR3() before calling this function. 618 * 619 * 620 * @returns VBox status code. 621 * 622 * @param pVM VM handle. 623 * @param pDevIns PDM device instance owning the port range. 624 * @param PortStart First port number in the range. 625 * @param cPorts Number of ports to register. 626 * @param pvUser User argument for the callbacks. 627 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in GC. 628 * @param pfnInCallback Pointer to function which is gonna handle IN operations in GC. 629 * @param pfnOutStrCallback Pointer to function which is gonna handle string OUT operations in GC. 630 * @param pfnInStrCallback Pointer to function which is gonna handle string IN operations in GC. 631 * @param pszDesc Pointer to description string. This must not be freed. 632 */ 633 IOMR3DECL(int) IOMR3IOPortRegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTGCPTR pvUser, 634 GCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, GCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback, 635 GCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, GCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, const char *pszDesc) 636 { 637 LogFlow(("IOMR3IOPortRegisterGC: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%VGv pfnOutCallback=%VGv pfnInCallback=%VGv pfnOutStrCallback=%VGv pfnInStrCallback=%VGv pszDesc=%s\n", 638 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc)); 639 640 /* 641 * Validate input. 642 */ 643 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart 644 || (RTUINT)PortStart + cPorts > 0x10000) 645 { 646 AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc)); 647 return VERR_IOM_INVALID_IOPORT_RANGE; 648 } 649 RTIOPORT PortLast = PortStart + (cPorts - 1); 650 if (!pfnOutCallback && !pfnInCallback) 651 { 652 AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc)); 653 return VERR_INVALID_PARAMETER; 654 } 655 656 /* 657 * Validate that there are ring-3 ranges for the ports. 658 */ 659 RTIOPORT Port = PortStart; 660 while (Port <= PortLast && Port >= PortStart) 661 { 662 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeR3, Port); 663 if (!pRange) 664 { 665 AssertMsgFailed(("No R3! Port=#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); 666 return VERR_IOM_NO_HC_IOPORT_RANGE; 667 } 668 #ifndef IOM_NO_PDMINS_CHECKS 669 # ifndef IN_GC 670 if (pRange->pDevIns != pDevIns) 671 # else 672 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns)) 673 # endif 674 { 675 AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); 676 return VERR_IOM_NOT_IOPORT_RANGE_OWNER; 677 } 678 #endif 679 Port = pRange->Core.KeyLast + 1; 680 } 681 682 /* Flush the IO port lookup cache */ 683 iomR3FlushCache(pVM); 684 685 /* 686 * Allocate new range record and initialize it. 687 */ 688 PIOMIOPORTRANGEGC pRange; 689 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 690 if (VBOX_SUCCESS(rc)) 691 { 692 pRange->Core.Key = PortStart; 693 pRange->Core.KeyLast = PortLast; 694 pRange->Port = PortStart; 695 pRange->cPorts = cPorts; 696 pRange->pvUser = pvUser; 697 pRange->pfnOutCallback = pfnOutCallback; 698 pRange->pfnInCallback = pfnInCallback; 699 pRange->pfnOutStrCallback = pfnOutStrCallback; 700 pRange->pfnInStrCallback = pfnInStrCallback; 701 #ifdef IN_GC 702 pRange->pDevIns = pDevIns; 703 pRange->pszDesc = MMHyperGC2HC(pVM, (void *)pszDesc); 704 #else 705 pRange->pDevIns = MMHyperHC2GC(pVM, pDevIns); 706 pRange->pszDesc = pszDesc; 707 #endif 708 709 /* 710 * Insert it. 711 */ 712 if (RTAvlroIOPortInsert(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeGC, &pRange->Core)) 713 return VINF_SUCCESS; 714 715 /* conflict. */ 716 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); 717 MMHyperFree(pVM, pRange); 718 rc = VERR_IOM_IOPORT_RANGE_CONFLICT; 719 } 720 721 return rc; 722 } 723 724 725 /** 726 * Registers a Port IO R0 handler. 727 * 728 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges 729 * using IOMR3IOPortRegisterR3() before calling this function. 730 * 731 * 732 * @returns VBox status code. 733 * 734 * @param pVM VM handle. 735 * @param pDevIns PDM device instance owning the port range. 736 * @param PortStart First port number in the range. 737 * @param cPorts Number of ports to register. 738 * @param pvUser User argument for the callbacks. 739 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in GC. 740 * @param pfnInCallback Pointer to function which is gonna handle IN operations in GC. 741 * @param pfnOutStrCallback Pointer to function which is gonna handle OUT operations in GC. 742 * @param pfnInStrCallback Pointer to function which is gonna handle IN operations in GC. 743 * @param pszDesc Pointer to description string. This must not be freed. 744 */ 745 IOMR3DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser, 746 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback, 747 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, 748 const char *pszDesc) 749 { 750 LogFlow(("IOMR3IOPortRegisterR0: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%VHv pfnOutCallback=%VGv pfnInCallback=%VGv pfnOutStrCallback=%VGv pfnInStrCallback=%VGv pszDesc=%s\n", 751 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc)); 752 753 /* 754 * Validate input. 755 */ 756 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart 757 || (RTUINT)PortStart + cPorts > 0x10000) 758 { 759 AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc)); 760 return VERR_IOM_INVALID_IOPORT_RANGE; 761 } 762 RTIOPORT PortLast = PortStart + (cPorts - 1); 763 if (!pfnOutCallback && !pfnInCallback) 764 { 765 AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc)); 766 return VERR_INVALID_PARAMETER; 767 } 768 769 /* 770 * Validate that there are ring-3 ranges for the ports. 771 */ 772 RTIOPORT Port = PortStart; 773 while (Port <= PortLast && Port >= PortStart) 774 { 775 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeR3, Port); 776 if (!pRange) 777 { 778 AssertMsgFailed(("No R3! Port=#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); 779 return VERR_IOM_NO_HC_IOPORT_RANGE; 780 } 781 #ifndef IOM_NO_PDMINS_CHECKS 782 # ifndef IN_GC 783 if (pRange->pDevIns != pDevIns) 784 # else 785 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns)) 786 # endif 787 { 788 AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); 789 return VERR_IOM_NOT_IOPORT_RANGE_OWNER; 790 } 791 #endif 792 Port = pRange->Core.KeyLast + 1; 793 } 794 795 /* Flush the IO port lookup cache */ 796 iomR3FlushCache(pVM); 797 798 /* 799 * Allocate new range record and initialize it. 800 */ 801 PIOMIOPORTRANGER0 pRange; 802 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 803 if (VBOX_SUCCESS(rc)) 804 { 805 pRange->Core.Key = PortStart; 806 pRange->Core.KeyLast = PortLast; 807 pRange->Port = PortStart; 808 pRange->cPorts = cPorts; 809 pRange->pvUser = pvUser; 810 pRange->pfnOutCallback = pfnOutCallback; 811 pRange->pfnInCallback = pfnInCallback; 812 pRange->pfnOutStrCallback = pfnOutStrCallback; 813 pRange->pfnInStrCallback = pfnInStrCallback; 814 #ifdef IN_GC 815 pRange->pDevIns = MMHyperGCToR0(pVM, pDevIns); 816 pRange->pszDesc = MMHyperGCToR3(pVM, (void *)pszDesc); 817 #elif defined(IN_RING3) 818 pRange->pDevIns = MMHyperR3ToR0(pVM, pDevIns); 819 pRange->pszDesc = pszDesc; 820 #else 821 pRange->pDevIns = pDevIns; 822 pRange->pszDesc = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc); 823 #endif 824 825 /* 826 * Insert it. 827 */ 828 if (RTAvlroIOPortInsert(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeR0, &pRange->Core)) 829 return VINF_SUCCESS; 830 831 /* conflict. */ 832 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc)); 833 MMHyperFree(pVM, pRange); 834 rc = VERR_IOM_IOPORT_RANGE_CONFLICT; 835 } 836 837 return rc; 838 } 839 840 841 /** 586 842 * Deregisters a I/O Port range. 587 843 * … … 617 873 618 874 /* Flush the IO port lookup cache */ 619 IOMFlushCache(pVM);875 iomR3FlushCache(pVM); 620 876 621 877 /* … … 1136 1392 * 1137 1393 * This API is called by PDM on behalf of a device. Devices must register ring-3 ranges 1138 * before any GC and R0 ranges can be registered using IOM MMIORegisterGC() and IOMMMIORegisterR0().1394 * before any GC and R0 ranges can be registered using IOMR3MMIORegisterGC() and IOMR3MMIORegisterR0(). 1139 1395 * 1140 1396 * @returns VBox status code. … … 1185 1441 1186 1442 /* 1187 * Try register it with PGM and then insert it .1443 * Try register it with PGM and then insert it into the tree. 1188 1444 */ 1189 int rc = PGMR3HandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_MMIO, GCPhysStart, GCPhysStart + (cbRange - 1), 1445 //rc = PGMR3PhysMMIORegister(pVM, GCPhysStart, cbRange); 1446 //if (RT_SUCCESS(rc)) 1447 rc = PGMR3HandlerPhysicalRegister(pVM, PGMPHYSHANDLERTYPE_MMIO, GCPhysStart, GCPhysStart + (cbRange - 1), 1190 1448 /*IOMR3MMIOHandler*/ NULL, pRange, 1191 1449 NULL, "IOMMMIOHandler", MMHyperR3ToR0(pVM, pRange), 1192 1450 NULL, "IOMMMIOHandler", MMHyperR3ToGC(pVM, pRange), pszDesc); 1193 if ( VBOX_SUCCESS(rc))1451 if (RT_SUCCESS(rc)) 1194 1452 { 1195 1453 if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesHC->MMIOTreeR3, &pRange->Core)) … … 1201 1459 } 1202 1460 MMHyperFree(pVM, pRange); 1461 } 1462 1463 return rc; 1464 } 1465 1466 1467 /** 1468 * Registers a Memory Mapped I/O GC handler range. 1469 * 1470 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges 1471 * using IOMMMIORegisterR3() before calling this function. 1472 * 1473 * 1474 * @returns VBox status code. 1475 * 1476 * @param pVM VM handle. 1477 * @param pDevIns PDM device instance owning the MMIO range. 1478 * @param GCPhysStart First physical address in the range. 1479 * @param cbRange The size of the range (in bytes). 1480 * @param pvUser User argument for the callbacks. 1481 * @param pfnWriteCallback Pointer to function which is gonna handle Write operations. 1482 * @param pfnReadCallback Pointer to function which is gonna handle Read operations. 1483 * @param pfnFillCallback Pointer to function which is gonna handle Fill/memset operations. 1484 * @param pszDesc Pointer to description string. This must not be freed. 1485 */ 1486 IOMR3DECL(int) IOMR3MMIORegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser, 1487 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback, 1488 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc) 1489 { 1490 LogFlow(("IOMR3MMIORegisterGC: pDevIns=%p GCPhysStart=%VGp cbRange=%#x pvUser=%VGv pfnWriteCallback=%#x pfnReadCallback=%#x pfnFillCallback=%#x pszDesc=%s\n", 1491 pDevIns, GCPhysStart, cbRange, pvUser, pfnWriteCallback, pfnReadCallback, pfnFillCallback, pszDesc)); 1492 1493 /* 1494 * Validate input. 1495 */ 1496 if (!pfnWriteCallback && !pfnReadCallback) 1497 { 1498 AssertMsgFailed(("No callbacks! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1499 return VERR_INVALID_PARAMETER; 1500 } 1501 RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1); 1502 if (GCPhysLast < GCPhysStart) 1503 { 1504 AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1505 return VERR_IOM_INVALID_MMIO_RANGE; 1506 } 1507 1508 /* 1509 * Check that a ring-3 MMIO range exists. 1510 */ 1511 RTGCPHYS GCPhys = GCPhysStart; 1512 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1513 { 1514 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys); 1515 if (!pRange) 1516 { 1517 AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc)); 1518 return VERR_IOM_NO_HC_MMIO_RANGE; 1519 } 1520 #ifndef IOM_NO_PDMINS_CHECKS 1521 #ifndef IN_GC 1522 if (pRange->pDevIns != pDevIns) 1523 #else 1524 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns)) 1525 #endif 1526 { 1527 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc, 1528 pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc))); 1529 return VERR_IOM_NOT_MMIO_RANGE_OWNER; 1530 } 1531 #endif /* !IOM_NO_PDMINS_CHECKS */ 1532 /* next */ 1533 Assert(GCPhys <= pRange->Core.KeyLast); 1534 GCPhys = pRange->Core.KeyLast + 1; 1535 } 1536 1537 1538 /* 1539 * Allocate new range record and initialize it. 1540 */ 1541 PIOMMMIORANGEGC pRange; 1542 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 1543 if (VBOX_SUCCESS(rc)) 1544 { 1545 pRange->Core.Key = GCPhysStart; 1546 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1); 1547 pRange->GCPhys = GCPhysStart; 1548 pRange->cbSize = cbRange; 1549 pRange->pvUser = pvUser; 1550 pRange->pfnReadCallback = pfnReadCallback; 1551 pRange->pfnWriteCallback= pfnWriteCallback; 1552 pRange->pfnFillCallback = pfnFillCallback; 1553 #ifdef IN_GC 1554 pRange->pDevIns = pDevIns; 1555 pRange->pszDesc = MMHyperGC2HC(pVM, (void *)pszDesc); 1556 #else 1557 pRange->pDevIns = MMHyperHC2GC(pVM, pDevIns); 1558 pRange->pszDesc = pszDesc; 1559 #endif 1560 1561 /* 1562 * Try insert it. 1563 */ 1564 if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeGC, &pRange->Core)) 1565 return VINF_SUCCESS; 1566 1567 AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1568 MMHyperFree(pVM, pRange); 1569 rc = VERR_IOM_MMIO_RANGE_CONFLICT; 1570 } 1571 1572 return rc; 1573 } 1574 1575 1576 /** 1577 * Registers a Memory Mapped I/O R0 handler range. 1578 * 1579 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges 1580 * using IOMMR3MIORegisterHC() before calling this function. 1581 * 1582 * 1583 * @returns VBox status code. 1584 * 1585 * @param pVM VM handle. 1586 * @param pDevIns PDM device instance owning the MMIO range. 1587 * @param GCPhysStart First physical address in the range. 1588 * @param cbRange The size of the range (in bytes). 1589 * @param pvUser User argument for the callbacks. 1590 * @param pfnWriteCallback Pointer to function which is gonna handle Write operations. 1591 * @param pfnReadCallback Pointer to function which is gonna handle Read operations. 1592 * @param pfnFillCallback Pointer to function which is gonna handle Fill/memset operations. 1593 * @param pszDesc Pointer to description string. This must not be freed. 1594 */ 1595 IOMR3DECL(int) IOMR3MMIORegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser, 1596 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback, 1597 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc) 1598 { 1599 LogFlow(("IOMR3MMIORegisterR0: pDevIns=%p GCPhysStart=%VGp cbRange=%#x pvUser=%VHv pfnWriteCallback=%#x pfnReadCallback=%#x pfnFillCallback=%#x pszDesc=%s\n", 1600 pDevIns, GCPhysStart, cbRange, pvUser, pfnWriteCallback, pfnReadCallback, pfnFillCallback, pszDesc)); 1601 1602 /* 1603 * Validate input. 1604 */ 1605 if (!pfnWriteCallback && !pfnReadCallback) 1606 { 1607 AssertMsgFailed(("No callbacks! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1608 return VERR_INVALID_PARAMETER; 1609 } 1610 RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1); 1611 if (GCPhysLast < GCPhysStart) 1612 { 1613 AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1614 return VERR_IOM_INVALID_MMIO_RANGE; 1615 } 1616 1617 /* 1618 * Check that a ring-3 MMIO range exists. 1619 */ 1620 RTGCPHYS GCPhys = GCPhysStart; 1621 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart) 1622 { 1623 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys); 1624 if (!pRange) 1625 { 1626 AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc)); 1627 return VERR_IOM_NO_HC_MMIO_RANGE; 1628 } 1629 #ifndef IOM_NO_PDMINS_CHECKS 1630 # ifndef IN_GC 1631 if (pRange->pDevIns != pDevIns) 1632 # else 1633 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns)) 1634 # endif 1635 { 1636 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc, 1637 pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc))); 1638 return VERR_IOM_NOT_MMIO_RANGE_OWNER; 1639 } 1640 #endif /* !IOM_NO_PDMINS_CHECKS */ 1641 /* next */ 1642 Assert(GCPhys <= pRange->Core.KeyLast); 1643 GCPhys = pRange->Core.KeyLast + 1; 1644 } 1645 1646 1647 /* 1648 * Allocate new range record and initialize it. 1649 */ 1650 PIOMMMIORANGER0 pRange; 1651 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange); 1652 if (VBOX_SUCCESS(rc)) 1653 { 1654 pRange->Core.Key = GCPhysStart; 1655 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1); 1656 pRange->GCPhys = GCPhysStart; 1657 pRange->cbSize = cbRange; 1658 pRange->pvUser = pvUser; 1659 pRange->pfnReadCallback = pfnReadCallback; 1660 pRange->pfnWriteCallback= pfnWriteCallback; 1661 pRange->pfnFillCallback = pfnFillCallback; 1662 #ifdef IN_GC 1663 pRange->pDevIns = MMHyperGCToR0(pVM, pDevIns); 1664 pRange->pszDesc = MMHyperGCToR3(pVM, (void *)pszDesc); 1665 #elif defined(IN_RING3) 1666 pRange->pDevIns = MMHyperR3ToR0(pVM, pDevIns); 1667 pRange->pszDesc = pszDesc; 1668 #else 1669 pRange->pDevIns = pDevIns; 1670 pRange->pszDesc = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc); 1671 #endif 1672 1673 /* 1674 * Try insert it. 1675 */ 1676 if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR0, &pRange->Core)) 1677 return VINF_SUCCESS; 1678 1679 AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc)); 1680 MMHyperFree(pVM, pRange); 1681 rc = VERR_IOM_MMIO_RANGE_CONFLICT; 1203 1682 } 1204 1683 -
trunk/src/VBox/VMM/PDMDevice.cpp
r7635 r7726 1277 1277 1278 1278 if (VBOX_SUCCESS(rc)) 1279 rc = IOM IOPortRegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc);1279 rc = IOMR3IOPortRegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, GCPtrOut, GCPtrIn, GCPtrOutStr, GCPtrInStr, pszDesc); 1280 1280 } 1281 1281 else … … 1333 1333 1334 1334 if (VBOX_SUCCESS(rc)) 1335 rc = IOM IOPortRegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc);1335 rc = IOMR3IOPortRegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, Port, cPorts, pvUser, pfnR0PtrOut, pfnR0PtrIn, pfnR0PtrOutStr, pfnR0PtrInStr, pszDesc); 1336 1336 } 1337 1337 else … … 1408 1408 rc3 = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszFill, &GCPtrFill); 1409 1409 if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3)) 1410 rc = IOM MMIORegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill, pszDesc);1410 rc = IOMR3MMIORegisterGC(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, GCPtrWrite, GCPtrRead, GCPtrFill, pszDesc); 1411 1411 else 1412 1412 { … … 1460 1460 rc3 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill); 1461 1461 if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3)) 1462 rc = IOM MMIORegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill, pszDesc);1462 rc = IOMR3MMIORegisterR0(pDevIns->Internal.s.pVMHC, pDevIns, GCPhysStart, cbRange, pvUser, pfnR0PtrWrite, pfnR0PtrRead, pfnR0PtrFill, pszDesc); 1463 1463 else 1464 1464 { -
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r7724 r7726 61 61 } 62 62 63 63 64 /** 64 65 * Returns the contents of register or immediate data of instruction's parameter. … … 184 185 * Internal - statistics only. 185 186 */ 186 inline voidiomGCMMIOStatLength(PVM pVM, unsigned cb)187 DECLINLINE(void) iomGCMMIOStatLength(PVM pVM, unsigned cb) 187 188 { 188 189 #ifdef VBOX_WITH_STATISTICS … … 208 209 } 209 210 210 #ifndef IN_RING0211 /**212 * Registers a Port IO GC handler.213 *214 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges215 * using IOMIOPortRegisterR3() before calling this function.216 *217 *218 * @returns VBox status code.219 *220 * @param pVM VM handle.221 * @param pDevIns PDM device instance owning the port range.222 * @param PortStart First port number in the range.223 * @param cPorts Number of ports to register.224 * @param pvUser User argument for the callbacks.225 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in GC.226 * @param pfnInCallback Pointer to function which is gonna handle IN operations in GC.227 * @param pfnOutStrCallback Pointer to function which is gonna handle string OUT operations in GC.228 * @param pfnInStrCallback Pointer to function which is gonna handle string IN operations in GC.229 * @param pszDesc Pointer to description string. This must not be freed.230 */231 IOMDECL(int) IOMIOPortRegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTGCPTR pvUser,232 GCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, GCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback,233 GCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, GCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback, const char *pszDesc)234 {235 LogFlow(("IOMIOPortRegisterGC: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%VGv pfnOutCallback=%VGv pfnInCallback=%VGv pfnOutStrCallback=%VGv pfnInStrCallback=%VGv pszDesc=%s\n",236 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));237 238 /*239 * Validate input.240 */241 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart242 || (RTUINT)PortStart + cPorts > 0x10000)243 {244 AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));245 return VERR_IOM_INVALID_IOPORT_RANGE;246 }247 RTIOPORT PortLast = PortStart + (cPorts - 1);248 if (!pfnOutCallback && !pfnInCallback)249 {250 AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc));251 return VERR_INVALID_PARAMETER;252 }253 254 /*255 * Validate that there are ring-3 ranges for the ports.256 */257 RTIOPORT Port = PortStart;258 while (Port <= PortLast && Port >= PortStart)259 {260 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeR3, Port);261 if (!pRange)262 {263 AssertMsgFailed(("No R3! Port=#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));264 return VERR_IOM_NO_HC_IOPORT_RANGE;265 }266 #ifndef IOM_NO_PDMINS_CHECKS267 #ifndef IN_GC268 if (pRange->pDevIns != pDevIns)269 #else270 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))271 #endif272 {273 AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));274 return VERR_IOM_NOT_IOPORT_RANGE_OWNER;275 }276 #endif277 Port = pRange->Core.KeyLast + 1;278 }279 280 /* Flush the IO port lookup cache */281 IOMFlushCache(pVM);282 283 /*284 * Allocate new range record and initialize it.285 */286 PIOMIOPORTRANGEGC pRange;287 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);288 if (VBOX_SUCCESS(rc))289 {290 pRange->Core.Key = PortStart;291 pRange->Core.KeyLast = PortLast;292 pRange->Port = PortStart;293 pRange->cPorts = cPorts;294 pRange->pvUser = pvUser;295 pRange->pfnOutCallback = pfnOutCallback;296 pRange->pfnInCallback = pfnInCallback;297 pRange->pfnOutStrCallback = pfnOutStrCallback;298 pRange->pfnInStrCallback = pfnInStrCallback;299 #ifdef IN_GC300 pRange->pDevIns = pDevIns;301 pRange->pszDesc = MMHyperGC2HC(pVM, (void *)pszDesc);302 #else303 pRange->pDevIns = MMHyperHC2GC(pVM, pDevIns);304 pRange->pszDesc = pszDesc;305 #endif306 307 /*308 * Insert it.309 */310 if (RTAvlroIOPortInsert(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeGC, &pRange->Core))311 return VINF_SUCCESS;312 313 /* conflict. */314 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));315 MMHyperFree(pVM, pRange);316 rc = VERR_IOM_IOPORT_RANGE_CONFLICT;317 }318 319 return rc;320 }321 322 323 /**324 * Registers a Memory Mapped I/O GC handler range.325 *326 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges327 * using IOMMMIORegisterR3() before calling this function.328 *329 *330 * @returns VBox status code.331 *332 * @param pVM VM handle.333 * @param pDevIns PDM device instance owning the MMIO range.334 * @param GCPhysStart First physical address in the range.335 * @param cbRange The size of the range (in bytes).336 * @param pvUser User argument for the callbacks.337 * @param pfnWriteCallback Pointer to function which is gonna handle Write operations.338 * @param pfnReadCallback Pointer to function which is gonna handle Read operations.339 * @param pfnFillCallback Pointer to function which is gonna handle Fill/memset operations.340 * @param pszDesc Pointer to description string. This must not be freed.341 */342 IOMDECL(int) IOMMMIORegisterGC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTGCPTR pvUser,343 GCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, GCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,344 GCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc)345 {346 LogFlow(("IOMMMIORegisterGC: pDevIns=%p GCPhysStart=%VGp cbRange=%#x pvUser=%VGv pfnWriteCallback=%#x pfnReadCallback=%#x pfnFillCallback=%#x pszDesc=%s\n",347 pDevIns, GCPhysStart, cbRange, pvUser, pfnWriteCallback, pfnReadCallback, pfnFillCallback, pszDesc));348 349 /*350 * Validate input.351 */352 if (!pfnWriteCallback && !pfnReadCallback)353 {354 AssertMsgFailed(("No callbacks! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));355 return VERR_INVALID_PARAMETER;356 }357 RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1);358 if (GCPhysLast < GCPhysStart)359 {360 AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));361 return VERR_IOM_INVALID_MMIO_RANGE;362 }363 364 /*365 * Check that a ring-3 MMIO range exists.366 */367 RTGCPHYS GCPhys = GCPhysStart;368 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)369 {370 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);371 if (!pRange)372 {373 AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc));374 return VERR_IOM_NO_HC_MMIO_RANGE;375 }376 #ifndef IOM_NO_PDMINS_CHECKS377 #ifndef IN_GC378 if (pRange->pDevIns != pDevIns)379 #else380 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))381 #endif382 {383 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc,384 pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc)));385 return VERR_IOM_NOT_MMIO_RANGE_OWNER;386 }387 #endif /* !IOM_NO_PDMINS_CHECKS */388 /* next */389 Assert(GCPhys <= pRange->Core.KeyLast);390 GCPhys = pRange->Core.KeyLast + 1;391 }392 393 394 /*395 * Allocate new range record and initialize it.396 */397 PIOMMMIORANGEGC pRange;398 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);399 if (VBOX_SUCCESS(rc))400 {401 pRange->Core.Key = GCPhysStart;402 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1);403 pRange->GCPhys = GCPhysStart;404 pRange->cbSize = cbRange;405 pRange->pvUser = pvUser;406 pRange->pfnReadCallback = pfnReadCallback;407 pRange->pfnWriteCallback= pfnWriteCallback;408 pRange->pfnFillCallback = pfnFillCallback;409 #ifdef IN_GC410 pRange->pDevIns = pDevIns;411 pRange->pszDesc = MMHyperGC2HC(pVM, (void *)pszDesc);412 #else413 pRange->pDevIns = MMHyperHC2GC(pVM, pDevIns);414 pRange->pszDesc = pszDesc;415 #endif416 417 /*418 * Try insert it.419 */420 if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeGC, &pRange->Core))421 return VINF_SUCCESS;422 423 AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));424 MMHyperFree(pVM, pRange);425 rc = VERR_IOM_MMIO_RANGE_CONFLICT;426 }427 428 return rc;429 }430 #endif431 432 /**433 * Registers a Port IO R0 handler.434 *435 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges436 * using IOMR3IOPortRegisterR3() before calling this function.437 *438 *439 * @returns VBox status code.440 *441 * @param pVM VM handle.442 * @param pDevIns PDM device instance owning the port range.443 * @param PortStart First port number in the range.444 * @param cPorts Number of ports to register.445 * @param pvUser User argument for the callbacks.446 * @param pfnOutCallback Pointer to function which is gonna handle OUT operations in GC.447 * @param pfnInCallback Pointer to function which is gonna handle IN operations in GC.448 * @param pfnOutStrCallback Pointer to function which is gonna handle OUT operations in GC.449 * @param pfnInStrCallback Pointer to function which is gonna handle IN operations in GC.450 * @param pszDesc Pointer to description string. This must not be freed.451 */452 IOMDECL(int) IOMIOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser,453 R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,454 R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,455 const char *pszDesc)456 {457 LogFlow(("IOMIOPortRegisterR0: pDevIns=%p PortStart=%#x cPorts=%#x pvUser=%VHv pfnOutCallback=%VGv pfnInCallback=%VGv pfnOutStrCallback=%VGv pfnInStrCallback=%VGv pszDesc=%s\n",458 pDevIns, PortStart, cPorts, pvUser, pfnOutCallback, pfnInCallback, pfnOutStrCallback, pfnInStrCallback, pszDesc));459 460 /*461 * Validate input.462 */463 if ( (RTUINT)PortStart + cPorts <= (RTUINT)PortStart464 || (RTUINT)PortStart + cPorts > 0x10000)465 {466 AssertMsgFailed(("Invalid port range %#x-%#x! (%s)\n", PortStart, (RTUINT)PortStart + (cPorts - 1), pszDesc));467 return VERR_IOM_INVALID_IOPORT_RANGE;468 }469 RTIOPORT PortLast = PortStart + (cPorts - 1);470 if (!pfnOutCallback && !pfnInCallback)471 {472 AssertMsgFailed(("Invalid port range %#x-%#x! No callbacks! (%s)\n", PortStart, PortLast, pszDesc));473 return VERR_INVALID_PARAMETER;474 }475 476 /*477 * Validate that there are ring-3 ranges for the ports.478 */479 RTIOPORT Port = PortStart;480 while (Port <= PortLast && Port >= PortStart)481 {482 PIOMIOPORTRANGER3 pRange = (PIOMIOPORTRANGER3)RTAvlroIOPortRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeR3, Port);483 if (!pRange)484 {485 AssertMsgFailed(("No R3! Port=#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));486 return VERR_IOM_NO_HC_IOPORT_RANGE;487 }488 #ifndef IOM_NO_PDMINS_CHECKS489 # ifndef IN_GC490 if (pRange->pDevIns != pDevIns)491 # else492 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))493 # endif494 {495 AssertMsgFailed(("Not owner! Port=%#x %#x-%#x! (%s)\n", Port, PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));496 return VERR_IOM_NOT_IOPORT_RANGE_OWNER;497 }498 #endif499 Port = pRange->Core.KeyLast + 1;500 }501 502 /* Flush the IO port lookup cache */503 IOMFlushCache(pVM);504 505 /*506 * Allocate new range record and initialize it.507 */508 PIOMIOPORTRANGER0 pRange;509 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);510 if (VBOX_SUCCESS(rc))511 {512 pRange->Core.Key = PortStart;513 pRange->Core.KeyLast = PortLast;514 pRange->Port = PortStart;515 pRange->cPorts = cPorts;516 pRange->pvUser = pvUser;517 pRange->pfnOutCallback = pfnOutCallback;518 pRange->pfnInCallback = pfnInCallback;519 pRange->pfnOutStrCallback = pfnOutStrCallback;520 pRange->pfnInStrCallback = pfnInStrCallback;521 #ifdef IN_GC522 pRange->pDevIns = MMHyperGCToR0(pVM, pDevIns);523 pRange->pszDesc = MMHyperGCToR3(pVM, (void *)pszDesc);524 #elif defined(IN_RING3)525 pRange->pDevIns = MMHyperR3ToR0(pVM, pDevIns);526 pRange->pszDesc = pszDesc;527 #else528 pRange->pDevIns = pDevIns;529 pRange->pszDesc = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc);530 #endif531 532 /*533 * Insert it.534 */535 if (RTAvlroIOPortInsert(&pVM->iom.s.CTXSUFF(pTrees)->IOPortTreeR0, &pRange->Core))536 return VINF_SUCCESS;537 538 /* conflict. */539 AssertMsgFailed(("Port range %#x-%#x (%s) conflicts with existing range(s)!\n", PortStart, (unsigned)PortStart + cPorts - 1, pszDesc));540 MMHyperFree(pVM, pRange);541 rc = VERR_IOM_IOPORT_RANGE_CONFLICT;542 }543 544 return rc;545 }546 547 548 /**549 * Registers a Memory Mapped I/O R0 handler range.550 *551 * This API is called by PDM on behalf of a device. Devices must first register ring-3 ranges552 * using IOMMR3MIORegisterHC() before calling this function.553 *554 *555 * @returns VBox status code.556 *557 * @param pVM VM handle.558 * @param pDevIns PDM device instance owning the MMIO range.559 * @param GCPhysStart First physical address in the range.560 * @param cbRange The size of the range (in bytes).561 * @param pvUser User argument for the callbacks.562 * @param pfnWriteCallback Pointer to function which is gonna handle Write operations.563 * @param pfnReadCallback Pointer to function which is gonna handle Read operations.564 * @param pfnFillCallback Pointer to function which is gonna handle Fill/memset operations.565 * @param pszDesc Pointer to description string. This must not be freed.566 */567 IOMDECL(int) IOMMMIORegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTR0PTR pvUser,568 R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,569 R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc)570 {571 LogFlow(("IOMMMIORegisterR0: pDevIns=%p GCPhysStart=%VGp cbRange=%#x pvUser=%VHv pfnWriteCallback=%#x pfnReadCallback=%#x pfnFillCallback=%#x pszDesc=%s\n",572 pDevIns, GCPhysStart, cbRange, pvUser, pfnWriteCallback, pfnReadCallback, pfnFillCallback, pszDesc));573 574 /*575 * Validate input.576 */577 if (!pfnWriteCallback && !pfnReadCallback)578 {579 AssertMsgFailed(("No callbacks! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));580 return VERR_INVALID_PARAMETER;581 }582 RTGCPHYS GCPhysLast = GCPhysStart + (cbRange - 1);583 if (GCPhysLast < GCPhysStart)584 {585 AssertMsgFailed(("Wrapped! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));586 return VERR_IOM_INVALID_MMIO_RANGE;587 }588 589 /*590 * Check that a ring-3 MMIO range exists.591 */592 RTGCPHYS GCPhys = GCPhysStart;593 while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)594 {595 PIOMMMIORANGER3 pRange = (PIOMMMIORANGER3)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR3, GCPhys);596 if (!pRange)597 {598 AssertMsgFailed(("No R3 range! GCPhys=%VGp %VGp LB%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc));599 return VERR_IOM_NO_HC_MMIO_RANGE;600 }601 #ifndef IOM_NO_PDMINS_CHECKS602 # ifndef IN_GC603 if (pRange->pDevIns != pDevIns)604 # else605 if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))606 # endif607 {608 AssertMsgFailed(("Not owner! GCPhys=%VGp %VGp LB%#x %s / %#x-%#x %s\n", GCPhys, GCPhysStart, cbRange, pszDesc,609 pRange->Core.Key, pRange->Core.KeyLast, MMHyper2HC(pVM, (uintptr_t)pRange->pszDesc)));610 return VERR_IOM_NOT_MMIO_RANGE_OWNER;611 }612 #endif /* !IOM_NO_PDMINS_CHECKS */613 /* next */614 Assert(GCPhys <= pRange->Core.KeyLast);615 GCPhys = pRange->Core.KeyLast + 1;616 }617 618 619 /*620 * Allocate new range record and initialize it.621 */622 PIOMMMIORANGER0 pRange;623 int rc = MMHyperAlloc(pVM, sizeof(*pRange), 0, MM_TAG_IOM, (void **)&pRange);624 if (VBOX_SUCCESS(rc))625 {626 pRange->Core.Key = GCPhysStart;627 pRange->Core.KeyLast = GCPhysStart + (cbRange - 1);628 pRange->GCPhys = GCPhysStart;629 pRange->cbSize = cbRange;630 pRange->pvUser = pvUser;631 pRange->pfnReadCallback = pfnReadCallback;632 pRange->pfnWriteCallback= pfnWriteCallback;633 pRange->pfnFillCallback = pfnFillCallback;634 #ifdef IN_GC635 pRange->pDevIns = MMHyperGCToR0(pVM, pDevIns);636 pRange->pszDesc = MMHyperGCToR3(pVM, (void *)pszDesc);637 #elif defined(IN_RING3)638 pRange->pDevIns = MMHyperR3ToR0(pVM, pDevIns);639 pRange->pszDesc = pszDesc;640 #else641 pRange->pDevIns = pDevIns;642 pRange->pszDesc = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc);643 #endif644 645 /*646 * Try insert it.647 */648 if (RTAvlroGCPhysInsert(&pVM->iom.s.CTXSUFF(pTrees)->MMIOTreeR0, &pRange->Core))649 return VINF_SUCCESS;650 651 AssertMsgFailed(("Conflict! %VGp LB%#x %s\n", GCPhysStart, cbRange, pszDesc));652 MMHyperFree(pVM, pRange);653 rc = VERR_IOM_MMIO_RANGE_CONFLICT;654 }655 656 return rc;657 }658 659 660 /**661 * Flushes the IOM port & statistics lookup cache662 *663 * @param pVM The VM.664 */665 IOMDECL(void) IOMFlushCache(PVM pVM)666 {667 /*668 * Caching of port and statistics (saves some time in rep outs/ins instruction emulation)669 */670 pVM->iom.s.pRangeLastReadGC = 0;671 pVM->iom.s.pRangeLastWriteGC = 0;672 pVM->iom.s.pStatsLastReadGC = 0;673 pVM->iom.s.pStatsLastWriteGC = 0;674 675 pVM->iom.s.pRangeLastReadR3 = 0;676 pVM->iom.s.pRangeLastWriteR3 = 0;677 pVM->iom.s.pStatsLastReadR3 = 0;678 pVM->iom.s.pStatsLastWriteR3 = 0;679 680 pVM->iom.s.pRangeLastReadR0 = 0;681 pVM->iom.s.pRangeLastWriteR0 = 0;682 pVM->iom.s.pStatsLastReadR0 = 0;683 pVM->iom.s.pStatsLastWriteR0 = 0;684 }685 686 211 687 212 //#undef LOG_GROUP
Note:
See TracChangeset
for help on using the changeset viewer.