Changeset 65271 in vbox
- Timestamp:
- Jan 12, 2017 7:54:10 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 112826
- Location:
- trunk/src/VBox/Devices/Graphics
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
r65267 r65271 1574 1574 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr); 1575 1575 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 1583 1576 /* Validate current GMR id. */ 1577 uint32_t idGMR = pThis->svga.u32CurrentGMRId; 1584 1578 AssertBreak(idGMR < VMSVGA_MAX_GMR_IDS); 1585 1579 … … 1588 1582 1589 1583 /* Just undefine the GMR? */ 1584 RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT; 1590 1585 if (GCPhys == 0) 1586 { 1587 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree); 1591 1588 break; 1592 1593 pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR)); 1594 AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY); 1589 } 1590 1595 1591 1596 1592 /* 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; 1597 1599 while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase)) 1598 1600 { 1599 1601 /* Read descriptor. */ 1602 SVGAGuestMemDescriptor desc; 1600 1603 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc)); 1601 1604 AssertRCBreak(rc); 1602 1605 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) 1609 1607 { 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) 1616 1613 { 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; 1620 1617 } 1621 1618 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; 1625 1621 1626 1622 /* Continue with the next descriptor. */ 1627 1623 GCPhys += sizeof(desc); 1628 1624 } 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 } 1640 1651 break; 1641 1652 } … … 3091 3102 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Modify); 3092 3103 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 3093 3110 pGMR->cMaxPages = pCmd->numPages; 3094 3111 /* The rest is done by the REMAP_GMR2 command. */ … … 3104 3121 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2); 3105 3122 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 3110 3123 Log(("vmsvgaFIFOLoop: SVGA_CMD_REMAP_GMR2 id=%x flags=%x offset=%x npages=%x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages)); 3111 3124 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS); 3112 3125 3113 3126 /* Calculate the size of what comes after next and fetch it. */ 3114 cbCmd = sizeof(SVGAFifoCmdRemapGMR2);3127 uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2); 3115 3128 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR) 3116 3129 cbCmd += sizeof(SVGAGuestPtr); 3117 3130 else 3118 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)3119 3131 { 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 } 3127 3143 } 3128 3144 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd); 3129 3145 3130 /* Validate current GMR id . */3146 /* Validate current GMR id and size. */ 3131 3147 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS); 3132 3148 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))); 3134 3151 AssertBreak(!pCmd->offsetPages || pGMR->paDesc); /** @todo */ 3135 3152 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; 3137 3167 if (pGMR->paDesc) 3138 3168 { 3169 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2Modify); 3170 3171 paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t)); 3172 AssertBreak(paNewPage64); 3173 3139 3174 uint32_t idxPage = 0; 3140 paNewPage64 = (uint64_t *)RTMemAllocZ(pGMR->cMaxPages * sizeof(uint64_t));3141 AssertBreak(paNewPage64);3142 3143 3175 for (uint32_t i = 0; i < pGMR->numDescriptors; i++) 3144 {3145 3176 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)); 3151 3179 } 3152 3180 … … 3156 3184 3157 3185 /* 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)); 3160 3189 3161 3190 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR) … … 3163 3192 /** @todo */ 3164 3193 AssertFailed(); 3194 pGMR->numDescriptors = 0; 3165 3195 } 3166 3196 else 3167 3197 { 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); 3173 3201 3174 3202 if (paNewPage64) 3175 3203 { 3176 3204 /* 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 else3182 paNewPage64[i] = p Page32[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 3184 3212 /* Use the updated page array instead of the command data. */ 3185 3213 fGCPhys64 = true; 3186 p Page64= paNewPage64;3187 pCmd->numPages = pGMR->cbTotal >> PAGE_SHIFT;3214 paPages64 = paNewPage64; 3215 pCmd->numPages = cNewTotalPages; 3188 3216 } 3189 3217 3218 /* The first page. */ 3219 /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be 3220 * applied to paNewPage64. */ 3221 RTGCPHYS GCPhys; 3190 3222 if (fGCPhys64) 3191 GCPhys = (p Page64[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. */ 3192 3224 else 3193 GCPhys = (RTGCPHYS)p Page32[0] << PAGE_SHIFT;3194 3195 p GMR->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; 3199 3231 for (uint32_t i = 1; i < pCmd->numPages; i++) 3200 3232 { 3201 3233 if (pCmd->flags & SVGA_REMAP_GMR2_PPN64) 3202 GCPhys = (p Page64[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. */ 3203 3235 else 3204 GCPhys = (RTGCPHYS)p Page32[i] <<PAGE_SHIFT;3236 GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT; 3205 3237 3206 3238 /* Continuous physical memory? */ 3207 if (GCPhys == p GMR->paDesc[iDescriptor].GCPhys + pGMR->paDesc[iDescriptor].numPages *PAGE_SIZE)3239 if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE) 3208 3240 { 3209 Assert(p GMR->paDesc[iDescriptor].numPages);3210 p GMR->paDesc[iDescriptor].numPages++;3241 Assert(paDescs[iDescriptor].numPages); 3242 paDescs[iDescriptor].numPages++; 3211 3243 LogFlow(("Page %x GCPhys=%RGp successor\n", i, GCPhys)); 3212 3244 } … … 3214 3246 { 3215 3247 iDescriptor++; 3216 p GMR->paDesc[iDescriptor].GCPhys = GCPhys;3217 p GMR->paDesc[iDescriptor].numPages = 1;3218 LogFlow(("Page %x GCPhys=%RGp\n", i, p GMR->paDesc[iDescriptor].GCPhys));3248 paDescs[iDescriptor].GCPhys = GCPhys; 3249 paDescs[iDescriptor].numPages = 1; 3250 LogFlow(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys)); 3219 3251 } 3220 3221 pGMR->cbTotal += PAGE_SIZE;3222 3252 } 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)); 3224 3256 pGMR->numDescriptors = iDescriptor + 1; 3225 3257 } … … 3835 3867 3836 3868 /* 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 { 3840 3873 # ifdef DEBUG_GMR_ACCESS 3841 3874 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaDeregisterGMR, 2, pThis->pDevInsR3, idGMR); … … 3849 3882 pGMR->cMaxPages = 0; 3850 3883 } 3851 Assert(!pSVGAState->aGMR[idGMR].cbTotal); 3884 Assert(!pGMR->cMaxPages); 3885 Assert(!pGMR->cbTotal); 3852 3886 } 3853 3887 … … 4308 4342 if (pGMR->numDescriptors) 4309 4343 { 4310 /* Allocate the maximum amount possible (everything non-continuous) */4311 4344 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)); 4313 4346 AssertReturn(pGMR->paDesc, VERR_NO_MEMORY); 4314 4347 -
trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.h
r64387 r65271 29 29 /** Maximum nr of GMR ids. */ 30 30 #define VMSVGA_MAX_GMR_IDS 0x100 31 /** Maximum number of GMR descriptors. */ 32 #define VMSVGA_MAX_GMR_DESC_LOOP_COUNT VMSVGA_MAX_GMR_PAGES 31 33 32 34 #define VMSVGA_VAL_UNINITIALIZED (unsigned)-1
Note:
See TracChangeset
for help on using the changeset viewer.