VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPCr.cpp@ 71595

Last change on this file since 71595 was 71595, checked in by vboxsync, 7 years ago

DevVGA,VBoxVideo: Code cleanup in progress. bugref:9094

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.0 KB
Line 
1/* $Id: VBoxMPCr.cpp 71595 2018-03-31 20:24:41Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2012-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifdef VBOX_WITH_CROGL
19
20#include "VBoxMPWddm.h"
21#include "VBoxMPCr.h"
22
23#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
24
25#include <cr_protocol.h>
26
27CR_CAPS_INFO g_VBoxMpCrHostCapsInfo;
28static uint32_t g_VBoxMpCr3DSupported = 0;
29
30uint32_t VBoxMpCrGetHostCaps(void)
31{
32 return g_VBoxMpCrHostCapsInfo.u32Caps;
33}
34
35bool VBoxMpCrCtlConIs3DSupported(void)
36{
37 return !!g_VBoxMpCr3DSupported;
38}
39
40static void RT_UNTRUSTED_VOLATILE_HOST *vboxMpCrShgsmiBufferAlloc(PVBOXMP_DEVEXT pDevExt, HGSMISIZE cbData)
41{
42 return VBoxSHGSMIHeapBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, cbData);
43}
44
45static VBOXVIDEOOFFSET vboxMpCrShgsmiBufferOffset(PVBOXMP_DEVEXT pDevExt, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
46{
47 return (VBOXVIDEOOFFSET)HGSMIPointerToOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, pvBuffer);
48}
49
50static void RT_UNTRUSTED_VOLATILE_HOST *vboxMpCrShgsmiBufferFromOffset(PVBOXMP_DEVEXT pDevExt, VBOXVIDEOOFFSET offBuffer)
51{
52 return HGSMIOffsetToPointer(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, (HGSMIOFFSET)offBuffer);
53}
54
55static void vboxMpCrShgsmiBufferFree(PVBOXMP_DEVEXT pDevExt, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
56{
57 VBoxSHGSMIHeapBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, pvBuffer);
58}
59
60static VBOXVIDEOOFFSET vboxMpCrShgsmiTransportBufOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
61{
62 return vboxMpCrShgsmiBufferOffset(pCon->pDevExt, pvBuffer);
63}
64
65static void RT_UNTRUSTED_VOLATILE_HOST *vboxMpCrShgsmiTransportBufFromOffset(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVIDEOOFFSET offBuffer)
66{
67 return vboxMpCrShgsmiBufferFromOffset(pCon->pDevExt, offBuffer);
68}
69
70void RT_UNTRUSTED_VOLATILE_HOST *VBoxMpCrShgsmiTransportBufAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t cbBuffer)
71{
72 return vboxMpCrShgsmiBufferAlloc(pCon->pDevExt, cbBuffer);
73}
74
75void VBoxMpCrShgsmiTransportBufFree(PVBOXMP_CRSHGSMITRANSPORT pCon, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
76{
77 vboxMpCrShgsmiBufferFree(pCon->pDevExt, pvBuffer);
78}
79
80static int vboxMpCrShgsmiBufCacheBufReinit(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache,
81 PVBOXMP_CRSHGSMICON_BUFDR pDr, uint32_t cbRequested)
82{
83 RT_NOREF(pCache);
84 if (pDr->cbBuf >= cbRequested)
85 return VINF_SUCCESS;
86
87 if (pDr->pvBuf)
88 VBoxMpCrShgsmiTransportBufFree(pCon, pDr->pvBuf);
89
90 pDr->pvBuf = VBoxMpCrShgsmiTransportBufAlloc(pCon, cbRequested);
91 if (!pDr->pvBuf)
92 {
93 WARN(("VBoxMpCrShgsmiTransportBufAlloc failed"));
94 pDr->cbBuf = 0;
95 return VERR_NO_MEMORY;
96 }
97
98 pDr->cbBuf = cbRequested;
99 return VINF_SUCCESS;
100}
101
102static void vboxMpCrShgsmiBufCacheFree(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache,
103 PVBOXMP_CRSHGSMICON_BUFDR pDr)
104{
105 if (ASMAtomicCmpXchgPtr(&pCache->pBufDr, pDr, NULL))
106 return;
107
108 /* the value is already cached, free the current one */
109 VBoxMpCrShgsmiTransportBufFree(pCon, pDr->pvBuf);
110 vboxWddmMemFree(pDr);
111}
112
113static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheGetAllocDr(PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
114{
115 PVBOXMP_CRSHGSMICON_BUFDR pBufDr = (PVBOXMP_CRSHGSMICON_BUFDR)ASMAtomicXchgPtr((void * volatile *)&pCache->pBufDr, NULL);
116 if (!pBufDr)
117 {
118 pBufDr = (PVBOXMP_CRSHGSMICON_BUFDR)vboxWddmMemAllocZero(sizeof (*pBufDr));
119 if (!pBufDr)
120 {
121 WARN(("vboxWddmMemAllocZero failed!"));
122 return NULL;
123 }
124 }
125 return pBufDr;
126}
127
128static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAlloc(PVBOXMP_CRSHGSMITRANSPORT pCon,
129 PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
130{
131 PVBOXMP_CRSHGSMICON_BUFDR pBufDr = vboxMpCrShgsmiBufCacheGetAllocDr(pCache);
132 int rc = vboxMpCrShgsmiBufCacheBufReinit(pCon, pCache, pBufDr, cbBuffer);
133 if (RT_SUCCESS(rc))
134 return pBufDr;
135
136 WARN(("vboxMpCrShgsmiBufCacheBufReinit failed, rc %d", rc));
137
138 vboxMpCrShgsmiBufCacheFree(pCon, pCache, pBufDr);
139 return NULL;
140}
141
142static PVBOXMP_CRSHGSMICON_BUFDR vboxMpCrShgsmiBufCacheAllocAny(PVBOXMP_CRSHGSMITRANSPORT pCon,
143 PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache, uint32_t cbBuffer)
144{
145 PVBOXMP_CRSHGSMICON_BUFDR pBufDr = vboxMpCrShgsmiBufCacheGetAllocDr(pCache);
146
147 if (pBufDr->cbBuf)
148 return pBufDr;
149
150 int rc = vboxMpCrShgsmiBufCacheBufReinit(pCon, pCache, pBufDr, cbBuffer);
151 if (RT_SUCCESS(rc))
152 return pBufDr;
153
154 WARN(("vboxMpCrShgsmiBufCacheBufReinit failed, rc %d", rc));
155
156 vboxMpCrShgsmiBufCacheFree(pCon, pCache, pBufDr);
157 return NULL;
158}
159
160
161static int vboxMpCrShgsmiBufCacheInit(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
162{
163 RT_NOREF(pCon);
164 memset(pCache, 0, sizeof (*pCache));
165 return VINF_SUCCESS;
166}
167
168static void vboxMpCrShgsmiBufCacheTerm(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_CRSHGSMICON_BUFDR_CACHE pCache)
169{
170 if (pCache->pBufDr)
171 vboxMpCrShgsmiBufCacheFree(pCon, pCache, pCache->pBufDr);
172}
173
174int VBoxMpCrShgsmiTransportCreate(PVBOXMP_CRSHGSMITRANSPORT pCon, PVBOXMP_DEVEXT pDevExt)
175{
176 memset(pCon, 0, sizeof (*pCon));
177 pCon->pDevExt = pDevExt;
178 return VINF_SUCCESS;
179#if 0 /** @todo should this be unreachable? */
180 int rc;
181// int rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->CmdDrCache);
182// if (RT_SUCCESS(rc))
183 {
184 rc = vboxMpCrShgsmiBufCacheInit(pCon, &pCon->WbDrCache);
185 if (RT_SUCCESS(rc))
186 {
187 }
188 else
189 {
190 WARN(("vboxMpCrShgsmiBufCacheInit2 failed rc %d", rc));
191 }
192// vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
193 }
194// else
195// {
196// WARN(("vboxMpCrShgsmiBufCacheInit1 failed rc %d", rc));
197// }
198
199 return rc;
200#endif
201}
202
203void VBoxMpCrShgsmiTransportTerm(PVBOXMP_CRSHGSMITRANSPORT pCon)
204{
205 vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->WbDrCache);
206// vboxMpCrShgsmiBufCacheTerm(pCon, &pCon->CmdDrCache);
207}
208
209typedef struct VBOXMP_CRHGSMICMD_BASE
210{
211// VBOXMP_CRHGSMICMD_HDR Hdr;
212 CRVBOXHGSMIHDR CmdHdr;
213} VBOXMP_CRHGSMICMD_BASE, *PVBOXMP_CRHGSMICMD_BASE;
214
215typedef struct VBOXMP_CRHGSMICMD_WRITEREAD
216{
217// VBOXMP_CRHGSMICMD_HDR Hdr;
218 CRVBOXHGSMIWRITEREAD Cmd;
219} VBOXMP_CRHGSMICMD_WRITEREAD, *PVBOXMP_CRHGSMICMD_WRITEREAD;
220
221typedef struct VBOXMP_CRHGSMICMD_READ
222{
223// VBOXMP_CRHGSMICMD_HDR Hdr;
224 CRVBOXHGSMIREAD Cmd;
225} VBOXMP_CRHGSMICMD_READ, *PVBOXMP_CRHGSMICMD_READ;
226
227typedef struct VBOXMP_CRHGSMICMD_WRITE
228{
229// VBOXMP_CRHGSMICMD_HDR Hdr;
230 CRVBOXHGSMIWRITE Cmd;
231} VBOXMP_CRHGSMICMD_WRITE, *PVBOXMP_CRHGSMICMD_WRITE;
232
233
234#define VBOXMP_CRSHGSMICON_CMD_CMDBUF_OFFSET(_cBuffers) \
235 VBOXWDDM_ROUNDBOUND(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[_cBuffers]), 8)
236#define VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) \
237 ( VBOXMP_CRSHGSMICON_CMD_CMDBUF_OFFSET(_cBuffers) + VBOXWDDM_ROUNDBOUND(_cbCmdBuf, 8))
238#define VBOXMP_CRSHGSMICON_CMD_GET_CMDBUF(_pCmd, _cBuffers, _type) \
239 ((_type*)(((uint8_t*)(_pCmd)) + VBOXMP_CRSHGSMICON_CMD_CMDBUF_OFFSET(_cBuffers)))
240#define VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(_pCmd, _cBuffers, _cbCmdBuf, _type) \
241 ((_type*)(((uint8_t*)(_pCmd)) + VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
242#define VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(_pCtx, _cBuffers, _cbCmdBuf, _type) \
243 ((_type*)(((uint8_t*)(_pCtx)) - VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
244#define VBOXMP_CRSHGSMICON_CMD_SIZE(_cBuffers, _cbCmdBuf, _cbCtx) \
245 (VBOXMP_CRSHGSMICON_CMD_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) + (_cbCtx))
246
247
248#define VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) \
249 VBOXWDDM_ROUNDBOUND((VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[_cBuffers]))), 8)
250#define VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) \
251 ( VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers) + VBOXWDDM_ROUNDBOUND(_cbCmdBuf, 8))
252#define VBOXMP_CRSHGSMICON_DR_GET_CRCMD(_pDr) \
253 (VBOXVDMACMD_BODY((_pDr), VBOXVDMACMD_CHROMIUM_CMD))
254#define VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(_pDr, _cBuffers, _type) \
255 ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDBUF_OFFSET(_cBuffers)))
256#define VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(_pDr, _cBuffers, _cbCmdBuf, _type) \
257 ((_type*)(((uint8_t*)(_pDr)) + VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
258#define VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(_pCtx, _cBuffers, _cbCmdBuf) \
259 ((VBOXVDMACMD*)(((uint8_t*)(_pCtx)) - VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf)))
260#define VBOXMP_CRSHGSMICON_DR_SIZE(_cBuffers, _cbCmdBuf, _cbCtx) \
261 (VBOXMP_CRSHGSMICON_DR_CMDCTX_OFFSET(_cBuffers, _cbCmdBuf) + (_cbCtx))
262
263
264static int vboxMpCrShgsmiTransportCmdSubmitDr(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr,
265 PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete)
266{
267
268 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
269 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
270 vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, pfnComplete, pCon);
271 /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
272 vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
273 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
274 if (RT_SUCCESS(rc))
275 {
276 return VINF_SUCCESS;
277 }
278
279 WARN(("vboxVdmaCBufDrSubmit failed rc %d", rc));
280 return rc;
281}
282
283static int vboxMpCrShgsmiTransportCmdSubmitDmaCmd(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr,
284 PFNVBOXVDMADDICMDCOMPLETE_DPC pfnComplete)
285{
286 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = VBOXVDMACBUF_DR_FROM_TAIL(pHdr);
287 return vboxMpCrShgsmiTransportCmdSubmitDr(pCon, pDr, pfnComplete);
288}
289
290static void vboxMpCrShgsmiTransportCmdTermDmaCmd(PVBOXMP_CRSHGSMITRANSPORT pCon, VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr)
291{
292 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = VBOXVDMACBUF_DR_FROM_TAIL(pHdr);
293 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
294 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
295}
296
297
298typedef DECLCALLBACK(void) FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc,
299 void RT_UNTRUSTED_VOLATILE_HOST *pvRx,
300 uint32_t cbRx, void *pvCtx);
301typedef FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION *PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION;
302
303static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
304 PVOID pvContext)
305{
306 RT_NOREF(pDevExt);
307 /* we should be called from our DPC routine */
308 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
309
310 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
311 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
312 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
313 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
314 const UINT cBuffers = 2;
315 Assert(pBody->cBuffers == cBuffers);
316
317 PVBOXMP_CRHGSMICMD_READ pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_READ);
318 CRVBOXHGSMIREAD *pCmd = &pWrData->Cmd;
319 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
320 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIREAD));
321
322 CRVBOXHGSMIREAD *pWr = (CRVBOXHGSMIREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
323 PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION)pBufCmd->u64GuestData;
324 VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[1];
325 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
326 void RT_UNTRUSTED_VOLATILE_HOST *pvRx = NULL;
327 uint32_t cbRx = 0;
328
329 int rc = pDr->rc;
330 if (RT_SUCCESS(rc))
331 {
332 rc = pWr->hdr.result;
333 if (RT_SUCCESS(rc))
334 {
335 cbRx = pCmd->cbBuffer;
336 if (cbRx)
337 pvRx = pWbDr->pvBuf;
338 }
339 else
340 {
341 WARN(("CRVBOXHGSMIREAD failed, rc %d", rc));
342 }
343 }
344 else
345 {
346 WARN(("dma command buffer failed rc %d!", rc));
347 }
348
349 if (pfnCompletion)
350 {
351 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), void);
352 pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
353 }
354
355 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
356}
357
358static void* vboxMpCrShgsmiTransportCmdCreateReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, PVBOXVDMACBUF_DR pDr,
359 uint32_t cbDrData, PVBOXMP_CRSHGSMICON_BUFDR pWbDr,
360 PFNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION pfnCompletion,
361 uint32_t cbContextData)
362{
363 RT_NOREF(cbDrData);
364 const uint32_t cBuffers = 2;
365 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), cbContextData);
366 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
367 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
368 PVBOXMP_CRHGSMICMD_READ pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_READ);
369 CRVBOXHGSMIREAD *pCmd = &pWrData->Cmd;
370
371 if (cbCmd > cbContextData)
372 {
373 ERR(("the passed descriptor is less than needed!"));
374 return NULL;
375 }
376
377 memset(pDr, 0, VBOXVDMACBUF_DR_SIZE(cbCmd));
378
379 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_VRAM_OFFSET;
380 pDr->cbBuf = cbCmd;
381 pDr->rc = VERR_NOT_IMPLEMENTED;
382 pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
383
384 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
385 pHdr->u32CmdSpecific = 0;
386
387 pBody->cBuffers = cBuffers;
388
389 pCmd->hdr.result = VERR_WRONG_ORDER;
390 pCmd->hdr.u32ClientID = u32ClientID;
391 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
392 // pCmd->hdr.u32Reserved = 0;
393 pCmd->iBuffer = 1;
394
395 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
396 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
397 pBufCmd->cbBuffer = sizeof (*pCmd);
398 pBufCmd->u32GuestData = 0;
399 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
400
401 pBufCmd = &pBody->aBuffers[1];
402 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
403 pBufCmd->cbBuffer = pWbDr->cbBuf;
404 pBufCmd->u32GuestData = 0;
405 pBufCmd->u64GuestData = (uintptr_t)pWbDr;
406
407 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_READ), void);
408}
409
410static int vboxMpCrShgsmiTransportCmdSubmitReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
411{
412 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof(VBOXMP_CRHGSMICMD_READ));
413 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendReadAsyncCompletion);
414}
415
416typedef struct VBOXMP_CRHGSMICON_WRR_COMPLETION_CTX
417{
418 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion;
419 void *pvContext;
420
421} VBOXMP_CRHGSMICON_WRR_COMPLETION_CTX, *PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX;
422
423/** @callback_method_impl{FNVBOXMP_CRSHGSMITRANSPORT_SENDREADASYNC_COMPLETION} */
424static DECLCALLBACK(void) vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion(PVBOXMP_CRSHGSMITRANSPORT pCon, int rc,
425 void RT_UNTRUSTED_VOLATILE_HOST *pvRx,
426 uint32_t cbRx, void *pvCtx)
427{
428 PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pData = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)pvCtx;
429 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = pData->pfnCompletion;
430 if (pfnCompletion)
431 pfnCompletion(pCon, rc, pvRx, cbRx, pData->pvContext);
432}
433
434static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
435 PVOID pvContext)
436{
437 RT_NOREF(pDevExt);
438 /* we should be called from our DPC routine */
439 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
440
441 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
442 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
443 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
444 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
445 const UINT cBuffers = 3;
446 Assert(pBody->cBuffers == cBuffers);
447
448 PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
449 CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
450 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
451 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITEREAD));
452
453 CRVBOXHGSMIWRITEREAD *pWr = (CRVBOXHGSMIWRITEREAD*)vboxMpCrShgsmiTransportBufFromOffset(pCon, pBufCmd->offBuffer);
454 VBOXVDMACMD_CHROMIUM_BUFFER *pRxBuf = &pBody->aBuffers[2];
455 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = (PVBOXMP_CRSHGSMICON_BUFDR)pRxBuf->u64GuestData;
456 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION)pBufCmd->u64GuestData;
457 void RT_UNTRUSTED_VOLATILE_HOST *pvRx = NULL;
458 uint32_t cbRx = 0;
459
460 int rc = pDr->rc;
461 if (RT_SUCCESS(rc))
462 {
463 rc = pWr->hdr.result;
464 if (RT_SUCCESS(rc))
465 {
466 cbRx = pCmd->cbWriteback;
467 if (cbRx)
468 pvRx = pWbDr->pvBuf;
469 }
470 else if (rc == VERR_BUFFER_OVERFLOW)
471 {
472 /* issue read */
473 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
474 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
475 pWbDr = vboxMpCrShgsmiBufCacheAlloc(pCon, &pCon->WbDrCache, pCmd->cbWriteback);
476 if (pWbDr)
477 {
478 /* the Read Command is shorter than WriteRead, so just reuse the Write-Read descriptor here */
479 PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX pReadCtx;
480 pReadCtx = (PVBOXMP_CRHGSMICON_WRR_COMPLETION_CTX)vboxMpCrShgsmiTransportCmdCreateReadAsync(pCon,
481 pCmd->hdr.u32ClientID,
482 pDr,
483 VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof(VBOXMP_CRHGSMICMD_WRITEREAD), 0),
484 pWbDr,
485 vboxMpCrShgsmiTransportSendWriteReadReadRepostCompletion,
486 sizeof(*pReadCtx));
487 pReadCtx->pfnCompletion = pfnCompletion;
488 pReadCtx->pvContext = pvCtx;
489 vboxMpCrShgsmiTransportCmdSubmitReadAsync(pCon, pReadCtx);
490 /* don't do completion here, the completion will be called from the read completion we issue here */
491 pfnCompletion = NULL;
492 /* the current pWbDr was already freed, and we'll free the Read dr in the Read Completion */
493 pWbDr = NULL;
494 }
495 else
496 {
497 WARN(("vboxMpCrShgsmiBufCacheAlloc failed for %d", pCmd->cbWriteback));
498 rc = VERR_NO_MEMORY;
499 }
500 }
501 else
502 {
503 WARN(("CRVBOXHGSMIWRITEREAD failed, rc %d", rc));
504 }
505 }
506 else
507 {
508 WARN(("dma command buffer failed rc %d!", rc));
509 }
510
511 if (pfnCompletion)
512 {
513 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
514 pfnCompletion(pCon, rc, pvRx, cbRx, pvCtx);
515 }
516
517 if (pWbDr)
518 vboxMpCrShgsmiBufCacheFree(pCon, &pCon->WbDrCache, pWbDr);
519}
520
521static DECLCALLBACK(VOID) vboxMpCrShgsmiTransportVdmaSendWriteAsyncCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pDdiCmd,
522 PVOID pvContext)
523{
524 RT_NOREF(pDevExt);
525 /* we should be called from our DPC routine */
526 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
527
528 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
529 PVBOXVDMACBUF_DR pDr = VBOXVDMACBUF_DR_FROM_DDI_CMD(pDdiCmd);
530 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
531 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
532 const UINT cBuffers = 2;
533 Assert(pBody->cBuffers == cBuffers);
534
535 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
536 CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
537 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
538 Assert(pBufCmd->cbBuffer == sizeof (CRVBOXHGSMIWRITE));
539 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)pBufCmd->u64GuestData;
540
541 int rc = pDr->rc;
542 if (RT_SUCCESS(rc))
543 {
544 rc = pCmd->hdr.result;
545 if (!RT_SUCCESS(rc))
546 {
547 WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
548 }
549 }
550 else
551 {
552 WARN(("dma command buffer failed rc %d!", rc));
553 }
554
555 if (pfnCompletion)
556 {
557 void *pvCtx = VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
558 pfnCompletion(pCon, rc, pvCtx);
559 }
560}
561
562/** @callback_method_impl{FNVBOXSHGSMICMDCOMPLETION} */
563static DECLCALLBACK(VOID)
564vboxMpCrShgsmiTransportVbvaSendWriteAsyncCompletion(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvCmd, void *pvContext)
565{
566 RT_NOREF(pHeap);
567 /* we should be called from our DPC routine */
568 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
569
570 PVBOXMP_CRSHGSMITRANSPORT pCon = (PVBOXMP_CRSHGSMITRANSPORT)pvContext;
571 VBOXCMDVBVA_CRCMD_CMD RT_UNTRUSTED_VOLATILE_HOST *pCmd = NULL;
572 int rc = VBoxCmdVbvaConCmdCompletionData(pvCmd, &pCmd);
573 const UINT cBuffers = 2;
574 Assert(pCmd->cBuffers == cBuffers);
575 uint64_t*pu64Completion = VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(pCmd, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), uint64_t);
576 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion = (PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION)(*pu64Completion);
577
578 if (!RT_SUCCESS(rc))
579 WARN(("CRVBOXHGSMIWRITE failed, rc %d", rc));
580
581 if (pfnCompletion)
582 pfnCompletion(pCon, rc, (void*)(pu64Completion+1));
583}
584
585void* VBoxMpCrShgsmiTransportCmdCreateWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer,
586 uint32_t cbBuffer,
587 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEREADASYNC_COMPLETION pfnCompletion,
588 uint32_t cbContextData)
589{
590 const uint32_t cBuffers = 3;
591 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), cbContextData);
592 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
593 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
594 if (!pDr)
595 {
596 WARN(("vboxVdmaCBufDrCreate failed"));
597 return NULL;
598 }
599
600 PVBOXMP_CRSHGSMICON_BUFDR pWbDr = vboxMpCrShgsmiBufCacheAllocAny(pCon, &pCon->WbDrCache, 1000);
601 if (!pWbDr)
602 {
603 WARN(("vboxMpCrShgsmiBufCacheAlloc for wb dr failed"));
604 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
605 return NULL;
606 }
607
608 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
609 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
610 PVBOXMP_CRHGSMICMD_WRITEREAD pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITEREAD);
611 CRVBOXHGSMIWRITEREAD *pCmd = &pWrData->Cmd;
612
613 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
614 pDr->cbBuf = cbCmd;
615 pDr->rc = VERR_NOT_IMPLEMENTED;
616// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
617
618
619 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
620 pHdr->u32CmdSpecific = 0;
621
622 pBody->cBuffers = cBuffers;
623
624 pCmd->hdr.result = VERR_WRONG_ORDER;
625 pCmd->hdr.u32ClientID = u32ClientID;
626 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE_READ;
627 // pCmd->hdr.u32Reserved = 0;
628 pCmd->iBuffer = 1;
629 pCmd->iWriteback = 2;
630 pCmd->cbWriteback = 0;
631
632 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
633 pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
634 pBufCmd->cbBuffer = sizeof (*pCmd);
635 pBufCmd->u32GuestData = 0;
636 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
637
638 pBufCmd = &pBody->aBuffers[1];
639 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pvBuffer);
640 pBufCmd->cbBuffer = cbBuffer;
641 pBufCmd->u32GuestData = 0;
642 pBufCmd->u64GuestData = 0;
643
644 pBufCmd = &pBody->aBuffers[2];
645 pBufCmd->offBuffer = vboxMpCrShgsmiTransportBufOffset(pCon, pWbDr->pvBuf);
646 pBufCmd->cbBuffer = pWbDr->cbBuf;
647 pBufCmd->u32GuestData = 0;
648 pBufCmd->u64GuestData = (uintptr_t)pWbDr;
649
650 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD), void);
651}
652
653static void * vboxMpCrShgsmiTransportCmdVbvaCreateWriteAsync(PVBOXMP_DEVEXT pDevExt, uint32_t u32ClientID, void *pvBuffer,
654 uint32_t cbBuffer,
655 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
656 uint32_t cbContextData)
657{
658 const uint32_t cBuffers = 2;
659 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_CMD_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8, cbContextData);
660 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBoxCmdVbvaConCmdAlloc(pDevExt, cbCmd);
661 if (!pCmd)
662 {
663 WARN(("VBoxCmdVbvaConCmdAlloc failed"));
664 return NULL;
665 }
666
667 pCmd->cBuffers = cBuffers;
668
669 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_CMD_GET_CMDBUF(pCmd, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
670 CRVBOXHGSMIWRITE *pCmdWrite = &pWrData->Cmd;
671
672 pCmdWrite->hdr.result = VERR_WRONG_ORDER;
673 pCmdWrite->hdr.u32ClientID = u32ClientID;
674 pCmdWrite->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
675 // pCmdWrite->hdr.u32Reserved = 0;
676 pCmdWrite->iBuffer = 1;
677
678 VBOXCMDVBVA_CRCMD_BUFFER *pBufCmd = &pCmd->aBuffers[0];
679 pBufCmd->offBuffer = (VBOXCMDVBVAOFFSET)vboxMpCrShgsmiBufferOffset(pDevExt, pCmdWrite);
680 pBufCmd->cbBuffer = sizeof (*pCmdWrite);
681
682 pBufCmd = &pCmd->aBuffers[1];
683 pBufCmd->offBuffer = (VBOXCMDVBVAOFFSET)vboxMpCrShgsmiBufferOffset(pDevExt, pvBuffer);
684 pBufCmd->cbBuffer = cbBuffer;
685
686 uint64_t*pu64Completion = VBOXMP_CRSHGSMICON_CMD_GET_CMDCTX(pCmd, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), uint64_t);
687 *pu64Completion = (uintptr_t)pfnCompletion;
688 return pu64Completion + 1;
689}
690
691void* vboxMpCrShgsmiTransportCmdVdmaCreateWriteAsync(PVBOXMP_DEVEXT pDevExt, uint32_t u32ClientID, void *pvBuffer,
692 uint32_t cbBuffer,
693 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
694 uint32_t cbContextData)
695{
696 const uint32_t cBuffers = 2;
697 const uint32_t cbCmd = VBOXMP_CRSHGSMICON_DR_SIZE(cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), cbContextData);
698 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
699 if (!pDr)
700 {
701 WARN(("vboxVdmaCBufDrCreate failed"));
702 return NULL;
703 }
704
705 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
706 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXMP_CRSHGSMICON_DR_GET_CRCMD(pHdr);
707 PVBOXMP_CRHGSMICMD_WRITE pWrData = VBOXMP_CRSHGSMICON_DR_GET_CMDBUF(pHdr, cBuffers, VBOXMP_CRHGSMICMD_WRITE);
708 CRVBOXHGSMIWRITE *pCmd = &pWrData->Cmd;
709
710 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
711 pDr->cbBuf = cbCmd;
712 pDr->rc = VERR_NOT_IMPLEMENTED;
713// pDr->Location.offVramBuf = vboxMpCrShgsmiTransportBufOffset(pCon, pCmd);
714
715 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
716 pHdr->u32CmdSpecific = 0;
717
718 pBody->cBuffers = cBuffers;
719
720 pCmd->hdr.result = VERR_WRONG_ORDER;
721 pCmd->hdr.u32ClientID = u32ClientID;
722 pCmd->hdr.u32Function = SHCRGL_GUEST_FN_WRITE;
723 // pCmd->hdr.u32Reserved = 0;
724 pCmd->iBuffer = 1;
725
726 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[0];
727 pBufCmd->offBuffer = vboxVdmaCBufDrPtrOffset(&pDevExt->u.primary.Vdma, pCmd);
728 pBufCmd->cbBuffer = sizeof (*pCmd);
729 pBufCmd->u32GuestData = 0;
730 pBufCmd->u64GuestData = (uintptr_t)pfnCompletion;
731
732 pBufCmd = &pBody->aBuffers[1];
733 pBufCmd->offBuffer = vboxMpCrShgsmiBufferOffset(pDevExt, pvBuffer);
734 pBufCmd->cbBuffer = cbBuffer;
735 pBufCmd->u32GuestData = 0;
736 pBufCmd->u64GuestData = 0;
737
738 return VBOXMP_CRSHGSMICON_DR_GET_CMDCTX(pHdr, cBuffers, sizeof (VBOXMP_CRHGSMICMD_WRITE), void);
739}
740
741void* VBoxMpCrShgsmiTransportCmdCreateWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, uint32_t u32ClientID, void *pvBuffer,
742 uint32_t cbBuffer,
743 PFNVBOXMP_CRSHGSMITRANSPORT_SENDWRITEASYNC_COMPLETION pfnCompletion,
744 uint32_t cbContextData)
745{
746 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
747 if (pDevExt->fCmdVbvaEnabled)
748 return vboxMpCrShgsmiTransportCmdVbvaCreateWriteAsync(pDevExt, u32ClientID, pvBuffer, cbBuffer, pfnCompletion,
749 cbContextData);
750 return vboxMpCrShgsmiTransportCmdVdmaCreateWriteAsync(pDevExt, u32ClientID, pvBuffer, cbBuffer, pfnCompletion, cbContextData);
751}
752
753int VBoxMpCrShgsmiTransportCmdSubmitWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
754{
755 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3, sizeof (VBOXMP_CRHGSMICMD_WRITEREAD));
756 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportSendWriteReadAsyncCompletion);
757}
758
759static int vboxMpCrShgsmiTransportCmdVdmaSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
760{
761 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
762 return vboxMpCrShgsmiTransportCmdSubmitDmaCmd(pCon, pHdr, vboxMpCrShgsmiTransportVdmaSendWriteAsyncCompletion);
763}
764
765static int vboxMpCrShgsmiTransportCmdVbvaSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
766{
767 PVBOXMP_DEVEXT pDevExt = pCon->pDevExt;
768 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8,
769 VBOXCMDVBVA_CRCMD_CMD);
770 return VBoxCmdVbvaConCmdSubmitAsync(pDevExt, pCmd, vboxMpCrShgsmiTransportVbvaSendWriteAsyncCompletion, pCon);
771}
772
773int VBoxMpCrShgsmiTransportCmdSubmitWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
774{
775 if (pCon->pDevExt->fCmdVbvaEnabled)
776 return vboxMpCrShgsmiTransportCmdVbvaSubmitWriteAsync(pCon, pvContext);
777 return vboxMpCrShgsmiTransportCmdVdmaSubmitWriteAsync(pCon, pvContext);
778}
779
780void VBoxMpCrShgsmiTransportCmdTermWriteReadAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
781{
782 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 3,
783 sizeof(VBOXMP_CRHGSMICMD_WRITEREAD));
784 vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
785}
786
787static void vboxMpCrShgsmiTransportCmdVbvaTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
788{
789 VBOXCMDVBVA_CRCMD_CMD* pCmd = VBOXMP_CRSHGSMICON_CMD_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE) + 8,
790 VBOXCMDVBVA_CRCMD_CMD);
791 VBoxCmdVbvaConCmdFree(pCon->pDevExt, pCmd);
792}
793
794static void vboxMpCrShgsmiTransportCmdVdmaTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
795{
796 VBOXVDMACMD* pHdr = VBOXMP_CRSHGSMICON_DR_GET_FROM_CMDCTX(pvContext, 2, sizeof (VBOXMP_CRHGSMICMD_WRITE));
797 vboxMpCrShgsmiTransportCmdTermDmaCmd(pCon, pHdr);
798}
799
800void VBoxMpCrShgsmiTransportCmdTermWriteAsync(PVBOXMP_CRSHGSMITRANSPORT pCon, void *pvContext)
801{
802 if (pCon->pDevExt->fCmdVbvaEnabled)
803 vboxMpCrShgsmiTransportCmdVbvaTermWriteAsync(pCon, pvContext);
804 else
805 vboxMpCrShgsmiTransportCmdVdmaTermWriteAsync(pCon, pvContext);
806}
807
808static int vboxMpCrCtlAddRef(PVBOXMP_CRCTLCON pCrCtlCon)
809{
810 if (pCrCtlCon->cCrCtlRefs++)
811 return VINF_ALREADY_INITIALIZED;
812
813 int rc = VbglR0CrCtlCreate(&pCrCtlCon->hCrCtl);
814 if (RT_SUCCESS(rc))
815 {
816 Assert(pCrCtlCon->hCrCtl);
817 return VINF_SUCCESS;
818 }
819
820 WARN(("vboxCrCtlCreate failed, rc (%d)", rc));
821
822 --pCrCtlCon->cCrCtlRefs;
823 return rc;
824}
825
826static int vboxMpCrCtlRelease(PVBOXMP_CRCTLCON pCrCtlCon)
827{
828 Assert(pCrCtlCon->cCrCtlRefs);
829 if (--pCrCtlCon->cCrCtlRefs)
830 {
831 return VINF_SUCCESS;
832 }
833
834 int rc = VbglR0CrCtlDestroy(pCrCtlCon->hCrCtl);
835 if (RT_SUCCESS(rc))
836 {
837 pCrCtlCon->hCrCtl = NULL;
838 return VINF_SUCCESS;
839 }
840
841 WARN(("vboxCrCtlDestroy failed, rc (%d)", rc));
842
843 ++pCrCtlCon->cCrCtlRefs;
844 return rc;
845}
846
847static int vboxMpCrCtlConSetVersion(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor)
848{
849 CRVBOXHGCMSETVERSION parms;
850 int rc;
851
852 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_SET_VERSION, SHCRGL_CPARMS_SET_VERSION);
853
854 parms.vMajor.type = VMMDevHGCMParmType_32bit;
855 parms.vMajor.u.value32 = vMajor;
856 parms.vMinor.type = VMMDevHGCMParmType_32bit;
857 parms.vMinor.u.value32 = vMinor;
858
859 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
860 if (RT_FAILURE(rc))
861 WARN(("vboxCrCtlConCall/SET_VERSION failed, rc = %Rrc", rc));
862 return rc;
863}
864
865static int vboxMpCrCtlConGetCapsLegacy(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, uint32_t *pu32Caps)
866{
867 CRVBOXHGCMGETCAPS parms;
868 int rc;
869
870 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_GET_CAPS_LEGACY, SHCRGL_CPARMS_GET_CAPS_LEGACY);
871
872 parms.Caps.type = VMMDevHGCMParmType_32bit;
873 parms.Caps.u.value32 = 0;
874
875 *pu32Caps = 0;
876
877 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
878 if (RT_FAILURE(rc))
879 {
880 WARN(("vboxCrCtlConCall/GET_CAPS_LEAGCY failed, rc=%Rrc", rc));
881 return rc;
882 }
883
884 /* if host reports it supports CR_VBOX_CAP_CMDVBVA, clean it up,
885 * we only support CR_VBOX_CAP_CMDVBVA of the proper version reported by SHCRGL_GUEST_FN_GET_CAPS_NEW */
886 parms.Caps.u.value32 &= ~CR_VBOX_CAP_CMDVBVA;
887
888 *pu32Caps = parms.Caps.u.value32;
889
890 return VINF_SUCCESS;
891}
892
893static int vboxMpCrCtlConGetCapsNew(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID, CR_CAPS_INFO *pCapsInfo)
894{
895 pCapsInfo->u32Caps = CR_VBOX_CAPS_ALL;
896 pCapsInfo->u32CmdVbvaVersion = CR_CMDVBVA_VERSION;
897
898 CRVBOXHGCMGETCAPS parms;
899 int rc;
900
901 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_GET_CAPS_NEW, SHCRGL_CPARMS_GET_CAPS_NEW);
902
903 parms.Caps.type = VMMDevHGCMParmType_LinAddr;
904 parms.Caps.u.Pointer.u.linearAddr = (uintptr_t)pCapsInfo;
905 parms.Caps.u.Pointer.size = sizeof (*pCapsInfo);
906
907 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
908 if (RT_FAILURE(rc))
909 {
910 WARN(("vboxCrCtlConCall/GET_CAPS_NEW failed, rc=%Rrc", rc));
911 return rc;
912 }
913
914 if (pCapsInfo->u32CmdVbvaVersion != CR_CMDVBVA_VERSION)
915 {
916 WARN(("CmdVbva version mismatch (%d), expected(%d)", pCapsInfo->u32CmdVbvaVersion, CR_CMDVBVA_VERSION));
917 pCapsInfo->u32Caps &= ~CR_VBOX_CAP_CMDVBVA;
918 }
919
920 pCapsInfo->u32Caps &= CR_VBOX_CAPS_ALL;
921
922 return VINF_SUCCESS;
923}
924
925static int vboxMpCrCtlConSetPID(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
926{
927 CRVBOXHGCMSETPID parms;
928 int rc;
929
930 VBGL_HGCM_HDR_INIT(&parms.hdr, u32ClientID, SHCRGL_GUEST_FN_SET_PID, SHCRGL_CPARMS_SET_PID);
931
932 parms.u64PID.type = VMMDevHGCMParmType_64bit;
933 parms.u64PID.u.value64 = (uintptr_t)PsGetCurrentProcessId();
934
935 Assert(parms.u64PID.u.value64);
936
937 rc = VbglR0CrCtlConCall(pCrCtlCon->hCrCtl, &parms.hdr, sizeof (parms));
938 if (RT_FAILURE(rc))
939 WARN(("vboxCrCtlConCall/SET_PIDfailed, rc=%Rrc", rc));
940 return rc;
941}
942
943int VBoxMpCrCtlConConnectHgcm(PVBOXMP_CRCTLCON pCrCtlCon,
944 uint32_t crVersionMajor, uint32_t crVersionMinor,
945 uint32_t *pu32ClientID)
946{
947 uint32_t u32ClientID;
948 int rc = vboxMpCrCtlAddRef(pCrCtlCon);
949 if (RT_SUCCESS(rc))
950 {
951 rc = VbglR0CrCtlConConnect(pCrCtlCon->hCrCtl, &u32ClientID);
952 if (RT_SUCCESS(rc))
953 {
954 rc = vboxMpCrCtlConSetVersion(pCrCtlCon, u32ClientID, crVersionMajor, crVersionMinor);
955 if (RT_SUCCESS(rc))
956 {
957 rc = vboxMpCrCtlConSetPID(pCrCtlCon, u32ClientID);
958 if (RT_SUCCESS(rc))
959 {
960 *pu32ClientID = u32ClientID;
961 return VINF_SUCCESS;
962 }
963 else
964 {
965 WARN(("vboxMpCrCtlConSetPID failed, rc (%d)", rc));
966 }
967 }
968 else
969 {
970 WARN(("vboxMpCrCtlConSetVersion failed, rc (%d)", rc));
971 }
972 VbglR0CrCtlConDisconnect(pCrCtlCon->hCrCtl, u32ClientID);
973 }
974 else
975 {
976 WARN(("vboxCrCtlConConnect failed, rc (%d)", rc));
977 }
978 vboxMpCrCtlRelease(pCrCtlCon);
979 }
980 else
981 {
982 WARN(("vboxMpCrCtlAddRef failed, rc (%d)", rc));
983 }
984
985 *pu32ClientID = 0;
986 Assert(RT_FAILURE(rc));
987 return rc;
988}
989
990int VBoxMpCrCtlConConnectVbva(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon,
991 uint32_t crVersionMajor, uint32_t crVersionMinor,
992 uint32_t *pu32ClientID)
993{
994 if (pCrCtlCon->hCrCtl)
995 {
996 WARN(("pCrCtlCon is HGCM connection"));
997 return VERR_INVALID_STATE;
998 }
999
1000 Assert(!pCrCtlCon->cCrCtlRefs);
1001 return VBoxCmdVbvaConConnect(pDevExt, &pDevExt->CmdVbva,
1002 crVersionMajor, crVersionMinor,
1003 pu32ClientID);
1004}
1005
1006int VBoxMpCrCtlConConnect(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon,
1007 uint32_t crVersionMajor, uint32_t crVersionMinor,
1008 uint32_t *pu32ClientID)
1009{
1010 if (pDevExt->fCmdVbvaEnabled)
1011 {
1012 return VBoxMpCrCtlConConnectVbva(pDevExt, pCrCtlCon,
1013 crVersionMajor, crVersionMinor,
1014 pu32ClientID);
1015 }
1016 return VBoxMpCrCtlConConnectHgcm(pCrCtlCon,
1017 crVersionMajor, crVersionMinor,
1018 pu32ClientID);
1019}
1020
1021int VBoxMpCrCtlConDisconnectHgcm(PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1022{
1023 int rc = VbglR0CrCtlConDisconnect(pCrCtlCon->hCrCtl, u32ClientID);
1024 if (RT_SUCCESS(rc))
1025 {
1026 vboxMpCrCtlRelease(pCrCtlCon);
1027 return VINF_SUCCESS;
1028 }
1029 WARN(("vboxCrCtlConDisconnect failed, rc (%d)", rc));
1030 return rc;
1031}
1032
1033int VBoxMpCrCtlConDisconnectVbva(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1034{
1035 RT_NOREF(pDevExt, pCrCtlCon);
1036 Assert(!pCrCtlCon->hCrCtl);
1037 Assert(!pCrCtlCon->cCrCtlRefs);
1038 return VBoxCmdVbvaConDisconnect(pDevExt, &pDevExt->CmdVbva, u32ClientID);
1039}
1040
1041int VBoxMpCrCtlConDisconnect(PVBOXMP_DEVEXT pDevExt, PVBOXMP_CRCTLCON pCrCtlCon, uint32_t u32ClientID)
1042{
1043 if (!pCrCtlCon->hCrCtl)
1044 return VBoxMpCrCtlConDisconnectVbva(pDevExt, pCrCtlCon, u32ClientID);
1045 return VBoxMpCrCtlConDisconnectHgcm(pCrCtlCon, u32ClientID);
1046}
1047
1048int VBoxMpCrCtlConCall(PVBOXMP_CRCTLCON pCrCtlCon, PVBGLIOCHGCMCALL pData, uint32_t cbData)
1049{
1050 int rc = VbglR0CrCtlConCallRaw(pCrCtlCon->hCrCtl, pData, cbData);
1051 if (RT_SUCCESS(rc))
1052 return VINF_SUCCESS;
1053
1054 WARN(("vboxCrCtlConCallUserData failed, rc(%d)", rc));
1055 return rc;
1056}
1057
1058int VBoxMpCrCtlConCallUserData(PVBOXMP_CRCTLCON pCrCtlCon, PVBGLIOCHGCMCALL pData, uint32_t cbData)
1059{
1060 int rc = VbglR0CrCtlConCallUserDataRaw(pCrCtlCon->hCrCtl, pData, cbData);
1061 if (RT_SUCCESS(rc))
1062 return VINF_SUCCESS;
1063
1064 WARN(("vboxCrCtlConCallUserData failed, rc(%d)", rc));
1065 return rc;
1066}
1067
1068void VBoxMpCrCtlConInit(void)
1069{
1070 g_VBoxMpCr3DSupported = 0;
1071 memset(&g_VBoxMpCrHostCapsInfo, 0, sizeof (g_VBoxMpCrHostCapsInfo));
1072
1073 VBOXMP_CRCTLCON CrCtlCon = {0};
1074 uint32_t u32ClientID = 0;
1075 int rc = VBoxMpCrCtlConConnectHgcm(&CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &u32ClientID);
1076 if (RT_FAILURE(rc))
1077 {
1078 LOGREL(("VBoxMpCrCtlConConnectHgcm failed with rc(%d), 3D not supported!", rc));
1079 return;
1080 }
1081
1082 rc = vboxMpCrCtlConGetCapsNew(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCapsInfo);
1083 if (RT_FAILURE(rc))
1084 {
1085 WARN(("vboxMpCrCtlConGetCapsNew failed rc (%d), ignoring..", rc));
1086 g_VBoxMpCrHostCapsInfo.u32CmdVbvaVersion = 0;
1087 rc = vboxMpCrCtlConGetCapsLegacy(&CrCtlCon, u32ClientID, &g_VBoxMpCrHostCapsInfo.u32Caps);
1088 if (RT_FAILURE(rc))
1089 {
1090 WARN(("vboxMpCrCtlConGetCapsLegacy failed rc (%d), ignoring..", rc));
1091 g_VBoxMpCrHostCapsInfo.u32Caps = 0;
1092 }
1093 }
1094
1095 if (g_VBoxMpCrHostCapsInfo.u32Caps & CR_VBOX_CAP_HOST_CAPS_NOT_SUFFICIENT)
1096 {
1097 LOGREL(("Insufficient host 3D capabilities"));
1098 g_VBoxMpCr3DSupported = 0;
1099 memset(&g_VBoxMpCrHostCapsInfo, 0, sizeof (g_VBoxMpCrHostCapsInfo));
1100 }
1101 else
1102 {
1103 g_VBoxMpCr3DSupported = 1;
1104 }
1105
1106#if 0 //ndef DEBUG_misha
1107 g_VBoxMpCrHostCapsInfo.u32Caps &= ~CR_VBOX_CAP_CMDVBVA;
1108 g_VBoxMpCrHostCapsInfo.u32CmdVbvaVersion = 0;
1109#endif
1110
1111 rc = VBoxMpCrCtlConDisconnectHgcm(&CrCtlCon, u32ClientID);
1112 if (RT_FAILURE(rc))
1113 WARN(("VBoxMpCrCtlConDisconnectHgcm failed rc (%d), ignoring..", rc));
1114}
1115
1116int VBoxMpCrCmdRxReadbackHandler(CRMessageReadback RT_UNTRUSTED_VOLATILE_HOST *pRx, uint32_t cbRx)
1117{
1118 if (cbRx < sizeof(*pRx))
1119 {
1120 WARN(("invalid rx size %d", cbRx));
1121 return VERR_INVALID_PARAMETER;
1122 }
1123 void *pvSrc = VBoxMpCrCmdRxReadbackData(pRx);
1124 uint32_t cbData = VBoxMpCrCmdRxReadbackDataSize(pRx, cbRx);
1125 void *pvDst = *((void**)&pRx->readback_ptr);
1126 memcpy(pvDst, pvSrc, cbData);
1127 return VINF_SUCCESS;
1128}
1129
1130int VBoxMpCrCmdRxHandler(CRMessageHeader RT_UNTRUSTED_VOLATILE_HOST *pRx, uint32_t cbRx)
1131{
1132 if (cbRx < sizeof(*pRx))
1133 {
1134 WARN(("invalid rx size %d", cbRx));
1135 return VERR_INVALID_PARAMETER;
1136 }
1137 CRMessageType enmType = pRx->type;
1138 switch (enmType)
1139 {
1140 case CR_MESSAGE_READBACK:
1141 return VBoxMpCrCmdRxReadbackHandler((CRMessageReadback RT_UNTRUSTED_VOLATILE_HOST *)pRx, cbRx);
1142 default:
1143 WARN(("unsupported rx message type: %d", enmType));
1144 return VERR_INVALID_PARAMETER;
1145 }
1146}
1147
1148#endif /* VBOX_WITH_CROGL */
Note: See TracBrowser for help on using the repository browser.

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