VirtualBox

Changeset 17434 in vbox for trunk/src


Ignore:
Timestamp:
Mar 6, 2009 3:22:21 AM (16 years ago)
Author:
vboxsync
Message:

PGM: Implemented the fun part of pgmPhysWriteHandler (to deal with partial virtual handlers).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp

    r17432 r17434  
    11331133 * @param   cbRange     Physical range
    11341134 * @param   pR3Ptr      Where to store the R3 pointer on success.
     1135 *
     1136 * @deprecated  Avoid when possible!
    11351137 */
    11361138VMMDECL(int) PGMPhysGCPhys2R3Ptr(PVM pVM, RTGCPHYS GCPhys, RTUINT cbRange, PRTR3PTR pR3Ptr)
    11371139{
    11381140#ifdef VBOX_WITH_NEW_PHYS_CODE
     1141/** @todo this is kind of hacky and needs some more work. */
    11391142    VM_ASSERT_EMT(pVM); /* no longer safe for use outside the EMT thread! */
    11401143
     
    12021205
    12031206
     1207#ifdef VBOX_STRICT
    12041208/**
    12051209 * PGMPhysGCPhys2R3Ptr convenience for use with assertions.
     
    12091213 * @param   GCPhys      The GC Physical addresss.
    12101214 * @param   cbRange     Physical range.
     1215 *
     1216 * @deprecated  Avoid when possible.
    12111217 */
    12121218VMMDECL(RTR3PTR) PGMPhysGCPhys2R3PtrAssert(PVM pVM, RTGCPHYS GCPhys, RTUINT cbRange)
     
    12181224    return NIL_RTR3PTR;
    12191225}
     1226#endif /* VBOX_STRICT */
    12201227
    12211228
     
    12691276 * @param   pR3Ptr      Where to store the R3 virtual address.
    12701277 *
    1271  * @deprecated
     1278 * @deprecated Don't use this.
    12721279 */
    12731280VMMDECL(int) PGMPhysGCPtr2R3Ptr(PVM pVM, RTGCPTR GCPtr, PRTR3PTR pR3Ptr)
     
    17551762{
    17561763    void *pvDst = NULL;
     1764    int rc;
    17571765
    17581766    /*
     
    17631771     * the heavy usage of full page handlers in the page pool.
    17641772     */
    1765     if (!PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage))
     1773    if (    !PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage)
     1774        ||  PGM_PAGE_IS_MMIO(pPage) /* screw virtual handlers on MMIO pages */)
    17661775    {
    17671776        PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
     
    17761785
    17771786#ifdef IN_RING3
    1778             int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
     1787            if (!PGM_PAGE_IS_MMIO(pPage))
     1788                rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
     1789            else
     1790                rc = VINF_SUCCESS;
    17791791            if (RT_SUCCESS(rc))
    17801792            {
     
    17851797                    memcpy(pvDst, pvBuf, cbRange);
    17861798                else
    1787                     AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp %s\n", rc, GCPhys, pCur->pszDesc));
     1799                    AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pCur->pszDesc));
    17881800            }
    17891801            else
    1790                 AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
    1791                                        GCPhys, pPage, rc));
     1802                AssertLogRelMsgFailedReturnVoid(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     1803                                                 GCPhys, pPage, rc));
    17921804#else
    17931805            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cbRange=%#x\n", GCPhys, cbRange));
     
    17971809
    17981810            /* more fun to be had below */
     1811            cbWrite -= cbRange;
    17991812            GCPhys  += cbRange;
    1800             cbWrite -= cbRange;
    18011813            pvBuf    = (uint8_t *)pvBuf + cbRange;
     1814            pvDst    = (uint8_t *)pvDst + cbRange;
    18021815        }
    18031816        /* else: the handler is somewhere else in the page, deal with it below. */
     1817        Assert(!PGM_PAGE_IS_MMIO(pPage)); /* MMIO handlers are all PAGE_SIZEed! */
    18041818    }
    18051819    /*
     
    18111825        unsigned        iPage;
    18121826        PPGMVIRTHANDLER pCur;
    1813         int rc = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pCur, &iPage);
     1827        rc = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pCur, &iPage);
    18141828        if (RT_SUCCESS(rc))
    18151829        {
     
    18191833
    18201834#ifdef IN_RING3
    1821             int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
     1835            rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
    18221836            if (RT_SUCCESS(rc))
    18231837            {
     
    18361850                    memcpy(pvDst, pvBuf, cbRange);
    18371851                else
    1838                     AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp %s\n", rc, GCPhys, pCur->pszDesc));
     1852                    AssertLogRelMsg(rc == VINF_SUCCESS, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pCur->pszDesc));
    18391853            }
    18401854            else
    1841                 AssertLogRelMsgFailed(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
    1842                                        GCPhys, pPage, rc));
     1855                AssertLogRelMsgFailedReturnVoid(("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     1856                                                 GCPhys, pPage, rc));
    18431857#else
    18441858            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cb=%#x\n", GCPhys, cbRange));
     
    18481862
    18491863            /* more fun to be had below */
     1864            cbWrite -= cbRange;
    18501865            GCPhys  += cbRange;
    1851             cbWrite -= cbRange;
    18521866            pvBuf    = (uint8_t *)pvBuf + cbRange;
     1867            pvDst    = (uint8_t *)pvDst + cbRange;
    18531868        }
    18541869        /* else: the handler is somewhere else in the page, deal with it below. */
     
    18581873     * Deal with all the odd ends.
    18591874     */
    1860     while (cbWrite > 0)
    1861     {
    1862         AssertReleaseMsgFailed(("%RGp %#x %R[pgmpage]\n", GCPhys, cbWrite, pPage));
     1875
     1876    /* We need a writable destination page. */
     1877    if (!pvDst)
     1878    {
     1879        rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDst);
     1880        AssertLogRelMsgReturnVoid(RT_SUCCESS(rc),
     1881                                  ("pgmPhysGCPhys2CCPtrInternal failed on %RGp / %R[pgmpage] -> %Rrc\n",
     1882                                   GCPhys, pPage, rc));
     1883    }
     1884
     1885    /* The loop state (big + ugly). */
     1886    unsigned        iVirtPage   = 0;
     1887    PPGMVIRTHANDLER pVirt       = NULL;
     1888    uint32_t        offVirt     = PAGE_SIZE;
     1889    uint32_t        offVirtLast = PAGE_SIZE;
     1890    bool            fMoreVirt   = PGM_PAGE_HAS_ACTIVE_VIRTUAL_HANDLERS(pPage);
     1891
     1892    PPGMPHYSHANDLER pPhys       = NULL;
     1893    uint32_t        offPhys     = PAGE_SIZE;
     1894    uint32_t        offPhysLast = PAGE_SIZE;
     1895    bool            fMorePhys   = PGM_PAGE_HAS_ACTIVE_PHYSICAL_HANDLERS(pPage);
     1896
     1897    /* The loop. */
     1898    for (;;)
     1899    {
     1900        /*
     1901         * Find the closest handler above GCPhys.
     1902         */
     1903        if (fMoreVirt && !pVirt)
     1904        {
     1905            int rc = pgmHandlerVirtualFindByPhysAddr(pVM, GCPhys, &pVirt, &iVirtPage);
     1906            if (RT_SUCCESS(rc))
     1907            {
     1908                offVirt = 0;
     1909                offVirtLast = (pVirt->aPhysToVirt[iVirtPage].Core.KeyLast & PAGE_OFFSET_MASK) - (GCPhys & PAGE_OFFSET_MASK);
     1910            }
     1911            else
     1912            {
     1913                PPGMPHYS2VIRTHANDLER pVirtPhys;
     1914                pVirtPhys = (PPGMPHYS2VIRTHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysToVirtHandlers,
     1915                                                                          GCPhys, true /* fAbove */);
     1916                if (pVirtPhys)
     1917                {
     1918                    /* ASSUME that pVirtPhys only covers one page. */
     1919                    Assert((pVirtPhys->Core.Key >> PAGE_SHIFT) == (pVirtPhys->Core.KeyLast >> PAGE_SHIFT));
     1920                    pVirt = (PPGMVIRTHANDLER)((uintptr_t)pVirtPhys + pVirtPhys->offVirtHandler);
     1921                    iVirtPage = pVirtPhys - &pVirt->aPhysToVirt[0]; Assert(iVirtPage == 0);
     1922                    offVirtLast = pVirtPhys->Core.KeyLast & PAGE_OFFSET_MASK - (GCPhys & PAGE_OFFSET_MASK);
     1923                }
     1924                else
     1925                {
     1926                    pVirt     = NULL;
     1927                    fMoreVirt = false;
     1928                    offVirt   = offVirtLast = PAGE_SIZE;
     1929                }
     1930            }
     1931        }
     1932
     1933        if (fMorePhys && !pPhys)
     1934        {
     1935            pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysRangeGet(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers, GCPhys);
     1936            if (pPhys)
     1937            {
     1938                offPhys = 0;
     1939                offPhysLast = pPhys->Core.KeyLast - GCPhys; /* ASSUMES < 4GB handlers... */
     1940            }
     1941            else
     1942            {
     1943                pPhys = (PPGMPHYSHANDLER)RTAvlroGCPhysGetBestFit(&pVM->pgm.s.CTX_SUFF(pTrees)->PhysHandlers,
     1944                                                                 GCPhys, true /* fAbove */);
     1945                if (    pPhys
     1946                    &&  pPhys->Core.Key <= GCPhys + (cbWrite - 1))
     1947                {
     1948                    offPhys     = pPhys->Core.Key     - GCPhys;
     1949                    offPhysLast = pPhys->Core.KeyLast - GCPhys; /* ASSUMES < 4GB handlers... */
     1950                }
     1951                else
     1952                {
     1953                    pPhys     = NULL;
     1954                    fMorePhys = false;
     1955                    offPhys   = offPhysLast = PAGE_SIZE;
     1956                }
     1957            }
     1958        }
     1959
     1960        /*
     1961         * Handle access to space without handlers (that's easy).
     1962         */
     1963        rc = VINF_PGM_HANDLER_DO_DEFAULT;
     1964        size_t cbRange = cbWrite;
     1965        if (offPhys && offVirt)
     1966        {
     1967            if (cbRange > offPhys)
     1968                cbRange = offPhys;
     1969            if (cbRange > offVirt)
     1970                cbRange = offVirt;
     1971        }
     1972        /*
     1973         * Physical handler.
     1974         */
     1975        else if (!offPhys && offVirt)
     1976        {
     1977            if (cbRange > offPhysLast + 1)
     1978                cbRange = offPhysLast + 1;
     1979            if (cbRange > offVirt)
     1980                cbRange = offVirt;
     1981#ifdef IN_RING3
     1982            STAM_PROFILE_START(&pPhys->Stat, h);
     1983            rc = pPhys->CTX_SUFF(pfnHandler)(pVM, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, pPhys->CTX_SUFF(pvUser));
     1984            STAM_PROFILE_STOP(&pPhys->Stat, h);
     1985            AssertLogRelMsg(rc != VINF_SUCCESS && rc != VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pPhys->pszDesc));
     1986#else
     1987            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cbRange=%#x\n", GCPhys, cbRange));
     1988#endif
     1989            pPhys = NULL;
     1990        }
     1991        /*
     1992         * Virtual handler.
     1993         */
     1994        else if (offPhys && !offVirt)
     1995        {
     1996            if (cbRange > offVirtLast + 1)
     1997                cbRange = offVirtLast + 1;
     1998            if (cbRange > offPhys)
     1999                cbRange = offPhys;
     2000#ifdef IN_RING3
     2001            if (pVirt->pfnHandlerR3)
     2002            {
     2003                RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)
     2004                                  + (iVirtPage << PAGE_SHIFT)
     2005                                  + (GCPhys & PAGE_OFFSET_MASK);
     2006                STAM_PROFILE_START(&pVirt->Stat, h);
     2007                rc = pVirt->CTX_SUFF(pfnHandler)(pVM, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, /*pCur->CTX_SUFF(pvUser)*/ NULL);
     2008                STAM_PROFILE_STOP(&pVirt->Stat, h);
     2009                AssertLogRelMsg(rc != VINF_SUCCESS && rc != VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pVirt->pszDesc));
     2010            }
     2011#else
     2012            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cb=%#x\n", GCPhys, cbRange));
     2013#endif
     2014            pVirt = NULL;
     2015        }
     2016        /*
     2017         * Both... give the physical one priority.
     2018         */
     2019        else
     2020        {
     2021            Assert(!offPhys && !offVirt);
     2022            if (cbRange > offVirtLast + 1)
     2023                cbRange = offVirtLast + 1;
     2024            if (cbRange > offPhysLast + 1)
     2025                cbRange = offPhysLast + 1;
     2026
     2027#ifdef IN_RING3
     2028            if (pVirt->pfnHandlerR3)
     2029                Log(("pgmPhysWriteHandler: overlapping phys and virt handlers at %RGp %R[pgmpage]; cbRange=%#x\n", GCPhys, pPage, cbRange));
     2030
     2031            STAM_PROFILE_START(&pPhys->Stat, h);
     2032            rc = pPhys->CTX_SUFF(pfnHandler)(pVM, GCPhys, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, pPhys->CTX_SUFF(pvUser));
     2033            STAM_PROFILE_STOP(&pPhys->Stat, h);
     2034            AssertLogRelMsg(rc != VINF_SUCCESS && rc != VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pPhys->pszDesc));
     2035            if (pVirt->pfnHandlerR3)
     2036            {
     2037
     2038                RTGCUINTPTR GCPtr = ((RTGCUINTPTR)pVirt->Core.Key & PAGE_BASE_GC_MASK)
     2039                                  + (iVirtPage << PAGE_SHIFT)
     2040                                  + (GCPhys & PAGE_OFFSET_MASK);
     2041                STAM_PROFILE_START(&pVirt->Stat, h);
     2042                int rc2 = pVirt->CTX_SUFF(pfnHandler)(pVM, GCPtr, pvDst, (void *)pvBuf, cbRange, PGMACCESSTYPE_WRITE, /*pCur->CTX_SUFF(pvUser)*/ NULL);
     2043                STAM_PROFILE_STOP(&pVirt->Stat, h);
     2044                AssertLogRelMsg(rc2 != VINF_SUCCESS && rc2 != VINF_PGM_HANDLER_DO_DEFAULT, ("rc=%Rrc GCPhys=%RGp pPage=%R[pgmpage] %s\n", rc, GCPhys, pPage, pVirt->pszDesc));
     2045                if (rc2 == VINF_SUCCESS && rc == VINF_PGM_HANDLER_DO_DEFAULT)
     2046                    rc = VINF_SUCCESS;
     2047            }
     2048#else
     2049            AssertReleaseMsgFailed(("Wrong API! GCPhys=%RGp cbRange=%#x\n", GCPhys, cbRange));
     2050#endif
     2051            pPhys = NULL;
     2052            pVirt = NULL;
     2053        }
     2054        if (rc == VINF_PGM_HANDLER_DO_DEFAULT)
     2055            memcpy(pvDst, pvBuf, cbRange);
     2056
     2057        /*
     2058         * Advance if we've got more stuff to do.
     2059         */
     2060        if (cbRange >= cbWrite)
     2061            return;
     2062
     2063        cbWrite         -= cbRange;
     2064        GCPhys          += cbRange;
     2065        pvBuf            = (uint8_t *)pvBuf + cbRange;
     2066        pvDst            = (uint8_t *)pvDst + cbRange;
     2067
     2068        offPhys         -= cbRange;
     2069        offPhysLast     -= cbRange;
     2070        offVirt         -= cbRange;
     2071        offVirtLast     -= cbRange;
    18632072    }
    18642073}
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