VirtualBox

Ignore:
Timestamp:
May 5, 2025 6:17:33 PM (4 days ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168723
Message:

WDDM: Miniport: unify handling of guest backing memory for surfaces, object tables, etc. bugref:10885

File:
1 edited

Legend:

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

    r108786 r109165  
    55
    66/*
    7  * Copyright (C) 2016-2024 Oracle and/or its affiliates.
     7 * Copyright (C) 2016-2025 Oracle and/or its affiliates.
    88 *
    99 * This file is part of VirtualBox base platform packages, as
     
    6161
    6262    for (uint32_t i = 0; i < RT_ELEMENTS(pSvga->aOT); ++i)
    63     {
    64         SvgaGboFree(&pSvga->aOT[i].gbo);
    65 
    66         RTR0MemObjFree(pSvga->aOT[i].hMemObj, true);
    67         pSvga->aOT[i].hMemObj = NIL_RTR0MEMOBJ;
    68     }
     63        SvgaGboUnreference(pSvga, &pSvga->aOT[i].pGbo);
    6964
    7065    return Status;
     
    7469struct VMSVGAOTFREE
    7570{
    76     VMSVGAGBO  gbo;
    77     RTR0MEMOBJ hMemObj;
     71    PVMSVGAGBO  pGbo;
    7872};
    7973
     
    8175static DECLCALLBACK(void) svgaOTFreeCb(VBOXWDDM_EXT_VMSVGA *pSvga, void *pvData, uint32_t cbData)
    8276{
    83     RT_NOREF(pSvga);
    8477    AssertReturnVoid(cbData == sizeof(struct VMSVGAOTFREE));
    8578    struct VMSVGAOTFREE *p = (struct VMSVGAOTFREE *)pvData;
    86     SvgaGboFree(&p->gbo);
    87     RTR0MemObjFree(p->hMemObj, true);
     79    SvgaGboUnreference(pSvga, &p->pGbo);
    8880}
    8981
     
    9486    uint32_t cMaxEntries;
    9587} VMSVGAOTINFO, *PVMSVGAOTINFO;
    96 
    9788
    9889static VMSVGAOTINFO const s_aOTInfo[SVGA_OTABLE_DX_MAX] =
     
    133124        cbOT *= 2;
    134125
    135     /* Allocate pages for the new COTable. */
    136     RTR0MEMOBJ hMemObjOT;
    137     int rc = RTR0MemObjAllocPageTag(&hMemObjOT, cbOT, false /* executable R0 mapping */, "VMSVGAOT");
    138     AssertRCReturn(rc, STATUS_INSUFFICIENT_RESOURCES);
    139 
    140     memset(RTR0MemObjAddress(hMemObjOT), 0, cbOT);
    141 
    142     /* Allocate a new gbo. */
    143     VMSVGAGBO gbo;
    144     NTSTATUS Status = SvgaGboInit(&gbo, cbOT >> PAGE_SHIFT);
    145     AssertReturnStmt(NT_SUCCESS(Status),
    146                      RTR0MemObjFree(hMemObjOT, true),
    147                      Status);
    148 
    149     Status = SvgaGboFillPageTableForMemObj(&gbo, hMemObjOT);
    150     AssertReturnStmt(NT_SUCCESS(Status),
    151                      SvgaGboFree(&gbo); RTR0MemObjFree(hMemObjOT, true),
    152                      Status);
     126    PVMSVGAGBO pGbo;
     127    NTSTATUS Status = SvgaGboCreate(pSvga, &pGbo, cbOT, "VMSVGAOT");
     128    AssertReturn(NT_SUCCESS(Status), Status);
     129
     130    memset(RTR0MemObjAddress(pGbo->hMemObj), 0, cbOT);
    153131
    154132    if (pOT->cEntries == 0)
     
    160138            SVGA3dCmdSetOTableBase64 *pCmd = (SVGA3dCmdSetOTableBase64 *)pvCmd;
    161139            pCmd->type             = enmType;
    162             pCmd->baseAddress      = gbo.base;
    163             pCmd->sizeInBytes      = gbo.cbGbo;
     140            pCmd->baseAddress      = pGbo->base;
     141            pCmd->sizeInBytes      = pGbo->cbGbo;
    164142            pCmd->validSizeInBytes = 0;
    165             pCmd->ptDepth          = gbo.enmMobFormat;
     143            pCmd->ptDepth          = pGbo->enmMobFormat;
    166144
    167145            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
    168146        }
    169147        else
    170             AssertFailedReturnStmt(SvgaGboFree(&gbo); RTR0MemObjFree(hMemObjOT, true),
     148            AssertFailedReturnStmt(SvgaGboUnreference(pSvga, &pGbo),
    171149                                   STATUS_INSUFFICIENT_RESOURCES);
    172150    }
     
    179157            SVGA3dCmdGrowOTable *pCmd = (SVGA3dCmdGrowOTable *)pvCmd;
    180158            pCmd->type             = enmType;
    181             pCmd->baseAddress      = gbo.base;
    182             pCmd->sizeInBytes      = gbo.cbGbo;
     159            pCmd->baseAddress      = pGbo->base;
     160            pCmd->sizeInBytes      = pGbo->cbGbo;
    183161            pCmd->validSizeInBytes = pOT->cEntries * pOTInfo->cbEntry;
    184             pCmd->ptDepth          = gbo.enmMobFormat;
     162            pCmd->ptDepth          = pGbo->enmMobFormat;
    185163
    186164            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
    187165        }
    188166        else
    189             AssertFailedReturnStmt(SvgaGboFree(&gbo); RTR0MemObjFree(hMemObjOT, true),
     167            AssertFailedReturnStmt(SvgaGboUnreference(pSvga, &pGbo),
    190168                                   STATUS_INSUFFICIENT_RESOURCES);
    191169
    192         /* Command buffer completion callback to free the OT. */
     170        /* Command buffer completion callback to free the old OT. */
    193171        struct VMSVGAOTFREE callbackData;
    194         callbackData.gbo = pOT->gbo;
    195         callbackData.hMemObj = pOT->hMemObj;
     172        callbackData.pGbo = pOT->pGbo;
    196173        SvgaCmdBufSetCompletionCallback(pSvga, svgaOTFreeCb, &callbackData, sizeof(callbackData));
    197174
    198         memset(&pOT->gbo, 0, sizeof(pOT->gbo));
    199         pOT->hMemObj = NIL_RTR0MEMOBJ;
    200     }
    201 
     175        pOT->pGbo = 0;
     176    }
     177
     178    Assert(!pOT->pGbo);
    202179    SvgaCmdBufFlush(pSvga);
    203180
    204     pOT->gbo = gbo;
    205     pOT->hMemObj = hMemObjOT;
     181    pOT->pGbo = pGbo;
    206182    pOT->cEntries = cbOT / pOTInfo->cbEntry;
    207183
     
    223199}
    224200
     201
    225202static NTSTATUS svgaCreateMiniportMob(VBOXWDDM_EXT_VMSVGA *pSvga)
    226203{
    227     NTSTATUS Status;
    228 
    229204    uint32_t const cbMiniportMob = RT_ALIGN_32(sizeof(VMSVGAMINIPORTMOB), PAGE_SIZE);
    230     RTR0MEMOBJ hMemObjMiniportMob;
    231     int rc = RTR0MemObjAllocPageTag(&hMemObjMiniportMob, cbMiniportMob,
    232                                     false /* executable R0 mapping */, "VMSVGAMOB0");
    233     if (RT_SUCCESS(rc))
    234     {
    235         Status = SvgaMobCreate(pSvga, &pSvga->pMiniportMob, cbMiniportMob / PAGE_SIZE, 0);
     205
     206    NTSTATUS Status = SvgaGboCreate(pSvga, &pSvga->pMiniportGbo, cbMiniportMob, "VMSVGAMOB0");
     207    if (NT_SUCCESS(Status))
     208    {
     209        Status = SvgaMobAlloc(pSvga, &pSvga->mobidMiniport, pSvga->pMiniportGbo);
    236210        if (NT_SUCCESS(Status))
    237211        {
    238             Status = SvgaMobSetMemObj(pSvga->pMiniportMob, hMemObjMiniportMob);
    239             if (NT_SUCCESS(Status))
     212            uint32_t cbCmd = 0;
     213            SvgaMobDefine(pSvga, SVGA3D_INVALID_ID, NULL, 0, &cbCmd);
     214            void *pvCmd = SvgaCmdBufReserve(pSvga, cbCmd, SVGA3D_INVALID_ID);
     215            if (pvCmd)
    240216            {
    241                 void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DEFINE_GB_MOB64, sizeof(SVGA3dCmdDefineGBMob64), SVGA3D_INVALID_ID);
    242                 if (pvCmd)
    243                 {
    244                     SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    245                     pCmd->mobid       = VMSVGAMOB_ID(pSvga->pMiniportMob);
    246                     pCmd->ptDepth     = pSvga->pMiniportMob->gbo.enmMobFormat;
    247                     pCmd->base        = pSvga->pMiniportMob->gbo.base;
    248                     pCmd->sizeInBytes = pSvga->pMiniportMob->gbo.cbGbo;
    249                     SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
    250 
    251                     pSvga->pMiniportMobData = (VMSVGAMINIPORTMOB volatile *)RTR0MemObjAddress(hMemObjMiniportMob);
    252                     memset((void *)pSvga->pMiniportMobData, 0, cbMiniportMob);
    253                     RTListInit(&pSvga->listMobDeferredDestruction);
    254                     //pSvga->u64MobFence = 0;
    255                 }
    256                 else
    257                     AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     217                SvgaMobDefine(pSvga, pSvga->mobidMiniport, pvCmd, cbCmd, &cbCmd);
     218                SvgaCmdBufCommit(pSvga, cbCmd);
     219
     220                pSvga->pMiniportMobData = (VMSVGAMINIPORTMOB volatile *)RTR0MemObjAddress(pSvga->pMiniportGbo->hMemObj);
     221                memset((void *)pSvga->pMiniportMobData, 0, cbMiniportMob);
     222                RTListInit(&pSvga->listMobDeferredDestruction);
     223                //pSvga->u64MobFence = 0;
    258224            }
    259         }
    260     }
    261     else
    262         AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     225            else
     226                AssertFailedStmt(SvgaMobFree(pSvga, &pSvga->mobidMiniport); STATUS_INSUFFICIENT_RESOURCES);
     227        }
     228        else
     229            SvgaGboUnreference(pSvga, &pSvga->pMiniportGbo);
     230    }
    263231
    264232    return Status;
     
    275243    /* Wait for buffers to complete. Up to 5 seconds, arbitrary. */
    276244    int cIntervals = 0;
    277     while (!SvgaCmdBufIsIdle(pSvga) && cIntervals++ < 50)
     245    while (!SvgaCmdBufIsIdle(pSvga) && ASMAtomicReadS32(&pSvga->cQueuedWorkItems) && cIntervals++ < 50)
    278246    {
    279247        /* Give the host some time to process them. */
     
    303271    pSvga->u32MaxWidth  = SVGARegRead(pSvga, SVGA_REG_MAX_WIDTH);
    304272    pSvga->u32MaxHeight = SVGARegRead(pSvga, SVGA_REG_MAX_HEIGHT);
     273
     274    if (pSvga->u32Caps & SVGA_CAP_GBOBJECTS)
     275    {
     276        pSvga->u32MaxMobSize  = SVGARegRead(pSvga, SVGA_REG_MOB_MAX_SIZE);
     277    }
    305278
    306279    if (pSvga->u32Caps & SVGA_CAP_GMR2)
     
    357330}
    358331
     332#ifdef DEBUG
     333static DECLCALLBACK(int) mobDumpCb(PAVLU32NODECORE pNode, void *pvUser);
     334#endif
     335
    359336void SvgaAdapterStop(PVBOXWDDM_EXT_VMSVGA pSvga,
    360337                     DXGKRNL_INTERFACE *pDxgkInterface)
     
    381358        }
    382359
    383         if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
     360        if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX) && pSvga->mobidMiniport != SVGA3D_INVALID_ID)
    384361        {
    385362            /* Free the miniport mob at last. Can't use SvgaMobDestroy here because it tells the host to write a fence
     
    389366            {
    390367                SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
    391                 pCmd->mobid = VMSVGAMOB_ID(pSvga->pMiniportMob);
     368                pCmd->mobid = pSvga->mobidMiniport;
    392369                SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
    393370            }
     
    399376
    400377        if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
    401             SvgaMobFree(pSvga, pSvga->pMiniportMob); /* After svgaHwStop because it waits for command buffer completion. */
     378        {
     379            SvgaMobFree(pSvga, &pSvga->mobidMiniport); /* After svgaHwStop because it waits for command buffer completion. */
     380            SvgaGboUnreference(pSvga, &pSvga->pMiniportGbo);
     381        }
    402382
    403383        Status = pDxgkInterface->DxgkCbUnmapMemory(pDxgkInterface->DeviceHandle,
    404384                                                   (PVOID)pSvga->pu32FIFO);
    405385        Assert(Status == STATUS_SUCCESS); RT_NOREF(Status);
     386
     387#ifdef DEBUG
     388        uint32_t cMobs = 0;
     389        RTAvlU32DoWithAll(&pSvga->MobTree, 0, mobDumpCb, &cMobs);
     390        GALOG(("cMobs = %u\n", cMobs));
     391        Assert(cMobs == 0);
     392#endif
    406393
    407394        GaMemFree(pSvga);
     
    435422    // pSvga->MobTree = NULL;
    436423    RTListInit(&pSvga->DeletedHostObjectsList);
     424    pSvga->mobidMiniport = SVGA3D_INVALID_ID;
    437425
    438426    /* The port IO address is also needed for hardware access. */
     
    18681856typedef struct GAWDDMREGION
    18691857{
    1870     /* Key is GMR id (equal to u32GmrId). */
     1858    /* Key is GMR id (equal to 'mobid'). */
    18711859    AVLU32NODECORE Core;
    18721860    /* Pointer to a graphics context device (PVBOXWDDM_DEVICE) the GMR is associated with. */
    18731861    void      *pvOwner;
    1874     /* The ring-3 mapping memory object handle (from mob). */
     1862    /* Memory. */
     1863    PVMSVGAGBO pGbo;
     1864    /* A corresponding MOB, which provides the GMR id to the host. */
     1865    SVGAMobId mobid;
     1866    /* The ring-3 mapping memory object handle. */
    18751867    RTR0MEMOBJ MapObjR3;
    18761868    RTR3PTR    pvR3;
    1877     /* A corresponding MOB, which provides the GMR id and RTR0MEMOBJ for the region memory. */
    1878     PVMSVGAMOB pMob;
    1879     /* The allocated size in pages. */
     1869    /* The allocated size in pages and number of elements in the aPhys array. */
    18801870    uint32_t   u32NumPages;
    18811871    /* Physical addresses of the pages. */
     
    18841874
    18851875
     1876/* Deallocate gmr.
     1877 */
     1878static void gmrFreeMemory(VBOXWDDM_EXT_VMSVGA *pSvga, GAWDDMREGION *pRegion)
     1879{
     1880    if (pRegion->MapObjR3 != NIL_RTR0MEMOBJ)
     1881    {
     1882        int rc = RTR0MemObjFree(pRegion->MapObjR3, false);
     1883        AssertRC(rc);
     1884        pRegion->MapObjR3 = NIL_RTR0MEMOBJ;
     1885    }
     1886
     1887    SvgaMobFree(pSvga, &pRegion->mobid);
     1888
     1889    SvgaGboUnreference(pSvga, &pRegion->pGbo);
     1890}
     1891
    18861892/* Allocate memory pages and the corresponding mob.
    18871893 */
     
    18901896    NTSTATUS Status;
    18911897
    1892     /* Allocate memory. */
    1893     RTR0MEMOBJ MemObj;
    1894     int rc = RTR0MemObjAllocPageTag(&MemObj, u32NumPages << PAGE_SHIFT,
    1895                                     false /* executable R0 mapping */, "VMSVGAGMR");
    1896     AssertRC(rc);
    1897     if (RT_SUCCESS(rc))
    1898     {
    1899         if (!RTR0MemObjWasZeroInitialized(MemObj))
    1900             RT_BZERO(RTR0MemObjAddress(MemObj), (size_t)u32NumPages << PAGE_SHIFT);
    1901 
    1902         /* Allocate corresponding mob. */
    1903         Status = SvgaMobCreate(pSvga, &pRegion->pMob, u32NumPages, 0);
    1904         Assert(NT_SUCCESS(Status));
    1905         if (NT_SUCCESS(Status))
    1906         {
    1907             Status = SvgaMobSetMemObj(pRegion->pMob, MemObj);
     1898    Status = SvgaGboCreate(pSvga, &pRegion->pGbo, u32NumPages << PAGE_SHIFT, "VMSVGAGMR");
     1899
     1900    if (NT_SUCCESS(Status))
     1901    {
     1902        int rc = RTR0MemObjMapUser(&pRegion->MapObjR3, pRegion->pGbo->hMemObj, (RTR3PTR)-1, 0,
     1903                                   RTMEM_PROT_WRITE | RTMEM_PROT_READ, NIL_RTR0PROCESS);
     1904        AssertRC(rc);
     1905        if (RT_SUCCESS(rc))
     1906        {
     1907            if (!RTR0MemObjWasZeroInitialized(pRegion->pGbo->hMemObj))
     1908                RT_BZERO(RTR0MemObjAddress(pRegion->pGbo->hMemObj), (size_t)u32NumPages << PAGE_SHIFT);
     1909
     1910            /* Allocate corresponding mob. */
     1911            Status = SvgaMobAlloc(pSvga, &pRegion->mobid, pRegion->pGbo);
    19081912            Assert(NT_SUCCESS(Status));
    19091913            if (NT_SUCCESS(Status))
     1914            {
     1915                /*
     1916                 * Success.
     1917                 */
    19101918                return STATUS_SUCCESS;
    1911         }
    1912 
    1913         if (   pRegion->pMob
    1914             && pRegion->pMob->hMemObj == NIL_RTR0MEMOBJ)
    1915         {
    1916             /* The memory object has not been assigned to the mob yet. Clean up the local object.
    1917              * Otherwise the caller will clean up.
    1918              */
    1919             int rc2 = RTR0MemObjFree(MemObj, false);
    1920             AssertRC(rc2);
    1921         }
     1919            }
     1920        }
     1921        else
     1922            AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     1923
     1924        /*
     1925         * Cleanup.
     1926         */
     1927        gmrFreeMemory(pSvga, pRegion);
    19221928    }
    19231929    else
     
    19341940    if (NT_SUCCESS(Status))
    19351941    {
    1936         int rc = RTR0MemObjMapUser(&pRegion->MapObjR3, pRegion->pMob->hMemObj, (RTR3PTR)-1, 0,
    1937                                    RTMEM_PROT_WRITE | RTMEM_PROT_READ, NIL_RTR0PROCESS);
    1938         AssertRC(rc);
    1939         if (RT_SUCCESS(rc))
    1940         {
    1941             uint32_t iPage;
    1942             for (iPage = 0; iPage < u32NumPages; ++iPage)
    1943                 pRegion->aPhys[iPage] = RTR0MemObjGetPagePhysAddr(pRegion->pMob->hMemObj, iPage);
    1944 
    1945             pRegion->pvR3 = RTR0MemObjAddressR3(pRegion->MapObjR3);
    1946 
    1947             pRegion->pvOwner = pvOwner;
    1948             pRegion->u32NumPages = u32NumPages;
    1949         }
    1950         else
    1951             AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     1942        uint32_t iPage;
     1943        for (iPage = 0; iPage < u32NumPages; ++iPage)
     1944            pRegion->aPhys[iPage] = RTR0MemObjGetPagePhysAddr(pRegion->pGbo->hMemObj, iPage);
     1945
     1946        pRegion->pvR3 = RTR0MemObjAddressR3(pRegion->MapObjR3);
     1947
     1948        pRegion->pvOwner = pvOwner;
     1949        pRegion->u32NumPages = u32NumPages;
    19521950    }
    19531951
     
    19831981    {
    19841982    SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)pu8Cmd;
    1985     pCmd->gmrId = VMSVGAMOB_ID(pRegion->pMob);
     1983    pCmd->gmrId = pRegion->mobid;
    19861984    pCmd->numPages = pRegion->u32NumPages;
    19871985    pu8Cmd += sizeof(*pCmd);
     
    19941992    {
    19951993    SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)pu8Cmd;
    1996     pCmd->gmrId = VMSVGAMOB_ID(pRegion->pMob);
     1994    pCmd->gmrId = pRegion->mobid;
    19971995    pCmd->flags = SVGA_REMAP_GMR2_PPN64;
    19981996    pCmd->offsetPages = 0;
     
    20202018        {
    20212019        SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pu8Cmd;
    2022         pCmd->mobid       = VMSVGAMOB_ID(pRegion->pMob);
    2023         pCmd->ptDepth     = pRegion->pMob->gbo.enmMobFormat;
    2024         pCmd->base        = pRegion->pMob->gbo.base;
    2025         pCmd->sizeInBytes = pRegion->pMob->gbo.cbGbo;
     2020        pCmd->mobid       = pRegion->mobid;
     2021        pCmd->ptDepth     = pRegion->pGbo->enmMobFormat;
     2022        pCmd->base        = pRegion->pGbo->base;
     2023        pCmd->sizeInBytes = pRegion->pGbo->cbGbo;
    20262024        pu8Cmd += sizeof(*pCmd);
    20272025        }
     
    20402038    AssertReturn(pRegion, STATUS_INVALID_PARAMETER);
    20412039
    2042     /* Mapping must be freed prior to the mob destruction. Otherwise, due to a race condition,
    2043      * SvgaMobFree could free the mapping in a system worker thread after DPC, which would not
    2044      * work obviously, because the mapping was created for another process.
    2045      */
    2046     if (pRegion->MapObjR3 != NIL_RTR0MEMOBJ)
    2047     {
    2048         int rc = RTR0MemObjFree(pRegion->MapObjR3, false);
    2049         AssertRC(rc);
    2050         pRegion->MapObjR3 = NIL_RTR0MEMOBJ;
    2051     }
    2052 
    20532040    /* Issue commands to delete the gmr. */
    20542041    uint32_t cbRequired = 0;
    2055     SvgaMobDestroy(pSvga, pRegion->pMob, NULL, 0, &cbRequired);
     2042    if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
     2043        SvgaMobDestroy(pSvga, 0, NULL, 0, &cbRequired);
    20562044    cbRequired += sizeof(uint32_t) + sizeof(SVGAFifoCmdDefineGMR2);
    20572045
     
    20682056
    20692057    SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)pu8Cmd;
    2070     pCmd->gmrId = VMSVGAMOB_ID(pRegion->pMob);
     2058    pCmd->gmrId = pRegion->mobid;
    20712059    pCmd->numPages = 0;
    20722060    pu8Cmd += sizeof(*pCmd);
    20732061
    2074     uint32_t cbCmd = 0;
    2075     NTSTATUS Status = SvgaMobDestroy(pSvga, pRegion->pMob, pu8Cmd,
    2076                                      cbRequired - ((uintptr_t)pu8Cmd - (uintptr_t)pvCmd),
    2077                                      &cbCmd);
    2078     AssertReturn(NT_SUCCESS(Status), Status);
    2079     pu8Cmd += cbCmd;
     2062    if (RT_BOOL(pSvga->u32Caps & SVGA_CAP_DX))
     2063    {
     2064        uint32_t cbCmd = 0;
     2065        NTSTATUS Status = SvgaMobDestroy(pSvga, pRegion->mobid, pu8Cmd,
     2066                                         cbRequired - ((uintptr_t)pu8Cmd - (uintptr_t)pvCmd),
     2067                                         &cbCmd);
     2068        AssertReturn(NT_SUCCESS(Status), Status);
     2069        pu8Cmd += cbCmd;
     2070    }
    20802071
    20812072    Assert(((uintptr_t)pu8Cmd - (uintptr_t)pvCmd) == cbRequired);
    20822073    SvgaCmdBufCommit(pSvga, ((uintptr_t)pu8Cmd - (uintptr_t)pvCmd));
    2083 
    2084     /* The mob will be deleted in DPC routine after host reports completion of the above commands. */
    2085     pRegion->pMob = NULL;
    20862074
    20872075#ifdef DEBUG
     
    20892077    ASMAtomicSubU32(&pSvga->cAllocatedGmrPages, pRegion->u32NumPages);
    20902078#endif
     2079
     2080    /* The mob id will be deleted in DPC routine after host reports completion of the above commands. */
     2081    pRegion->mobid = SVGA3D_INVALID_ID;
     2082    gmrFreeMemory(pSvga, pRegion);
     2083
    20912084    GaMemFree(pRegion);
    20922085    return STATUS_SUCCESS;
     
    21102103    {
    21112104        AssertReturn(pCtx->cIds < pCtx->cMaxIds, -1);
    2112         pCtx->au32Ids[pCtx->cIds++] = VMSVGAMOB_ID(pRegion->pMob);
     2105        pCtx->au32Ids[pCtx->cIds++] = pRegion->mobid;
    21132106    }
    21142107    return 0;
     
    21422135        if (pRegion)
    21432136        {
    2144             Assert(VMSVGAMOB_ID(pRegion->pMob) == pCtx->au32Ids[i]);
     2137            Assert(pRegion->mobid == pCtx->au32Ids[i]);
    21452138            GALOG(("Deallocate gmrId %d, pv %p, aPhys[0] %RHp\n",
    2146                    VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
     2139                   pRegion->mobid, pRegion->pvR3, pRegion->aPhys[0]));
    21472140
    21482141            gmrDestroy(pSvga, pRegion);
     
    21682161    AssertReturn(pRegion, STATUS_INVALID_PARAMETER);
    21692162
    2170     Assert(VMSVGAMOB_ID(pRegion->pMob) == u32GmrId);
     2163    Assert(pRegion->mobid == u32GmrId);
    21712164    GALOG(("Freed gmrId %d, pv %p, aPhys[0] %RHp\n",
    2172            VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
     2165           pRegion->mobid, pRegion->pvR3, pRegion->aPhys[0]));
    21732166
    21742167    return gmrDestroy(pSvga, pRegion);
     
    21922185    AssertReturn(pRegion, STATUS_INVALID_PARAMETER);
    21932186
    2194     Assert(VMSVGAMOB_ID(pRegion->pMob) == u32GmrId);
     2187    Assert(pRegion->mobid == u32GmrId);
    21952188    GALOG(("Get gmrId %d, UserAddress 0x%p\n",
    2196            VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3));
     2189           pRegion->mobid, pRegion->pvR3));
    21972190    *pu64UserAddress = (uintptr_t)pRegion->pvR3;
    21982191    *pu32Size = pRegion->u32NumPages * PAGE_SIZE;
     
    22162209    if (pRegion)
    22172210    {
     2211        pRegion->mobid = SVGA3D_INVALID_ID;
     2212
    22182213        /* Region id and VGPU10+ mobid are the same. So a mob is always allocated for the gmr.
    22192214         * The mob provides an id and, if SVGA_CAP_DX is available, is reported to the host on VGPU10.
     
    22252220        if (NT_SUCCESS(Status))
    22262221        {
    2227             if (VMSVGAMOB_ID(pRegion->pMob) < pSvga->u32GmrMaxIds)
     2222            if (pRegion->mobid < pSvga->u32GmrMaxIds)
    22282223            {
    22292224                GALOG(("Allocated gmrId %d, pv %p, aPhys[0] %RHp\n",
    2230                        VMSVGAMOB_ID(pRegion->pMob), pRegion->pvR3, pRegion->aPhys[0]));
     2225                       pRegion->mobid, pRegion->pvR3, pRegion->aPhys[0]));
    22312226
    22322227                Status = gmrReportToHost(pSvga, pRegion);
     
    22342229                if (NT_SUCCESS(Status))
    22352230                {
    2236                     pRegion->Core.Key = VMSVGAMOB_ID(pRegion->pMob);
     2231                    pRegion->Core.Key = pRegion->mobid;
    22372232
    22382233                    ExAcquireFastMutex(&pSvga->SvgaMutex);
     
    22402235                    ExReleaseFastMutex(&pSvga->SvgaMutex);
    22412236
    2242                     *pu32GmrId = VMSVGAMOB_ID(pRegion->pMob);
     2237                    *pu32GmrId = pRegion->mobid;
    22432238                    *pu64UserAddress = (uint64_t)pRegion->pvR3;
    22442239
     
    22632258        }
    22642259
    2265         SvgaMobFree(pSvga, pRegion->pMob);
    2266         pRegion->pMob = NULL;
     2260        SvgaMobFree(pSvga, &pRegion->mobid);
    22672261
    22682262        GaMemFree(pRegion);
     
    23362330 */
    23372331
    2338 void SvgaGboFree(VMSVGAGBO *pGbo)
    2339 {
     2332void SvgaGboFree(VBOXWDDM_EXT_VMSVGA *pSvga,
     2333                 VMSVGAGBO *pGbo)
     2334{
     2335    RT_NOREF(pSvga);
     2336
     2337    GALOG(("gbo = %p\n", pGbo));
     2338    if (!pGbo->flags.fMdl)
     2339    {
     2340        if (pGbo->hMemObj != NIL_RTR0MEMOBJ)
     2341        {
     2342            int rc = RTR0MemObjFree(pGbo->hMemObj, true);
     2343            AssertRC(rc);
     2344            pGbo->hMemObj = NIL_RTR0MEMOBJ;
     2345        }
     2346    }
     2347
    23402348    if (pGbo->hMemObjPT != NIL_RTR0MEMOBJ)
    23412349    {
     
    23442352        pGbo->hMemObjPT = NIL_RTR0MEMOBJ;
    23452353    }
     2354
     2355#ifdef DEBUG
     2356    ASMAtomicDecU32(&pSvga->cAllocatedGbos);
     2357    GALOG(("cAllocatedGbos = %u\n", pSvga->cAllocatedGbos));
     2358#endif
     2359
    23462360    memset(pGbo, 0, sizeof(*pGbo));
    2347 }
    2348 
    2349 NTSTATUS SvgaGboInit(VMSVGAGBO *pGbo, uint32_t cPages)
     2361    GaMemFree(pGbo);
     2362}
     2363
     2364static NTSTATUS svgaGboInit(VMSVGAGBO *pGbo, uint32_t cPages)
    23502365{
    23512366    /*
     
    23992414
    24002415
    2401 NTSTATUS SvgaGboFillPageTableForMDL(PVMSVGAGBO pGbo,
    2402                                     PMDL pMdl,
    2403                                     uint32_t MdlOffset)
     2416static NTSTATUS svgaGboFillPageTableForMDL(PVMSVGAGBO pGbo,
     2417                                           PMDL pMdl,
     2418                                           uint32_t MdlOffset)
    24042419{
    24052420    PPFN_NUMBER paMdlPfn = &MmGetMdlPfnArray(pMdl)[MdlOffset];
     
    24282443
    24292444
    2430 NTSTATUS SvgaGboFillPageTableForMemObj(PVMSVGAGBO pGbo,
    2431                                        RTR0MEMOBJ hMemObj)
     2445static NTSTATUS svgaGboFillPageTableForMemObj(PVMSVGAGBO pGbo,
     2446                                              RTR0MEMOBJ hMemObj)
    24322447{
    24332448    if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_0)
     
    24552470
    24562471
     2472NTSTATUS SvgaGboCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
     2473                       PVMSVGAGBO *ppGbo,
     2474                       uint32_t cbGbo,
     2475                       const char *pszTag)
     2476{
     2477    AssertCompile(NIL_RTR0MEMOBJ == 0);
     2478
     2479    NTSTATUS Status;
     2480
     2481    PVMSVGAGBO pGbo = (PVMSVGAGBO)GaMemAllocZero(sizeof(VMSVGAGBO));
     2482    AssertReturn(pGbo, STATUS_INSUFFICIENT_RESOURCES);
     2483
     2484    pGbo->cRefs = 1;
     2485
     2486    int rc = RTR0MemObjAllocPageTag(&pGbo->hMemObj, cbGbo, false /* executable R0 mapping */, pszTag);
     2487    if (RT_SUCCESS(rc))
     2488    {
     2489        size_t const cPages = RTR0MemObjSize(pGbo->hMemObj) / PAGE_SIZE;
     2490        if (cPages > 0 && cPages < pSvga->u32MaxMobSize / PAGE_SIZE)
     2491        {
     2492            Status = svgaGboInit(pGbo, (uint32_t)cPages);
     2493            if (NT_SUCCESS(Status))
     2494            {
     2495                Status = svgaGboFillPageTableForMemObj(pGbo, pGbo->hMemObj);
     2496                if (NT_SUCCESS(Status))
     2497                {
     2498#ifdef DEBUG
     2499                    ASMAtomicIncU32(&pSvga->cAllocatedGbos);
     2500#endif
     2501                    *ppGbo = pGbo;
     2502                    GALOG(("gbo = %p %s\n", pGbo, pszTag));
     2503                    return STATUS_SUCCESS;
     2504                }
     2505            }
     2506        }
     2507        else
     2508            AssertFailedStmt(Status = STATUS_INVALID_PARAMETER);
     2509    }
     2510    else
     2511        AssertFailedStmt(Status = STATUS_INSUFFICIENT_RESOURCES);
     2512
     2513    SvgaGboUnreference(pSvga, &pGbo);
     2514    return Status;
     2515}
     2516
     2517
     2518NTSTATUS SvgaGboCreateForMdl(VBOXWDDM_EXT_VMSVGA *pSvga,
     2519                             PVMSVGAGBO *ppGbo,
     2520                             SIZE_T NumberOfPages,
     2521                             PMDL pMdl,
     2522                             ULONG MdlOffset)
     2523{
     2524    NTSTATUS Status;
     2525
     2526    AssertReturn(NumberOfPages > 0 && NumberOfPages < pSvga->u32MaxMobSize / PAGE_SIZE, STATUS_INVALID_PARAMETER);
     2527
     2528    PVMSVGAGBO pGbo = (PVMSVGAGBO)GaMemAllocZero(sizeof(VMSVGAGBO));
     2529    AssertReturn(pGbo, STATUS_INSUFFICIENT_RESOURCES);
     2530
     2531    pGbo->cRefs = 1;
     2532    pGbo->flags.fMdl = 1;
     2533    pGbo->pMdl = pMdl;
     2534
     2535    Status = svgaGboInit(pGbo, (uint32_t)NumberOfPages);
     2536    if (NT_SUCCESS(Status))
     2537    {
     2538        Status = svgaGboFillPageTableForMDL(pGbo, pGbo->pMdl, MdlOffset);
     2539        if (NT_SUCCESS(Status))
     2540        {
     2541#ifdef DEBUG
     2542            ASMAtomicIncU32(&pSvga->cAllocatedGbos);
     2543#endif
     2544            *ppGbo = pGbo;
     2545            GALOG(("gbo = %p\n", pGbo));
     2546            return STATUS_SUCCESS;
     2547        }
     2548    }
     2549
     2550    SvgaGboUnreference(pSvga, &pGbo);
     2551    return Status;
     2552}
     2553
     2554
    24572555/*
    24582556 *
     
    24602558 *
    24612559 */
    2462 
    2463 static NTSTATUS svgaMobAlloc(VBOXWDDM_EXT_VMSVGA *pSvga,
    2464                              PVMSVGAMOB *ppMob)
    2465 {
    2466     GALOG(("[%p]\n", pSvga));
    2467 
    2468     NTSTATUS Status;
    2469     AssertCompile(NIL_RTR0MEMOBJ == 0);
    2470 
    2471     *ppMob = (PVMSVGAMOB)GaMemAllocZero(sizeof(VMSVGAMOB));
    2472     AssertReturn(*ppMob, STATUS_INSUFFICIENT_RESOURCES);
    2473 
    2474     Status = SvgaMobIdAlloc(pSvga, &VMSVGAMOB_ID(*ppMob));
    2475     AssertReturnStmt(NT_SUCCESS(Status), GaMemFree(*ppMob), STATUS_INSUFFICIENT_RESOURCES);
     2560/* Memory OBject tracking structure: and id accisiated with a gbo. */
     2561typedef struct VMSVGAMOB
     2562{
     2563    AVLU32NODECORE              core;                       /* AVL entry. Key is mobid, allocated by the miniport. */
     2564    PVMSVGAGBO                  pGbo;                       /* The mob has been created for this GBO and holds a reference to it. */
     2565    uint32_t                    u64MobFence;                /* Mob id can be freed by the guest when the host reports this fence value. */
     2566    RTLISTNODE                  node;                       /* VBOXWDDM_EXT_VMSVGA::listMobDeferredDestruction */
     2567} VMSVGAMOB, *PVMSVGAMOB;
     2568
     2569#define VMSVGAMOB_ID(a_pMob) ((a_pMob)->core.Key)
     2570
     2571void SvgaMobFree(VBOXWDDM_EXT_VMSVGA *pSvga,
     2572                 SVGAMobId *pMobid)
     2573{
     2574    GALOG(("[%p] %u\n", pSvga, pMobid));
     2575
     2576    if (*pMobid != SVGA3D_INVALID_ID)
     2577    {
     2578        GALOG(("mobid = %u\n", *pMobid));
     2579
     2580        KIRQL OldIrql;
     2581        KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
     2582        PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Remove(&pSvga->MobTree, *pMobid);
     2583        KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2584
     2585        Assert(pMob);
     2586        if (pMob)
     2587        {
     2588            SvgaGboUnreference(pSvga, &pMob->pGbo);
     2589#ifdef DEBUG
     2590            ASMAtomicDecU32(&pSvga->cAllocatedMobs);
     2591            GALOG(("cAllocatedMobs = %u\n", pSvga->cAllocatedMobs));
     2592#endif
     2593
     2594            NTSTATUS Status = SvgaMobIdFree(pSvga, *pMobid);
     2595            Assert(NT_SUCCESS(Status)); RT_NOREF(Status);
     2596            GaMemFree(pMob);
     2597        }
     2598
     2599        *pMobid = SVGA3D_INVALID_ID;
     2600    }
     2601}
     2602
     2603
     2604NTSTATUS SvgaMobAlloc(VBOXWDDM_EXT_VMSVGA *pSvga,
     2605                      SVGAMobId *pMobid,
     2606                      PVMSVGAGBO pGbo)
     2607{
     2608    PVMSVGAMOB pMob = (PVMSVGAMOB)GaMemAllocZero(sizeof(VMSVGAMOB));
     2609    AssertReturn(pMob, STATUS_INSUFFICIENT_RESOURCES);
     2610
     2611    NTSTATUS Status = SvgaMobIdAlloc(pSvga, &VMSVGAMOB_ID(pMob));
     2612    AssertReturnStmt(NT_SUCCESS(Status), GaMemFree(pMob), STATUS_INSUFFICIENT_RESOURCES);
     2613    GALOG(("mobid = %u\n", VMSVGAMOB_ID(pMob)));
     2614
     2615    pMob->pGbo = pGbo;
     2616    SvgaGboReference(pGbo);
    24762617
    24772618    KIRQL OldIrql;
    24782619    KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
    2479     bool fInserted = RTAvlU32Insert(&pSvga->MobTree, &(*ppMob)->core);
     2620    bool fInserted = RTAvlU32Insert(&pSvga->MobTree, &pMob->core);
    24802621    KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
    24812622    Assert(fInserted); RT_NOREF(fInserted);
    24822623
    2483     GALOG(("mobid = %u\n", VMSVGAMOB_ID(*ppMob)));
    2484     return STATUS_SUCCESS;
    2485 }
    2486 
    2487 void SvgaMobFree(VBOXWDDM_EXT_VMSVGA *pSvga,
    2488                  PVMSVGAMOB pMob)
    2489 {
    2490     GALOG(("[%p] %p\n", pSvga, pMob));
    2491 
    2492     if (pMob)
    2493     {
    2494         GALOG(("mobid = %u\n", VMSVGAMOB_ID(pMob)));
    2495 
    2496         KIRQL OldIrql;
    2497         KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
    2498         RTAvlU32Remove(&pSvga->MobTree, pMob->core.Key);
    2499         KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
    2500 
    2501 #ifdef DEBUG
    2502         ASMAtomicSubU32(&pSvga->cAllocatedMobPages, pMob->gbo.cbGbo / PAGE_SIZE);
    2503         ASMAtomicDecU32(&pSvga->cAllocatedMobs);
    2504 #endif
    2505 
    2506         SvgaGboFree(&pMob->gbo);
    2507 
    2508         if (pMob->hMemObj != NIL_RTR0MEMOBJ)
    2509         {
    2510             int rc = RTR0MemObjFree(pMob->hMemObj, true);
    2511             AssertRC(rc);
    2512             pMob->hMemObj = NIL_RTR0MEMOBJ;
    2513         }
    2514 
    2515         NTSTATUS Status = SvgaMobIdFree(pSvga, VMSVGAMOB_ID(pMob));
    2516         Assert(NT_SUCCESS(Status)); RT_NOREF(Status);
    2517         GaMemFree(pMob);
    2518     }
    2519 }
    2520 
    2521 PVMSVGAMOB SvgaMobQuery(VBOXWDDM_EXT_VMSVGA *pSvga,
    2522                         uint32_t mobid)
    2523 {
    2524     KIRQL OldIrql;
    2525     KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
    2526     PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, mobid);
    2527     KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
    2528 
    2529     GALOG(("[%p] mobid = %u -> %p\n", pSvga, mobid, pMob));
    2530     return pMob;
    2531 }
    2532 
    2533 NTSTATUS SvgaMobCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
    2534                        PVMSVGAMOB *ppMob,
    2535                        uint32_t cMobPages,
    2536                        HANDLE hAllocation)
    2537 {
    2538     PVMSVGAMOB pMob;
    2539     NTSTATUS Status = svgaMobAlloc(pSvga, &pMob);
    2540     AssertReturn(NT_SUCCESS(Status), Status);
    2541 
    2542     Status = SvgaGboInit(&pMob->gbo, cMobPages);
    2543     AssertReturnStmt(NT_SUCCESS(Status), SvgaMobFree(pSvga, pMob), Status);
    2544 
    2545     pMob->hAllocation = hAllocation;
    2546     *ppMob = pMob;
    2547 
    25482624#ifdef DEBUG
    25492625    ASMAtomicIncU32(&pSvga->cAllocatedMobs);
    2550     ASMAtomicAddU32(&pSvga->cAllocatedMobPages, cMobPages);
    25512626#endif
    25522627
     2628    *pMobid = VMSVGAMOB_ID(pMob);
    25532629    return STATUS_SUCCESS;
    2554 }
    2555 
    2556 NTSTATUS SvgaMobSetMemObj(PVMSVGAMOB pMob,
    2557                           RTR0MEMOBJ hMemObj)
    2558 {
    2559     NTSTATUS Status = SvgaGboFillPageTableForMemObj(&pMob->gbo, hMemObj);
    2560     if (NT_SUCCESS(Status))
    2561         pMob->hMemObj = hMemObj;
    2562     return Status;
    25632630}
    25642631
     
    25842651    AssertReturn(id < SVGA_COTABLE_MAX_IDS, STATUS_INVALID_PARAMETER);
    25852652
    2586     /* Allocate a new larger mob and inform the host. */
     2653    /* Allocate a new larger gbo and inform the host. */
    25872654    static uint32_t const s_acbEntry[] =
    25882655    {
     
    26162683        cbCOT *= 2;
    26172684
    2618     /* Allocate pages for the new COTable. */
    2619     RTR0MEMOBJ hMemObjCOT;
    2620     int rc = RTR0MemObjAllocPageTag(&hMemObjCOT, cbCOT, false /* executable R0 mapping */, "VMSVGACOT");
    2621     AssertRCReturn(rc, STATUS_INSUFFICIENT_RESOURCES);
    2622 
    2623     /* Allocate a new mob. */
    2624     PVMSVGAMOB pMob;
    2625     NTSTATUS Status = SvgaMobCreate(pSvga, &pMob, cbCOT >> PAGE_SHIFT, 0);
     2685    /* Allocate memory for the new COTable. */
     2686    PVMSVGAGBO pGbo;
     2687    NTSTATUS Status = SvgaGboCreate(pSvga, &pGbo, cbCOT, "VMSVGACOT");
     2688    AssertReturn(NT_SUCCESS(Status), Status);
     2689
     2690    /* Allocate a new mobid. */
     2691    SVGAMobId mobid;
     2692    Status = SvgaMobAlloc(pSvga, &mobid, pGbo);
    26262693    AssertReturnStmt(NT_SUCCESS(Status),
    2627                      RTR0MemObjFree(hMemObjCOT, true),
     2694                     SvgaGboUnreference(pSvga, &pGbo),
    26282695                     Status);
    26292696
    2630     Status = SvgaMobSetMemObj(pMob, hMemObjCOT);
    2631     AssertReturnStmt(NT_SUCCESS(Status),
    2632                      SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
    2633                      Status);
     2697    /* Now the new allocated mob holds a reference to the gbo. */
     2698    SvgaGboUnreference(pSvga, &pGbo);
    26342699
    26352700    /* Emit commands. */
    2636     void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DEFINE_GB_MOB64, sizeof(SVGA3dCmdDefineGBMob64), SVGA3D_INVALID_ID);
     2701    uint32_t cbCmd = 0;
     2702    SvgaMobDefine(pSvga, SVGA3D_INVALID_ID, NULL, 0, &cbCmd);
     2703    void *pvCmd = SvgaCmdBufReserve(pSvga, cbCmd, SVGA3D_INVALID_ID);
    26372704    if (pvCmd)
    26382705    {
    2639         SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    2640         pCmd->mobid       = VMSVGAMOB_ID(pMob);
    2641         pCmd->ptDepth     = pMob->gbo.enmMobFormat;
    2642         pCmd->base        = pMob->gbo.base;
    2643         pCmd->sizeInBytes = pMob->gbo.cbGbo;
    2644         SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
    2645     }
    2646     else
    2647         AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2706        SvgaMobDefine(pSvga, mobid, pvCmd, cbCmd, &cbCmd);
     2707        SvgaCmdBufCommit(pSvga, cbCmd);
     2708    }
     2709    else
     2710        AssertFailedReturnStmt(SvgaMobFree(pSvga, &mobid),
    26482711                               STATUS_INSUFFICIENT_RESOURCES);
    26492712
     
    26562719            SVGA3dCmdDXSetCOTable *pCmd = (SVGA3dCmdDXSetCOTable *)pvCmd;
    26572720            pCmd->cid              = pSvgaContext->u32Cid;
    2658             pCmd->mobid            = VMSVGAMOB_ID(pMob);
     2721            pCmd->mobid            = mobid;
    26592722            pCmd->type             = enmType;
    26602723            pCmd->validSizeInBytes = pCOT->cEntries * s_acbEntry[idxCOTable];
     
    26622725        }
    26632726        else
    2664             AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2727            AssertFailedReturnStmt(SvgaMobFree(pSvga, &mobid),
    26652728                                   STATUS_INSUFFICIENT_RESOURCES);
    26662729    }
     
    26732736            SVGA3dCmdDXGrowCOTable *pCmd = (SVGA3dCmdDXGrowCOTable *)pvCmd;
    26742737            pCmd->cid              = pSvgaContext->u32Cid;
    2675             pCmd->mobid            = VMSVGAMOB_ID(pMob);
     2738            pCmd->mobid            = mobid;
    26762739            pCmd->type             = enmType;
    26772740            pCmd->validSizeInBytes = pCOT->cEntries * s_acbEntry[idxCOTable];
     
    26792742        }
    26802743        else
    2681             AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2744            AssertFailedReturnStmt(SvgaMobFree(pSvga, &mobid),
    26822745                                   STATUS_INSUFFICIENT_RESOURCES);
    26832746
     2747        /* Delete old mob. */
    26842748        uint32_t cbCmdRequired = 0;
    2685         SvgaMobDestroy(pSvga, pCOT->pMob, NULL, 0, &cbCmdRequired);
     2749        SvgaMobDestroy(pSvga, 0, NULL, 0, &cbCmdRequired);
    26862750        pvCmd = SvgaCmdBufReserve(pSvga, cbCmdRequired, SVGA3D_INVALID_ID);
    26872751        if (pvCmd)
    26882752        {
    2689             SvgaMobDestroy(pSvga, pCOT->pMob, pvCmd, cbCmdRequired, &cbCmdRequired);
     2753            SvgaMobDestroy(pSvga, pCOT->mobid, pvCmd, cbCmdRequired, &cbCmdRequired);
    26902754            SvgaCmdBufCommit(pSvga, cbCmdRequired);
    26912755        }
    26922756
    2693         pCOT->pMob = NULL;
     2757        pCOT->mobid = SVGA3D_INVALID_ID;
    26942758    }
    26952759
    26962760    SvgaCmdBufFlush(pSvga);
    26972761
    2698     pCOT->pMob = pMob;
     2762    pCOT->mobid = mobid;
    26992763    pCOT->cEntries = cbCOT / s_acbEntry[idxCOTable];
    27002764
     
    27022766}
    27032767
     2768
     2769void *SvgaMobAddress(VBOXWDDM_EXT_VMSVGA *pSvga,
     2770                     SVGAMobId mobid)
     2771{
     2772    KIRQL OldIrql;
     2773    KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
     2774    PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, mobid);
     2775    KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2776    AssertReturn(pMob && pMob->pGbo, NULL);
     2777
     2778    return RTR0MemObjAddress(pMob->pGbo->hMemObj);
     2779}
     2780
     2781
     2782NTSTATUS SvgaMobDefine(VBOXWDDM_EXT_VMSVGA *pSvga,
     2783                       SVGAMobId mobid,
     2784                       void *pvCmd,
     2785                       uint32_t cbReserved,
     2786                       uint32_t *pcbCmd)
     2787{
     2788    uint32_t cbRequired = sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdDefineGBMob64);
     2789
     2790    *pcbCmd = cbRequired;
     2791    if (cbReserved < cbRequired)
     2792        return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     2793
     2794    /* Find the mob. */
     2795    KIRQL OldIrql;
     2796    KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
     2797    PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, mobid);
     2798    KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2799    AssertReturn(pMob && pMob->pGbo, STATUS_INVALID_PARAMETER);
     2800
     2801    /* Generate commands. */
     2802    uint8_t *pu8Cmd = (uint8_t *)pvCmd;
     2803    SVGA3dCmdHeader *pHdr;
     2804
     2805    pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     2806    pHdr->id   = SVGA_3D_CMD_DEFINE_GB_MOB64;
     2807    pHdr->size = sizeof(SVGA3dCmdDefineGBMob64);
     2808    pu8Cmd += sizeof(*pHdr);
     2809
     2810    {
     2811    SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pu8Cmd;
     2812    pCmd->mobid       = mobid;
     2813    pCmd->ptDepth     = pMob->pGbo->enmMobFormat;
     2814    pCmd->base        = pMob->pGbo->base;
     2815    pCmd->sizeInBytes = pMob->pGbo->cbGbo;
     2816    pu8Cmd += sizeof(*pCmd);
     2817    }
     2818
     2819    Assert((uintptr_t)pu8Cmd - (uintptr_t)pvCmd == cbRequired);
     2820
     2821    return STATUS_SUCCESS;
     2822}
    27042823
    27052824
     
    27202839 */
    27212840NTSTATUS SvgaMobDestroy(VBOXWDDM_EXT_VMSVGA *pSvga,
    2722                         PVMSVGAMOB pMob,
     2841                        SVGAMobId mobid,
    27232842                        void *pvCmd,
    27242843                        uint32_t cbReserved,
     
    27322851        return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
    27332852
     2853    /* Find the mob. */
     2854    KIRQL OldIrql;
     2855    KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
     2856    PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, mobid);
     2857    KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2858    AssertReturn(pMob, STATUS_INVALID_PARAMETER);
     2859
     2860    /* Mob will be actually deallocated after the host processes the fence. */
     2861    pMob->u64MobFence = ASMAtomicIncU64(&pSvga->u64MobFence);
     2862
     2863    /* Add the mob to the deferred destruction queue. */
     2864    SvgaHostObjectsLock(pSvga, &OldIrql);
     2865    RTListAppend(&pSvga->listMobDeferredDestruction, &pMob->node);
     2866    SvgaHostObjectsUnlock(pSvga, OldIrql);
     2867
     2868    /* Generate commands. */
    27342869    uint8_t *pu8Cmd = (uint8_t *)pvCmd;
    27352870    SVGA3dCmdHeader *pHdr;
     
    27422877    {
    27432878    SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pu8Cmd;
    2744     pCmd->mobid = VMSVGAMOB_ID(pMob);
     2879    pCmd->mobid = mobid;
    27452880    pu8Cmd += sizeof(*pCmd);
    27462881    }
    2747 
    2748     pMob->u64MobFence = ASMAtomicIncU64(&pSvga->u64MobFence);
    27492882
    27502883    pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     
    27562889    SVGA3dCmdDXMobFence64 *pCmd = (SVGA3dCmdDXMobFence64 *)pu8Cmd;
    27572890    pCmd->value = pMob->u64MobFence;
    2758     pCmd->mobId = VMSVGAMOB_ID(pSvga->pMiniportMob);
     2891    pCmd->mobId = pSvga->mobidMiniport;
    27592892    pCmd->mobOffset = RT_OFFSETOF(VMSVGAMINIPORTMOB, u64MobFence);
    27602893    pu8Cmd += sizeof(*pCmd);
    27612894    }
    27622895
    2763     /* Add the mob to the deferred destruction queue. */
    2764     KIRQL OldIrql;
    2765     SvgaHostObjectsLock(pSvga, &OldIrql);
    2766     RTListAppend(&pSvga->listMobDeferredDestruction, &pMob->node);
    2767     SvgaHostObjectsUnlock(pSvga, OldIrql);
    2768 
    27692896    Assert((uintptr_t)pu8Cmd - (uintptr_t)pvCmd == cbRequired);
    27702897
    27712898    return STATUS_SUCCESS;
    27722899}
     2900
     2901DECLINLINE(int) SvgaFenceCmp64(uint64_t u64FenceA, uint64_t u64FenceB)
     2902{
     2903     if (   u64FenceA < u64FenceB
     2904         || u64FenceA - u64FenceB > UINT64_MAX / 2)
     2905     {
     2906         return -1; /* FenceA is newer than FenceB. */
     2907     }
     2908     else if (u64FenceA == u64FenceB)
     2909     {
     2910         /* FenceA is equal to FenceB. */
     2911         return 0;
     2912     }
     2913
     2914     /* FenceA is older than FenceB. */
     2915     return 1;
     2916}
     2917
     2918void SvgaDeferredMobDestruction(PVBOXWDDM_EXT_VMSVGA pSvga)
     2919{
     2920    if (pSvga->pMiniportMobData)
     2921    {
     2922        uint64_t const u64MobFence = ASMAtomicReadU64(&pSvga->pMiniportMobData->u64MobFence);
     2923
     2924        /* Move mobs which were deleted by the host to the local list under the lock. */
     2925        RTLISTANCHOR listDestroyedMobs;
     2926        RTListInit(&listDestroyedMobs);
     2927
     2928        KIRQL OldIrql;
     2929        SvgaHostObjectsLock(pSvga, &OldIrql);
     2930
     2931        PVMSVGAMOB pIter, pNext;
     2932        RTListForEachSafe(&pSvga->listMobDeferredDestruction, pIter, pNext, VMSVGAMOB, node)
     2933        {
     2934            if (SvgaFenceCmp64(pIter->u64MobFence, u64MobFence) <= 0)
     2935            {
     2936                RTListNodeRemove(&pIter->node);
     2937                RTListAppend(&listDestroyedMobs, &pIter->node);
     2938            }
     2939        }
     2940
     2941        SvgaHostObjectsUnlock(pSvga, OldIrql);
     2942
     2943        RTListForEachSafe(&listDestroyedMobs, pIter, pNext, VMSVGAMOB, node)
     2944        {
     2945            /* Delete the data. SvgaMobFree deallocates pIter. */
     2946            RTListNodeRemove(&pIter->node);
     2947            SVGAMobId mobid = VMSVGAMOB_ID(pIter);
     2948            SvgaMobFree(pSvga, &mobid);
     2949        }
     2950    }
     2951}
     2952
     2953#ifdef DEBUG
     2954static DECLCALLBACK(int) mobDumpCb(PAVLU32NODECORE pNode, void *pvUser)
     2955{
     2956    PVMSVGAMOB pMob = (PVMSVGAMOB)pNode;
     2957    uint32_t *pcMobs = (uint32_t *)pvUser;
     2958    *pcMobs += 1;
     2959
     2960    GALOG(("mobid = %u, refs = %d, mdl = %u, cb = %u\n",
     2961        VMSVGAMOB_ID(pMob),
     2962        pMob->pGbo ? pMob->pGbo->cRefs : -1,
     2963        pMob->pGbo ? pMob->pGbo->flags.fMdl : 2,
     2964        pMob->pGbo ? pMob->pGbo->cbGbo : 0));
     2965    return 0;
     2966}
     2967#endif /* DEBUG */
Note: See TracChangeset for help on using the changeset viewer.

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