VirtualBox

Changeset 65271 in vbox


Ignore:
Timestamp:
Jan 12, 2017 7:54:10 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
112826
Message:

VMSVGA: GMR work.

Location:
trunk/src/VBox/Devices/Graphics
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp

    r65267 r65271  
    15741574        STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
    15751575
    1576         SVGAGuestMemDescriptor desc;
    1577         RTGCPHYS               GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
    1578         RTGCPHYS               GCPhysBase = GCPhys;
    1579         uint32_t               idGMR = pThis->svga.u32CurrentGMRId;
    1580         uint32_t               cDescriptorsAllocated = 16;
    1581         uint32_t               iDescriptor = 0;
    1582 
    15831576        /* Validate current GMR id. */
     1577        uint32_t idGMR = pThis->svga.u32CurrentGMRId;
    15841578        AssertBreak(idGMR < VMSVGA_MAX_GMR_IDS);
    15851579
     
    15881582
    15891583        /* Just undefine the GMR? */
     1584        RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
    15901585        if (GCPhys == 0)
     1586        {
     1587            STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
    15911588            break;
    1592 
    1593         pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
    1594         AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
     1589        }
     1590
    15951591
    15961592        /* Never cross a page boundary automatically. */
     1593        const uint32_t          cMaxPages   = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
     1594        uint32_t                cPagesTotal = 0;
     1595        uint32_t                iDesc       = 0;
     1596        PVMSVGAGMRDESCRIPTOR    paDescs     = NULL;
     1597        uint32_t                cLoops      = 0;
     1598        RTGCPHYS                GCPhysBase  = GCPhys;
    15971599        while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
    15981600        {
    15991601            /* Read descriptor. */
     1602            SVGAGuestMemDescriptor desc;
    16001603            rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc));
    16011604            AssertRCBreak(rc);
    16021605
    1603             if (    desc.ppn == 0
    1604                 &&  desc.numPages == 0)
    1605                 break;  /* terminator */
    1606 
    1607             if (    desc.ppn != 0
    1608                 &&  desc.numPages == 0)
     1606            if (desc.numPages != 0)
    16091607            {
    1610                 /* Pointer to the next physical page of descriptors. */
    1611                 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    1612             }
    1613             else
    1614             {
    1615                 if (iDescriptor == cDescriptorsAllocated)
     1608                AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
     1609                cPagesTotal += desc.numPages;
     1610                AssertBreakStmt(cPagesTotal   <= cMaxPages, rc = VERR_OUT_OF_RANGE);
     1611
     1612                if ((iDesc & 15) == 0)
    16161613                {
    1617                     cDescriptorsAllocated += 16;
    1618                     pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemRealloc(pSVGAState->aGMR[idGMR].paDesc, cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
    1619                     AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
     1614                    void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
     1615                    AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
     1616                    paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
    16201617                }
    16211618
    1622                 pSVGAState->aGMR[idGMR].paDesc[iDescriptor].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    1623                 pSVGAState->aGMR[idGMR].paDesc[iDescriptor++].numPages = desc.numPages;
    1624                 pSVGAState->aGMR[idGMR].cbTotal += desc.numPages * PAGE_SIZE;
     1619                paDescs[iDesc].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
     1620                paDescs[iDesc++].numPages = desc.numPages;
    16251621
    16261622                /* Continue with the next descriptor. */
    16271623                GCPhys += sizeof(desc);
    16281624            }
    1629         }
    1630         pSVGAState->aGMR[idGMR].numDescriptors = iDescriptor;
    1631         Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x\n", idGMR, iDescriptor, pSVGAState->aGMR[idGMR].cbTotal));
    1632 
    1633         if (!pSVGAState->aGMR[idGMR].numDescriptors)
    1634         {
    1635             AssertFailed();
    1636             RTMemFree(pSVGAState->aGMR[idGMR].paDesc);
    1637             pSVGAState->aGMR[idGMR].paDesc = NULL;
    1638         }
    1639         AssertRC(rc);
     1625            else if (desc.ppn == 0)
     1626                break;  /* terminator */
     1627            else /* Pointer to the next physical page of descriptors. */
     1628                GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
     1629
     1630            cLoops++;
     1631            AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
     1632        }
     1633
     1634        AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
     1635        if (RT_SUCCESS(rc))
     1636        {
     1637            /* Commit the GMR. */
     1638            pSVGAState->aGMR[idGMR].paDesc         = paDescs;
     1639            pSVGAState->aGMR[idGMR].numDescriptors = iDesc;
     1640            pSVGAState->aGMR[idGMR].cMaxPages      = cPagesTotal;
     1641            pSVGAState->aGMR[idGMR].cbTotal        = cPagesTotal * PAGE_SIZE;
     1642            Assert((pSVGAState->aGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
     1643            Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
     1644                 idGMR, iDesc, pSVGAState->aGMR[idGMR].cbTotal, cPagesTotal));
     1645        }
     1646        else
     1647        {
     1648            RTMemFree(paDescs);
     1649            STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
     1650        }
    16401651        break;
    16411652    }
     
    30913102                        STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Modify);
    30923103
     3104                    /* Not sure if we should always free the descriptor, but for simplicity
     3105                       we do so if the new size is smaller than the current. */
     3106                    /** @todo always free the descriptor in SVGA_CMD_DEFINE_GMR2? */
     3107                    if (pGMR->cbTotal / X86_PAGE_SIZE > pGMR->cMaxPages)
     3108                        vmsvgaGMRFree(pThis, pCmd->gmrId);
     3109
    30933110                    pGMR->cMaxPages = pCmd->numPages;
    30943111                    /* The rest is done by the REMAP_GMR2 command. */
     
    31043121                STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2);
    31053122
    3106                 uint32_t cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
    3107                 uint32_t cbCmd;
    3108                 uint64_t *paNewPage64 = NULL;
    3109 
    31103123                Log(("vmsvgaFIFOLoop: SVGA_CMD_REMAP_GMR2 id=%x flags=%x offset=%x npages=%x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
    31113124                AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
    31123125
    31133126                /* Calculate the size of what comes after next and fetch it. */
    3114                 cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
     3127                uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
    31153128                if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    31163129                    cbCmd += sizeof(SVGAGuestPtr);
    31173130                else
    3118                 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
    31193131                {
    3120                     cbCmd         += cbPageDesc;
    3121                     pCmd->numPages = 1;
    3122                 }
    3123                 else
    3124                 {
    3125                     AssertBreak(pCmd->numPages <= VMSVGA_FIFO_SIZE);
    3126                     cbCmd += cbPageDesc * pCmd->numPages;
     3132                    uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
     3133                    if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
     3134                    {
     3135                        cbCmd         += cbPageDesc;
     3136                        pCmd->numPages = 1;
     3137                    }
     3138                    else
     3139                    {
     3140                        AssertBreak(pCmd->numPages <= VMSVGA_FIFO_SIZE / cbPageDesc);
     3141                        cbCmd += cbPageDesc * pCmd->numPages;
     3142                    }
    31273143                }
    31283144                VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
    31293145
    3130                 /* Validate current GMR id. */
     3146                /* Validate current GMR id and size. */
    31313147                AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
    31323148                PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
    3133                 AssertBreak(pCmd->offsetPages + pCmd->numPages <= pGMR->cMaxPages);
     3149                AssertBreak(   (uint64_t)pCmd->offsetPages + pCmd->numPages
     3150                            <= RT_MIN(pGMR->cMaxPages, RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE)));
    31343151                AssertBreak(!pCmd->offsetPages || pGMR->paDesc); /** @todo */
    31353152
    3136                 /* Save the old page descriptors as an array of page addresses (>> PAGE_SHIFT) */
     3153                if (pCmd->numPages == 0)
     3154                    break;
     3155
     3156                /* Calc new total page count so we can use it instead of cMaxPages for allocations below. */
     3157                uint32_t const cNewTotalPages = RT_MAX(pGMR->cbTotal >> X86_PAGE_SHIFT, pCmd->offsetPages + pCmd->numPages);
     3158
     3159                /*
     3160                 * We flatten the existing descriptors into a page array, overwrite the
     3161                 * pages specified in this command and then recompress the descriptor.
     3162                 */
     3163                /** @todo Optimize the GMR remap algorithm! */
     3164
     3165                /* Save the old page descriptors as an array of page frame numbers (address >> X86_PAGE_SHIFT) */
     3166                uint64_t *paNewPage64 = NULL;
    31373167                if (pGMR->paDesc)
    31383168                {
     3169                    STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2Modify);
     3170
     3171                    paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t));
     3172                    AssertBreak(paNewPage64);
     3173
    31393174                    uint32_t idxPage = 0;
    3140                     paNewPage64 = (uint64_t *)RTMemAllocZ(pGMR->cMaxPages * sizeof(uint64_t));
    3141                     AssertBreak(paNewPage64);
    3142 
    31433175                    for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    3144                     {
    31453176                        for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++)
    3146                         {
    3147                             paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * PAGE_SIZE) >> PAGE_SHIFT;
    3148                         }
    3149                     }
    3150                     AssertBreak(idxPage == pGMR->cbTotal >> PAGE_SHIFT);
     3177                            paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * X86_PAGE_SIZE) >> X86_PAGE_SHIFT;
     3178                    AssertBreakStmt(idxPage == pGMR->cbTotal >> X86_PAGE_SHIFT, RTMemFree(paNewPage64));
    31513179                }
    31523180
     
    31563184
    31573185                /* Allocate the maximum amount possible (everything non-continuous) */
    3158                 pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->cMaxPages * sizeof(VMSVGAGMRDESCRIPTOR));
    3159                 AssertBreak(pGMR->paDesc);
     3186                PVMSVGAGMRDESCRIPTOR paDescs;
     3187                pGMR->paDesc = paDescs = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cNewTotalPages * sizeof(VMSVGAGMRDESCRIPTOR));
     3188                AssertBreakStmt(paDescs, RTMemFree(paNewPage64));
    31603189
    31613190                if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
     
    31633192                    /** @todo */
    31643193                    AssertFailed();
     3194                    pGMR->numDescriptors = 0;
    31653195                }
    31663196                else
    31673197                {
    3168                     uint32_t            *pPage32 = (uint32_t *)(pCmd + 1);
    3169                     uint64_t            *pPage64 = (uint64_t *)(pCmd + 1);
    3170                     uint32_t             iDescriptor = 0;
    3171                     RTGCPHYS             GCPhys;
    3172                     bool                 fGCPhys64 = !!(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
     3198                    uint32_t  *paPages32 = (uint32_t *)(pCmd + 1);
     3199                    uint64_t  *paPages64 = (uint64_t *)(pCmd + 1);
     3200                    bool       fGCPhys64 = RT_BOOL(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
    31733201
    31743202                    if (paNewPage64)
    31753203                    {
    31763204                        /* Overwrite the old page array with the new page values. */
    3177                         for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
    3178                         {
    3179                             if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
    3180                                 paNewPage64[i] = pPage64[i - pCmd->offsetPages];
    3181                             else
    3182                                 paNewPage64[i] = pPage32[i - pCmd->offsetPages];
    3183                         }
     3205                        if (fGCPhys64)
     3206                            for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
     3207                                paNewPage64[i] = paPages64[i - pCmd->offsetPages];
     3208                        else
     3209                            for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
     3210                                paNewPage64[i] = paPages32[i - pCmd->offsetPages];
     3211
    31843212                        /* Use the updated page array instead of the command data. */
    31853213                        fGCPhys64      = true;
    3186                         pPage64        = paNewPage64;
    3187                         pCmd->numPages = pGMR->cbTotal >> PAGE_SHIFT;
     3214                        paPages64      = paNewPage64;
     3215                        pCmd->numPages = cNewTotalPages;
    31883216                    }
    31893217
     3218                    /* The first page. */
     3219                    /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be
     3220                     *        applied to paNewPage64. */
     3221                    RTGCPHYS GCPhys;
    31903222                    if (fGCPhys64)
    3191                         GCPhys = (pPage64[0] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL;    /* seeing rubbish in the top bits with certain linux guests*/
     3223                        GCPhys = (paPages64[0] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
    31923224                    else
    3193                         GCPhys = (RTGCPHYS)pPage32[0] << PAGE_SHIFT;
    3194 
    3195                     pGMR->paDesc[0].GCPhys    = GCPhys;
    3196                     pGMR->paDesc[0].numPages  = 1;
    3197                     pGMR->cbTotal             = PAGE_SIZE;
    3198 
     3225                        GCPhys = (RTGCPHYS)paPages32[0] << PAGE_SHIFT;
     3226                    paDescs[0].GCPhys    = GCPhys;
     3227                    paDescs[0].numPages  = 1;
     3228
     3229                    /* Subsequent pages. */
     3230                    uint32_t iDescriptor = 0;
    31993231                    for (uint32_t i = 1; i < pCmd->numPages; i++)
    32003232                    {
    32013233                        if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
    3202                             GCPhys = (pPage64[i] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL;    /* seeing rubbish in the top bits with certain linux guests*/
     3234                            GCPhys = (paPages64[i] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
    32033235                        else
    3204                             GCPhys = (RTGCPHYS)pPage32[i] << PAGE_SHIFT;
     3236                            GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT;
    32053237
    32063238                        /* Continuous physical memory? */
    3207                         if (GCPhys == pGMR->paDesc[iDescriptor].GCPhys + pGMR->paDesc[iDescriptor].numPages * PAGE_SIZE)
     3239                        if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE)
    32083240                        {
    3209                             Assert(pGMR->paDesc[iDescriptor].numPages);
    3210                             pGMR->paDesc[iDescriptor].numPages++;
     3241                            Assert(paDescs[iDescriptor].numPages);
     3242                            paDescs[iDescriptor].numPages++;
    32113243                            LogFlow(("Page %x GCPhys=%RGp successor\n", i, GCPhys));
    32123244                        }
     
    32143246                        {
    32153247                            iDescriptor++;
    3216                             pGMR->paDesc[iDescriptor].GCPhys   = GCPhys;
    3217                             pGMR->paDesc[iDescriptor].numPages = 1;
    3218                             LogFlow(("Page %x GCPhys=%RGp\n", i, pGMR->paDesc[iDescriptor].GCPhys));
     3248                            paDescs[iDescriptor].GCPhys   = GCPhys;
     3249                            paDescs[iDescriptor].numPages = 1;
     3250                            LogFlow(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys));
    32193251                        }
    3220 
    3221                         pGMR->cbTotal += PAGE_SIZE;
    32223252                    }
    3223                     LogFlow(("Nr of descriptors %x\n", iDescriptor + 1));
     3253
     3254                    pGMR->cbTotal = cNewTotalPages << X86_PAGE_SHIFT;
     3255                    LogFlow(("Nr of descriptors %x; cbTotal=%#x\n", iDescriptor + 1, cNewTotalPages));
    32243256                    pGMR->numDescriptors = iDescriptor + 1;
    32253257                }
     
    38353867
    38363868    /* Free the old descriptor if present. */
    3837     if (pSVGAState->aGMR[idGMR].numDescriptors)
    3838     {
    3839         PGMR pGMR = &pSVGAState->aGMR[idGMR];
     3869    PGMR pGMR = &pSVGAState->aGMR[idGMR];
     3870    if (   pGMR->numDescriptors
     3871        || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */)
     3872    {
    38403873# ifdef DEBUG_GMR_ACCESS
    38413874        VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaDeregisterGMR, 2, pThis->pDevInsR3, idGMR);
     
    38493882        pGMR->cMaxPages      = 0;
    38503883    }
    3851     Assert(!pSVGAState->aGMR[idGMR].cbTotal);
     3884    Assert(!pGMR->cMaxPages);
     3885    Assert(!pGMR->cbTotal);
    38523886}
    38533887
     
    43084342        if (pGMR->numDescriptors)
    43094343        {
    4310             /* Allocate the maximum amount possible (everything non-continuous) */
    43114344            Assert(pGMR->cMaxPages || pGMR->cbTotal);
    4312             pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ((pGMR->cMaxPages) ? pGMR->cMaxPages : (pGMR->cbTotal >> PAGE_SHIFT) * sizeof(VMSVGAGMRDESCRIPTOR));
     4345            pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
    43134346            AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
    43144347
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h

    r64387 r65271  
    2929/** Maximum nr of GMR ids. */
    3030#define VMSVGA_MAX_GMR_IDS              0x100
     31/** Maximum number of GMR descriptors.  */
     32#define VMSVGA_MAX_GMR_DESC_LOOP_COUNT  VMSVGA_MAX_GMR_PAGES
    3133
    3234#define VMSVGA_VAL_UNINITIALIZED        (unsigned)-1
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