VirtualBox

Ignore:
Timestamp:
Jan 15, 2018 10:46:29 PM (7 years ago)
Author:
vboxsync
Message:

DevVGA: cleanup in progress

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp

    r69884 r70596  
    136136struct VBVAEXHOSTCTL;
    137137
    138 typedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete);
     138typedef DECLCALLBACK(void) FNVBVAEXHOSTCTL_COMPLETE(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete);
     139typedef FNVBVAEXHOSTCTL_COMPLETE *PFNVBVAEXHOSTCTL_COMPLETE;
    139140
    140141typedef struct VBVAEXHOSTCTL
     
    205206*********************************************************************************************************************************/
    206207#ifdef VBOX_WITH_CRHGSMI
    207 static DECLCALLBACK(int) vdmaVBVANotifyDisable(PVGASTATE pVGAState);
    208 static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd);
     208static int vdmaVBVANotifyDisable(PVGASTATE pVGAState);
    209209
    210210static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd);
     
    383383}
    384384
     385/**
     386 * Worker for vboxVBVAExHPDataGet.
     387 * @thread VDMA
     388 * @todo r=bird: revalidate this code.
     389 */
    385390static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
    386391{
     
    393398    uint32_t indexRecordFree = pVBVA->indexRecordFree;
    394399
    395     Log(("first = %d, free = %d\n",
    396                    indexRecordFirst, indexRecordFree));
     400    Log(("first = %d, free = %d\n", indexRecordFirst, indexRecordFree));
    397401
    398402    if (indexRecordFirst == indexRecordFree)
     
    458462
    459463
     464/**
     465 * Worker for VBoxVBVAExHPDataGet.
     466 * @thread VDMA
     467 */
    460468static VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
    461469{
     
    479487                continue;
    480488            }
    481             else
    482             {
    483                 *ppCmd = (uint8_t*)pCtl;
    484                 *pcbCmd = sizeof (*pCtl);
    485                 return VBVAEXHOST_DATA_TYPE_GUESTCTL;
    486             }
     489            *ppCmd = (uint8_t*)pCtl;
     490            *pcbCmd = sizeof (*pCtl);
     491            return VBVAEXHOST_DATA_TYPE_GUESTCTL;
    487492        }
    488493
     
    509514}
    510515
     516/**
     517 * Called by vboxVDMAWorkerThread to get the next command to process.
     518 * @thread VDMA
     519 */
    511520static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd)
    512521{
     
    516525        vboxVBVAExHPHgEventClear(pCmdVbva);
    517526        vboxVBVAExHPProcessorRelease(pCmdVbva);
    518         /* we need to prevent racing between us clearing the flag and command check/submission thread, i.e.
     527
     528        /*
     529         * We need to prevent racing between us clearing the flag and command check/submission thread, i.e.
    519530         * 1. we check the queue -> and it is empty
    520531         * 2. submitter adds command to the queue
     
    523534         * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command
    524535         * 6. if the queue appears to be not-empty set the "processing" state back to "true"
    525          **/
     536         */
    526537        int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva);
    527538        if (RT_SUCCESS(rc))
     
    809820
    810821
    811 static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     822static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource,
     823                                PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
    812824{
    813825    if (!VBoxVBVAExHSIsEnabled(pCmdVbva))
     
    831843
    832844        if (enmSource > VBVAEXHOSTCTL_SOURCE_GUEST)
    833         {
    834845            RTListAppend(&pCmdVbva->HostCtlList, &pCtl->Node);
    835         }
    836846        else
    837847            RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node);
     
    849859}
    850860
     861/**
     862 * Call VDMA thread creation notification callback.
     863 */
    851864void VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread, void *pvThreadContext)
    852865{
     
    864877}
    865878
     879/**
     880 * Call VDMA thread termination notification callback.
     881 */
    866882void VBoxVDMAThreadNotifyTerminatingSucceeded(PVBOXVDMATHREAD pThread, void *pvThreadContext)
    867883{
     
    877893}
    878894
     895/**
     896 * Check if VDMA thread is terminating.
     897 */
    879898DECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread)
    880899{
     
    882901}
    883902
     903/**
     904 * Init VDMA thread.
     905 */
    884906void VBoxVDMAThreadInit(PVBOXVDMATHREAD pThread)
    885907{
     
    888910}
    889911
     912/**
     913 * Clean up VDMA thread.
     914 */
    890915int VBoxVDMAThreadCleanup(PVBOXVDMATHREAD pThread)
    891916{
     
    915940}
    916941
    917 int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread, PFNVBOXVDMATHREAD_CHANGED pfnCreated, void*pvCreated)
     942/**
     943 * Start VDMA thread.
     944 */
     945int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread,
     946                         PFNVBOXVDMATHREAD_CHANGED pfnCreated, void *pvCreated)
    918947{
    919948    int rc = VBoxVDMAThreadCleanup(pThread);
     
    933962        if (RT_SUCCESS(rc))
    934963            return VINF_SUCCESS;
    935         else
    936             WARN(("RTThreadCreate failed %d\n", rc));
     964        WARN(("RTThreadCreate failed %d\n", rc));
    937965
    938966        RTSemEventDestroy(pThread->hEvent);
     
    10011029}
    10021030
    1003 static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource);
     1031static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL *pCtl, VBVAEXHOSTCTL_SOURCE enmSource);
    10041032
    10051033typedef DECLCALLBACK(void) FNVBOXVDMACRCTL_CALLBACK(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext);
     
    10861114}
    10871115
     1116/**
     1117 * Posts stuff and waits.
     1118 */
    10881119static int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd)
    10891120{
     
    17361767}
    17371768
    1738 /**
     1769
     1770/**
     1771 * Copies one page in a VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER command.
     1772 *
    17391773 * @param fIn - whether this is a page in or out op.
     1774 * @thread VDMA
     1775 *
    17401776 * the direction is VRA#M - related, so fIn == true - transfer to VRAM); false - transfer from VRAM
    17411777 */
    1742 static int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, VBOXCMDVBVAPAGEIDX iPage, uint8_t *pu8Vram, bool fIn)
    1743 {
    1744     RTGCPHYS phPage = (RTGCPHYS)iPage << PAGE_SHIFT;
     1778static int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, VBOXCMDVBVAPAGEIDX uPageNo, uint8_t *pbVram, bool fIn)
     1779{
     1780    RTGCPHYS       GCPhysPage = (RTGCPHYS)uPageNo << X86_PAGE_SHIFT;
    17451781    PGMPAGEMAPLOCK Lock;
    17461782    int rc;
     
    17481784    if (fIn)
    17491785    {
    1750         const void * pvPage;
    1751         rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPage, &Lock);
    1752         if (!RT_SUCCESS(rc))
    1753         {
     1786        const void *pvPage;
     1787        rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysPage, 0, &pvPage, &Lock);
     1788        if (RT_SUCCESS(rc))
     1789        {
     1790            memcpy(pbVram, pvPage, PAGE_SIZE);
     1791            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1792        }
     1793        else
    17541794            WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d", rc));
    1755             return rc;
    1756         }
    1757 
    1758         memcpy(pu8Vram, pvPage, PAGE_SIZE);
    1759 
    1760         PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
    17611795    }
    17621796    else
    17631797    {
    1764         void * pvPage;
    1765         rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvPage, &Lock);
    1766         if (!RT_SUCCESS(rc))
    1767         {
     1798        void *pvPage;
     1799        rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysPage, 0, &pvPage, &Lock);
     1800        if (RT_SUCCESS(rc))
     1801        {
     1802            memcpy(pvPage, pbVram, PAGE_SIZE);
     1803            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     1804        }
     1805        else
    17681806            WARN(("PDMDevHlpPhysGCPhys2CCPtr failed %d", rc));
    1769             return rc;
    1770         }
    1771 
    1772         memcpy(pvPage, pu8Vram, PAGE_SIZE);
    1773 
    1774         PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
    1775     }
    1776 
    1777     return VINF_SUCCESS;
    1778 }
    1779 
    1780 static int vboxVDMACrCmdVbvaProcessPagingEls(PPDMDEVINS pDevIns, const VBOXCMDVBVAPAGEIDX *piPages, uint32_t cPages, uint8_t *pu8Vram, bool fIn)
    1781 {
    1782     for (uint32_t i = 0; i < cPages; ++i, pu8Vram += PAGE_SIZE)
    1783     {
    1784         int rc = vboxVDMACrCmdVbvaProcessPagingEl(pDevIns, piPages[i], pu8Vram, fIn);
    1785         if (!RT_SUCCESS(rc))
    1786         {
    1787             WARN(("vboxVDMACrCmdVbvaProcessPagingEl failed %d", rc));
    1788             return rc;
    1789         }
    1790     }
    1791 
    1792     return VINF_SUCCESS;
    1793 }
    1794 
    1795 static int8_t vboxVDMACrCmdVbvaPagingDataInit(PVGASTATE pVGAState, const VBOXCMDVBVA_HDR *pHdr, const VBOXCMDVBVA_PAGING_TRANSFER_DATA *pData, uint32_t cbCmd,
    1796                             const VBOXCMDVBVAPAGEIDX **ppPages, VBOXCMDVBVAPAGEIDX *pcPages,
    1797                             uint8_t **ppu8Vram, bool *pfIn)
    1798 {
    1799     if (cbCmd < sizeof (VBOXCMDVBVA_PAGING_TRANSFER))
    1800     {
    1801         WARN(("cmd too small"));
    1802         return -1;
    1803     }
    1804 
    1805     VBOXCMDVBVAPAGEIDX cPages = cbCmd - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, Data.aPageNumbers);
    1806     if (cPages % sizeof (VBOXCMDVBVAPAGEIDX))
    1807     {
    1808         WARN(("invalid cmd size"));
    1809         return -1;
    1810     }
    1811     cPages /= sizeof (VBOXCMDVBVAPAGEIDX);
    1812 
    1813     VBOXCMDVBVAOFFSET offVRAM = pData->Alloc.u.offVRAM;
    1814     if (offVRAM & PAGE_OFFSET_MASK)
    1815     {
     1807    }
     1808
     1809    return rc;
     1810}
     1811
     1812/**
     1813 * Handles a VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER command.
     1814 *
     1815 * @return 0 on success, -1 on failure.
     1816 *
     1817 * @thread VDMA
     1818 */
     1819static int8_t vboxVDMACrCmdVbvaPageTransfer(PVGASTATE pVGAState, VBOXCMDVBVA_HDR const volatile *pHdr, uint32_t cbCmd,
     1820                                            const VBOXCMDVBVA_PAGING_TRANSFER_DATA *pData)
     1821{
     1822    /*
     1823     * Extract and validate information.
     1824     */
     1825    AssertMsgReturn(cbCmd >= sizeof(VBOXCMDVBVA_PAGING_TRANSFER), ("%#x\n", cbCmd), -1);
     1826
     1827    bool const fIn = RT_BOOL(pHdr->u8Flags & VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN);
     1828
     1829    uint32_t cbPageNumbers = cbCmd - RT_OFFSETOF(VBOXCMDVBVA_PAGING_TRANSFER, Data.aPageNumbers);
     1830    AssertMsgReturn(!(cbPageNumbers % sizeof(VBOXCMDVBVAPAGEIDX)), ("%#x\n", cbPageNumbers), -1);
     1831    VBOXCMDVBVAPAGEIDX const cPages = cbPageNumbers / sizeof(VBOXCMDVBVAPAGEIDX);
     1832
     1833    VBOXCMDVBVAOFFSET offVRam = pData->Alloc.u.offVRAM;
     1834    AssertMsgReturn(!(offVRam & X86_PAGE_OFFSET_MASK), ("%#x\n", offVRam), -1);
     1835    AssertMsgReturn(offVRam < pVGAState->vram_size, ("%#x vs %#x\n", offVRam, pVGAState->vram_size), -1);
     1836    uint32_t cVRamPages = (pVGAState->vram_size - offVRam) >> X86_PAGE_SHIFT;
     1837    AssertMsgReturn(cPages <= cVRamPages, ("cPages=%#x vs cVRamPages=%#x @ offVRam=%#x\n", cPages, cVRamPages, offVRam), -1);
     1838
     1839    /*
     1840     * Execute the command.
     1841     */
     1842    uint8_t *pbVRam = (uint8_t *)pVGAState->vram_ptrR3 + offVRam;
     1843    for (uint32_t iPage = 0; iPage < cPages; iPage++, pbVRam += X86_PAGE_SIZE)
     1844    {
     1845        uint32_t uPageNo = pData->aPageNumbers[iPage];
     1846        int rc = vboxVDMACrCmdVbvaProcessPagingEl(pVGAState->pDevInsR3, uPageNo, pbVRam, fIn);
     1847        AssertMsgReturn(RT_SUCCESS(rc), ("#%#x: uPageNo=%#x rc=%Rrc\n", iPage, uPageNo, rc), -1);
     1848    }
     1849    return 0;
     1850}
     1851
     1852
     1853/**
     1854 * Handles VBOXCMDVBVA_OPTYPE_PAGING_FILL.
     1855 *
     1856 * @returns 0 on success, -1 on failure.
     1857 * @param   pVGAState           The VGA state.
     1858 * @param   pFill               The fill command (volatile).
     1859 *
     1860 * @thread VDMA
     1861 */
     1862static int8_t vboxVDMACrCmdVbvaPagingFill(PVGASTATE pVGAState, VBOXCMDVBVA_PAGING_FILL *pFill)
     1863{
     1864    VBOXCMDVBVA_PAGING_FILL FillSafe = *pFill;
     1865    VBOXCMDVBVAOFFSET       offVRAM  = FillSafe.offVRAM;
     1866    if (!(offVRAM & X86_PAGE_OFFSET_MASK))
     1867    {
     1868        if (offVRAM <= pVGAState->vram_size)
     1869        {
     1870            uint32_t cbFill = FillSafe.u32CbFill;
     1871            AssertStmt(!(cbFill & 3), cbFill &= ~(uint32_t)3);
     1872
     1873            if (   cbFill < pVGAState->vram_size
     1874                && offVRAM <= pVGAState->vram_size - cbFill)
     1875            {
     1876                uint32_t      *pu32Vram = (uint32_t *)((uint8_t *)pVGAState->vram_ptrR3 + offVRAM);
     1877                uint32_t const u32Color = FillSafe.u32Pattern;
     1878
     1879                uint32_t cLoops = cbFill / 4;
     1880                while (cLoops-- > 0)
     1881                    pu32Vram[cLoops] = u32Color;
     1882
     1883                return 0;
     1884
     1885            }
     1886            else
     1887                WARN(("invalid cbFill"));
     1888
     1889        }
     1890        WARN(("invalid vram offset"));
     1891
     1892    }
     1893    else
    18161894        WARN(("offVRAM address is not on page boundary\n"));
    1817         return -1;
    1818     }
    1819     const VBOXCMDVBVAPAGEIDX *pPages = pData->aPageNumbers;
    1820 
    1821     uint8_t * pu8VramBase = pVGAState->vram_ptrR3;
    1822     if (offVRAM >= pVGAState->vram_size)
    1823     {
    1824         WARN(("invalid vram offset"));
    1825         return -1;
    1826     }
    1827 
    1828     if (~(~(VBOXCMDVBVAPAGEIDX)0 >> PAGE_SHIFT) & cPages)
    1829     {
    1830         WARN(("invalid cPages %d", cPages));
    1831         return -1;
    1832     }
    1833 
    1834     if (offVRAM + ((VBOXCMDVBVAOFFSET)cPages << PAGE_SHIFT) >= pVGAState->vram_size)
    1835     {
    1836         WARN(("invalid cPages %d, exceeding vram size", cPages));
    1837         return -1;
    1838     }
    1839 
    1840     uint8_t *pu8Vram = pu8VramBase + offVRAM;
    1841     bool fIn = !!(pHdr->u8Flags & VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN);
    1842 
    1843     *ppPages = pPages;
    1844     *pcPages = cPages;
    1845     *ppu8Vram = pu8Vram;
    1846     *pfIn = fIn;
    1847     return 0;
    1848 }
    1849 
    1850 static int8_t vboxVDMACrCmdVbvaPagingFill(PVGASTATE pVGAState, VBOXCMDVBVA_PAGING_FILL *pFill)
    1851 {
    1852     VBOXCMDVBVAOFFSET offVRAM = pFill->offVRAM;
    1853     if (offVRAM & PAGE_OFFSET_MASK)
    1854     {
    1855         WARN(("offVRAM address is not on page boundary\n"));
    1856         return -1;
    1857     }
    1858 
    1859     uint8_t * pu8VramBase = pVGAState->vram_ptrR3;
    1860     if (offVRAM >= pVGAState->vram_size)
    1861     {
    1862         WARN(("invalid vram offset"));
    1863         return -1;
    1864     }
    1865 
    1866     uint32_t cbFill = pFill->u32CbFill;
    1867 
    1868     if (offVRAM + cbFill >= pVGAState->vram_size)
    1869     {
    1870         WARN(("invalid cPages"));
    1871         return -1;
    1872     }
    1873 
    1874     uint32_t *pu32Vram = (uint32_t*)(pu8VramBase + offVRAM);
    1875     uint32_t u32Color = pFill->u32Pattern;
    1876 
    1877     Assert(!(cbFill % 4));
    1878     for (uint32_t i = 0; i < cbFill / 4; ++i)
    1879     {
    1880         pu32Vram[i] = u32Color;
    1881     }
    1882 
    1883     return 0;
    1884 }
    1885 
     1895    return -1;
     1896}
     1897
     1898/**
     1899 * Process command data.
     1900 *
     1901 * @returns zero or positive is success, negative failure.
     1902 * @param   pVdma               The VDMA channel.
     1903 * @param   pCmd                The command data to process. Assume volatile.
     1904 * @param   cbCmd               The amount of command data.
     1905 *
     1906 * @thread VDMA
     1907 */
    18861908static int8_t vboxVDMACrCmdVbvaProcessCmdData(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
    18871909{
    1888     switch (pCmd->u8OpCode)
     1910    uint8_t bOpCode = pCmd->u8OpCode;
     1911    switch (bOpCode)
    18891912    {
    18901913        case VBOXCMDVBVA_OPTYPE_NOPCMD:
    18911914            return 0;
     1915
    18921916        case VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER:
    1893         {
    1894             PVGASTATE pVGAState = pVdma->pVGAState;
    1895             const VBOXCMDVBVAPAGEIDX *pPages;
    1896             uint32_t cPages;
    1897             uint8_t *pu8Vram;
    1898             bool fIn;
    1899             int8_t i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pCmd, &((VBOXCMDVBVA_PAGING_TRANSFER*)pCmd)->Data, cbCmd,
    1900                                                                 &pPages, &cPages,
    1901                                                                 &pu8Vram, &fIn);
    1902             if (i8Result < 0)
    1903             {
    1904                 WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result));
    1905                 return i8Result;
    1906             }
    1907 
    1908             PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
    1909             int rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pPages, cPages, pu8Vram, fIn);
    1910             if (!RT_SUCCESS(rc))
    1911             {
    1912                 WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc));
    1913                 return -1;
    1914             }
    1915 
    1916             return 0;
    1917         }
     1917            return vboxVDMACrCmdVbvaPageTransfer(pVdma->pVGAState, pCmd, cbCmd, &((VBOXCMDVBVA_PAGING_TRANSFER *)pCmd)->Data);
     1918
    19181919        case VBOXCMDVBVA_OPTYPE_PAGING_FILL:
    1919         {
    1920             PVGASTATE pVGAState = pVdma->pVGAState;
    1921             if (cbCmd != sizeof (VBOXCMDVBVA_PAGING_FILL))
    1922             {
    1923                 WARN(("cmd too small"));
    1924                 return -1;
    1925             }
    1926 
    1927             return vboxVDMACrCmdVbvaPagingFill(pVGAState, (VBOXCMDVBVA_PAGING_FILL*)pCmd);
    1928         }
     1920            if (cbCmd == sizeof(VBOXCMDVBVA_PAGING_FILL))
     1921                return vboxVDMACrCmdVbvaPagingFill(pVdma->pVGAState, (VBOXCMDVBVA_PAGING_FILL *)pCmd);
     1922            WARN(("cmd too small"));
     1923            return -1;
     1924
    19291925        default:
    1930             if (!pVdma->CrSrvInfo.pfnCmd)
    1931             {
    1932                 /* Unexpected. */
    1933                 WARN(("no HGCM"));
    1934                 return -1;
    1935             }
    1936             return pVdma->CrSrvInfo.pfnCmd(pVdma->CrSrvInfo.hSvr, pCmd, cbCmd);
     1926            if (pVdma->CrSrvInfo.pfnCmd)
     1927                return pVdma->CrSrvInfo.pfnCmd(pVdma->CrSrvInfo.hSvr, pCmd, cbCmd);
     1928            /* Unexpected. */
     1929            WARN(("no HGCM"));
     1930            return -1;
    19371931    }
    19381932}
     
    19531947AssertCompile(sizeof (VBOXCMDVBVA_ALLOCINFO) == 4);
    19541948AssertCompile(sizeof (VBOXCMDVBVAPAGEIDX) == 4);
    1955 AssertCompile(!(PAGE_SIZE % sizeof (VBOXCMDVBVAPAGEIDX)));
    1956 
    1957 # define VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE (PAGE_SIZE / sizeof (VBOXCMDVBVA_SYSMEMEL))
    1958 
    1959 static int8_t vboxVDMACrCmdVbvaProcess(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd)
    1960 {
    1961     LogRelFlow(("VDMA: vboxVDMACrCmdVbvaProcess: ENTER, opCode(%i)\n", pCmd->u8OpCode));
    1962     int8_t i8Result = 0;
    1963 
    1964     switch (pCmd->u8OpCode)
     1949AssertCompile(!(X86_PAGE_SIZE % sizeof (VBOXCMDVBVAPAGEIDX)));
     1950
     1951# define VBOXCMDVBVA_NUM_SYSMEMEL_PER_PAGE (X86_PAGE_SIZE / sizeof (VBOXCMDVBVA_SYSMEMEL))
     1952
     1953/**
     1954 * Worker for vboxVDMACrCmdProcess.
     1955 *
     1956 * @returns 8-bit result.
     1957 * @param   pVdma       The VDMA channel.
     1958 * @param   pCmd        The command.  Consider volatile!
     1959 * @param   cbCmd       The size of what @a pCmd points to.  At least
     1960 *                      sizeof(VBOXCMDVBVA_HDR).
     1961 * @param   fRecursion  Set if recursive call, false if not.
     1962 *
     1963 * @thread VDMA
     1964 */
     1965static int8_t vboxVDMACrCmdVbvaProcess(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd, bool fRecursion)
     1966{
     1967    int8_t        i8Result = 0;
     1968    uint8_t const bOpCode  = pCmd->u8OpCode;
     1969    LogRelFlow(("VDMA: vboxVDMACrCmdVbvaProcess: ENTER, bOpCode=%u\n", bOpCode));
     1970    switch (bOpCode)
    19651971    {
    19661972        case VBOXCMDVBVA_OPTYPE_SYSMEMCMD:
    19671973        {
    1968             if (cbCmd < sizeof (VBOXCMDVBVA_SYSMEMCMD))
    1969             {
    1970                 WARN(("invalid command size"));
    1971                 return -1;
    1972             }
    1973             VBOXCMDVBVA_SYSMEMCMD *pSysmemCmd = (VBOXCMDVBVA_SYSMEMCMD*)pCmd;
    1974             const VBOXCMDVBVA_HDR *pRealCmdHdr;
    1975             uint32_t cbRealCmd = pCmd->u8Flags;
     1974            /*
     1975             * Extract the command physical address and size.
     1976             */
     1977            AssertMsgReturn(cbCmd >= sizeof(VBOXCMDVBVA_SYSMEMCMD), ("%#x\n", cbCmd), -1);
     1978            RTGCPHYS GCPhysCmd  = ((VBOXCMDVBVA_SYSMEMCMD *)pCmd)->phCmd;
     1979            uint32_t cbCmdPart  = X86_PAGE_SIZE - (uint32_t)(GCPhysCmd & X86_PAGE_OFFSET_MASK);
     1980
     1981            uint32_t cbRealCmd  = pCmd->u8Flags;
    19761982            cbRealCmd |= (uint32_t)pCmd->u.u8PrimaryID << 8;
    1977             if (cbRealCmd < sizeof (VBOXCMDVBVA_HDR))
    1978             {
    1979                 WARN(("invalid sysmem cmd size"));
    1980                 return -1;
    1981             }
    1982 
    1983             RTGCPHYS phCmd = (RTGCPHYS)pSysmemCmd->phCmd;
    1984 
     1983            AssertMsgReturn(cbRealCmd >= sizeof(VBOXCMDVBVA_HDR), ("%#x\n", cbRealCmd), -1);
     1984            AssertMsgReturn(cbRealCmd <= _1M, ("%#x\n", cbRealCmd), -1);
     1985
     1986            /*
     1987             * Lock down the first page of the memory specified by the command.
     1988             */
    19851989            PGMPAGEMAPLOCK Lock;
    19861990            PVGASTATE pVGAState = pVdma->pVGAState;
    19871991            PPDMDEVINS pDevIns = pVGAState->pDevInsR3;
    1988             const void * pvCmd;
    1989             int rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phCmd, 0, &pvCmd, &Lock);
     1992            VBOXCMDVBVA_HDR const *pRealCmdHdr = NULL;
     1993            int rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysCmd, 0, (const void **)&pRealCmdHdr, &Lock);
    19901994            if (!RT_SUCCESS(rc))
    19911995            {
     
    19931997                return -1;
    19941998            }
    1995 
    1996             Assert((phCmd & PAGE_OFFSET_MASK) == (((uintptr_t)pvCmd) & PAGE_OFFSET_MASK));
    1997 
    1998             uint32_t cbCmdPart = PAGE_SIZE - (((uintptr_t)pvCmd) & PAGE_OFFSET_MASK);
    1999 
     1999            Assert((GCPhysCmd & PAGE_OFFSET_MASK) == (((uintptr_t)pRealCmdHdr) & PAGE_OFFSET_MASK));
     2000
     2001            /*
     2002             * All fits within one page?  We can handle that pretty efficiently.
     2003             */
    20002004            if (cbRealCmd <= cbCmdPart)
    20012005            {
    2002                 pRealCmdHdr = (const VBOXCMDVBVA_HDR *)pvCmd;
    20032006                i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pRealCmdHdr, cbRealCmd);
    20042007                PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
    2005                 return i8Result;
    2006             }
    2007 
    2008             VBOXCMDVBVA_HDR Hdr;
    2009             const void *pvCurCmdTail;
    2010             uint32_t cbCurCmdTail;
    2011             if (cbCmdPart >= sizeof (*pRealCmdHdr))
    2012             {
    2013                 pRealCmdHdr = (const VBOXCMDVBVA_HDR *)pvCmd;
    2014                 pvCurCmdTail = (const void*)(pRealCmdHdr + 1);
    2015                 cbCurCmdTail = cbCmdPart - sizeof (*pRealCmdHdr);
    20162008            }
    20172009            else
    20182010            {
    2019                 memcpy(&Hdr, pvCmd, cbCmdPart);
    2020                 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
    2021                 phCmd += cbCmdPart;
    2022                 Assert(!(phCmd & PAGE_OFFSET_MASK));
    2023                 rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phCmd, 0, &pvCmd, &Lock);
    2024                 if (!RT_SUCCESS(rc))
     2011                /*
     2012                 * To keep things damn simple, just double buffer cross page or
     2013                 * multipage requests.
     2014                 */
     2015                uint8_t *pbCmdBuf = (uint8_t *)RTMemTmpAllocZ(RT_ALIGN_Z(cbRealCmd, 16));
     2016                if (pbCmdBuf)
    20252017                {
    2026                     WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
    2027                     return -1;
     2018                    memcpy(pbCmdBuf, pRealCmdHdr, cbCmdPart);
     2019                    PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     2020                    pRealCmdHdr = NULL;
     2021
     2022                    rc = PDMDevHlpPhysRead(pDevIns, GCPhysCmd + cbCmdPart, &pbCmdBuf[cbCmdPart], cbRealCmd - cbCmdPart);
     2023                    if (RT_SUCCESS(rc))
     2024                        i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, (VBOXCMDVBVA_HDR const *)pbCmdBuf, cbRealCmd);
     2025                    else
     2026                        LogRelMax(200, ("VDMA: Error reading %#x bytes of guest memory %#RGp!\n", cbRealCmd, GCPhysCmd));
     2027                    RTMemTmpFree(pbCmdBuf);
    20282028                }
    2029 
    2030                 cbCmdPart = sizeof (*pRealCmdHdr) - cbCmdPart;
    2031                 memcpy(((uint8_t*)(&Hdr)) + cbCmdPart, pvCmd, cbCmdPart);
    2032                 pRealCmdHdr = &Hdr;
    2033                 pvCurCmdTail = (const void*)(((uint8_t*)pvCmd) + cbCmdPart);
    2034                 cbCurCmdTail = PAGE_SIZE - cbCmdPart;
    2035             }
    2036 
    2037             if (cbCurCmdTail > cbRealCmd - sizeof (*pRealCmdHdr))
    2038                 cbCurCmdTail = cbRealCmd - sizeof (*pRealCmdHdr);
    2039 
    2040             switch (pRealCmdHdr->u8OpCode)
    2041             {
    2042                 case VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER:
     2029                else
    20432030                {
    2044                     const uint32_t *pPages;
    2045                     uint32_t cPages;
    2046                     uint8_t *pu8Vram;
    2047                     bool fIn;
    2048                     i8Result = vboxVDMACrCmdVbvaPagingDataInit(pVGAState, pRealCmdHdr, (const VBOXCMDVBVA_PAGING_TRANSFER_DATA*)pvCurCmdTail, cbRealCmd,
    2049                                                                         &pPages, &cPages,
    2050                                                                         &pu8Vram, &fIn);
    2051                     if (i8Result < 0)
    2052                     {
    2053                         WARN(("vboxVDMACrCmdVbvaPagingDataInit failed %d", i8Result));
    2054                         /* we need to break, not return, to ensure currently locked page is released */
    2055                         break;
    2056                     }
    2057 
    2058                     if (cbCurCmdTail & 3)
    2059                     {
    2060                         WARN(("command is not alligned properly %d", cbCurCmdTail));
    2061                         i8Result = -1;
    2062                         /* we need to break, not return, to ensure currently locked page is released */
    2063                         break;
    2064                     }
    2065 
    2066                     uint32_t cCurPages = cbCurCmdTail / sizeof (VBOXCMDVBVAPAGEIDX);
    2067                     Assert(cCurPages < cPages);
    2068 
    2069                     do
    2070                     {
    2071                         rc = vboxVDMACrCmdVbvaProcessPagingEls(pDevIns, pPages, cCurPages, pu8Vram, fIn);
    2072                         if (!RT_SUCCESS(rc))
    2073                         {
    2074                             WARN(("vboxVDMACrCmdVbvaProcessPagingEls failed %d", rc));
    2075                             i8Result = -1;
    2076                             /* we need to break, not return, to ensure currently locked page is released */
    2077                             break;
    2078                         }
    2079 
    2080                         Assert(cPages >= cCurPages);
    2081                         cPages -= cCurPages;
    2082 
    2083                         if (!cPages)
    2084                             break;
    2085 
    2086                         PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
    2087 
    2088                         Assert(!(phCmd & PAGE_OFFSET_MASK));
    2089 
    2090                         phCmd += PAGE_SIZE;
    2091                         pu8Vram += (VBOXCMDVBVAOFFSET)cCurPages << PAGE_SHIFT;
    2092 
    2093                         rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phCmd, 0, &pvCmd, &Lock);
    2094                         if (!RT_SUCCESS(rc))
    2095                         {
    2096                             WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d\n", rc));
    2097                             /* the page is not locked, return */
    2098                             return -1;
    2099                         }
    2100 
    2101                         cCurPages = PAGE_SIZE / sizeof (VBOXCMDVBVAPAGEIDX);
    2102                         if (cCurPages > cPages)
    2103                             cCurPages = cPages;
    2104                     } while (1);
    2105                     break;
     2031                    PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     2032                    LogRelMax(200, ("VDMA: Out of temporary memory! %#x\n", cbRealCmd));
     2033                    i8Result = -1;
    21062034                }
    2107                 default:
    2108                     WARN(("command can not be splitted"));
    2109                     i8Result = -1;
    2110                     break;
    2111             }
    2112 
    2113             PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     2035            }
    21142036            return i8Result;
    21152037        }
     2038
    21162039        case VBOXCMDVBVA_OPTYPE_COMPLEXCMD:
    21172040        {
    2118             Assert(cbCmd >= sizeof (VBOXCMDVBVA_HDR));
    2119             ++pCmd;
    2120             cbCmd -= sizeof (*pCmd);
    2121             uint32_t cbCurCmd = 0;
    2122             for ( ; cbCmd; cbCmd -= cbCurCmd, pCmd = (VBOXCMDVBVA_HDR*)(((uint8_t*)pCmd) + cbCurCmd))
    2123             {
    2124                 if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
    2125                 {
    2126                     WARN(("invalid command size"));
    2127                     return -1;
    2128                 }
    2129 
    2130                 cbCurCmd = pCmd->u2.complexCmdEl.u16CbCmdHost;
    2131                 if (cbCmd < cbCurCmd)
    2132                 {
    2133                     WARN(("invalid command size"));
    2134                     return -1;
    2135                 }
    2136 
    2137                 i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCurCmd);
     2041            Assert(cbCmd >= sizeof(VBOXCMDVBVA_HDR)); /* caller already checked this */
     2042            AssertReturn(!fRecursion, -1);
     2043
     2044            /* Skip current command. */
     2045            cbCmd -= sizeof(*pCmd);
     2046            pCmd++;
     2047
     2048            /* Process subcommands. */
     2049            while (cbCmd > 0)
     2050            {
     2051                AssertMsgReturn(cbCmd >= sizeof(VBOXCMDVBVA_HDR), ("%#x\n", cbCmd), -1);
     2052
     2053                uint16_t cbCurCmd = pCmd->u2.complexCmdEl.u16CbCmdHost;
     2054                AssertMsgReturn(cbCurCmd <= cbCmd, ("cbCurCmd=%#x, cbCmd=%#x\n", cbCurCmd, cbCmd), -1);
     2055
     2056                i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCurCmd, true /*fRecursive*/);
    21382057                if (i8Result < 0)
    21392058                {
     
    21412060                    return i8Result;
    21422061                }
     2062
     2063                /* Advance to the next command. */
     2064                pCmd  = (VBOXCMDVBVA_HDR *)((uintptr_t)pCmd + cbCurCmd);
     2065                cbCmd -= cbCurCmd;
    21432066            }
    21442067            return 0;
    21452068        }
     2069
    21462070        default:
    21472071            i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pCmd, cbCmd);
     
    21512075}
    21522076
    2153 static void vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pu8Cmd, uint32_t cbCmd)
    2154 {
    2155     if (*pu8Cmd == VBOXCMDVBVA_OPTYPE_NOP)
    2156         return;
    2157 
    2158     if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
    2159     {
     2077/**
     2078 * Worker for vboxVDMAWorkerThread handling VBVAEXHOST_DATA_TYPE_CMD.
     2079 *
     2080 * @thread VDMA
     2081 */
     2082static void vboxVDMACrCmdProcess(struct VBOXVDMAHOST *pVdma, uint8_t* pbCmd, uint32_t cbCmd)
     2083{
     2084    if (   cbCmd > 0
     2085        && *pbCmd == VBOXCMDVBVA_OPTYPE_NOP)
     2086    { /* nop */ }
     2087    else if (cbCmd >= sizeof(VBOXCMDVBVA_HDR))
     2088    {
     2089        PVBOXCMDVBVA_HDR pCmd = (PVBOXCMDVBVA_HDR)pbCmd;
     2090
     2091        /* check if the command is cancelled */
     2092        if (ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_IN_PROGRESS, VBOXCMDVBVA_STATE_SUBMITTED))
     2093        {
     2094            /* Process it. */
     2095            pCmd->u.i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCmd, false /*fRecursion*/);
     2096        }
     2097        else
     2098            Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
     2099    }
     2100    else
    21602101        WARN(("invalid command size"));
    2161         return;
    2162     }
    2163 
    2164     PVBOXCMDVBVA_HDR pCmd = (PVBOXCMDVBVA_HDR)pu8Cmd;
    2165 
    2166     /* check if the command is cancelled */
    2167     if (!ASMAtomicCmpXchgU8(&pCmd->u8State, VBOXCMDVBVA_STATE_IN_PROGRESS, VBOXCMDVBVA_STATE_SUBMITTED))
    2168     {
    2169         Assert(pCmd->u8State == VBOXCMDVBVA_STATE_CANCELLED);
    2170         return;
    2171     }
    2172 
    2173     pCmd->u.i8Result = vboxVDMACrCmdVbvaProcess(pVdma, pCmd, cbCmd);
     2102
    21742103}
    21752104
     
    22082137}
    22092138
    2210 static int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer);
    2211 
    2212 /* check if this is external cmd to be passed to chromium backend */
     2139static int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const VBOXVDMACMD_DMA_BPB_TRANSFER *pTransfer, uint32_t cbBuffer);
     2140
     2141/**
     2142 * Check if this is an external command to be passed to the chromium backend.
     2143 *
     2144 * @retval VINF_NOT_SUPPORTED if not chromium command.
     2145 *
     2146 * @note    cbCmdDr is at least sizeof(VBOXVDMACBUF_DR).
     2147 */
    22132148static int vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmdDr, uint32_t cbCmdDr)
    22142149{
    2215     PVBOXVDMACMD pDmaCmd = NULL;
    22162150    uint32_t cbDmaCmd = 0;
    2217     uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
     2151    uint8_t *pbRam = pVdma->pVGAState->vram_ptrR3;
    22182152    int rc = VINF_NOT_SUPPORTED;
    22192153
    22202154    cbDmaCmd = pCmdDr->cbBuf;
    22212155
     2156    PVBOXVDMACMD pDmaCmd;
    22222157    if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
    22232158    {
    2224         if (cbCmdDr < sizeof (*pCmdDr) + VBOXVDMACMD_HEADER_SIZE())
    2225         {
    2226             AssertMsgFailed(("invalid buffer data!"));
    2227             return VERR_INVALID_PARAMETER;
    2228         }
    2229 
    2230         if (cbDmaCmd < cbCmdDr - sizeof (*pCmdDr) - VBOXVDMACMD_HEADER_SIZE())
    2231         {
    2232             AssertMsgFailed(("invalid command buffer data!"));
    2233             return VERR_INVALID_PARAMETER;
    2234         }
     2159        AssertReturn(cbCmdDr  >=           sizeof(*pCmdDr) + VBOXVDMACMD_HEADER_SIZE(), VERR_INVALID_PARAMETER);
     2160        AssertReturn(cbDmaCmd >= cbCmdDr - sizeof(*pCmdDr) - VBOXVDMACMD_HEADER_SIZE(), VERR_INVALID_PARAMETER);
    22352161
    22362162        pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmdDr, VBOXVDMACMD);
     
    22392165    {
    22402166        VBOXVIDEOOFFSET offBuf = pCmdDr->Location.offVramBuf;
    2241         if (offBuf + cbDmaCmd > pVdma->pVGAState->vram_size)
    2242         {
    2243             AssertMsgFailed(("invalid command buffer data from offset!"));
    2244             return VERR_INVALID_PARAMETER;
    2245         }
    2246         pDmaCmd = (VBOXVDMACMD*)(pvRam + offBuf);
    2247     }
    2248 
     2167        AssertReturn(   cbDmaCmd <= pVdma->pVGAState->vram_size
     2168                     && offBuf <= pVdma->pVGAState->vram_size - cbDmaCmd, VERR_INVALID_PARAMETER);
     2169        pDmaCmd = (VBOXVDMACMD *)(pbRam + offBuf);
     2170    }
     2171    else
     2172        pDmaCmd = NULL;
    22492173    if (pDmaCmd)
    22502174    {
     
    22572181            {
    22582182                PVBOXVDMACMD_CHROMIUM_CMD pCrCmd = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_CHROMIUM_CMD);
    2259                 if (cbBody < sizeof (*pCrCmd))
    2260                 {
    2261                     AssertMsgFailed(("invalid chromium command buffer size!"));
    2262                     return VERR_INVALID_PARAMETER;
    2263                 }
     2183                AssertReturn(cbBody >= sizeof(*pCrCmd), VERR_INVALID_PARAMETER);
     2184
    22642185                PVGASTATE pVGAState = pVdma->pVGAState;
    22652186                rc = VINF_SUCCESS;
     
    22702191                    break;
    22712192                }
    2272                 else
    2273                 {
    2274                     Assert(0);
    2275                 }
    2276 
    2277                 int tmpRc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
     2193
     2194                AssertFailed();
     2195                int tmpRc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmdDr);
    22782196                AssertRC(tmpRc);
    22792197                break;
    22802198            }
     2199
    22812200            case VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER:
    22822201            {
    22832202                PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pDmaCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
    2284                 if (cbBody < sizeof (*pTransfer))
    2285                 {
    2286                     AssertMsgFailed(("invalid bpb transfer buffer size!"));
    2287                     return VERR_INVALID_PARAMETER;
    2288                 }
     2203                AssertReturn(cbBody >= sizeof(*pTransfer), VERR_INVALID_PARAMETER);
    22892204
    22902205                rc = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, sizeof (*pTransfer));
     
    22932208                {
    22942209                    pCmdDr->rc = VINF_SUCCESS;
    2295                     rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmdDr);
     2210                    rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmdDr);
    22962211                    AssertRC(rc);
    22972212                    rc = VINF_SUCCESS;
     
    22992214                break;
    23002215            }
     2216
    23012217            default:
    23022218                break;
     
    23332249}
    23342250
     2251/**
     2252 * Worker for vboxVDMACmdExecBlt().
     2253 */
    23352254static int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma, const VBOXVIDEOOFFSET offDst, const VBOXVIDEOOFFSET offSrc,
    23362255                                     const PVBOXVDMA_SURF_DESC pDstDesc, const PVBOXVDMA_SURF_DESC pSrcDesc,
    2337                                      const VBOXVDMA_RECTL * pDstRectl, const VBOXVDMA_RECTL * pSrcRectl)
    2338 {
    2339     /* we do not support color conversion */
    2340     Assert(pDstDesc->format == pSrcDesc->format);
    2341     /* we do not support stretching */
     2256                                     const VBOXVDMA_RECTL *pDstRectl, const VBOXVDMA_RECTL *pSrcRectl)
     2257{
     2258    /*
     2259     * We do not support color conversion.
     2260     */
     2261    AssertReturn(pDstDesc->format == pSrcDesc->format, VERR_INVALID_FUNCTION);
     2262
     2263    /* we do not support stretching (checked by caller) */
    23422264    Assert(pDstRectl->height == pSrcRectl->height);
    2343     Assert(pDstRectl->width == pSrcRectl->width);
    2344 
    2345     if (pDstDesc->format != pSrcDesc->format)
    2346         return VERR_INVALID_FUNCTION;
    2347 
    2348     uint8_t *pvRam = pVdma->pVGAState->vram_ptrR3;
    2349     uint8_t *pvDstSurf = pvRam + offDst;
    2350     uint8_t *pvSrcSurf = pvRam + offSrc;
    2351 
    2352     if (pDstDesc->width == pDstRectl->width
    2353             && pSrcDesc->width == pSrcRectl->width
    2354             && pSrcDesc->width == pDstDesc->width
    2355             && pSrcDesc->pitch == pDstDesc->pitch)
     2265    Assert(pDstRectl->width  == pSrcRectl->width);
     2266
     2267    uint8_t *pbRam = pVdma->pVGAState->vram_ptrR3;
     2268    AssertCompileSize(pVdma->pVGAState->vram_size, sizeof(uint32_t));
     2269    uint32_t cbVRamSize = pVdma->pVGAState->vram_size;
     2270    uint8_t *pbDstSurf = pbRam + offDst;
     2271    uint8_t *pbSrcSurf = pbRam + offSrc;
     2272
     2273    if (   pDstDesc->width == pDstRectl->width
     2274        && pSrcDesc->width == pSrcRectl->width
     2275        && pSrcDesc->width == pDstDesc->width
     2276        && pSrcDesc->pitch == pDstDesc->pitch)
    23562277    {
    23572278        Assert(!pDstRectl->left);
    23582279        Assert(!pSrcRectl->left);
    2359         uint32_t cbOff = pDstDesc->pitch * pDstRectl->top;
    2360         uint32_t cbSize = pDstDesc->pitch * pDstRectl->height;
    2361         memcpy(pvDstSurf + cbOff, pvSrcSurf + cbOff, cbSize);
     2280        uint32_t offBoth  = pDstDesc->pitch * pDstRectl->top;
     2281        uint32_t cbToCopy = pDstDesc->pitch * pDstRectl->height;
     2282
     2283        if (   cbToCopy <= cbVRamSize
     2284            && (uintptr_t)(pbDstSurf + offBoth) - (uintptr_t)pbRam <= cbVRamSize - cbToCopy
     2285            && (uintptr_t)(pbSrcSurf + offBoth) - (uintptr_t)pbRam <= cbVRamSize - cbToCopy)
     2286            memcpy(pbDstSurf + offBoth, pbSrcSurf + offBoth, cbToCopy);
     2287        else
     2288            return VERR_INVALID_PARAMETER;
    23622289    }
    23632290    else
    23642291    {
    2365         uint32_t offDstLineStart = pDstRectl->left * pDstDesc->bpp >> 3;
    2366         uint32_t offDstLineEnd = ((pDstRectl->left * pDstDesc->bpp + 7) >> 3) + ((pDstDesc->bpp * pDstRectl->width + 7) >> 3);
    2367         uint32_t cbDstLine = offDstLineEnd - offDstLineStart;
    2368         uint32_t offDstStart = pDstDesc->pitch * pDstRectl->top + offDstLineStart;
     2292        uint32_t offDstLineStart =   pDstRectl->left * pDstDesc->bpp >> 3;
     2293        uint32_t offDstLineEnd   = ((pDstRectl->left * pDstDesc->bpp + 7) >> 3) + ((pDstDesc->bpp * pDstRectl->width + 7) >> 3);
     2294        uint32_t cbDstLine       = offDstLineEnd - offDstLineStart;
     2295        uint32_t offDstStart     = pDstDesc->pitch * pDstRectl->top + offDstLineStart;
    23692296        Assert(cbDstLine <= pDstDesc->pitch);
    2370         uint32_t cbDstSkip = pDstDesc->pitch;
    2371         uint8_t * pvDstStart = pvDstSurf + offDstStart;
    2372 
    2373         uint32_t offSrcLineStart = pSrcRectl->left * pSrcDesc->bpp >> 3;
     2297        uint32_t cbDstSkip       = pDstDesc->pitch;
     2298        uint8_t *pbDstStart      = pbDstSurf + offDstStart;
     2299
     2300        uint32_t offSrcLineStart =   pSrcRectl->left * pSrcDesc->bpp >> 3;
    23742301# ifdef VBOX_STRICT
    2375         uint32_t offSrcLineEnd = ((pSrcRectl->left * pSrcDesc->bpp + 7) >> 3) + ((pSrcDesc->bpp * pSrcRectl->width + 7) >> 3);
    2376         uint32_t cbSrcLine = offSrcLineEnd - offSrcLineStart;
     2302        uint32_t offSrcLineEnd   = ((pSrcRectl->left * pSrcDesc->bpp + 7) >> 3) + ((pSrcDesc->bpp * pSrcRectl->width + 7) >> 3);
     2303        uint32_t cbSrcLine       = offSrcLineEnd - offSrcLineStart;
    23772304# endif
    2378         uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;
     2305        uint32_t offSrcStart     = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;
    23792306        Assert(cbSrcLine <= pSrcDesc->pitch);
    2380         uint32_t cbSrcSkip = pSrcDesc->pitch;
    2381         const uint8_t * pvSrcStart = pvSrcSurf + offSrcStart;
     2307        uint32_t cbSrcSkip       = pSrcDesc->pitch;
     2308        const uint8_t *pbSrcStart = pbSrcSurf + offSrcStart;
    23822309
    23832310        Assert(cbDstLine == cbSrcLine);
     
    23852312        for (uint32_t i = 0; ; ++i)
    23862313        {
    2387             memcpy (pvDstStart, pvSrcStart, cbDstLine);
     2314            if (   cbDstLine <= cbVRamSize
     2315                && (uintptr_t)pbSrcStart - (uintptr_t)pbRam <= cbVRamSize - cbDstLine
     2316                && (uintptr_t)pbSrcStart - (uintptr_t)pbRam <= cbVRamSize - cbDstLine)
     2317                memcpy(pbDstStart, pbSrcStart, cbDstLine);
     2318            else
     2319                return VERR_INVALID_PARAMETER;
    23882320            if (i == pDstRectl->height)
    23892321                break;
    2390             pvDstStart += cbDstSkip;
    2391             pvSrcStart += cbSrcSkip;
     2322            pbDstStart += cbDstSkip;
     2323            pbSrcStart += cbSrcSkip;
    23922324        }
    23932325    }
     
    23952327}
    23962328
     2329#if 0 /* unused */
    23972330static void vboxVDMARectlUnite(VBOXVDMA_RECTL * pRectl1, const VBOXVDMA_RECTL * pRectl2)
    23982331{
     
    24222355    }
    24232356}
    2424 
    2425 /*
    2426  * @return on success the number of bytes the command contained, otherwise - VERR_xxx error code
     2357#endif /* unused */
     2358
     2359/**
     2360 * Handles VBOXVDMACMD_TYPE_DMA_PRESENT_BLT for vboxVDMACmdExec().
     2361 *
     2362 * @returns number of bytes (positive) of the full command on success,
     2363 *          otherwise a negative error status (VERR_XXX).
     2364 *
     2365 * @param   pVdma           The VDMA channel.
     2366 * @param   pBlt            Blit command buffer.  This is to be considered
     2367 *                          volatile!
     2368 * @param   cbBuffer        Number of bytes accessible at @a pBtl.
    24272369 */
    24282370static int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer)
    24292371{
    2430     const uint32_t cbBlt = VBOXVDMACMD_BODY_FIELD_OFFSET(uint32_t, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[pBlt->cDstSubRects]);
    2431     Assert(cbBlt <= cbBuffer);
    2432     if (cbBuffer < cbBlt)
    2433         return VERR_INVALID_FUNCTION;
    2434 
    2435     /* we do not support stretching for now */
    2436     Assert(pBlt->srcRectl.width == pBlt->dstRectl.width);
    2437     Assert(pBlt->srcRectl.height == pBlt->dstRectl.height);
    2438     if (pBlt->srcRectl.width != pBlt->dstRectl.width)
    2439         return VERR_INVALID_FUNCTION;
    2440     if (pBlt->srcRectl.height != pBlt->dstRectl.height)
    2441         return VERR_INVALID_FUNCTION;
    2442     Assert(pBlt->cDstSubRects);
    2443 
    2444     VBOXVDMA_RECTL updateRectl = {0, 0, 0, 0};
    2445 
    2446     if (pBlt->cDstSubRects)
    2447     {
    2448         for (uint32_t i = 0; i < pBlt->cDstSubRects; ++i)
     2372    /*
     2373     * Validate and make a local copy of the blt command up to the rectangle array.
     2374     */
     2375    AssertReturn(cbBuffer >= RT_UOFFSETOF(VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects), VERR_INVALID_PARAMETER);
     2376    VBOXVDMACMD_DMA_PRESENT_BLT BltSafe;
     2377    memcpy(&BltSafe, pBlt, RT_UOFFSETOF(VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects));
     2378
     2379    AssertReturn(BltSafe.cDstSubRects < _8M, VERR_INVALID_PARAMETER);
     2380    uint32_t const cbBlt = RT_UOFFSETOF(VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[BltSafe.cDstSubRects]);
     2381    AssertReturn(cbBuffer >= cbBlt, VERR_INVALID_PARAMETER);
     2382
     2383
     2384    /*
     2385     * We do not support stretching.
     2386     */
     2387    AssertReturn(BltSafe.srcRectl.width  == BltSafe.dstRectl.width,  VERR_INVALID_FUNCTION);
     2388    AssertReturn(BltSafe.srcRectl.height == BltSafe.dstRectl.height, VERR_INVALID_FUNCTION);
     2389
     2390    Assert(BltSafe.cDstSubRects);
     2391
     2392    //VBOXVDMA_RECTL updateRectl = {0, 0, 0, 0}; - pointless
     2393
     2394    if (BltSafe.cDstSubRects)
     2395    {
     2396        for (uint32_t i = 0; i < BltSafe.cDstSubRects; ++i)
    24492397        {
    24502398            VBOXVDMA_RECTL dstSubRectl = pBlt->aDstSubRects[i];
    24512399            VBOXVDMA_RECTL srcSubRectl = dstSubRectl;
    24522400
    2453             dstSubRectl.left += pBlt->dstRectl.left;
    2454             dstSubRectl.top  += pBlt->dstRectl.top;
    2455 
    2456             srcSubRectl.left += pBlt->srcRectl.left;
    2457             srcSubRectl.top  += pBlt->srcRectl.top;
    2458 
    2459             int rc = vboxVDMACmdExecBltPerform(pVdma, pBlt->offDst, pBlt->offSrc,
    2460                     &pBlt->dstDesc, &pBlt->srcDesc,
    2461                     &dstSubRectl,
    2462                     &srcSubRectl);
    2463             AssertRC(rc);
    2464             if (!RT_SUCCESS(rc))
    2465                 return rc;
    2466 
    2467             vboxVDMARectlUnite(&updateRectl, &dstSubRectl);
     2401            dstSubRectl.left += BltSafe.dstRectl.left;
     2402            dstSubRectl.top  += BltSafe.dstRectl.top;
     2403
     2404            srcSubRectl.left += BltSafe.srcRectl.left;
     2405            srcSubRectl.top  += BltSafe.srcRectl.top;
     2406
     2407            int rc = vboxVDMACmdExecBltPerform(pVdma, BltSafe.offDst, BltSafe.offSrc, &BltSafe.dstDesc, &BltSafe.srcDesc,
     2408                                               &dstSubRectl, &srcSubRectl);
     2409            AssertRCReturn(rc, rc);
     2410
     2411            //vboxVDMARectlUnite(&updateRectl, &dstSubRectl); - pointless
    24682412        }
    24692413    }
    24702414    else
    24712415    {
    2472         int rc = vboxVDMACmdExecBltPerform(pVdma, pBlt->offDst, pBlt->offSrc,
    2473                 &pBlt->dstDesc, &pBlt->srcDesc,
    2474                 &pBlt->dstRectl,
    2475                 &pBlt->srcRectl);
    2476         AssertRC(rc);
    2477         if (!RT_SUCCESS(rc))
    2478             return rc;
    2479 
    2480         vboxVDMARectlUnite(&updateRectl, &pBlt->dstRectl);
     2416        int rc = vboxVDMACmdExecBltPerform(pVdma, BltSafe.offDst, BltSafe.offSrc, &BltSafe.dstDesc, &BltSafe.srcDesc,
     2417                                           &BltSafe.dstRectl, &BltSafe.srcRectl);
     2418        AssertRCReturn(rc, rc);
     2419
     2420        //vboxVDMARectlUnite(&updateRectl, &BltSafe.dstRectl); - pointless
    24812421    }
    24822422
     
    24842424}
    24852425
    2486 static int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer, uint32_t cbBuffer)
    2487 {
    2488     if (cbBuffer < sizeof (*pTransfer))
    2489         return VERR_INVALID_PARAMETER;
    2490 
    2491     PVGASTATE pVGAState = pVdma->pVGAState;
    2492     uint8_t * pvRam = pVGAState->vram_ptrR3;
    2493     PGMPAGEMAPLOCK SrcLock;
    2494     PGMPAGEMAPLOCK DstLock;
    2495     PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
    2496     const void * pvSrc;
    2497     void * pvDst;
    2498     int rc = VINF_SUCCESS;
    2499     uint32_t cbTransfer = pTransfer->cbTransferSize;
    2500     uint32_t cbTransfered = 0;
    2501     bool bSrcLocked = false;
    2502     bool bDstLocked = false;
     2426
     2427/**
     2428 * Handles VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER for vboxVDMACmdCheckCrCmd() and
     2429 * vboxVDMACmdExec().
     2430 *
     2431 * @returns number of bytes (positive) of the full command on success,
     2432 *          otherwise a negative error status (VERR_XXX).
     2433 *
     2434 * @param   pVdma           The VDMA channel.
     2435 * @param   pTransfer       Transfer command buffer.  This is to be considered
     2436 *                          volatile!
     2437 * @param   cbBuffer        Number of bytes accessible at @a pTransfer.
     2438 */
     2439static int vboxVDMACmdExecBpbTransfer(PVBOXVDMAHOST pVdma, const VBOXVDMACMD_DMA_BPB_TRANSFER *pTransfer, uint32_t cbBuffer)
     2440{
     2441    /*
     2442     * Make a copy of the command (it's volatile).
     2443     */
     2444    AssertReturn(cbBuffer >= sizeof(*pTransfer), VERR_INVALID_PARAMETER);
     2445    VBOXVDMACMD_DMA_BPB_TRANSFER const TransferSafeCopy = *pTransfer;
     2446    pTransfer = &TransferSafeCopy;
     2447
     2448    PVGASTATE   pVGAState    = pVdma->pVGAState;
     2449    PPDMDEVINS  pDevIns      = pVGAState->pDevInsR3;
     2450    uint8_t    *pbRam        = pVGAState->vram_ptrR3;
     2451    uint32_t    cbTransfer   = TransferSafeCopy.cbTransferSize;
     2452
     2453    /*
     2454     * Validate VRAM offset.
     2455     */
     2456    if (TransferSafeCopy.fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET)
     2457        AssertReturn(   cbTransfer <= pVGAState->vram_size
     2458                     && TransferSafeCopy.Src.offVramBuf <= pVGAState->vram_size - cbTransfer,
     2459                     VERR_INVALID_PARAMETER);
     2460
     2461    if (TransferSafeCopy.fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET)
     2462        AssertReturn(   cbTransfer <= pVGAState->vram_size
     2463                     && TransferSafeCopy.Dst.offVramBuf <= pVGAState->vram_size - cbTransfer,
     2464                     VERR_INVALID_PARAMETER);
     2465
     2466    /*
     2467     * Transfer loop.
     2468     */
     2469    uint32_t    cbTransfered = 0;
     2470    int         rc           = VINF_SUCCESS;
    25032471    do
    25042472    {
    25052473        uint32_t cbSubTransfer = cbTransfer;
    2506         if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET)
    2507         {
    2508             pvSrc  = pvRam + pTransfer->Src.offVramBuf + cbTransfered;
    2509         }
     2474
     2475        const void     *pvSrc;
     2476        bool            fSrcLocked = false;
     2477        PGMPAGEMAPLOCK  SrcLock;
     2478        if (TransferSafeCopy.fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET)
     2479            pvSrc = pbRam + TransferSafeCopy.Src.offVramBuf + cbTransfered;
    25102480        else
    25112481        {
    2512             RTGCPHYS phPage = pTransfer->Src.phBuf;
    2513             phPage += cbTransfered;
    2514             rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvSrc, &SrcLock);
     2482            RTGCPHYS GCPhysSrcPage = TransferSafeCopy.Src.phBuf + cbTransfered;
     2483            rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysSrcPage, 0, &pvSrc, &SrcLock);
    25152484            AssertRC(rc);
    25162485            if (RT_SUCCESS(rc))
    25172486            {
    2518                 bSrcLocked = true;
    2519                 cbSubTransfer = RT_MIN(cbSubTransfer, 0x1000);
     2487                fSrcLocked = true;
     2488                cbSubTransfer = RT_MIN(cbSubTransfer, X86_PAGE_SIZE - (uint32_t)(GCPhysSrcPage & X86_PAGE_OFFSET_MASK));
    25202489            }
    25212490            else
    2522             {
    25232491                break;
    2524             }
    2525         }
    2526 
    2527         if (pTransfer->fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET)
    2528         {
    2529             pvDst  = pvRam + pTransfer->Dst.offVramBuf + cbTransfered;
    2530         }
     2492        }
     2493
     2494        void           *pvDst;
     2495        PGMPAGEMAPLOCK  DstLock;
     2496        bool            fDstLocked = false;
     2497        if (TransferSafeCopy.fFlags & VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET)
     2498            pvDst = pbRam + TransferSafeCopy.Dst.offVramBuf + cbTransfered;
    25312499        else
    25322500        {
    2533             RTGCPHYS phPage = pTransfer->Dst.phBuf;
    2534             phPage += cbTransfered;
    2535             rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, phPage, 0, &pvDst, &DstLock);
     2501            RTGCPHYS GCPhysDstPage = TransferSafeCopy.Dst.phBuf + cbTransfered;
     2502            rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysDstPage, 0, &pvDst, &DstLock);
    25362503            AssertRC(rc);
    25372504            if (RT_SUCCESS(rc))
    25382505            {
    2539                 bDstLocked = true;
    2540                 cbSubTransfer = RT_MIN(cbSubTransfer, 0x1000);
    2541             }
    2542             else
    2543             {
    2544                 break;
     2506                fDstLocked = true;
     2507                cbSubTransfer = RT_MIN(cbSubTransfer, X86_PAGE_SIZE - (uint32_t)(GCPhysDstPage & X86_PAGE_OFFSET_MASK));
    25452508            }
    25462509        }
     
    25492512        {
    25502513            memcpy(pvDst, pvSrc, cbSubTransfer);
    2551             cbTransfer -= cbSubTransfer;
    25522514            cbTransfered += cbSubTransfer;
     2515            cbTransfer   -= cbSubTransfer;
    25532516        }
    25542517        else
    2555         {
    2556             cbTransfer = 0; /* to break */
    2557         }
    2558 
    2559         if (bSrcLocked)
     2518            cbTransfer = 0; /* force break below */
     2519
     2520        if (fSrcLocked)
    25602521            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &SrcLock);
    2561         if (bDstLocked)
     2522        if (fDstLocked)
    25622523            PDMDevHlpPhysReleasePageMappingLock(pDevIns, &DstLock);
    25632524    } while (cbTransfer);
    25642525
    25652526    if (RT_SUCCESS(rc))
    2566         return sizeof (*pTransfer);
     2527        return sizeof(TransferSafeCopy);
    25672528    return rc;
    25682529}
    25692530
    2570 static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pvBuffer, uint32_t cbBuffer)
    2571 {
    2572     do
    2573     {
    2574         Assert(pvBuffer);
    2575         Assert(cbBuffer >= VBOXVDMACMD_HEADER_SIZE());
    2576 
    2577         if (!pvBuffer)
    2578             return VERR_INVALID_PARAMETER;
    2579         if (cbBuffer < VBOXVDMACMD_HEADER_SIZE())
    2580             return VERR_INVALID_PARAMETER;
    2581 
    2582         PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pvBuffer;
    2583         switch (pCmd->enmType)
     2531/**
     2532 * Worker for vboxVDMACommandProcess().
     2533 *
     2534 * @param   pVdma       Tthe VDMA channel.
     2535 * @param   pbBuffer    Command buffer, considered volatile.
     2536 * @param   cbBuffer    The number of bytes at @a pbBuffer.
     2537 */
     2538static int vboxVDMACmdExec(PVBOXVDMAHOST pVdma, const uint8_t *pbBuffer, uint32_t cbBuffer)
     2539{
     2540    AssertReturn(pbBuffer, VERR_INVALID_POINTER);
     2541
     2542    for (;;)
     2543    {
     2544        AssertReturn(cbBuffer >= VBOXVDMACMD_HEADER_SIZE(), VERR_INVALID_PARAMETER);
     2545
     2546        VBOXVDMACMD const  *pCmd       = (VBOXVDMACMD const *)pbBuffer;
     2547        VBOXVDMACMD_TYPE    enmCmdType = pCmd->enmType;
     2548        int                 cbProcessed;
     2549        switch (enmCmdType)
    25842550        {
    25852551            case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
     
    26032569                return VINF_SUCCESS;
    26042570            }
     2571
    26052572            case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
    26062573            {
    26072574                const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
    2608                 int cbBlt = vboxVDMACmdExecBlt(pVdma, pBlt, cbBuffer);
    2609                 Assert(cbBlt >= 0);
    2610                 Assert((uint32_t)cbBlt <= cbBuffer);
    2611                 if (cbBlt >= 0)
    2612                 {
    2613                     if ((uint32_t)cbBlt == cbBuffer)
    2614                         return VINF_SUCCESS;
    2615                     else
    2616                     {
    2617                         cbBuffer -= (uint32_t)cbBlt;
    2618                         pvBuffer -= cbBlt;
    2619                     }
    2620                 }
    2621                 else
    2622                     return cbBlt; /* error */
     2575                cbProcessed = vboxVDMACmdExecBlt(pVdma, pBlt, cbBuffer - VBOXVDMACMD_HEADER_SIZE());
     2576                Assert(cbProcessed >= 0);
    26232577                break;
    26242578            }
     2579
    26252580            case VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER:
    26262581            {
    26272582                const PVBOXVDMACMD_DMA_BPB_TRANSFER pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER);
    2628                 int cbTransfer = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, cbBuffer);
    2629                 Assert(cbTransfer >= 0);
    2630                 Assert((uint32_t)cbTransfer <= cbBuffer);
    2631                 if (cbTransfer >= 0)
    2632                 {
    2633                     if ((uint32_t)cbTransfer == cbBuffer)
    2634                         return VINF_SUCCESS;
    2635                     else
    2636                     {
    2637                         cbBuffer -= (uint32_t)cbTransfer;
    2638                         pvBuffer -= cbTransfer;
    2639                     }
    2640                 }
    2641                 else
    2642                     return cbTransfer; /* error */
     2583                cbProcessed = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, cbBuffer - VBOXVDMACMD_HEADER_SIZE());
     2584                Assert(cbProcessed >= 0);
    26432585                break;
    26442586            }
     2587
    26452588            case VBOXVDMACMD_TYPE_DMA_NOP:
    26462589                return VINF_SUCCESS;
     2590
    26472591            case VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ:
    26482592                return VINF_SUCCESS;
     2593
    26492594            default:
    2650                 AssertBreakpoint();
    2651                 return VERR_INVALID_FUNCTION;
    2652         }
    2653     } while (1);
    2654 
    2655     /* we should not be here */
    2656     AssertBreakpoint();
    2657     return VERR_INVALID_STATE;
    2658 }
    2659 
     2595                AssertFailedReturn(VERR_INVALID_FUNCTION);
     2596        }
     2597
     2598        /* Advance buffer or return. */
     2599        if (cbProcessed >= 0)
     2600        {
     2601            Assert(cbProcessed > 0);
     2602            cbProcessed += VBOXVDMACMD_HEADER_SIZE();
     2603            if ((uint32_t)cbProcessed >= cbBuffer)
     2604            {
     2605                Assert((uint32_t)cbProcessed == cbBuffer);
     2606                return VINF_SUCCESS;
     2607            }
     2608
     2609            cbBuffer -= cbProcessed;
     2610            pbBuffer += cbProcessed;
     2611        }
     2612        else
     2613            return cbProcessed; /* error status */
     2614
     2615    }
     2616}
     2617
     2618/**
     2619 * VDMA worker thread procedure, see vdmaVBVACtlEnableSubmitInternal().
     2620 *
     2621 * @thread VDMA
     2622 */
    26602623static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD hThreadSelf, void *pvUser)
    26612624{
    26622625    RT_NOREF(hThreadSelf);
    2663     PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvUser;
    2664     PVGASTATE pVGAState = pVdma->pVGAState;
    2665     VBVAEXHOSTCONTEXT *pCmdVbva = &pVdma->CmdVbva;
    2666     uint8_t *pCmd;
    2667     uint32_t cbCmd;
     2626    PVBOXVDMAHOST       pVdma     = (PVBOXVDMAHOST)pvUser;
     2627    PVGASTATE           pVGAState = pVdma->pVGAState;
     2628    VBVAEXHOSTCONTEXT  *pCmdVbva  = &pVdma->CmdVbva;
    26682629    int rc;
    26692630
     
    26722633    while (!VBoxVDMAThreadIsTerminating(&pVdma->Thread))
    26732634    {
    2674         VBVAEXHOST_DATA_TYPE enmType = VBoxVBVAExHPDataGet(pCmdVbva, &pCmd, &cbCmd);
     2635        uint8_t             *pbCmd   = NULL;
     2636        uint32_t             cbCmd   = 0;
     2637        VBVAEXHOST_DATA_TYPE enmType = VBoxVBVAExHPDataGet(pCmdVbva, &pbCmd, &cbCmd);
    26752638        switch (enmType)
    26762639        {
    26772640            case VBVAEXHOST_DATA_TYPE_CMD:
    2678                 vboxVDMACrCmdProcess(pVdma, pCmd, cbCmd);
     2641                vboxVDMACrCmdProcess(pVdma, pbCmd, cbCmd);
    26792642                VBoxVBVAExHPDataCompleteCmd(pCmdVbva, cbCmd);
    26802643                VBVARaiseIrq(pVGAState, 0);
    26812644                break;
     2645
    26822646            case VBVAEXHOST_DATA_TYPE_GUESTCTL:
    2683                 rc = vboxVDMACrGuestCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd);
    2684                 VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc);
     2647                rc = vboxVDMACrGuestCtlProcess(pVdma, (VBVAEXHOSTCTL *)pbCmd);
     2648                VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL *)pbCmd, rc);
    26852649                break;
     2650
    26862651            case VBVAEXHOST_DATA_TYPE_HOSTCTL:
    26872652            {
    26882653                bool fContinue = true;
    2689                 rc = vboxVDMACrHostCtlProcess(pVdma, (VBVAEXHOSTCTL*)pCmd, &fContinue);
    2690                 VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL*)pCmd, rc);
     2654                rc = vboxVDMACrHostCtlProcess(pVdma, (VBVAEXHOSTCTL *)pbCmd, &fContinue);
     2655                VBoxVBVAExHPDataCompleteCtl(pCmdVbva, (VBVAEXHOSTCTL *)pbCmd, rc);
    26912656                if (fContinue)
    26922657                    break;
     
    26972662                AssertRC(rc);
    26982663                break;
     2664
    26992665            default:
    27002666                WARN(("unexpected type %d\n", enmType));
     
    27082674}
    27092675
     2676/**
     2677 * Worker for vboxVDMACommand.
     2678 *
     2679 * @param   pCmd        The command to process.  Consider content volatile.
     2680 * @param   cbCmd       Number of valid bytes at @a pCmd.  This is at least
     2681 *                      sizeof(VBOXVDMACBUF_DR).
     2682 */
    27102683static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd)
    27112684{
    2712     RT_NOREF(cbCmd);
    27132685    PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi;
    2714     const uint8_t * pvBuf;
    2715     PGMPAGEMAPLOCK Lock;
    27162686    int rc;
    2717     bool bReleaseLocked = false;
    2718 
    2719     do
    2720     {
    2721         PPDMDEVINS pDevIns = pVdma->pVGAState->pDevInsR3;
    2722 
     2687
     2688    do /* break loop */
     2689    {
     2690        /*
     2691         * Get the command buffer (volatile).
     2692         */
     2693        uint16_t const  cbCmdBuf = pCmd->cbBuf;
     2694        const uint8_t  *pbCmdBuf;
     2695        PGMPAGEMAPLOCK  Lock;
     2696        bool            bReleaseLocked = false;
    27232697        if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR)
    2724             pvBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t);
     2698        {
     2699            pbCmdBuf = VBOXVDMACBUF_DR_TAIL(pCmd, const uint8_t);
     2700            rc = VINF_SUCCESS;
     2701            AssertBreakStmt((uintptr_t)&pbCmdBuf[cbCmdBuf] <= (uintptr_t)&((uint8_t *)pCmd)[cbCmd],
     2702                            rc = VERR_INVALID_PARAMETER);
     2703        }
    27252704        else if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET)
    27262705        {
    2727             uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;
    2728             pvBuf = pvRam + pCmd->Location.offVramBuf;
     2706            uint64_t offVRam = pCmd->Location.offVramBuf;
     2707            pbCmdBuf = (uint8_t const *)pVdma->pVGAState->vram_ptrR3 + offVRam;
     2708            rc = VINF_SUCCESS;
     2709            AssertBreakStmt(   offVRam <= pVdma->pVGAState->vram_size
     2710                            && offVRam + cbCmdBuf <= pVdma->pVGAState->vram_size,
     2711                            rc = VERR_INVALID_PARAMETER);
    27292712        }
    27302713        else
    27312714        {
    2732             RTGCPHYS phPage = pCmd->Location.phBuf & ~0xfffULL;
    2733             uint32_t offset = pCmd->Location.phBuf & 0xfff;
    2734             Assert(offset + pCmd->cbBuf <= 0x1000);
    2735             if (offset + pCmd->cbBuf > 0x1000)
    2736             {
    2737                 /** @todo more advanced mechanism of command buffer proc is actually needed */
    2738                 rc = VERR_INVALID_PARAMETER;
    2739                 break;
    2740             }
    2741 
    2742             const void * pvPageBuf;
    2743             rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, phPage, 0, &pvPageBuf, &Lock);
    2744             AssertRC(rc);
    2745             if (!RT_SUCCESS(rc))
    2746             {
    2747                 /** @todo if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */
    2748                 break;
    2749             }
    2750 
    2751             pvBuf = (const uint8_t *)pvPageBuf;
    2752             pvBuf += offset;
    2753 
     2715            /* Make sure it doesn't cross a page. */
     2716            RTGCPHYS GCPhysBuf = pCmd->Location.phBuf;
     2717            AssertBreakStmt((uint32_t)(GCPhysBuf & X86_PAGE_OFFSET_MASK) + cbCmdBuf <= (uint32_t)X86_PAGE_SIZE,
     2718                            rc = VERR_INVALID_PARAMETER);
     2719
     2720            rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pVdma->pVGAState->pDevInsR3, GCPhysBuf, 0 /*fFlags*/,
     2721                                                   (const void **)&pbCmdBuf, &Lock);
     2722            AssertRCBreak(rc); /* if (rc == VERR_PGM_PHYS_PAGE_RESERVED) -> fall back on using PGMPhysRead ?? */
    27542723            bReleaseLocked = true;
    27552724        }
    27562725
    2757         rc = vboxVDMACmdExec(pVdma, pvBuf, pCmd->cbBuf);
     2726        /*
     2727         * Process the command.
     2728         */
     2729        rc = vboxVDMACmdExec(pVdma, pbCmdBuf, cbCmdBuf);
    27582730        AssertRC(rc);
    27592731
     2732        /* Clean up comand buffer. */
    27602733        if (bReleaseLocked)
    2761             PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);
     2734            PDMDevHlpPhysReleasePageMappingLock(pVdma->pVGAState->pDevInsR3, &Lock);
     2735
    27622736    } while (0);
    27632737
     2738    /*
     2739     * Complete the command.
     2740     */
    27642741    pCmd->rc = rc;
    2765 
    2766     rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd);
     2742    rc = VBoxSHGSMICommandComplete(pHgsmi, pCmd);
    27672743    AssertRC(rc);
    27682744}
     
    27812757#ifdef VBOX_VDMA_WITH_WATCHDOG
    27822758
     2759/**
     2760 * @callback_method_impl{TMTIMER, VDMA watchdog timer.}
     2761 */
    27832762static DECLCALLBACK(void) vboxVDMAWatchDogTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    27842763{
     
    27882767}
    27892768
     2769/**
     2770 * Handles VBOXVDMA_CTL_TYPE_WATCHDOG for vboxVDMAControl.
     2771 */
    27902772static int vboxVDMAWatchDogCtl(struct VBOXVDMAHOST *pVdma, uint32_t cMillis)
    27912773{
     
    28002782#endif /* VBOX_VDMA_WITH_WATCHDOG */
    28012783
     2784/**
     2785 * Called by vgaR3Construct() to initialize the state.
     2786 *
     2787 * @returns VBox status code.
     2788 */
    28022789int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements)
    28032790{
     
    28082795    if (pVdma)
    28092796    {
    2810         pVdma->pHgsmi = pVGAState->pHGSMI;
     2797        pVdma->pHgsmi    = pVGAState->pHGSMI;
    28112798        pVdma->pVGAState = pVGAState;
    28122799
    28132800#ifdef VBOX_VDMA_WITH_WATCHDOG
    28142801        rc = PDMDevHlpTMTimerCreate(pVGAState->pDevInsR3, TMCLOCK_REAL, vboxVDMAWatchDogTimer,
    2815                                         pVdma, TMTIMER_FLAGS_NO_CRIT_SECT,
    2816                                         "VDMA WatchDog Timer", &pVdma->WatchDogTimer);
     2802                                    pVdma, TMTIMER_FLAGS_NO_CRIT_SECT,
     2803                                    "VDMA WatchDog Timer", &pVdma->WatchDogTimer);
    28172804        AssertRC(rc);
     2805#else
     2806        rc = VINF_SUCCESS;
    28182807#endif
    2819 
     2808        if (RT_SUCCESS(rc))
     2809        {
    28202810#ifdef VBOX_WITH_CRHGSMI
    2821         VBoxVDMAThreadInit(&pVdma->Thread);
    2822 
    2823         rc = RTSemEventMultiCreate(&pVdma->HostCrCtlCompleteEvent);
    2824         if (RT_SUCCESS(rc))
    2825         {
    2826             rc = VBoxVBVAExHSInit(&pVdma->CmdVbva);
     2811            VBoxVDMAThreadInit(&pVdma->Thread);
     2812
     2813            rc = RTSemEventMultiCreate(&pVdma->HostCrCtlCompleteEvent);
    28272814            if (RT_SUCCESS(rc))
    28282815            {
    2829                 rc = RTCritSectInit(&pVdma->CalloutCritSect);
     2816                rc = VBoxVBVAExHSInit(&pVdma->CmdVbva);
    28302817                if (RT_SUCCESS(rc))
    28312818                {
    2832                     pVGAState->pVdma = pVdma;
    2833 
    2834                     /* No HGCM service if VMSVGA is enabled. */
    2835                     if (!pVGAState->fVMSVGAEnabled)
     2819                    rc = RTCritSectInit(&pVdma->CalloutCritSect);
     2820                    if (RT_SUCCESS(rc))
    28362821                    {
    2837                         int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
     2822#endif
     2823                        pVGAState->pVdma = pVdma;
     2824
     2825                        /* No HGCM service if VMSVGA is enabled. */
     2826                        if (!pVGAState->fVMSVGAEnabled)
     2827                        {
     2828                            int rcIgnored = vboxVDMACrCtlHgsmiSetup(pVdma); NOREF(rcIgnored); /** @todo is this ignoring intentional? */
     2829                        }
     2830                        return VINF_SUCCESS;
     2831
     2832#ifdef VBOX_WITH_CRHGSMI
    28382833                    }
    2839                     return VINF_SUCCESS;
     2834
     2835                    WARN(("RTCritSectInit failed %d\n", rc));
     2836                    VBoxVBVAExHSTerm(&pVdma->CmdVbva);
    28402837                }
    2841                 WARN(("RTCritSectInit failed %d\n", rc));
    2842 
    2843                 VBoxVBVAExHSTerm(&pVdma->CmdVbva);
     2838                else
     2839                    WARN(("VBoxVBVAExHSInit failed %d\n", rc));
     2840                RTSemEventMultiDestroy(pVdma->HostCrCtlCompleteEvent);
    28442841            }
    28452842            else
    2846                 WARN(("VBoxVBVAExHSInit failed %d\n", rc));
    2847 
    2848             RTSemEventMultiDestroy(pVdma->HostCrCtlCompleteEvent);
    2849         }
    2850         else
    2851             WARN(("RTSemEventMultiCreate failed %d\n", rc));
    2852 
    2853 
     2843                WARN(("RTSemEventMultiCreate failed %d\n", rc));
     2844#endif
     2845            /* the timer is cleaned up automatically */
     2846        }
    28542847        RTMemFree(pVdma);
    2855 #else
    2856         pVGAState->pVdma = pVdma;
    2857         return VINF_SUCCESS;
    2858 #endif
    28592848    }
    28602849    else
    28612850        rc = VERR_OUT_OF_RESOURCES;
    2862 
    28632851    return rc;
    28642852}
    28652853
    2866 int vboxVDMAReset(struct VBOXVDMAHOST *pVdma)
     2854/**
     2855 * Called by vgaR3Reset() to do reset.
     2856 */
     2857void  vboxVDMAReset(struct VBOXVDMAHOST *pVdma)
    28672858{
    28682859#ifdef VBOX_WITH_CRHGSMI
     
    28712862    RT_NOREF(pVdma);
    28722863#endif
    2873     return VINF_SUCCESS;
    2874 }
    2875 
    2876 int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma)
     2864}
     2865
     2866/**
     2867 * Called by vgaR3Destruct() to do cleanup..
     2868 */
     2869void vboxVDMADestruct(struct VBOXVDMAHOST *pVdma)
    28772870{
    28782871    if (!pVdma)
    2879         return VINF_SUCCESS;
     2872        return;
    28802873#ifdef VBOX_WITH_CRHGSMI
    28812874    if (pVdma->pVGAState->fVMSVGAEnabled)
     
    28942887#endif
    28952888    RTMemFree(pVdma);
    2896     return VINF_SUCCESS;
    2897 }
    2898 
     2889}
     2890
     2891/**
     2892 * Handle VBVA_VDMA_CTL, see vbvaChannelHandler
     2893 *
     2894 * @param   pVdma   The VDMA channel.
     2895 * @param   pCmd    The control command to handle.  Considered volatile.
     2896 * @param   cbCmd   The size of the command.  At least sizeof(VBOXVDMA_CTL).
     2897 */
    28992898void vboxVDMAControl(struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd, uint32_t cbCmd)
    29002899{
     
    29022901    PHGSMIINSTANCE pIns = pVdma->pHgsmi;
    29032902
    2904     switch (pCmd->enmCtl)
     2903    VBOXVDMA_CTL_TYPE enmCtl = pCmd->enmCtl;
     2904    switch (enmCtl)
    29052905    {
    29062906        case VBOXVDMA_CTL_TYPE_ENABLE:
     
    29212921            WARN(("cmd not supported"));
    29222922            pCmd->i32Result = VERR_NOT_SUPPORTED;
    2923     }
    2924 
    2925     int rc = VBoxSHGSMICommandComplete (pIns, pCmd);
     2923            break;
     2924    }
     2925
     2926    int rc = VBoxSHGSMICommandComplete(pIns, pCmd);
    29262927    AssertRC(rc);
    29272928}
    29282929
     2930/**
     2931 * Handle VBVA_VDMA_CMD, see vbvaChannelHandler().
     2932 *
     2933 * @param   pVdma   The VDMA channel.
     2934 * @param   pCmd    The command to handle.  Considered volatile.
     2935 * @param   cbCmd   The size of the command.  At least sizeof(VBOXVDMACBUF_DR).
     2936 */
    29292937void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd)
    29302938{
    2931     int rc = VERR_NOT_IMPLEMENTED;
    2932 
    29332939#ifdef VBOX_WITH_CRHGSMI
    29342940    /* chromium commands are processed by crhomium hgcm thread independently from our internal cmd processing pipeline
    29352941     * this is why we process them specially */
    2936     rc = vboxVDMACmdCheckCrCmd(pVdma, pCmd, cbCmd);
     2942    int rc = vboxVDMACmdCheckCrCmd(pVdma, pCmd, cbCmd);
    29372943    if (rc == VINF_SUCCESS)
    29382944        return;
     
    29412947    {
    29422948        pCmd->rc = rc;
    2943         rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmd);
     2949        rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd);
    29442950        AssertRC(rc);
    29452951        return;
     
    29472953
    29482954    vboxVDMACommandProcess(pVdma, pCmd, cbCmd);
     2955
    29492956#else
    29502957    RT_NOREF(cbCmd);
    2951     pCmd->rc = rc;
    2952     rc = VBoxSHGSMICommandComplete (pVdma->pHgsmi, pCmd);
     2958    pCmd->rc = VERR_NOT_IMPLEMENTED;
     2959    rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd);
    29532960    AssertRC(rc);
    29542961#endif
     
    29592966static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext);
    29602967
    2961 static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     2968static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource,
     2969                             PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
    29622970{
    29632971    int rc = VBoxVBVAExHCtlSubmit(&pVdma->CmdVbva, pCtl, enmSource, pfnComplete, pvComplete);
     
    29662974        if (rc == VINF_SUCCESS)
    29672975            return VBoxVDMAThreadEventNotify(&pVdma->Thread);
    2968         else
    2969             Assert(rc == VINF_ALREADY_INITIALIZED);
     2976        Assert(rc == VINF_ALREADY_INITIALIZED);
    29702977    }
    29712978    else
     
    29752982}
    29762983
    2977 static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext)
     2984/**
     2985 * @callback_method_impl{FNVBVAEXHOSTCTL_COMPLETE,
     2986 *      Used by vdmaVBVACtlEnableDisableSubmit() and vdmaVBVACtlEnableDisableSubmit() }
     2987 */
     2988static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl,
     2989                                                           int rc, void *pvContext)
    29782990{
    29792991    PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvContext;
     
    29893001}
    29903002
    2991 static int vdmaVBVACtlGenericSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, VBVAEXHOSTCTL_TYPE enmType, uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
    2992 {
    2993     VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, enmType);
     3003/**
     3004 * Worker for vdmaVBVACtlGenericGuestSubmit() and vdmaVBVACtlOpaqueHostSubmit().
     3005 */
     3006static int vdmaVBVACtlGenericSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_SOURCE enmSource, VBVAEXHOSTCTL_TYPE enmType,
     3007                                    uint8_t* pu8Cmd, uint32_t cbCmd, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     3008{
     3009    VBVAEXHOSTCTL *pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, enmType);
    29943010    if (!pHCtl)
    29953011    {
     
    30103026}
    30113027
     3028/**
     3029 * Handler for vboxCmdVBVACmdCtl()/VBOXCMDVBVACTL_TYPE_3DCTL.
     3030 */
    30123031static int vdmaVBVACtlGenericGuestSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_TYPE enmType, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
    30133032{
    30143033    Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL));
    30153034    VBoxSHGSMICommandMarkAsynchCompletion(pCtl);
    3016     int rc = vdmaVBVACtlGenericSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, enmType, (uint8_t*)(pCtl+1), cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma);
     3035    int rc = vdmaVBVACtlGenericSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_GUEST, enmType, (uint8_t*)(pCtl+1),
     3036                                      cbCtl - sizeof (VBOXCMDVBVA_CTL), vboxCmdVBVACmdCtlGuestCompletion, pVdma);
    30173037    if (RT_SUCCESS(rc))
    30183038        return VINF_SUCCESS;
     
    30253045}
    30263046
    3027 static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvCompletion)
     3047/**
     3048 * @callback_method_impl{FNVBVAEXHOSTCTL_COMPLETE, Used by vdmaVBVACtlOpaqueHostSubmit()}
     3049 */
     3050static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl,
     3051                                                          int rc, void *pvCompletion)
    30283052{
    30293053    VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd;
     
    30333057}
    30343058
     3059/**
     3060 * Worker for vboxCmdVBVACmdHostCtl() and vboxCmdVBVACmdHostCtlSync().
     3061 */
    30353062static int vdmaVBVACtlOpaqueHostSubmit(PVBOXVDMAHOST pVdma, struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
    3036         PFNCRCTLCOMPLETION pfnCompletion,
    3037         void *pvCompletion)
    3038 {
    3039     pCmd->u.pfnInternal = (void(*)())pfnCompletion;
    3040     int rc = vdmaVBVACtlGenericSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE, (uint8_t*)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion);
     3063                                       PFNCRCTLCOMPLETION pfnCompletion, void *pvCompletion)
     3064{
     3065    pCmd->u.pfnInternal = (PFNRT)pfnCompletion;
     3066    int rc = vdmaVBVACtlGenericSubmit(pVdma, VBVAEXHOSTCTL_SOURCE_HOST, VBVAEXHOSTCTL_TYPE_GHH_BE_OPAQUE,
     3067                                      (uint8_t *)pCmd, cbCmd, vboxCmdVBVACmdCtlHostCompletion, pvCompletion);
    30413068    if (RT_FAILURE(rc))
    30423069    {
     
    30583085}
    30593086
    3060 static DECLCALLBACK(int) vdmaVBVANotifyEnable(PVGASTATE pVGAState)
     3087/**
     3088 * Called from vdmaVBVACtlThreadCreatedEnable().
     3089 */
     3090static int vdmaVBVANotifyEnable(PVGASTATE pVGAState)
    30613091{
    30623092    for (uint32_t i = 0; i < pVGAState->cMonitors; i++)
     
    30773107}
    30783108
    3079 static DECLCALLBACK(int) vdmaVBVANotifyDisable(PVGASTATE pVGAState)
     3109/**
     3110 * Called from vdmaVBVACtlThreadCreatedEnable() and vdmaVBVADisableProcess().
     3111 */
     3112static int vdmaVBVANotifyDisable(PVGASTATE pVGAState)
    30803113{
    30813114    for (uint32_t i = 0; i < pVGAState->cMonitors; i++)
    3082     {
    3083         pVGAState->pDrv->pfnVBVADisable (pVGAState->pDrv, i);
    3084     }
     3115        pVGAState->pDrv->pfnVBVADisable(pVGAState->pDrv, i);
    30853116    return VINF_SUCCESS;
    30863117}
    30873118
     3119/**
     3120 * Hook that is called by vboxVDMAWorkerThread when it starts.
     3121 */
    30883122static DECLCALLBACK(void) vdmaVBVACtlThreadCreatedEnable(struct VBOXVDMATHREAD *pThread, int rc,
    30893123                                                         void *pvThreadContext, void *pvContext)
     
    31183152}
    31193153
     3154/**
     3155 * Worker for vdmaVBVACtlEnableDisableSubmitInternal() and vdmaVBVACtlEnableSubmitSync().
     3156 */
    31203157static int vdmaVBVACtlEnableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, bool fPaused, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
    31213158{
    31223159    int rc;
    3123     VBVAEXHOSTCTL* pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva, fPaused ? VBVAEXHOSTCTL_TYPE_GHH_ENABLE_PAUSED : VBVAEXHOSTCTL_TYPE_GHH_ENABLE);
     3160    VBVAEXHOSTCTL *pHCtl = VBoxVBVAExHCtlCreate(&pVdma->CmdVbva,
     3161                                                fPaused ? VBVAEXHOSTCTL_TYPE_GHH_ENABLE_PAUSED : VBVAEXHOSTCTL_TYPE_GHH_ENABLE);
    31243162    if (pHCtl)
    31253163    {
     
    31323170        if (RT_SUCCESS(rc))
    31333171            return VINF_SUCCESS;
    3134         else
    3135             WARN(("VBoxVDMAThreadCreate failed %d\n", rc));
     3172        WARN(("VBoxVDMAThreadCreate failed %d\n", rc));
    31363173
    31373174        VBoxVBVAExHCtlFree(&pVdma->CmdVbva, pHCtl);
     
    31463183}
    31473184
     3185/**
     3186 * Worker for vboxVDMASaveLoadExecPerform().
     3187 */
    31483188static int vdmaVBVACtlEnableSubmitSync(PVBOXVDMAHOST pVdma, uint32_t offVram, bool fPaused)
    31493189{
     
    31823222}
    31833223
    3184 static int vdmaVBVACtlDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     3224/**
     3225 * Worker for vdmaVBVACtlEnableDisableSubmitInternal().
     3226 */
     3227static int vdmaVBVACtlDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable,
     3228                                            PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
    31853229{
    31863230    int rc;
     
    32103254}
    32113255
    3212 static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
    3213 {
    3214     bool fEnable = ((pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE);
     3256/**
     3257 * Worker for vdmaVBVACtlEnableDisableSubmit().
     3258 */
     3259static int vdmaVBVACtlEnableDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable,
     3260                                                  PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete)
     3261{
     3262    bool fEnable = (pEnable->u32Flags & (VBVA_F_ENABLE | VBVA_F_DISABLE)) == VBVA_F_ENABLE;
    32153263    if (fEnable)
    32163264        return vdmaVBVACtlEnableSubmitInternal(pVdma, pEnable, false, pfnComplete, pvComplete);
     
    32183266}
    32193267
     3268/**
     3269 * Handler for vboxCmdVBVACmdCtl/VBOXCMDVBVACTL_TYPE_ENABLE.
     3270 */
    32203271static int vdmaVBVACtlEnableDisableSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable)
    32213272{
     
    32323283}
    32333284
     3285/**
     3286 * @callback_method_impl{FNVBVAEXHOSTCTL_COMPLETE,
     3287 *      Used by vdmaVBVACtlSubmitSync() and vdmaVBVACtlEnableSubmitSync().}
     3288 */
    32343289static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl,
    32353290                                                          int rc, void *pvContext)
    32363291{
    32373292    RT_NOREF(pVbva, pCtl);
    3238     VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION*)pvContext;
     3293    VDMA_VBVA_CTL_CYNC_COMPLETION *pData = (VDMA_VBVA_CTL_CYNC_COMPLETION *)pvContext;
    32393294    pData->rc = rc;
    32403295    rc = RTSemEventSignal(pData->hEvent);
     
    32433298}
    32443299
     3300
    32453301static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource)
    32463302{
     
    32753331}
    32763332
     3333/**
     3334 * Worker for vboxVDMASaveStateExecPrep().
     3335 */
    32773336static int vdmaVBVAPause(PVBOXVDMAHOST pVdma)
    32783337{
     
    32823341}
    32833342
     3343/**
     3344 * Worker for vboxVDMASaveLoadExecPerform() and vboxVDMASaveStateExecDone().
     3345 */
    32843346static int vdmaVBVAResume(PVBOXVDMAHOST pVdma)
    32853347{
     
    32893351}
    32903352
     3353/**
     3354 * Worker for vboxCmdVBVACmdSubmit(), vboxCmdVBVACmdFlush() and vboxCmdVBVATimerRefresh().
     3355 */
    32913356static int vboxVDMACmdSubmitPerform(struct VBOXVDMAHOST *pVdma)
    32923357{
     
    33073372
    33083373
     3374/**
     3375 * @interface_method_impl{PDMIDISPLAYVBVACALLBACKS,pfnCrCtlSubmit}
     3376 */
    33093377int vboxCmdVBVACmdHostCtl(PPDMIDISPLAYVBVACALLBACKS pInterface,
    3310                                                                struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd,
    3311                                                                PFNCRCTLCOMPLETION pfnCompletion,
    3312                                                                void *pvCompletion)
     3378                          struct VBOXCRCMDCTL *pCmd,
     3379                          uint32_t cbCmd,
     3380                          PFNCRCTLCOMPLETION pfnCompletion,
     3381                          void *pvCompletion)
    33133382{
    33143383    PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
     
    33203389}
    33213390
     3391/**
     3392 * Argument package from vboxCmdVBVACmdHostCtlSync to vboxCmdVBVACmdHostCtlSyncCb.
     3393 */
    33223394typedef struct VBOXCMDVBVA_CMDHOSTCTL_SYNC
    33233395{
     
    33273399} VBOXCMDVBVA_CMDHOSTCTL_SYNC;
    33283400
    3329 static DECLCALLBACK(void) vboxCmdVBVACmdHostCtlSyncCb(struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
     3401/**
     3402 * @interface_method_impl{FNCRCTLCOMPLETION, Used by vboxCmdVBVACmdHostCtlSync.}
     3403 */
     3404static DECLCALLBACK(void) vboxCmdVBVACmdHostCtlSyncCb(struct VBOXCRCMDCTL *pCmd, uint32_t cbCmd, int rc, void *pvCompletion)
    33303405{
    33313406    RT_NOREF(pCmd, cbCmd);
    3332     VBOXCMDVBVA_CMDHOSTCTL_SYNC *pData = (VBOXCMDVBVA_CMDHOSTCTL_SYNC*)pvCompletion;
     3407    VBOXCMDVBVA_CMDHOSTCTL_SYNC *pData = (VBOXCMDVBVA_CMDHOSTCTL_SYNC *)pvCompletion;
    33333408
    33343409    pData->rc = rc;
     
    33433418}
    33443419
    3345 static DECLCALLBACK(int) vboxCmdVBVACmdCallout(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd, VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry, PFNVBOXCRCMDCTL_CALLOUT_CB pfnCb)
     3420/**
     3421 * @callback_method_impl{FNVBOXCRCLIENT_CALLOUT, Worker for vboxVDMACrCtlHgsmiSetup }
     3422 *
     3423 * @note r=bird: not to be confused with the callout function below. sigh.
     3424 */
     3425static DECLCALLBACK(int) vboxCmdVBVACmdCallout(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd,
     3426                                               VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry, PFNVBOXCRCMDCTL_CALLOUT_CB pfnCb)
    33463427{
    33473428    pEntry->pfnCb = pfnCb;
     
    33613442
    33623443
     3444/**
     3445 * Worker for vboxCmdVBVACmdHostCtlSync.
     3446 */
    33633447static int vboxCmdVBVACmdCalloutProcess(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd)
    33643448{
     
    33893473}
    33903474
    3391 DECLCALLBACK(int) vboxCmdVBVACmdHostCtlSync(PPDMIDISPLAYVBVACALLBACKS pInterface,
    3392                                             struct VBOXCRCMDCTL* pCmd, uint32_t cbCmd)
    3393 {
    3394     PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
    3395     struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
     3475/**
     3476 * @interface_method_impl{PDMIDISPLAYVBVACALLBACKS,pfnCrCtlSubmitSync}
     3477 */
     3478DECLCALLBACK(int) vboxCmdVBVACmdHostCtlSync(PPDMIDISPLAYVBVACALLBACKS pInterface, struct VBOXCRCMDCTL *pCmd, uint32_t cbCmd)
     3479{
     3480    PVGASTATE               pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface);
     3481    struct VBOXVDMAHOST    *pVdma     = pVGAState->pVdma;
    33963482    if (pVdma == NULL)
    33973483        return VERR_INVALID_STATE;
     3484
    33983485    VBOXCMDVBVA_CMDHOSTCTL_SYNC Data;
    33993486    Data.pVdma = pVdma;
     
    34393526}
    34403527
     3528/**
     3529 * Handler for VBVA_CMDVBVA_CTL, see vbvaChannelHandler().
     3530 */
    34413531int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl)
    34423532{
    34433533    struct VBOXVDMAHOST *pVdma = pVGAState->pVdma;
    3444     int rc = VINF_SUCCESS;
    34453534    switch (pCtl->u32Type)
    34463535    {
     
    34503539            return vdmaVBVACtlGenericGuestSubmit(pVdma, VBVAEXHOSTCTL_TYPE_GHH_RESIZE, pCtl, cbCtl);
    34513540        case VBOXCMDVBVACTL_TYPE_ENABLE:
    3452             if (cbCtl != sizeof (VBOXCMDVBVA_CTL_ENABLE))
    3453             {
    3454                 WARN(("incorrect enable size\n"));
    3455                 rc = VERR_INVALID_PARAMETER;
    3456                 break;
    3457             }
    3458             return vdmaVBVACtlEnableDisableSubmit(pVdma, (VBOXCMDVBVA_CTL_ENABLE*)pCtl);
     3541            if (cbCtl == sizeof(VBOXCMDVBVA_CTL_ENABLE))
     3542                return vdmaVBVACtlEnableDisableSubmit(pVdma, (VBOXCMDVBVA_CTL_ENABLE *)pCtl);
     3543            WARN(("incorrect enable size\n"));
     3544            break;
    34593545        default:
    34603546            WARN(("unsupported type\n"));
    3461             rc = VERR_INVALID_PARAMETER;
    34623547            break;
    34633548    }
    34643549
    3465     pCtl->i32Result = rc;
    3466     rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);
     3550    pCtl->i32Result = VERR_INVALID_PARAMETER;
     3551    int rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);
    34673552    AssertRC(rc);
    34683553    return VINF_SUCCESS;
    34693554}
    34703555
     3556/**
     3557 * Handler for VBVA_CMDVBVA_SUBMIT, see vbvaChannelHandler().
     3558 */
    34713559int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState)
    34723560{
     
    34803568}
    34813569
     3570/**
     3571 * Handler for VBVA_CMDVBVA_FLUSH, see vbvaChannelHandler().
     3572 */
    34823573int vboxCmdVBVACmdFlush(PVGASTATE pVGAState)
    34833574{
     
    34913582}
    34923583
    3493 void vboxCmdVBVACmdTimer(PVGASTATE pVGAState)
     3584/**
     3585 * Called from vgaTimerRefresh().
     3586 */
     3587void vboxCmdVBVATimerRefresh(PVGASTATE pVGAState)
    34943588{
    34953589    if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva))
     
    35043598
    35053599#endif /* VBOX_WITH_CRHGSMI */
     3600
     3601
     3602/*
     3603 *
     3604 *
     3605 * Saved state.
     3606 * Saved state.
     3607 * Saved state.
     3608 *
     3609 *
     3610 */
    35063611
    35073612int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma)
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