Changeset 70596 in vbox for trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
- Timestamp:
- Jan 15, 2018 10:46:29 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/DevVGA_VDMA.cpp
r69884 r70596 136 136 struct VBVAEXHOSTCTL; 137 137 138 typedef DECLCALLBACKPTR(void, PFNVBVAEXHOSTCTL_COMPLETE)(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete); 138 typedef DECLCALLBACK(void) FNVBVAEXHOSTCTL_COMPLETE(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvComplete); 139 typedef FNVBVAEXHOSTCTL_COMPLETE *PFNVBVAEXHOSTCTL_COMPLETE; 139 140 140 141 typedef struct VBVAEXHOSTCTL … … 205 206 *********************************************************************************************************************************/ 206 207 #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); 208 static int vdmaVBVANotifyDisable(PVGASTATE pVGAState); 209 209 210 210 static void VBoxVBVAExHPDataCompleteCmd(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint32_t cbCmd); … … 383 383 } 384 384 385 /** 386 * Worker for vboxVBVAExHPDataGet. 387 * @thread VDMA 388 * @todo r=bird: revalidate this code. 389 */ 385 390 static int vboxVBVAExHPCmdGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 386 391 { … … 393 398 uint32_t indexRecordFree = pVBVA->indexRecordFree; 394 399 395 Log(("first = %d, free = %d\n", 396 indexRecordFirst, indexRecordFree)); 400 Log(("first = %d, free = %d\n", indexRecordFirst, indexRecordFree)); 397 401 398 402 if (indexRecordFirst == indexRecordFree) … … 458 462 459 463 464 /** 465 * Worker for VBoxVBVAExHPDataGet. 466 * @thread VDMA 467 */ 460 468 static VBVAEXHOST_DATA_TYPE vboxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 461 469 { … … 479 487 continue; 480 488 } 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; 487 492 } 488 493 … … 509 514 } 510 515 516 /** 517 * Called by vboxVDMAWorkerThread to get the next command to process. 518 * @thread VDMA 519 */ 511 520 static VBVAEXHOST_DATA_TYPE VBoxVBVAExHPDataGet(struct VBVAEXHOSTCONTEXT *pCmdVbva, uint8_t **ppCmd, uint32_t *pcbCmd) 512 521 { … … 516 525 vboxVBVAExHPHgEventClear(pCmdVbva); 517 526 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. 519 530 * 1. we check the queue -> and it is empty 520 531 * 2. submitter adds command to the queue … … 523 534 * 5. ->here we need to re-check the queue state to ensure we do not leak the notification of the above command 524 535 * 6. if the queue appears to be not-empty set the "processing" state back to "true" 525 * */536 */ 526 537 int rc = vboxVBVAExHSProcessorAcquire(pCmdVbva); 527 538 if (RT_SUCCESS(rc)) … … 809 820 810 821 811 static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 822 static int VBoxVBVAExHCtlSubmit(VBVAEXHOSTCONTEXT *pCmdVbva, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, 823 PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 812 824 { 813 825 if (!VBoxVBVAExHSIsEnabled(pCmdVbva)) … … 831 843 832 844 if (enmSource > VBVAEXHOSTCTL_SOURCE_GUEST) 833 {834 845 RTListAppend(&pCmdVbva->HostCtlList, &pCtl->Node); 835 }836 846 else 837 847 RTListAppend(&pCmdVbva->GuestCtlList, &pCtl->Node); … … 849 859 } 850 860 861 /** 862 * Call VDMA thread creation notification callback. 863 */ 851 864 void VBoxVDMAThreadNotifyConstructSucceeded(PVBOXVDMATHREAD pThread, void *pvThreadContext) 852 865 { … … 864 877 } 865 878 879 /** 880 * Call VDMA thread termination notification callback. 881 */ 866 882 void VBoxVDMAThreadNotifyTerminatingSucceeded(PVBOXVDMATHREAD pThread, void *pvThreadContext) 867 883 { … … 877 893 } 878 894 895 /** 896 * Check if VDMA thread is terminating. 897 */ 879 898 DECLINLINE(bool) VBoxVDMAThreadIsTerminating(PVBOXVDMATHREAD pThread) 880 899 { … … 882 901 } 883 902 903 /** 904 * Init VDMA thread. 905 */ 884 906 void VBoxVDMAThreadInit(PVBOXVDMATHREAD pThread) 885 907 { … … 888 910 } 889 911 912 /** 913 * Clean up VDMA thread. 914 */ 890 915 int VBoxVDMAThreadCleanup(PVBOXVDMATHREAD pThread) 891 916 { … … 915 940 } 916 941 917 int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread, PFNVBOXVDMATHREAD_CHANGED pfnCreated, void*pvCreated) 942 /** 943 * Start VDMA thread. 944 */ 945 int VBoxVDMAThreadCreate(PVBOXVDMATHREAD pThread, PFNRTTHREAD pfnThread, void *pvThread, 946 PFNVBOXVDMATHREAD_CHANGED pfnCreated, void *pvCreated) 918 947 { 919 948 int rc = VBoxVDMAThreadCleanup(pThread); … … 933 962 if (RT_SUCCESS(rc)) 934 963 return VINF_SUCCESS; 935 else 936 WARN(("RTThreadCreate failed %d\n", rc)); 964 WARN(("RTThreadCreate failed %d\n", rc)); 937 965 938 966 RTSemEventDestroy(pThread->hEvent); … … 1001 1029 } 1002 1030 1003 static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL *pCtl, VBVAEXHOSTCTL_SOURCE enmSource);1031 static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL *pCtl, VBVAEXHOSTCTL_SOURCE enmSource); 1004 1032 1005 1033 typedef DECLCALLBACK(void) FNVBOXVDMACRCTL_CALLBACK(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, void* pvContext); … … 1086 1114 } 1087 1115 1116 /** 1117 * Posts stuff and waits. 1118 */ 1088 1119 static int vboxVDMACrCtlPost(PVGASTATE pVGAState, PVBOXVDMACMD_CHROMIUM_CTL pCmd, uint32_t cbCmd) 1089 1120 { … … 1736 1767 } 1737 1768 1738 /** 1769 1770 /** 1771 * Copies one page in a VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER command. 1772 * 1739 1773 * @param fIn - whether this is a page in or out op. 1774 * @thread VDMA 1775 * 1740 1776 * the direction is VRA#M - related, so fIn == true - transfer to VRAM); false - transfer from VRAM 1741 1777 */ 1742 static int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, VBOXCMDVBVAPAGEIDX iPage, uint8_t *pu8Vram, bool fIn)1743 { 1744 RTGCPHYS phPage = (RTGCPHYS)iPage <<PAGE_SHIFT;1778 static int vboxVDMACrCmdVbvaProcessPagingEl(PPDMDEVINS pDevIns, VBOXCMDVBVAPAGEIDX uPageNo, uint8_t *pbVram, bool fIn) 1779 { 1780 RTGCPHYS GCPhysPage = (RTGCPHYS)uPageNo << X86_PAGE_SHIFT; 1745 1781 PGMPAGEMAPLOCK Lock; 1746 1782 int rc; … … 1748 1784 if (fIn) 1749 1785 { 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 1754 1794 WARN(("PDMDevHlpPhysGCPhys2CCPtrReadOnly failed %d", rc)); 1755 return rc;1756 }1757 1758 memcpy(pu8Vram, pvPage, PAGE_SIZE);1759 1760 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock);1761 1795 } 1762 1796 else 1763 1797 { 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 1768 1806 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 */ 1819 static 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 */ 1862 static 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 1816 1894 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 */ 1886 1908 static int8_t vboxVDMACrCmdVbvaProcessCmdData(struct VBOXVDMAHOST *pVdma, const VBOXCMDVBVA_HDR *pCmd, uint32_t cbCmd) 1887 1909 { 1888 switch (pCmd->u8OpCode) 1910 uint8_t bOpCode = pCmd->u8OpCode; 1911 switch (bOpCode) 1889 1912 { 1890 1913 case VBOXCMDVBVA_OPTYPE_NOPCMD: 1891 1914 return 0; 1915 1892 1916 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 1918 1919 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 1929 1925 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; 1937 1931 } 1938 1932 } … … 1953 1947 AssertCompile(sizeof (VBOXCMDVBVA_ALLOCINFO) == 4); 1954 1948 AssertCompile(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) 1949 AssertCompile(!(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 */ 1965 static 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) 1965 1971 { 1966 1972 case VBOXCMDVBVA_OPTYPE_SYSMEMCMD: 1967 1973 { 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; 1976 1982 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 */ 1985 1989 PGMPAGEMAPLOCK Lock; 1986 1990 PVGASTATE pVGAState = pVdma->pVGAState; 1987 1991 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); 1990 1994 if (!RT_SUCCESS(rc)) 1991 1995 { … … 1993 1997 return -1; 1994 1998 } 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 */ 2000 2004 if (cbRealCmd <= cbCmdPart) 2001 2005 { 2002 pRealCmdHdr = (const VBOXCMDVBVA_HDR *)pvCmd;2003 2006 i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pRealCmdHdr, cbRealCmd); 2004 2007 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);2016 2008 } 2017 2009 else 2018 2010 { 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) 2025 2017 { 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); 2028 2028 } 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 2043 2030 { 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; 2106 2034 } 2107 default: 2108 WARN(("command can not be splitted")); 2109 i8Result = -1; 2110 break; 2111 } 2112 2113 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 2035 } 2114 2036 return i8Result; 2115 2037 } 2038 2116 2039 case VBOXCMDVBVA_OPTYPE_COMPLEXCMD: 2117 2040 { 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*/); 2138 2057 if (i8Result < 0) 2139 2058 { … … 2141 2060 return i8Result; 2142 2061 } 2062 2063 /* Advance to the next command. */ 2064 pCmd = (VBOXCMDVBVA_HDR *)((uintptr_t)pCmd + cbCurCmd); 2065 cbCmd -= cbCurCmd; 2143 2066 } 2144 2067 return 0; 2145 2068 } 2069 2146 2070 default: 2147 2071 i8Result = vboxVDMACrCmdVbvaProcessCmdData(pVdma, pCmd, cbCmd); … … 2151 2075 } 2152 2076 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 */ 2082 static 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 2160 2101 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 2174 2103 } 2175 2104 … … 2208 2137 } 2209 2138 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 */ 2139 static 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 */ 2213 2148 static int vboxVDMACmdCheckCrCmd(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmdDr, uint32_t cbCmdDr) 2214 2149 { 2215 PVBOXVDMACMD pDmaCmd = NULL;2216 2150 uint32_t cbDmaCmd = 0; 2217 uint8_t * pvRam = pVdma->pVGAState->vram_ptrR3;2151 uint8_t *pbRam = pVdma->pVGAState->vram_ptrR3; 2218 2152 int rc = VINF_NOT_SUPPORTED; 2219 2153 2220 2154 cbDmaCmd = pCmdDr->cbBuf; 2221 2155 2156 PVBOXVDMACMD pDmaCmd; 2222 2157 if (pCmdDr->fFlags & VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR) 2223 2158 { 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); 2235 2161 2236 2162 pDmaCmd = VBOXVDMACBUF_DR_TAIL(pCmdDr, VBOXVDMACMD); … … 2239 2165 { 2240 2166 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; 2249 2173 if (pDmaCmd) 2250 2174 { … … 2257 2181 { 2258 2182 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 2264 2185 PVGASTATE pVGAState = pVdma->pVGAState; 2265 2186 rc = VINF_SUCCESS; … … 2270 2191 break; 2271 2192 } 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); 2278 2196 AssertRC(tmpRc); 2279 2197 break; 2280 2198 } 2199 2281 2200 case VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER: 2282 2201 { 2283 2202 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); 2289 2204 2290 2205 rc = vboxVDMACmdExecBpbTransfer(pVdma, pTransfer, sizeof (*pTransfer)); … … 2293 2208 { 2294 2209 pCmdDr->rc = VINF_SUCCESS; 2295 rc = VBoxSHGSMICommandComplete 2210 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmdDr); 2296 2211 AssertRC(rc); 2297 2212 rc = VINF_SUCCESS; … … 2299 2214 break; 2300 2215 } 2216 2301 2217 default: 2302 2218 break; … … 2333 2249 } 2334 2250 2251 /** 2252 * Worker for vboxVDMACmdExecBlt(). 2253 */ 2335 2254 static int vboxVDMACmdExecBltPerform(PVBOXVDMAHOST pVdma, const VBOXVIDEOOFFSET offDst, const VBOXVIDEOOFFSET offSrc, 2336 2255 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) */ 2342 2264 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) 2356 2277 { 2357 2278 Assert(!pDstRectl->left); 2358 2279 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; 2362 2289 } 2363 2290 else 2364 2291 { 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; 2369 2296 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; 2374 2301 # 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; 2377 2304 # endif 2378 uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart;2305 uint32_t offSrcStart = pSrcDesc->pitch * pSrcRectl->top + offSrcLineStart; 2379 2306 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; 2382 2309 2383 2310 Assert(cbDstLine == cbSrcLine); … … 2385 2312 for (uint32_t i = 0; ; ++i) 2386 2313 { 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; 2388 2320 if (i == pDstRectl->height) 2389 2321 break; 2390 p vDstStart += cbDstSkip;2391 p vSrcStart += cbSrcSkip;2322 pbDstStart += cbDstSkip; 2323 pbSrcStart += cbSrcSkip; 2392 2324 } 2393 2325 } … … 2395 2327 } 2396 2328 2329 #if 0 /* unused */ 2397 2330 static void vboxVDMARectlUnite(VBOXVDMA_RECTL * pRectl1, const VBOXVDMA_RECTL * pRectl2) 2398 2331 { … … 2422 2355 } 2423 2356 } 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. 2427 2369 */ 2428 2370 static int vboxVDMACmdExecBlt(PVBOXVDMAHOST pVdma, const PVBOXVDMACMD_DMA_PRESENT_BLT pBlt, uint32_t cbBuffer) 2429 2371 { 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) 2449 2397 { 2450 2398 VBOXVDMA_RECTL dstSubRectl = pBlt->aDstSubRects[i]; 2451 2399 VBOXVDMA_RECTL srcSubRectl = dstSubRectl; 2452 2400 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 2468 2412 } 2469 2413 } 2470 2414 else 2471 2415 { 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 2481 2421 } 2482 2422 … … 2484 2424 } 2485 2425 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 */ 2439 static 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; 2503 2471 do 2504 2472 { 2505 2473 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; 2510 2480 else 2511 2481 { 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); 2515 2484 AssertRC(rc); 2516 2485 if (RT_SUCCESS(rc)) 2517 2486 { 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)); 2520 2489 } 2521 2490 else 2522 {2523 2491 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; 2531 2499 else 2532 2500 { 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); 2536 2503 AssertRC(rc); 2537 2504 if (RT_SUCCESS(rc)) 2538 2505 { 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)); 2545 2508 } 2546 2509 } … … 2549 2512 { 2550 2513 memcpy(pvDst, pvSrc, cbSubTransfer); 2551 cbTransfer -= cbSubTransfer;2552 2514 cbTransfered += cbSubTransfer; 2515 cbTransfer -= cbSubTransfer; 2553 2516 } 2554 2517 else 2555 { 2556 cbTransfer = 0; /* to break */ 2557 } 2558 2559 if (bSrcLocked) 2518 cbTransfer = 0; /* force break below */ 2519 2520 if (fSrcLocked) 2560 2521 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &SrcLock); 2561 if ( bDstLocked)2522 if (fDstLocked) 2562 2523 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &DstLock); 2563 2524 } while (cbTransfer); 2564 2525 2565 2526 if (RT_SUCCESS(rc)) 2566 return sizeof (*pTransfer);2527 return sizeof(TransferSafeCopy); 2567 2528 return rc; 2568 2529 } 2569 2530 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 */ 2538 static 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) 2584 2550 { 2585 2551 case VBOXVDMACMD_TYPE_CHROMIUM_CMD: … … 2603 2569 return VINF_SUCCESS; 2604 2570 } 2571 2605 2572 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT: 2606 2573 { 2607 2574 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); 2623 2577 break; 2624 2578 } 2579 2625 2580 case VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER: 2626 2581 { 2627 2582 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); 2643 2585 break; 2644 2586 } 2587 2645 2588 case VBOXVDMACMD_TYPE_DMA_NOP: 2646 2589 return VINF_SUCCESS; 2590 2647 2591 case VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ: 2648 2592 return VINF_SUCCESS; 2593 2649 2594 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 */ 2660 2623 static DECLCALLBACK(int) vboxVDMAWorkerThread(RTTHREAD hThreadSelf, void *pvUser) 2661 2624 { 2662 2625 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; 2668 2629 int rc; 2669 2630 … … 2672 2633 while (!VBoxVDMAThreadIsTerminating(&pVdma->Thread)) 2673 2634 { 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); 2675 2638 switch (enmType) 2676 2639 { 2677 2640 case VBVAEXHOST_DATA_TYPE_CMD: 2678 vboxVDMACrCmdProcess(pVdma, p Cmd, cbCmd);2641 vboxVDMACrCmdProcess(pVdma, pbCmd, cbCmd); 2679 2642 VBoxVBVAExHPDataCompleteCmd(pCmdVbva, cbCmd); 2680 2643 VBVARaiseIrq(pVGAState, 0); 2681 2644 break; 2645 2682 2646 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); 2685 2649 break; 2650 2686 2651 case VBVAEXHOST_DATA_TYPE_HOSTCTL: 2687 2652 { 2688 2653 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); 2691 2656 if (fContinue) 2692 2657 break; … … 2697 2662 AssertRC(rc); 2698 2663 break; 2664 2699 2665 default: 2700 2666 WARN(("unexpected type %d\n", enmType)); … … 2708 2674 } 2709 2675 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 */ 2710 2683 static void vboxVDMACommandProcess(PVBOXVDMAHOST pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd) 2711 2684 { 2712 RT_NOREF(cbCmd);2713 2685 PHGSMIINSTANCE pHgsmi = pVdma->pHgsmi; 2714 const uint8_t * pvBuf;2715 PGMPAGEMAPLOCK Lock;2716 2686 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; 2723 2697 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 } 2725 2704 else if (pCmd->fFlags & VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET) 2726 2705 { 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); 2729 2712 } 2730 2713 else 2731 2714 { 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 ?? */ 2754 2723 bReleaseLocked = true; 2755 2724 } 2756 2725 2757 rc = vboxVDMACmdExec(pVdma, pvBuf, pCmd->cbBuf); 2726 /* 2727 * Process the command. 2728 */ 2729 rc = vboxVDMACmdExec(pVdma, pbCmdBuf, cbCmdBuf); 2758 2730 AssertRC(rc); 2759 2731 2732 /* Clean up comand buffer. */ 2760 2733 if (bReleaseLocked) 2761 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &Lock); 2734 PDMDevHlpPhysReleasePageMappingLock(pVdma->pVGAState->pDevInsR3, &Lock); 2735 2762 2736 } while (0); 2763 2737 2738 /* 2739 * Complete the command. 2740 */ 2764 2741 pCmd->rc = rc; 2765 2766 rc = VBoxSHGSMICommandComplete (pHgsmi, pCmd); 2742 rc = VBoxSHGSMICommandComplete(pHgsmi, pCmd); 2767 2743 AssertRC(rc); 2768 2744 } … … 2781 2757 #ifdef VBOX_VDMA_WITH_WATCHDOG 2782 2758 2759 /** 2760 * @callback_method_impl{TMTIMER, VDMA watchdog timer.} 2761 */ 2783 2762 static DECLCALLBACK(void) vboxVDMAWatchDogTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) 2784 2763 { … … 2788 2767 } 2789 2768 2769 /** 2770 * Handles VBOXVDMA_CTL_TYPE_WATCHDOG for vboxVDMAControl. 2771 */ 2790 2772 static int vboxVDMAWatchDogCtl(struct VBOXVDMAHOST *pVdma, uint32_t cMillis) 2791 2773 { … … 2800 2782 #endif /* VBOX_VDMA_WITH_WATCHDOG */ 2801 2783 2784 /** 2785 * Called by vgaR3Construct() to initialize the state. 2786 * 2787 * @returns VBox status code. 2788 */ 2802 2789 int vboxVDMAConstruct(PVGASTATE pVGAState, uint32_t cPipeElements) 2803 2790 { … … 2808 2795 if (pVdma) 2809 2796 { 2810 pVdma->pHgsmi = pVGAState->pHGSMI;2797 pVdma->pHgsmi = pVGAState->pHGSMI; 2811 2798 pVdma->pVGAState = pVGAState; 2812 2799 2813 2800 #ifdef VBOX_VDMA_WITH_WATCHDOG 2814 2801 rc = PDMDevHlpTMTimerCreate(pVGAState->pDevInsR3, TMCLOCK_REAL, vboxVDMAWatchDogTimer, 2815 2816 2802 pVdma, TMTIMER_FLAGS_NO_CRIT_SECT, 2803 "VDMA WatchDog Timer", &pVdma->WatchDogTimer); 2817 2804 AssertRC(rc); 2805 #else 2806 rc = VINF_SUCCESS; 2818 2807 #endif 2819 2808 if (RT_SUCCESS(rc)) 2809 { 2820 2810 #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); 2827 2814 if (RT_SUCCESS(rc)) 2828 2815 { 2829 rc = RTCritSectInit(&pVdma->CalloutCritSect);2816 rc = VBoxVBVAExHSInit(&pVdma->CmdVbva); 2830 2817 if (RT_SUCCESS(rc)) 2831 2818 { 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)) 2836 2821 { 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 2838 2833 } 2839 return VINF_SUCCESS; 2834 2835 WARN(("RTCritSectInit failed %d\n", rc)); 2836 VBoxVBVAExHSTerm(&pVdma->CmdVbva); 2840 2837 } 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); 2844 2841 } 2845 2842 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 } 2854 2847 RTMemFree(pVdma); 2855 #else2856 pVGAState->pVdma = pVdma;2857 return VINF_SUCCESS;2858 #endif2859 2848 } 2860 2849 else 2861 2850 rc = VERR_OUT_OF_RESOURCES; 2862 2863 2851 return rc; 2864 2852 } 2865 2853 2866 int vboxVDMAReset(struct VBOXVDMAHOST *pVdma) 2854 /** 2855 * Called by vgaR3Reset() to do reset. 2856 */ 2857 void vboxVDMAReset(struct VBOXVDMAHOST *pVdma) 2867 2858 { 2868 2859 #ifdef VBOX_WITH_CRHGSMI … … 2871 2862 RT_NOREF(pVdma); 2872 2863 #endif 2873 return VINF_SUCCESS; 2874 } 2875 2876 int vboxVDMADestruct(struct VBOXVDMAHOST *pVdma) 2864 } 2865 2866 /** 2867 * Called by vgaR3Destruct() to do cleanup.. 2868 */ 2869 void vboxVDMADestruct(struct VBOXVDMAHOST *pVdma) 2877 2870 { 2878 2871 if (!pVdma) 2879 return VINF_SUCCESS;2872 return; 2880 2873 #ifdef VBOX_WITH_CRHGSMI 2881 2874 if (pVdma->pVGAState->fVMSVGAEnabled) … … 2894 2887 #endif 2895 2888 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 */ 2899 2898 void vboxVDMAControl(struct VBOXVDMAHOST *pVdma, PVBOXVDMA_CTL pCmd, uint32_t cbCmd) 2900 2899 { … … 2902 2901 PHGSMIINSTANCE pIns = pVdma->pHgsmi; 2903 2902 2904 switch (pCmd->enmCtl) 2903 VBOXVDMA_CTL_TYPE enmCtl = pCmd->enmCtl; 2904 switch (enmCtl) 2905 2905 { 2906 2906 case VBOXVDMA_CTL_TYPE_ENABLE: … … 2921 2921 WARN(("cmd not supported")); 2922 2922 pCmd->i32Result = VERR_NOT_SUPPORTED; 2923 } 2924 2925 int rc = VBoxSHGSMICommandComplete (pIns, pCmd); 2923 break; 2924 } 2925 2926 int rc = VBoxSHGSMICommandComplete(pIns, pCmd); 2926 2927 AssertRC(rc); 2927 2928 } 2928 2929 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 */ 2929 2937 void vboxVDMACommand(struct VBOXVDMAHOST *pVdma, PVBOXVDMACBUF_DR pCmd, uint32_t cbCmd) 2930 2938 { 2931 int rc = VERR_NOT_IMPLEMENTED;2932 2933 2939 #ifdef VBOX_WITH_CRHGSMI 2934 2940 /* chromium commands are processed by crhomium hgcm thread independently from our internal cmd processing pipeline 2935 2941 * this is why we process them specially */ 2936 rc = vboxVDMACmdCheckCrCmd(pVdma, pCmd, cbCmd);2942 int rc = vboxVDMACmdCheckCrCmd(pVdma, pCmd, cbCmd); 2937 2943 if (rc == VINF_SUCCESS) 2938 2944 return; … … 2941 2947 { 2942 2948 pCmd->rc = rc; 2943 rc = VBoxSHGSMICommandComplete 2949 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd); 2944 2950 AssertRC(rc); 2945 2951 return; … … 2947 2953 2948 2954 vboxVDMACommandProcess(pVdma, pCmd, cbCmd); 2955 2949 2956 #else 2950 2957 RT_NOREF(cbCmd); 2951 pCmd->rc = rc;2952 rc = VBoxSHGSMICommandComplete 2958 pCmd->rc = VERR_NOT_IMPLEMENTED; 2959 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCmd); 2953 2960 AssertRC(rc); 2954 2961 #endif … … 2959 2966 static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, int rc, void *pvContext); 2960 2967 2961 static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 2968 static int vdmaVBVACtlSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource, 2969 PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 2962 2970 { 2963 2971 int rc = VBoxVBVAExHCtlSubmit(&pVdma->CmdVbva, pCtl, enmSource, pfnComplete, pvComplete); … … 2966 2974 if (rc == VINF_SUCCESS) 2967 2975 return VBoxVDMAThreadEventNotify(&pVdma->Thread); 2968 else 2969 Assert(rc == VINF_ALREADY_INITIALIZED); 2976 Assert(rc == VINF_ALREADY_INITIALIZED); 2970 2977 } 2971 2978 else … … 2975 2982 } 2976 2983 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 */ 2988 static DECLCALLBACK(void) vboxCmdVBVACmdCtlGuestCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, 2989 int rc, void *pvContext) 2978 2990 { 2979 2991 PVBOXVDMAHOST pVdma = (PVBOXVDMAHOST)pvContext; … … 2989 3001 } 2990 3002 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 */ 3006 static 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); 2994 3010 if (!pHCtl) 2995 3011 { … … 3010 3026 } 3011 3027 3028 /** 3029 * Handler for vboxCmdVBVACmdCtl()/VBOXCMDVBVACTL_TYPE_3DCTL. 3030 */ 3012 3031 static int vdmaVBVACtlGenericGuestSubmit(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL_TYPE enmType, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl) 3013 3032 { 3014 3033 Assert(cbCtl >= sizeof (VBOXCMDVBVA_CTL)); 3015 3034 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); 3017 3037 if (RT_SUCCESS(rc)) 3018 3038 return VINF_SUCCESS; … … 3025 3045 } 3026 3046 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 */ 3050 static DECLCALLBACK(void) vboxCmdVBVACmdCtlHostCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, 3051 int rc, void *pvCompletion) 3028 3052 { 3029 3053 VBOXCRCMDCTL* pVboxCtl = (VBOXCRCMDCTL*)pCtl->u.cmd.pu8Cmd; … … 3033 3057 } 3034 3058 3059 /** 3060 * Worker for vboxCmdVBVACmdHostCtl() and vboxCmdVBVACmdHostCtlSync(). 3061 */ 3035 3062 static 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); 3041 3068 if (RT_FAILURE(rc)) 3042 3069 { … … 3058 3085 } 3059 3086 3060 static DECLCALLBACK(int) vdmaVBVANotifyEnable(PVGASTATE pVGAState) 3087 /** 3088 * Called from vdmaVBVACtlThreadCreatedEnable(). 3089 */ 3090 static int vdmaVBVANotifyEnable(PVGASTATE pVGAState) 3061 3091 { 3062 3092 for (uint32_t i = 0; i < pVGAState->cMonitors; i++) … … 3077 3107 } 3078 3108 3079 static DECLCALLBACK(int) vdmaVBVANotifyDisable(PVGASTATE pVGAState) 3109 /** 3110 * Called from vdmaVBVACtlThreadCreatedEnable() and vdmaVBVADisableProcess(). 3111 */ 3112 static int vdmaVBVANotifyDisable(PVGASTATE pVGAState) 3080 3113 { 3081 3114 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); 3085 3116 return VINF_SUCCESS; 3086 3117 } 3087 3118 3119 /** 3120 * Hook that is called by vboxVDMAWorkerThread when it starts. 3121 */ 3088 3122 static DECLCALLBACK(void) vdmaVBVACtlThreadCreatedEnable(struct VBOXVDMATHREAD *pThread, int rc, 3089 3123 void *pvThreadContext, void *pvContext) … … 3118 3152 } 3119 3153 3154 /** 3155 * Worker for vdmaVBVACtlEnableDisableSubmitInternal() and vdmaVBVACtlEnableSubmitSync(). 3156 */ 3120 3157 static int vdmaVBVACtlEnableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, bool fPaused, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 3121 3158 { 3122 3159 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); 3124 3162 if (pHCtl) 3125 3163 { … … 3132 3170 if (RT_SUCCESS(rc)) 3133 3171 return VINF_SUCCESS; 3134 else 3135 WARN(("VBoxVDMAThreadCreate failed %d\n", rc)); 3172 WARN(("VBoxVDMAThreadCreate failed %d\n", rc)); 3136 3173 3137 3174 VBoxVBVAExHCtlFree(&pVdma->CmdVbva, pHCtl); … … 3146 3183 } 3147 3184 3185 /** 3186 * Worker for vboxVDMASaveLoadExecPerform(). 3187 */ 3148 3188 static int vdmaVBVACtlEnableSubmitSync(PVBOXVDMAHOST pVdma, uint32_t offVram, bool fPaused) 3149 3189 { … … 3182 3222 } 3183 3223 3184 static int vdmaVBVACtlDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 3224 /** 3225 * Worker for vdmaVBVACtlEnableDisableSubmitInternal(). 3226 */ 3227 static int vdmaVBVACtlDisableSubmitInternal(PVBOXVDMAHOST pVdma, VBVAENABLE *pEnable, 3228 PFNVBVAEXHOSTCTL_COMPLETE pfnComplete, void *pvComplete) 3185 3229 { 3186 3230 int rc; … … 3210 3254 } 3211 3255 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 */ 3259 static 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; 3215 3263 if (fEnable) 3216 3264 return vdmaVBVACtlEnableSubmitInternal(pVdma, pEnable, false, pfnComplete, pvComplete); … … 3218 3266 } 3219 3267 3268 /** 3269 * Handler for vboxCmdVBVACmdCtl/VBOXCMDVBVACTL_TYPE_ENABLE. 3270 */ 3220 3271 static int vdmaVBVACtlEnableDisableSubmit(PVBOXVDMAHOST pVdma, VBOXCMDVBVA_CTL_ENABLE *pEnable) 3221 3272 { … … 3232 3283 } 3233 3284 3285 /** 3286 * @callback_method_impl{FNVBVAEXHOSTCTL_COMPLETE, 3287 * Used by vdmaVBVACtlSubmitSync() and vdmaVBVACtlEnableSubmitSync().} 3288 */ 3234 3289 static DECLCALLBACK(void) vdmaVBVACtlSubmitSyncCompletion(VBVAEXHOSTCONTEXT *pVbva, struct VBVAEXHOSTCTL *pCtl, 3235 3290 int rc, void *pvContext) 3236 3291 { 3237 3292 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; 3239 3294 pData->rc = rc; 3240 3295 rc = RTSemEventSignal(pData->hEvent); … … 3243 3298 } 3244 3299 3300 3245 3301 static int vdmaVBVACtlSubmitSync(PVBOXVDMAHOST pVdma, VBVAEXHOSTCTL* pCtl, VBVAEXHOSTCTL_SOURCE enmSource) 3246 3302 { … … 3275 3331 } 3276 3332 3333 /** 3334 * Worker for vboxVDMASaveStateExecPrep(). 3335 */ 3277 3336 static int vdmaVBVAPause(PVBOXVDMAHOST pVdma) 3278 3337 { … … 3282 3341 } 3283 3342 3343 /** 3344 * Worker for vboxVDMASaveLoadExecPerform() and vboxVDMASaveStateExecDone(). 3345 */ 3284 3346 static int vdmaVBVAResume(PVBOXVDMAHOST pVdma) 3285 3347 { … … 3289 3351 } 3290 3352 3353 /** 3354 * Worker for vboxCmdVBVACmdSubmit(), vboxCmdVBVACmdFlush() and vboxCmdVBVATimerRefresh(). 3355 */ 3291 3356 static int vboxVDMACmdSubmitPerform(struct VBOXVDMAHOST *pVdma) 3292 3357 { … … 3307 3372 3308 3373 3374 /** 3375 * @interface_method_impl{PDMIDISPLAYVBVACALLBACKS,pfnCrCtlSubmit} 3376 */ 3309 3377 int 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) 3313 3382 { 3314 3383 PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface); … … 3320 3389 } 3321 3390 3391 /** 3392 * Argument package from vboxCmdVBVACmdHostCtlSync to vboxCmdVBVACmdHostCtlSyncCb. 3393 */ 3322 3394 typedef struct VBOXCMDVBVA_CMDHOSTCTL_SYNC 3323 3395 { … … 3327 3399 } VBOXCMDVBVA_CMDHOSTCTL_SYNC; 3328 3400 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 */ 3404 static DECLCALLBACK(void) vboxCmdVBVACmdHostCtlSyncCb(struct VBOXCRCMDCTL *pCmd, uint32_t cbCmd, int rc, void *pvCompletion) 3330 3405 { 3331 3406 RT_NOREF(pCmd, cbCmd); 3332 VBOXCMDVBVA_CMDHOSTCTL_SYNC *pData = (VBOXCMDVBVA_CMDHOSTCTL_SYNC *)pvCompletion;3407 VBOXCMDVBVA_CMDHOSTCTL_SYNC *pData = (VBOXCMDVBVA_CMDHOSTCTL_SYNC *)pvCompletion; 3333 3408 3334 3409 pData->rc = rc; … … 3343 3418 } 3344 3419 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 */ 3425 static DECLCALLBACK(int) vboxCmdVBVACmdCallout(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd, 3426 VBOXCRCMDCTL_CALLOUT_LISTENTRY *pEntry, PFNVBOXCRCMDCTL_CALLOUT_CB pfnCb) 3346 3427 { 3347 3428 pEntry->pfnCb = pfnCb; … … 3361 3442 3362 3443 3444 /** 3445 * Worker for vboxCmdVBVACmdHostCtlSync. 3446 */ 3363 3447 static int vboxCmdVBVACmdCalloutProcess(struct VBOXVDMAHOST *pVdma, struct VBOXCRCMDCTL* pCmd) 3364 3448 { … … 3389 3473 } 3390 3474 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 */ 3478 DECLCALLBACK(int) vboxCmdVBVACmdHostCtlSync(PPDMIDISPLAYVBVACALLBACKS pInterface, struct VBOXCRCMDCTL *pCmd, uint32_t cbCmd) 3479 { 3480 PVGASTATE pVGAState = PPDMIDISPLAYVBVACALLBACKS_2_PVGASTATE(pInterface); 3481 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 3396 3482 if (pVdma == NULL) 3397 3483 return VERR_INVALID_STATE; 3484 3398 3485 VBOXCMDVBVA_CMDHOSTCTL_SYNC Data; 3399 3486 Data.pVdma = pVdma; … … 3439 3526 } 3440 3527 3528 /** 3529 * Handler for VBVA_CMDVBVA_CTL, see vbvaChannelHandler(). 3530 */ 3441 3531 int vboxCmdVBVACmdCtl(PVGASTATE pVGAState, VBOXCMDVBVA_CTL *pCtl, uint32_t cbCtl) 3442 3532 { 3443 3533 struct VBOXVDMAHOST *pVdma = pVGAState->pVdma; 3444 int rc = VINF_SUCCESS;3445 3534 switch (pCtl->u32Type) 3446 3535 { … … 3450 3539 return vdmaVBVACtlGenericGuestSubmit(pVdma, VBVAEXHOSTCTL_TYPE_GHH_RESIZE, pCtl, cbCtl); 3451 3540 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; 3459 3545 default: 3460 3546 WARN(("unsupported type\n")); 3461 rc = VERR_INVALID_PARAMETER;3462 3547 break; 3463 3548 } 3464 3549 3465 pCtl->i32Result = rc;3466 rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl);3550 pCtl->i32Result = VERR_INVALID_PARAMETER; 3551 int rc = VBoxSHGSMICommandComplete(pVdma->pHgsmi, pCtl); 3467 3552 AssertRC(rc); 3468 3553 return VINF_SUCCESS; 3469 3554 } 3470 3555 3556 /** 3557 * Handler for VBVA_CMDVBVA_SUBMIT, see vbvaChannelHandler(). 3558 */ 3471 3559 int vboxCmdVBVACmdSubmit(PVGASTATE pVGAState) 3472 3560 { … … 3480 3568 } 3481 3569 3570 /** 3571 * Handler for VBVA_CMDVBVA_FLUSH, see vbvaChannelHandler(). 3572 */ 3482 3573 int vboxCmdVBVACmdFlush(PVGASTATE pVGAState) 3483 3574 { … … 3491 3582 } 3492 3583 3493 void vboxCmdVBVACmdTimer(PVGASTATE pVGAState) 3584 /** 3585 * Called from vgaTimerRefresh(). 3586 */ 3587 void vboxCmdVBVATimerRefresh(PVGASTATE pVGAState) 3494 3588 { 3495 3589 if (!VBoxVBVAExHSIsEnabled(&pVGAState->pVdma->CmdVbva)) … … 3504 3598 3505 3599 #endif /* VBOX_WITH_CRHGSMI */ 3600 3601 3602 /* 3603 * 3604 * 3605 * Saved state. 3606 * Saved state. 3607 * Saved state. 3608 * 3609 * 3610 */ 3506 3611 3507 3612 int vboxVDMASaveStateExecPrep(struct VBOXVDMAHOST *pVdma)
Note:
See TracChangeset
for help on using the changeset viewer.