VirtualBox

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

Last change on this file since 76553 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: VBoxMPShgsmi.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2011-2019 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#include "VBoxMPWddm.h"
19#include <iprt/semaphore.h>
20
21/* SHGSMI */
22DECLINLINE(void) vboxSHGSMICommandRetain(VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pCmd)
23{
24 ASMAtomicIncU32(&pCmd->cRefs);
25}
26
27void vboxSHGSMICommandFree(PVBOXSHGSMI pHeap, VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pCmd)
28{
29 VBoxSHGSMIHeapFree(pHeap, pCmd);
30}
31
32DECLINLINE(void) vboxSHGSMICommandRelease(PVBOXSHGSMI pHeap, VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pCmd)
33{
34 uint32_t cRefs = ASMAtomicDecU32(&pCmd->cRefs);
35 Assert(cRefs < UINT32_MAX / 2);
36 if(!cRefs)
37 vboxSHGSMICommandFree(pHeap, pCmd);
38}
39
40static DECLCALLBACK(void) vboxSHGSMICompletionSetEvent(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvCmd, void *pvContext)
41{
42 RT_NOREF(pHeap, pvCmd);
43 RTSemEventSignal((RTSEMEVENT)pvContext);
44}
45
46DECLCALLBACK(void) vboxSHGSMICompletionCommandRelease(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvCmd, void *pvContext)
47{
48 RT_NOREF(pvContext);
49 vboxSHGSMICommandRelease(pHeap, VBoxSHGSMIBufferHeader(pvCmd));
50}
51
52/* do not wait for completion */
53DECLINLINE(const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *)
54vboxSHGSMICommandPrepAsynch(PVBOXSHGSMI pHeap, VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader)
55{
56 RT_NOREF(pHeap);
57 /* ensure the command is not removed until we're processing it */
58 vboxSHGSMICommandRetain(pHeader);
59 return pHeader;
60}
61
62DECLINLINE(void) vboxSHGSMICommandDoneAsynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader)
63{
64 if(!(ASMAtomicReadU32((volatile uint32_t *)&pHeader->fFlags) & VBOXSHGSMI_FLAG_HG_ASYNCH))
65 {
66 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = (PFNVBOXSHGSMICMDCOMPLETION)pHeader->u64Info1;
67 if (pfnCompletion)
68 pfnCompletion(pHeap, VBoxSHGSMIBufferData(pHeader), (PVOID)pHeader->u64Info2);
69 }
70
71 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
72}
73
74const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *
75VBoxSHGSMICommandPrepAsynchEvent(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvBuff, RTSEMEVENT hEventSem)
76{
77 VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader = VBoxSHGSMIBufferHeader(pvBuff);
78 pHeader->u64Info1 = (uint64_t)vboxSHGSMICompletionSetEvent;
79 pHeader->u64Info2 = (uintptr_t)hEventSem;
80 pHeader->fFlags = VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
81
82 return vboxSHGSMICommandPrepAsynch(pHeap, pHeader);
83}
84
85const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *VBoxSHGSMICommandPrepSynch(PVBOXSHGSMI pHeap,
86 void RT_UNTRUSTED_VOLATILE_HOST *pCmd)
87{
88 RTSEMEVENT hEventSem;
89 int rc = RTSemEventCreate(&hEventSem);
90 Assert(RT_SUCCESS(rc));
91 if (RT_SUCCESS(rc))
92 {
93 return VBoxSHGSMICommandPrepAsynchEvent(pHeap, pCmd, hEventSem);
94 }
95 return NULL;
96}
97
98void VBoxSHGSMICommandDoneAsynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader)
99{
100 vboxSHGSMICommandDoneAsynch(pHeap, pHeader);
101}
102
103int VBoxSHGSMICommandDoneSynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader)
104{
105 VBoxSHGSMICommandDoneAsynch(pHeap, pHeader);
106 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
107 int rc = RTSemEventWait(hEventSem, RT_INDEFINITE_WAIT);
108 AssertRC(rc);
109 if (RT_SUCCESS(rc))
110 RTSemEventDestroy(hEventSem);
111 return rc;
112}
113
114void VBoxSHGSMICommandCancelAsynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader)
115{
116 vboxSHGSMICommandRelease(pHeap, (PVBOXSHGSMIHEADER)pHeader);
117}
118
119void VBoxSHGSMICommandCancelSynch(PVBOXSHGSMI pHeap, const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader)
120{
121 VBoxSHGSMICommandCancelAsynch(pHeap, pHeader);
122 RTSEMEVENT hEventSem = (RTSEMEVENT)pHeader->u64Info2;
123 RTSemEventDestroy(hEventSem);
124}
125
126const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *
127VBoxSHGSMICommandPrepAsynch(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvBuff,
128 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion,
129 void RT_UNTRUSTED_VOLATILE_HOST *pvCompletion, uint32_t fFlags)
130{
131 fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
132 VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader = VBoxSHGSMIBufferHeader(pvBuff);
133 pHeader->u64Info1 = (uintptr_t)pfnCompletion;
134 pHeader->u64Info2 = (uintptr_t)pvCompletion;
135 pHeader->fFlags = fFlags;
136
137 return vboxSHGSMICommandPrepAsynch(pHeap, pHeader);
138}
139
140const VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *
141VBoxSHGSMICommandPrepAsynchIrq(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvBuff,
142 PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCompletion, PVOID pvCompletion, uint32_t fFlags)
143{
144 fFlags |= VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ | VBOXSHGSMI_FLAG_GH_ASYNCH_IRQ;
145 VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader = VBoxSHGSMIBufferHeader(pvBuff);
146 pHeader->u64Info1 = (uintptr_t)pfnCompletion;
147 pHeader->u64Info2 = (uintptr_t)pvCompletion;
148 /* we must assign rather than or because flags field does not get zeroed on command creation */
149 pHeader->fFlags = fFlags;
150
151 return vboxSHGSMICommandPrepAsynch(pHeap, pHeader);
152}
153
154void RT_UNTRUSTED_VOLATILE_HOST *VBoxSHGSMIHeapAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData, uint8_t u8Channel, uint16_t u16ChannelInfo)
155{
156 KIRQL OldIrql;
157 void RT_UNTRUSTED_VOLATILE_HOST *pvData;
158 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
159 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
160 pvData = HGSMIHeapAlloc(&pHeap->Heap, cbData, u8Channel, u16ChannelInfo);
161 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
162 if (!pvData)
163 WARN(("HGSMIHeapAlloc failed!"));
164 return pvData;
165}
166
167void VBoxSHGSMIHeapFree(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
168{
169 KIRQL OldIrql;
170 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
171 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
172 HGSMIHeapFree(&pHeap->Heap, pvBuffer);
173 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
174}
175
176void RT_UNTRUSTED_VOLATILE_HOST *VBoxSHGSMIHeapBufferAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData)
177{
178 KIRQL OldIrql;
179 void RT_UNTRUSTED_VOLATILE_HOST * pvData;
180 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
181 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
182 pvData = HGSMIHeapBufferAlloc(&pHeap->Heap, cbData);
183 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
184 if (!pvData)
185 WARN(("HGSMIHeapAlloc failed!"));
186 return pvData;
187}
188
189void VBoxSHGSMIHeapBufferFree(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
190{
191 KIRQL OldIrql;
192 Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
193 KeAcquireSpinLock(&pHeap->HeapLock, &OldIrql);
194 HGSMIHeapBufferFree(&pHeap->Heap, pvBuffer);
195 KeReleaseSpinLock(&pHeap->HeapLock, OldIrql);
196}
197
198int VBoxSHGSMIInit(PVBOXSHGSMI pHeap, void *pvBase, HGSMISIZE cbArea, HGSMIOFFSET offBase,
199 const HGSMIENV *pEnv)
200{
201 KeInitializeSpinLock(&pHeap->HeapLock);
202 return HGSMIHeapSetup(&pHeap->Heap, pvBase, cbArea, offBase, pEnv);
203}
204
205void VBoxSHGSMITerm(PVBOXSHGSMI pHeap)
206{
207 HGSMIHeapDestroy(&pHeap->Heap);
208}
209
210void RT_UNTRUSTED_VOLATILE_HOST *VBoxSHGSMICommandAlloc(PVBOXSHGSMI pHeap, HGSMISIZE cbData, uint8_t u8Channel,
211 uint16_t u16ChannelInfo)
212{
213 /* Issue the flush command. */
214 VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader =
215 (VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *)VBoxSHGSMIHeapAlloc(pHeap, cbData + sizeof(VBOXSHGSMIHEADER),
216 u8Channel, u16ChannelInfo);
217 Assert(pHeader);
218 if (pHeader)
219 {
220 pHeader->cRefs = 1;
221 return VBoxSHGSMIBufferData(pHeader);
222 }
223 return NULL;
224}
225
226void VBoxSHGSMICommandFree(PVBOXSHGSMI pHeap, void RT_UNTRUSTED_VOLATILE_HOST *pvBuffer)
227{
228 VBOXSHGSMIHEADER RT_UNTRUSTED_VOLATILE_HOST *pHeader = VBoxSHGSMIBufferHeader(pvBuffer);
229 vboxSHGSMICommandRelease(pHeap, pHeader);
230}
231
232#define VBOXSHGSMI_CMD2LISTENTRY(_pCmd) ((PVBOXVTLIST_ENTRY)&(_pCmd)->pvNext)
233#define VBOXSHGSMI_LISTENTRY2CMD(_pEntry) ( (PVBOXSHGSMIHEADER)((uint8_t *)(_pEntry) - RT_UOFFSETOF(VBOXSHGSMIHEADER, pvNext)) )
234
235int VBoxSHGSMICommandProcessCompletion(PVBOXSHGSMI pHeap, VBOXSHGSMIHEADER *pCur, bool bIrq, PVBOXVTLIST pPostProcessList)
236{
237 int rc = VINF_SUCCESS;
238
239 do
240 {
241 if (pCur->fFlags & VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ)
242 {
243 Assert(bIrq);
244
245 PFNVBOXSHGSMICMDCOMPLETION pfnCompletion = NULL;
246 void *pvCompletion;
247 PFNVBOXSHGSMICMDCOMPLETION_IRQ pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION_IRQ)pCur->u64Info1;
248 void *pvCallback = (void*)pCur->u64Info2;
249
250 pfnCompletion = pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback, &pvCompletion);
251 if (pfnCompletion)
252 {
253 pCur->u64Info1 = (uintptr_t)pfnCompletion;
254 pCur->u64Info2 = (uintptr_t)pvCompletion;
255 pCur->fFlags &= ~VBOXSHGSMI_FLAG_GH_ASYNCH_CALLBACK_IRQ;
256 }
257 else
258 {
259 /* nothing to do with this command */
260 break;
261 }
262 }
263
264 if (!bIrq)
265 {
266 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCur->u64Info1;
267 void *pvCallback = (void*)pCur->u64Info2;
268 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCur), pvCallback);
269 }
270 else
271 vboxVtListPut(pPostProcessList, VBOXSHGSMI_CMD2LISTENTRY(pCur), VBOXSHGSMI_CMD2LISTENTRY(pCur));
272 } while (0);
273
274
275 return rc;
276}
277
278int VBoxSHGSMICommandPostprocessCompletion (PVBOXSHGSMI pHeap, PVBOXVTLIST pPostProcessList)
279{
280 PVBOXVTLIST_ENTRY pNext, pCur;
281 for (pCur = pPostProcessList->pFirst; pCur; pCur = pNext)
282 {
283 /* need to save next since the command may be released in a pfnCallback and thus its data might be invalid */
284 pNext = pCur->pNext;
285 PVBOXSHGSMIHEADER pCmd = VBOXSHGSMI_LISTENTRY2CMD(pCur);
286 PFNVBOXSHGSMICMDCOMPLETION pfnCallback = (PFNVBOXSHGSMICMDCOMPLETION)pCmd->u64Info1;
287 void *pvCallback = (void*)pCmd->u64Info2;
288 pfnCallback(pHeap, VBoxSHGSMIBufferData(pCmd), pvCallback);
289 }
290
291 return VINF_SUCCESS;
292}
Note: See TracBrowser for help on using the repository browser.

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