VirtualBox

Ignore:
Timestamp:
May 29, 2023 10:00:48 AM (20 months ago)
Author:
vboxsync
Message:

WDDM: deferred GMR destruction. bugref:9845

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/Svga.cpp

    r99990 r99997  
    17541754}
    17551755
    1756 NTSTATUS SvgaGenGMRReport(PVBOXWDDM_EXT_VMSVGA pSvga,
    1757                           uint32_t u32GmrId,
    1758                           SVGARemapGMR2Flags fRemapGMR2Flags,
    1759                           uint32_t u32NumPages,
    1760                           RTHCPHYS *paPhysAddresses,
    1761                           void *pvDst,
    1762                           uint32_t cbDst,
    1763                           uint32_t *pcbOut)
    1764 {
    1765     /*
    1766      * SVGA_CMD_DEFINE_GMR2 + SVGA_CMD_REMAP_GMR2.
    1767      */
    1768 
    1769     AssertReturn(u32NumPages <= pSvga->u32GmrMaxPages, STATUS_INVALID_PARAMETER);
    1770 
    1771     NTSTATUS Status = STATUS_SUCCESS;
    1772 
    1773     uint32_t const cbCmdDefineGMR2 =   sizeof(uint32_t)
    1774                                      + sizeof(SVGAFifoCmdDefineGMR2);
    1775     uint32_t const cbCmdRemapGMR2 =   sizeof(uint32_t)
    1776                                     + sizeof(SVGAFifoCmdRemapGMR2);
    1777     uint32_t const cbPPN = (fRemapGMR2Flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
    1778     uint32_t const cbPPNArray = u32NumPages * cbPPN;
    1779 
    1780     uint32_t const cbCmd = cbCmdDefineGMR2 + cbCmdRemapGMR2 + cbPPNArray;
    1781     if (pcbOut)
    1782         *pcbOut = cbCmd;
    1783 
    1784     if (cbCmd <= cbDst)
    1785     {
    1786         uint8_t *pu8Dst = (uint8_t *)pvDst;
    1787 
    1788         SvgaCmdDefineGMR2(pu8Dst, u32GmrId, u32NumPages);
    1789         pu8Dst += cbCmdDefineGMR2;
    1790 
    1791         SvgaCmdRemapGMR2(pu8Dst, u32GmrId, fRemapGMR2Flags, 0, u32NumPages);
    1792         pu8Dst += cbCmdRemapGMR2;
    1793 
    1794         uint32_t iPage;
    1795         if (fRemapGMR2Flags & SVGA_REMAP_GMR2_PPN64)
    1796         {
    1797            uint64_t *paPPN64 = (uint64_t *)pu8Dst;
    1798            for (iPage = 0; iPage < u32NumPages; ++iPage)
    1799            {
    1800                RTHCPHYS const Phys = paPhysAddresses[iPage];
    1801                paPPN64[iPage] = Phys >> PAGE_SHIFT;
    1802            }
    1803         }
    1804         else
    1805         {
    1806            uint32_t *paPPN32 = (uint32_t *)pu8Dst;
    1807            for (iPage = 0; iPage < u32NumPages; ++iPage)
    1808            {
    1809                RTHCPHYS const Phys = paPhysAddresses[iPage];
    1810                AssertBreakStmt((Phys & UINT32_C(0xFFFFFFFF)) == Phys, Status = STATUS_INVALID_PARAMETER);
    1811                paPPN32[iPage] = (uint32_t)(Phys >> PAGE_SHIFT);
    1812            }
    1813         }
    1814     }
    1815     else
    1816         Status = STATUS_BUFFER_OVERFLOW;
    1817 
    1818     return Status;
    1819 }
    1820 
    1821 NTSTATUS SvgaGMRReport(PVBOXWDDM_EXT_VMSVGA pSvga,
    1822                        uint32_t u32GmrId,
    1823                        SVGARemapGMR2Flags fRemapGMR2Flags,
    1824                        uint32_t u32NumPages,
    1825                        RTHCPHYS *paPhysAddresses)
    1826 {
    1827     /*
    1828      * Issue SVGA_CMD_DEFINE_GMR2 + SVGA_CMD_REMAP_GMR2.
    1829      */
    1830 
    1831     NTSTATUS Status;
    1832 
    1833     uint32_t cbSubmit = 0;
    1834     SvgaGenGMRReport(pSvga, u32GmrId, fRemapGMR2Flags, u32NumPages, paPhysAddresses,
    1835                      NULL, 0, &cbSubmit);
    1836 
    1837     void *pvCmd = SvgaReserve(pSvga, cbSubmit);
    1838     if (pvCmd)
    1839     {
    1840         Status = SvgaGenGMRReport(pSvga, u32GmrId, fRemapGMR2Flags, u32NumPages, paPhysAddresses,
    1841                                   pvCmd, cbSubmit, NULL);
    1842         AssertStmt(Status == STATUS_SUCCESS, cbSubmit = 0);
    1843         SvgaCommit(pSvga, cbSubmit);
    1844     }
    1845     else
    1846     {
    1847         Status = STATUS_INSUFFICIENT_RESOURCES;
    1848     }
    1849 
    1850     return Status;
    1851 }
    18521756
    18531757/* SVGA Guest Memory Region (GMR). Memory known for both host and guest.
     
    18581762    /* Key is GMR id (equal to u32GmrId). */
    18591763    AVLU32NODECORE Core;
    1860     /* Device the GMR is associated with. */
     1764    /* Pointer to a graphics context device (PVBOXWDDM_DEVICE) the GMR is associated with. */
    18611765    void      *pvOwner;
    1862     /* The memory object handle. */
    1863     RTR0MEMOBJ MemObj;
    1864     /* The ring-3 mapping memory object handle. */
     1766    /* The ring-3 mapping memory object handle (from mob). */
    18651767    RTR0MEMOBJ MapObjR3;
    1866     RTR0PTR    pvR0;
    18671768    RTR3PTR    pvR3;
    1868     /* A corresponding MOB, which provides the Guest Memory Region ID. */
     1769    /* A corresponding MOB, which provides the GMR id and RTR0MEMOBJ for the region memory. */
    18691770    PVMSVGAMOB pMob;
    18701771    /* The allocated size in pages. */
     
    18741775} GAWDDMREGION;
    18751776
    1876 /** @todo Deferred destruction. */
    1877 static void svgaFreeGBMobForGMR(VBOXWDDM_EXT_VMSVGA *pSvga, PVMSVGAMOB pMob)
    1878 {
    1879     if (pMob)
    1880     {
    1881         if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
    1882         {
    1883             void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DESTROY_GB_MOB, sizeof(SVGA3dCmdDestroyGBMob), SVGA3D_INVALID_ID);
    1884             if (pvCmd)
    1885             {
    1886                 SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
    1887                 pCmd->mobid = VMSVGAMOB_ID(pMob);
    1888                 SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdDestroyGBMob));
    1889             }
    1890         }
    1891 
    1892         SvgaMobFree(pSvga, pMob);
    1893     }
    1894 }
    1895 
    1896 static NTSTATUS svgaCreateGBMobForGMR(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion)
    1897 {
    1898     /* Allocate a new mob. */
    1899     NTSTATUS Status = SvgaMobCreate(pSvga, &pRegion->pMob, pRegion->u32NumPages, 0);
    1900     Assert(NT_SUCCESS(Status));
    1901     if (NT_SUCCESS(Status))
    1902     {
    1903         Status = SvgaMobSetMemObj(pRegion->pMob, pRegion->MemObj);
     1777
     1778/* Allocate memory pages and the corresponding mob.
     1779 */
     1780static NTSTATUS gmrAllocMemory(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion, uint32_t u32NumPages)
     1781{
     1782    NTSTATUS Status;
     1783
     1784    /* Allocate memory. */
     1785    RTR0MEMOBJ MemObj;
     1786    int rc = RTR0MemObjAllocPageTag(&MemObj, u32NumPages << PAGE_SHIFT,
     1787                                    false /* executable R0 mapping */, "VMSVGAGMR");
     1788    AssertRC(rc);
     1789    if (RT_SUCCESS(rc))
     1790    {
     1791        if (!RTR0MemObjWasZeroInitialized(MemObj))
     1792            RT_BZERO(RTR0MemObjAddress(MemObj), (size_t)u32NumPages << PAGE_SHIFT);
     1793
     1794        /* Allocate corresponding mob. */
     1795        Status = SvgaMobCreate(pSvga, &pRegion->pMob, u32NumPages, 0);
    19041796        Assert(NT_SUCCESS(Status));
    19051797        if (NT_SUCCESS(Status))
    19061798        {
    1907             if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
    1908             {
    1909                 void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DEFINE_GB_MOB64, sizeof(SVGA3dCmdDefineGBMob64), SVGA3D_INVALID_ID);
    1910                 if (pvCmd)
    1911                 {
    1912                     SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    1913                     pCmd->mobid       = VMSVGAMOB_ID(pRegion->pMob);
    1914                     pCmd->ptDepth     = pRegion->pMob->gbo.enmMobFormat;
    1915                     pCmd->base        = pRegion->pMob->gbo.base;
    1916                     pCmd->sizeInBytes = pRegion->pMob->gbo.cbGbo;
    1917                     SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdDefineGBMob64));
    1918                 }
    1919                 else
    1920                     AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
    1921             }
    1922 
     1799            Status = SvgaMobSetMemObj(pRegion->pMob, MemObj);
     1800            Assert(NT_SUCCESS(Status));
    19231801            if (NT_SUCCESS(Status))
    19241802                return STATUS_SUCCESS;
    19251803        }
    1926     }
    1927 
    1928     svgaFreeGBMobForGMR(pSvga, pRegion->pMob);
    1929     pRegion->pMob = NULL;
    1930     return Status;
    1931 }
    1932 
    1933 
    1934 static void gmrFree(GAWDDMREGION *pRegion)
    1935 {
     1804
     1805        if (   pRegion->pMob
     1806            && pRegion->pMob->hMemObj == NIL_RTR0MEMOBJ)
     1807        {
     1808            /* The memory object has not been assigned to the mob yet. Clean up the local object.
     1809             * Otherwise the caller will clean up.
     1810             */
     1811            int rc2 = RTR0MemObjFree(MemObj, false);
     1812            AssertRC(rc2);
     1813        }
     1814    }
     1815    else
     1816        AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     1817
     1818    return Status;
     1819}
     1820
     1821/* Initialize the GMR to be ready for reporting to the host.
     1822 */
     1823static NTSTATUS gmrInit(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion, void *pvOwner, uint32_t u32NumPages)
     1824{
     1825    NTSTATUS Status = gmrAllocMemory(pSvga, pRegion, u32NumPages);
     1826    if (NT_SUCCESS(Status))
     1827    {
     1828        int rc = RTR0MemObjMapUser(&pRegion->MapObjR3, pRegion->pMob->hMemObj, (RTR3PTR)-1, 0,
     1829                                   RTMEM_PROT_WRITE | RTMEM_PROT_READ, NIL_RTR0PROCESS);
     1830        AssertRC(rc);
     1831        if (RT_SUCCESS(rc))
     1832        {
     1833            uint32_t iPage;
     1834            for (iPage = 0; iPage < u32NumPages; ++iPage)
     1835                pRegion->aPhys[iPage] = RTR0MemObjGetPagePhysAddr(pRegion->pMob->hMemObj, iPage);
     1836
     1837            pRegion->pvR3 = RTR0MemObjAddressR3(pRegion->MapObjR3);
     1838
     1839            pRegion->pvOwner = pvOwner;
     1840            pRegion->u32NumPages = u32NumPages;
     1841        }
     1842        else
     1843            AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     1844    }
     1845
     1846    return Status;
     1847}
     1848
     1849/* Send GMR creation commands to the host.
     1850 */
     1851static NTSTATUS gmrReportToHost(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion)
     1852{
     1853    /*
     1854     * Issue SVGA_CMD_DEFINE_GMR2 + SVGA_CMD_REMAP_GMR2 + SVGA_3D_CMD_DEFINE_GB_MOB64.
     1855     */
     1856    uint32_t const cbPPNArray = pRegion->u32NumPages * sizeof(uint64_t);
     1857
     1858    uint32_t cbSubmit = sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMR2);
     1859    cbSubmit += sizeof(uint32_t) + sizeof(SVGAFifoCmdRemapGMR2) + cbPPNArray;
     1860    if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
     1861        cbSubmit += sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdDefineGBMob64);
     1862
     1863    void *pvCmd = SvgaReserve(pSvga, cbSubmit);
     1864    if (!pvCmd)
     1865        return STATUS_INSUFFICIENT_RESOURCES;
     1866
     1867    uint8_t *pu8Cmd = (uint8_t *)pvCmd;
     1868
     1869    uint32_t *pu32CmdId;
     1870
     1871    pu32CmdId = (uint32_t *)pu8Cmd;
     1872    *pu32CmdId = SVGA_CMD_DEFINE_GMR2;
     1873    pu8Cmd += sizeof(*pu32CmdId);
     1874
     1875    {
     1876    SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)pu8Cmd;
     1877    pCmd->gmrId = VMSVGAMOB_ID(pRegion->pMob);
     1878    pCmd->numPages = pRegion->u32NumPages;
     1879    pu8Cmd += sizeof(*pCmd);
     1880    }
     1881
     1882    pu32CmdId = (uint32_t *)pu8Cmd;
     1883    *pu32CmdId = SVGA_CMD_REMAP_GMR2;
     1884    pu8Cmd += sizeof(*pu32CmdId);
     1885
     1886    {
     1887    SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)pu8Cmd;
     1888    pCmd->gmrId = VMSVGAMOB_ID(pRegion->pMob);
     1889    pCmd->flags = SVGA_REMAP_GMR2_PPN64;
     1890    pCmd->offsetPages = 0;
     1891    pCmd->numPages = pRegion->u32NumPages;
     1892    pu8Cmd += sizeof(*pCmd);
     1893    }
     1894
     1895    uint64_t *paPPN64 = (uint64_t *)pu8Cmd;
     1896    for (uint32_t iPage = 0; iPage < pRegion->u32NumPages; ++iPage)
     1897    {
     1898        RTHCPHYS const Phys = pRegion->aPhys[iPage];
     1899        paPPN64[iPage] = Phys >> PAGE_SHIFT;
     1900    }
     1901    pu8Cmd += cbPPNArray;
     1902
     1903    if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
     1904    {
     1905        SVGA3dCmdHeader *pHdr;
     1906
     1907        pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     1908        pHdr->id   = SVGA_3D_CMD_DEFINE_GB_MOB64;
     1909        pHdr->size = sizeof(SVGA3dCmdDefineGBMob64);
     1910        pu8Cmd += sizeof(*pHdr);
     1911
     1912        {
     1913        SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pu8Cmd;
     1914        pCmd->mobid       = VMSVGAMOB_ID(pRegion->pMob);
     1915        pCmd->ptDepth     = pRegion->pMob->gbo.enmMobFormat;
     1916        pCmd->base        = pRegion->pMob->gbo.base;
     1917        pCmd->sizeInBytes = pRegion->pMob->gbo.cbGbo;
     1918        pu8Cmd += sizeof(*pCmd);
     1919        }
     1920    }
     1921
     1922    Assert((uintptr_t)pu8Cmd - (uintptr_t)pvCmd == cbSubmit);
     1923    SvgaCommit(pSvga, (uintptr_t)pu8Cmd - (uintptr_t)pvCmd);
     1924
     1925    return STATUS_SUCCESS;
     1926}
     1927
     1928/* Destroy exising region.
     1929 */
     1930static NTSTATUS gmrDestroy(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion)
     1931{
     1932    AssertReturn(pRegion, STATUS_INVALID_PARAMETER);
     1933
     1934    /* Mapping must be freed prior to the mob destruction. Otherwise, due to a race condition,
     1935     * SvgaMobFree could free the mapping in a system worker thread after DPC, which would not
     1936     * work obviously, because the mapping was created for another process.
     1937     */
    19361938    if (pRegion->MapObjR3 != NIL_RTR0MEMOBJ)
    19371939    {
     
    19401942        pRegion->MapObjR3 = NIL_RTR0MEMOBJ;
    19411943    }
    1942     if (pRegion->pMob == NULL)
    1943     {
    1944         /* The memory will be deleted by SvgaMobFree. */
    1945         if (pRegion->MemObj != NIL_RTR0MEMOBJ)
    1946         {
    1947             int rc = RTR0MemObjFree(pRegion->MemObj, true /* fFreeMappings */);
    1948             AssertRC(rc);
    1949             pRegion->MemObj = NIL_RTR0MEMOBJ;
    1950         }
    1951     }
    1952 }
    1953 
    1954 static NTSTATUS gmrAlloc(GAWDDMREGION *pRegion)
    1955 {
    1956     int rc = RTR0MemObjAllocPageTag(&pRegion->MemObj, pRegion->u32NumPages << PAGE_SHIFT,
    1957                                     false /* executable R0 mapping */, "VMSVGAGMR");
    1958     AssertRC(rc);
    1959     if (RT_SUCCESS(rc))
    1960     {
    1961         if (!RTR0MemObjWasZeroInitialized(pRegion->MemObj))
    1962             RT_BZERO(RTR0MemObjAddress(pRegion->MemObj), (size_t)pRegion->u32NumPages << PAGE_SHIFT);
    1963 
    1964         rc = RTR0MemObjMapUser(&pRegion->MapObjR3, pRegion->MemObj, (RTR3PTR)-1, 0,
    1965                                RTMEM_PROT_WRITE | RTMEM_PROT_READ, NIL_RTR0PROCESS);
    1966         AssertRC(rc);
    1967         if (RT_SUCCESS(rc))
    1968         {
    1969             pRegion->pvR0 = RTR0MemObjAddress(pRegion->MemObj);
    1970             pRegion->pvR3 = RTR0MemObjAddressR3(pRegion->MapObjR3);
    1971 
    1972             uint32_t iPage;
    1973             for (iPage = 0; iPage < pRegion->u32NumPages; ++iPage)
    1974             {
    1975                 pRegion->aPhys[iPage] = RTR0MemObjGetPagePhysAddr(pRegion->MemObj, iPage);
    1976             }
    1977 
    1978             return STATUS_SUCCESS;
    1979         }
    1980 
    1981         int rc2 = RTR0MemObjFree(pRegion->MemObj, false);
    1982         AssertRC(rc2);
    1983     }
    1984 
    1985     return STATUS_INSUFFICIENT_RESOURCES;
    1986 }
    1987 
    1988 static void gaRegionFree(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion)
    1989 {
    1990     Assert(pRegion);
    1991     gmrFree(pRegion);
    1992     svgaFreeGBMobForGMR(pSvga, pRegion->pMob);
     1944
     1945    /* Issue commands to delete the gmr. */
     1946    uint32_t cbRequired = 0;
     1947    SvgaMobDestroy(pSvga, pRegion->pMob, NULL, 0, &cbRequired);
     1948    cbRequired += sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMR2);
     1949
     1950    void *pvCmd = SvgaCmdBufReserve(pSvga, cbRequired, SVGA3D_INVALID_ID);
     1951    AssertReturn(pvCmd, STATUS_INSUFFICIENT_RESOURCES);
     1952
     1953    uint8_t *pu8Cmd = (uint8_t *)pvCmd;
     1954    uint32_t *pu32CmdId;
     1955
     1956    /* Undefine GMR: SVGA_CMD_DEFINE_GMR2 with numPages = 0 */
     1957    pu32CmdId = (uint32_t *)pu8Cmd;
     1958    *pu32CmdId = SVGA_CMD_DEFINE_GMR2;
     1959    pu8Cmd += sizeof(*pu32CmdId);
     1960
     1961    SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)pu8Cmd;
     1962    pCmd->gmrId = VMSVGAMOB_ID(pRegion->pMob);
     1963    pCmd->numPages = 0;
     1964    pu8Cmd += sizeof(*pCmd);
     1965
     1966    uint32_t cbCmd = 0;
     1967    NTSTATUS Status = SvgaMobDestroy(pSvga, pRegion->pMob, pu8Cmd,
     1968                                     cbRequired - ((uintptr_t)pu8Cmd - (uintptr_t)pvCmd),
     1969                                     &cbCmd);
     1970    AssertReturn(NT_SUCCESS(Status), Status);
     1971    pu8Cmd += cbCmd;
     1972
     1973    Assert(((uintptr_t)pu8Cmd - (uintptr_t)pvCmd) == cbRequired);
     1974    SvgaCmdBufCommit(pSvga, ((uintptr_t)pu8Cmd - (uintptr_t)pvCmd));
     1975
     1976    /* The mob will be deleted in DPC routine after host reports completion of the above commands. */
     1977    pRegion->pMob = NULL;
     1978
     1979#ifdef DEBUG
     1980    ASMAtomicDecU32(&pSvga->cAllocatedGmrs);
     1981    ASMAtomicSubU32(&pSvga->cAllocatedGmrPages, pRegion->u32NumPages);
     1982#endif
    19931983    GaMemFree(pRegion);
     1984    return STATUS_SUCCESS;
    19941985}
    19951986
     
    20162007}
    20172008
     2009/* Destroy all regions of a particular owner.
     2010 */
    20182011void SvgaRegionsDestroy(VBOXWDDM_EXT_VMSVGA *pSvga,
    20192012                        void *pvOwner)
     
    20332026
    20342027    /* Free all found GMRs. */
    2035     uint32_t i;
    2036     for (i = 0; i < pCtx->cIds; ++i)
     2028    for (uint32_t i = 0; i < pCtx->cIds; i++)
    20372029    {
    20382030        ExAcquireFastMutex(&pSvga->SvgaMutex);
     
    20462038                   VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
    20472039
    2048             gaRegionFree(pSvga, pRegion);
     2040            gmrDestroy(pSvga, pRegion);
    20492041        }
    20502042    }
     
    20662058    ExReleaseFastMutex(&pSvga->SvgaMutex);
    20672059
    2068     if (pRegion)
    2069     {
    2070         Assert(VMSVGAMOB_ID(pRegion->pMob) == u32GmrId);
    2071         GALOG(("Freed gmrId %d, pv %p, aPhys[0] %RHp\n",
    2072                VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
    2073         gaRegionFree(pSvga, pRegion);
    2074         return STATUS_SUCCESS;
    2075     }
    2076 
    2077     AssertFailed();
    2078     return STATUS_INVALID_PARAMETER;
     2060    AssertReturn(pRegion, STATUS_INVALID_PARAMETER);
     2061
     2062    Assert(VMSVGAMOB_ID(pRegion->pMob) == u32GmrId);
     2063    GALOG(("Freed gmrId %d, pv %p, aPhys[0] %RHp\n",
     2064           VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
     2065
     2066    return gmrDestroy(pSvga, pRegion);
    20792067}
    20802068
     
    20942082    ExReleaseFastMutex(&pSvga->SvgaMutex);
    20952083
    2096     if (pRegion)
    2097     {
    2098         Assert(VMSVGAMOB_ID(pRegion->pMob) == u32GmrId);
    2099         GALOG(("Get gmrId %d, UserAddress 0x%p\n",
    2100                VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3));
    2101         *pu64UserAddress = (uintptr_t)pRegion->pvR3;
    2102         *pu32Size = pRegion->u32NumPages * PAGE_SIZE;
    2103         return STATUS_SUCCESS;
    2104     }
    2105 
    2106     AssertFailed();
    2107     return STATUS_INVALID_PARAMETER;
     2084    AssertReturn(pRegion, STATUS_INVALID_PARAMETER);
     2085
     2086    Assert(VMSVGAMOB_ID(pRegion->pMob) == u32GmrId);
     2087    GALOG(("Get gmrId %d, UserAddress 0x%p\n",
     2088           VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3));
     2089    *pu64UserAddress = (uintptr_t)pRegion->pvR3;
     2090    *pu32Size = pRegion->u32NumPages * PAGE_SIZE;
     2091    return STATUS_SUCCESS;
    21082092}
    21092093
     
    21202104    NTSTATUS Status;
    21212105
    2122     const uint32_t cbAlloc = RT_UOFFSETOF(GAWDDMREGION, aPhys) + u32NumPages * sizeof(RTHCPHYS);
     2106    uint32_t const cbAlloc = RT_UOFFSETOF(GAWDDMREGION, aPhys) + u32NumPages * sizeof(RTHCPHYS);
    21232107    GAWDDMREGION *pRegion = (GAWDDMREGION *)GaMemAllocZero(cbAlloc);
    21242108    if (pRegion)
    21252109    {
    2126         /* Region id and VGPU10+ mobid are the same. So a mob is allocated along with the gmr.
    2127          * The mob provides an id and also reported to the host on VGPU10.
     2110        /* Region id and VGPU10+ mobid are the same. So a mob is always allocated for the gmr.
     2111         * The mob provides an id and, if SVGA_CAP_DX is available, is reported to the host on VGPU10.
     2112         *
     2113         * Allocate memory and init pRegion fields.
    21282114         */
    2129         pRegion->pvOwner = pvOwner;
    2130         pRegion->u32NumPages = u32NumPages;
    2131         pRegion->MemObj = NIL_RTR0MEMOBJ;
    2132         pRegion->MapObjR3 = NIL_RTR0MEMOBJ;
    2133 
    2134         Status = gmrAlloc(pRegion);
     2115        Status = gmrInit(pSvga, pRegion, pvOwner, u32NumPages);
    21352116        Assert(NT_SUCCESS(Status));
    21362117        if (NT_SUCCESS(Status))
    21372118        {
    2138             Status = svgaCreateGBMobForGMR(pSvga, pRegion);
    2139             Assert(NT_SUCCESS(Status));
    2140             if (NT_SUCCESS(Status))
     2119            if (VMSVGAMOB_ID(pRegion->pMob) < pSvga->u32GmrMaxIds)
    21412120            {
    2142                 if (VMSVGAMOB_ID(pRegion->pMob) < pSvga->u32GmrMaxIds)
     2121                GALOG(("Allocated gmrId %d, pv %p, aPhys[0] %RHp\n",
     2122                       VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
     2123
     2124                Status = gmrReportToHost(pSvga, pRegion);
     2125                Assert(NT_SUCCESS(Status));
     2126                if (NT_SUCCESS(Status))
    21432127                {
    2144                     GALOG(("Allocated gmrId %d, pv %p, aPhys[0] %RHp\n",
    2145                            VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
    2146 
    2147                     /* Report the GMR to the host vmsvga device. */
    2148                     Status = SvgaGMRReport(pSvga,
    2149                                            VMSVGAMOB_ID(pRegion->pMob),
    2150                                            SVGA_REMAP_GMR2_PPN64,
    2151                                            pRegion->u32NumPages,
    2152                                            &pRegion->aPhys[0]);
    2153                     Assert(NT_SUCCESS(Status));
    2154                     if (NT_SUCCESS(Status))
    2155                     {
    2156                         /* Add to the container. */
    2157                         ExAcquireFastMutex(&pSvga->SvgaMutex);
    2158 
    2159                         pRegion->Core.Key = VMSVGAMOB_ID(pRegion->pMob);
    2160                         RTAvlU32Insert(&pSvga->GMRTree, &pRegion->Core);
    2161 
    2162                         ExReleaseFastMutex(&pSvga->SvgaMutex);
    2163 
    2164                         *pu32GmrId = VMSVGAMOB_ID(pRegion->pMob);
    2165                         *pu64UserAddress = (uint64_t)pRegion->pvR3;
    2166 
    2167                         /* Everything OK. */
    2168                         return STATUS_SUCCESS;
    2169                     }
     2128                    pRegion->Core.Key = VMSVGAMOB_ID(pRegion->pMob);
     2129
     2130                    ExAcquireFastMutex(&pSvga->SvgaMutex);
     2131                    RTAvlU32Insert(&pSvga->GMRTree, &pRegion->Core);
     2132                    ExReleaseFastMutex(&pSvga->SvgaMutex);
     2133
     2134                    *pu32GmrId = VMSVGAMOB_ID(pRegion->pMob);
     2135                    *pu64UserAddress = (uint64_t)pRegion->pvR3;
     2136
     2137#ifdef DEBUG
     2138                    ASMAtomicIncU32(&pSvga->cAllocatedGmrs);
     2139                    ASMAtomicAddU32(&pSvga->cAllocatedGmrPages, pRegion->u32NumPages);
     2140#endif
     2141                    /* Everything OK. */
     2142                    return STATUS_SUCCESS;
    21702143                }
    2171                 else
    2172                 {
    2173                     AssertFailed();
    2174                     Status = STATUS_INSUFFICIENT_RESOURCES;
    2175                 }
    2176 
    2177                 svgaFreeGBMobForGMR(pSvga, pRegion->pMob);
    21782144            }
    2179 
    2180             gmrFree(pRegion);
    2181         }
     2145            else
     2146                AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     2147        }
     2148
     2149        /* Clean up on failure. */
     2150        if (pRegion->MapObjR3 != NIL_RTR0MEMOBJ)
     2151        {
     2152            int rc = RTR0MemObjFree(pRegion->MapObjR3, false);
     2153            AssertRC(rc);
     2154            pRegion->MapObjR3 = NIL_RTR0MEMOBJ;
     2155        }
     2156
     2157        SvgaMobFree(pSvga, pRegion->pMob);
     2158        pRegion->pMob = NULL;
    21822159
    21832160        GaMemFree(pRegion);
    21842161    }
    21852162    else
    2186     {
    2187         AssertFailed();
    2188         Status = STATUS_INSUFFICIENT_RESOURCES;
    2189     }
     2163        AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
    21902164
    21912165    return Status;
     
    24172391        KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
    24182392
     2393#ifdef DEBUG
     2394        ASMAtomicSubU32(&pSvga->cAllocatedMobPages, pMob->gbo.cbGbo / PAGE_SIZE);
     2395        ASMAtomicDecU32(&pSvga->cAllocatedMobs);
     2396#endif
     2397
    24192398        SvgaGboFree(&pMob->gbo);
    24202399
     
    24582437    pMob->hAllocation = hAllocation;
    24592438    *ppMob = pMob;
     2439
     2440#ifdef DEBUG
     2441    ASMAtomicIncU32(&pSvga->cAllocatedMobs);
     2442    ASMAtomicAddU32(&pSvga->cAllocatedMobPages, cMobPages);
     2443#endif
     2444
    24602445    return STATUS_SUCCESS;
    24612446}
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/Svga.h

    r99990 r99997  
    266266    RTLISTANCHOR listMobDeferredDestruction; /* Mob to be deleted after. */
    267267
     268#ifdef DEBUG
     269    /* Statistics. */
     270    uint32_t volatile cAllocatedMobs;
     271    uint32_t volatile cAllocatedMobPages;
     272    uint32_t volatile cAllocatedGmrs;
     273    uint32_t volatile cAllocatedGmrPages;
     274#endif
     275
    268276    /** Bitmap of used GMR ids. Bit 0 - GMR id 0, etc. */
    269277    uint32_t *pu32GMRBits; /* Number of GMRs is controlled by the host (u32GmrMaxIds), so allocate the bitmap. */
     
    564572                         bool fForce);
    565573
    566 NTSTATUS SvgaGenGMRReport(PVBOXWDDM_EXT_VMSVGA pSvga,
    567                           uint32_t u32GmrId,
    568                           SVGARemapGMR2Flags fRemapGMR2Flags,
    569                           uint32_t u32NumPages,
    570                           RTHCPHYS *paPhysAddresses,
    571                           void *pvDst,
    572                           uint32_t cbDst,
    573                           uint32_t *pcbOut);
    574 NTSTATUS SvgaGMRReport(PVBOXWDDM_EXT_VMSVGA pSvga,
    575                        uint32_t u32GmrId,
    576                        SVGARemapGMR2Flags fRemapGMR2Flags,
    577                        uint32_t u32NumPages,
    578                        RTHCPHYS *paPhysAddresses);
    579 
    580574NTSTATUS SvgaRegionCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
    581575                          void *pvOwner,
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/SvgaCmd.cpp

    r98103 r99997  
    212212}
    213213
    214 void SvgaCmdDefineGMR2(void *pvCmd, uint32_t u32GmrId, uint32_t cPages)
    215 {
    216     uint32_t *pu32Id = (uint32_t *)pvCmd;
    217     SVGAFifoCmdDefineGMR2 *pCommand = (SVGAFifoCmdDefineGMR2 *)&pu32Id[1];
    218 
    219     *pu32Id = SVGA_CMD_DEFINE_GMR2;
    220 
    221     pCommand->gmrId = u32GmrId;
    222     pCommand->numPages = cPages;
    223 }
    224 
    225 void SvgaCmdRemapGMR2(void *pvCmd, uint32_t u32GmrId, SVGARemapGMR2Flags flags, uint32 offsetPages, uint32_t numPages)
    226 {
    227     uint32_t *pu32Id = (uint32_t *)pvCmd;
    228     SVGAFifoCmdRemapGMR2 *pCommand = (SVGAFifoCmdRemapGMR2 *)&pu32Id[1];
    229 
    230     *pu32Id = SVGA_CMD_REMAP_GMR2;
    231 
    232     pCommand->gmrId = u32GmrId;
    233     pCommand->flags = flags;
    234     pCommand->offsetPages = offsetPages;
    235     pCommand->numPages = numPages;
    236 }
    237 
    238214void Svga3dCmdSurfaceDMAToFB(void *pvCmd, uint32_t u32Sid, uint32_t u32Width, uint32_t u32Height, uint32_t u32Offset)
    239215{
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/SvgaCmd.h

    r98103 r99997  
    5050void Svga3dCmdDestroyContext(void *pvCmd, uint32_t u32Cid);
    5151
    52 void SvgaCmdDefineGMR2(void *pvCmd, uint32_t u32GmrId, uint32_t cPages);
    53 void SvgaCmdRemapGMR2(void *pvCmd, uint32_t u32GmrId, SVGARemapGMR2Flags flags, uint32 offsetPages, uint32_t numPages);
    54 
    5552void Svga3dCmdPresent(void *pvCmd, uint32_t u32Sid, uint32_t u32Width, uint32_t u32Height);
    5653
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/VBoxMPGaWddm.cpp

    r99990 r99997  
    15491549}
    15501550
     1551
     1552static void dxDeferredMobDestruction(PVOID IoObject, PVOID Context, PIO_WORKITEM IoWorkItem)
     1553{
     1554    RT_NOREF(IoObject);
     1555    IoFreeWorkItem(IoWorkItem);
     1556
     1557    PVBOXWDDM_EXT_VMSVGA pSvga = (PVBOXWDDM_EXT_VMSVGA)Context;
     1558    if (pSvga->pMiniportMobData)
     1559    {
     1560        uint64_t const u64MobFence = ASMAtomicReadU64(&pSvga->pMiniportMobData->u64MobFence);
     1561
     1562        /* Move mobs which were deleted by the host to the local list under the lock. */
     1563        RTLISTANCHOR listDestroyedMobs;
     1564        RTListInit(&listDestroyedMobs);
     1565
     1566        KIRQL OldIrql;
     1567        SvgaHostObjectsLock(pSvga, &OldIrql);
     1568
     1569        PVMSVGAMOB pIter, pNext;
     1570        RTListForEachSafe(&pSvga->listMobDeferredDestruction, pIter, pNext, VMSVGAMOB, node)
     1571        {
     1572            if (gaFenceCmp64(pIter->u64MobFence, u64MobFence) <= 0)
     1573            {
     1574                RTListNodeRemove(&pIter->node);
     1575                RTListAppend(&listDestroyedMobs, &pIter->node);
     1576            }
     1577        }
     1578
     1579        SvgaHostObjectsUnlock(pSvga, OldIrql);
     1580
     1581        RTListForEachSafe(&listDestroyedMobs, pIter, pNext, VMSVGAMOB, node)
     1582        {
     1583            /* Delete the data. SvgaMobFree deallocates pIter. */
     1584            RTListNodeRemove(&pIter->node);
     1585            SvgaMobFree(pSvga, pIter);
     1586        }
     1587    }
     1588}
     1589
     1590
    15511591VOID GaDxgkDdiDpcRoutine(const PVOID MiniportDeviceContext)
    15521592{
     
    16361676     * Deferred MOB destruction.
    16371677     */
    1638     if (pSvga->pMiniportMobData)
    1639     {
    1640         uint64_t const u64MobFence = pSvga->pMiniportMobData->u64MobFence;
    1641 
    1642         /* Move mobs which were deleted by the host to the local list under the lock. */
    1643         RTLISTANCHOR listDestroyedMobs;
    1644         RTListInit(&listDestroyedMobs);
    1645 
    1646         SvgaHostObjectsLock(pSvga, &OldIrql);
    1647 
    1648         if (!RTListIsEmpty(&pSvga->listMobDeferredDestruction))
    1649         {
    1650             PVMSVGAMOB pIter, pNext;
    1651             RTListForEachSafe(&pSvga->listMobDeferredDestruction, pIter, pNext, VMSVGAMOB, node)
    1652             {
    1653                 if (gaFenceCmp64(pIter->u64MobFence, u64MobFence) <= 0)
    1654                 {
    1655                     RTListNodeRemove(&pIter->node);
    1656                     RTListAppend(&listDestroyedMobs, &pIter->node);
    1657                 }
    1658             }
    1659         }
    1660 
    1661         SvgaHostObjectsUnlock(pSvga, OldIrql);
    1662 
    1663         if (!RTListIsEmpty(&listDestroyedMobs))
    1664         {
    1665             PVMSVGAMOB pIter, pNext;
    1666             RTListForEachSafe(&listDestroyedMobs, pIter, pNext, VMSVGAMOB, node)
    1667             {
    1668                 /* Delete the data. SvgaMobFree deallocates pIter. */
    1669                 RTListNodeRemove(&pIter->node);
    1670                 SvgaMobFree(pSvga, pIter);
    1671             }
    1672         }
     1678    SvgaHostObjectsLock(pSvga, &OldIrql);
     1679    bool fMobs = !RTListIsEmpty(&pSvga->listMobDeferredDestruction);
     1680    SvgaHostObjectsUnlock(pSvga, OldIrql);
     1681
     1682    if (fMobs)
     1683    {
     1684        /* Deallocate memory in a worker thread at PASSIVE_LEVEL. */
     1685        PIO_WORKITEM pWorkItem = IoAllocateWorkItem(pDevExt->pPDO);
     1686        if (pWorkItem)
     1687            IoQueueWorkItemEx(pWorkItem, dxDeferredMobDestruction, DelayedWorkQueue, pSvga);
    16731688    }
    16741689}
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