VirtualBox

Changeset 7726 in vbox


Ignore:
Timestamp:
Apr 3, 2008 2:52:04 PM (17 years ago)
Author:
vboxsync
Message:

Moved the R0/GC registration out of IOMAll.cpp and into IOM.cpp since it was only used in ring-3 and wasted R0/GC space in addition to making the code more difficult to navigate.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/iom.h

    r7725 r7726  
    196196typedef FNIOMMMIOFILL *PFNIOMMMIOFILL;
    197197
    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);
    214198IOMDECL(int)  IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
    215199IOMDECL(int)  IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
     
    222206IOMDECL(int)  IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
    223207IOMDECL(int)  IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, uint32_t cbTransfer);
    224 IOMDECL(void) IOMFlushCache(PVM pVM);
    225208IOMDECL(int)  IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue);
    226209IOMDECL(int)  IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
     
    252235                                      R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStringCallback, R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStringCallback,
    253236                                      const char *pszDesc);
     237IOMR3DECL(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);
     241IOMR3DECL(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);
     245IOMR3DECL(int)  IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts);
     246
    254247IOMR3DECL(int)  IOMR3MMIORegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange, RTHCPTR pvUser,
    255248                                    R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback, R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,
    256249                                    R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback, const char *pszDesc);
    257 IOMR3DECL(int)  IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts);
     250IOMR3DECL(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);
     253IOMR3DECL(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);
    258256IOMR3DECL(int)  IOMR3MMIODeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, RTUINT cbRange);
    259257/** @} */
  • trunk/src/VBox/VMM/IOM.cpp

    r7603 r7726  
    6767*   Internal Functions                                                         *
    6868*******************************************************************************/
     69static void iomR3FlushCache(PVM pVM);
    6970static DECLCALLBACK(int) iomr3RelocateIOPortCallback(PAVLROIOPORTNODECORE pNode, void *pvUser);
    7071static DECLCALLBACK(int) iomr3RelocateMMIOCallback(PAVLROGCPHYSNODECORE pNode, void *pvUser);
    7172static DECLCALLBACK(void) iomR3IOPortInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    7273static DECLCALLBACK(void) iomR3MMIOInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    73 static DECLCALLBACK(int)  iomR3IOPortDummyIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
    74 static DECLCALLBACK(int)  iomR3IOPortDummyOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
     74static DECLCALLBACK(int) iomR3IOPortDummyIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
     75static DECLCALLBACK(int) iomR3IOPortDummyOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
    7576static DECLCALLBACK(int) iomR3IOPortDummyInStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, unsigned *pcTransfer, unsigned cb);
    7677static DECLCALLBACK(int) iomR3IOPortDummyOutStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, unsigned *pcTransfer, unsigned cb);
     
    144145
    145146    /* Redundant, but just in case we change something in the future */
    146     IOMFlushCache(pVM);
     147    iomR3FlushCache(pVM);
    147148
    148149    LogFlow(("IOMR3Init: returns %Vrc\n", rc));
     
    152153
    153154/**
     155 * Flushes the IOM port & statistics lookup cache
     156 *
     157 * @param   pVM     The VM.
     158 */
     159static 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/**
    154182 * The VM is being reset.
    155183 *
     
    158186IOMR3DECL(void) IOMR3Reset(PVM pVM)
    159187{
    160     IOMFlushCache(pVM);
     188    iomR3FlushCache(pVM);
    161189}
    162190
     
    491519 *
    492520 * 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 IOMIOPortRegisterGC()
    494  * and IOMIOPortRegisterR0().
     521 * ring-3 ranges before any GC and R0 ranges can be registerd using IOMR3IOPortRegisterGC()
     522 * and IOMR3IOPortRegisterR0().
    495523 *
    496524 *
     
    539567
    540568    /* Flush the IO port lookup cache */
    541     IOMFlushCache(pVM);
     569    iomR3FlushCache(pVM);
    542570
    543571    /*
     
    584612
    585613/**
     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 */
     633IOMR3DECL(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 */
     745IOMR3DECL(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/**
    586842 * Deregisters a I/O Port range.
    587843 *
     
    617873
    618874    /* Flush the IO port lookup cache */
    619     IOMFlushCache(pVM);
     875    iomR3FlushCache(pVM);
    620876
    621877    /*
     
    11361392 *
    11371393 * 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 IOMMMIORegisterGC() and IOMMMIORegisterR0().
     1394 * before any GC and R0 ranges can be registered using IOMR3MMIORegisterGC() and IOMR3MMIORegisterR0().
    11391395 *
    11401396 * @returns VBox status code.
     
    11851441
    11861442        /*
    1187          * Try register it with PGM and then insert it.
     1443         * Try register it with PGM and then insert it into the tree.
    11881444         */
    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),
    11901448                                              /*IOMR3MMIOHandler*/ NULL, pRange,
    11911449                                              NULL, "IOMMMIOHandler", MMHyperR3ToR0(pVM, pRange),
    11921450                                              NULL, "IOMMMIOHandler", MMHyperR3ToGC(pVM, pRange), pszDesc);
    1193         if (VBOX_SUCCESS(rc))
     1451        if (RT_SUCCESS(rc))
    11941452        {
    11951453            if (RTAvlroGCPhysInsert(&pVM->iom.s.pTreesHC->MMIOTreeR3, &pRange->Core))
     
    12011459        }
    12021460        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 */
     1486IOMR3DECL(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 */
     1595IOMR3DECL(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;
    12031682    }
    12041683
  • trunk/src/VBox/VMM/PDMDevice.cpp

    r7635 r7726  
    12771277
    12781278        if (VBOX_SUCCESS(rc))
    1279             rc = IOMIOPortRegisterGC(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);
    12801280    }
    12811281    else
     
    13331333
    13341334        if (VBOX_SUCCESS(rc))
    1335             rc = IOMIOPortRegisterR0(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);
    13361336    }
    13371337    else
     
    14081408            rc3 = PDMR3GetSymbolGCLazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szGCMod, pszFill, &GCPtrFill);
    14091409        if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1410             rc = IOMMMIORegisterGC(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);
    14111411        else
    14121412        {
     
    14601460            rc3 = PDMR3GetSymbolR0Lazy(pDevIns->Internal.s.pVMHC, pDevIns->pDevReg->szR0Mod, pszFill, &pfnR0PtrFill);
    14611461        if (VBOX_SUCCESS(rc) && VBOX_SUCCESS(rc2) && VBOX_SUCCESS(rc3))
    1462             rc = IOMMMIORegisterR0(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);
    14631463        else
    14641464        {
  • trunk/src/VBox/VMM/VMMAll/IOMAll.cpp

    r7724 r7726  
    6161}
    6262
     63
    6364/**
    6465 * Returns the contents of register or immediate data of instruction's parameter.
     
    184185 * Internal - statistics only.
    185186 */
    186 inline void iomGCMMIOStatLength(PVM pVM, unsigned cb)
     187DECLINLINE(void) iomGCMMIOStatLength(PVM pVM, unsigned cb)
    187188{
    188189#ifdef VBOX_WITH_STATISTICS
     
    208209}
    209210
    210 #ifndef IN_RING0
    211 /**
    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 ranges
    215  * 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)PortStart
    242         ||  (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_CHECKS
    267         #ifndef IN_GC
    268         if (pRange->pDevIns != pDevIns)
    269         #else
    270         if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))
    271         #endif
    272         {
    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 #endif
    277         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_GC
    300         pRange->pDevIns         = pDevIns;
    301         pRange->pszDesc         = MMHyperGC2HC(pVM, (void *)pszDesc);
    302         #else
    303         pRange->pDevIns         = MMHyperHC2GC(pVM, pDevIns);
    304         pRange->pszDesc         = pszDesc;
    305         #endif
    306 
    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 ranges
    327  * 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_CHECKS
    377         #ifndef IN_GC
    378         if (pRange->pDevIns != pDevIns)
    379         #else
    380         if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))
    381         #endif
    382         {
    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_GC
    410         pRange->pDevIns         = pDevIns;
    411         pRange->pszDesc         = MMHyperGC2HC(pVM, (void *)pszDesc);
    412 #else
    413         pRange->pDevIns         = MMHyperHC2GC(pVM, pDevIns);
    414         pRange->pszDesc         = pszDesc;
    415 #endif
    416 
    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 #endif
    431 
    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 ranges
    436  * 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)PortStart
    464         ||  (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_CHECKS
    489 # ifndef IN_GC
    490         if (pRange->pDevIns != pDevIns)
    491 # else
    492         if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))
    493 # endif
    494         {
    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 #endif
    499         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_GC
    522         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 #else
    528         pRange->pDevIns         = pDevIns;
    529         pRange->pszDesc         = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc);
    530 #endif
    531 
    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 ranges
    552  * 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_CHECKS
    602 # ifndef IN_GC
    603         if (pRange->pDevIns != pDevIns)
    604 # else
    605         if (pRange->pDevIns != MMHyperGC2HC(pVM, pDevIns))
    606 # endif
    607         {
    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_GC
    635         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 #else
    641         pRange->pDevIns         = pDevIns;
    642         pRange->pszDesc         = MMHyperR0ToR3(pVM, (RTR0PTR)pszDesc);
    643 #endif
    644 
    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 cache
    662  *
    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 
    686211
    687212//#undef LOG_GROUP
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette