VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCM.cpp@ 75804

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

VBoxGuest: Added an IDC interface for faster HGCM calls (VBGL_IOCTL_IDC_HGCM_FAST_CALL, VbglR0HGCMFastCall). This expects the caller to construct a valid call and only concerns itself with issuing it to the host and waiting for the result to arrive. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.4 KB
Line 
1/* $Id: VBoxGuestR0LibHGCM.cpp 75547 2018-11-18 04:50:34Z vboxsync $ */
2/** @file
3 * VBoxGuestLib - Host-Guest Communication Manager, ring-0 client drivers.
4 *
5 * These public functions can be only used by other drivers. They all
6 * do an IOCTL to VBoxGuest via IDC.
7 */
8
9/*
10 * Copyright (C) 2006-2018 Oracle Corporation
11 *
12 * Permission is hereby granted, free of charge, to any person
13 * obtaining a copy of this software and associated documentation
14 * files (the "Software"), to deal in the Software without
15 * restriction, including without limitation the rights to use,
16 * copy, modify, merge, publish, distribute, sublicense, and/or sell
17 * copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following
19 * conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
26 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
28 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 * OTHER DEALINGS IN THE SOFTWARE.
32 */
33
34
35/*********************************************************************************************************************************
36* Header Files *
37*********************************************************************************************************************************/
38#include "VBoxGuestR0LibInternal.h"
39
40#include <iprt/assert.h>
41#include <iprt/semaphore.h>
42#include <iprt/string.h>
43
44#ifdef VBGL_VBOXGUEST
45# error "This file shouldn't be part of the VBoxGuestR0LibBase library that is linked into VBoxGuest. It's client code."
46#endif
47
48
49/*********************************************************************************************************************************
50* Defined Constants And Macros *
51*********************************************************************************************************************************/
52#define VBGL_HGCM_ASSERT_MSG AssertReleaseMsg
53
54
55/*********************************************************************************************************************************
56* Global Variables *
57*********************************************************************************************************************************/
58/**
59 * Fast heap for HGCM handles data.
60 * @{
61 */
62static RTSEMFASTMUTEX g_hMtxHGCMHandleData;
63static struct VBGLHGCMHANDLEDATA g_aHGCMHandleData[64];
64/** @} */
65
66
67/**
68 * Initializes the HGCM VBGL bits.
69 *
70 * @return VBox status code.
71 */
72DECLR0VBGL(int) VbglR0HGCMInit(void)
73{
74 AssertReturn(g_hMtxHGCMHandleData == NIL_RTSEMFASTMUTEX, VINF_ALREADY_INITIALIZED);
75 return RTSemFastMutexCreate(&g_hMtxHGCMHandleData);
76}
77
78/**
79 * Initializes the HGCM VBGL bits.
80 *
81 * @return VBox status code.
82 */
83DECLR0VBGL(int) VbglR0HGCMTerminate(void)
84{
85 RTSemFastMutexDestroy(g_hMtxHGCMHandleData);
86 g_hMtxHGCMHandleData = NIL_RTSEMFASTMUTEX;
87
88 return VINF_SUCCESS;
89}
90
91DECLINLINE(int) vbglR0HandleHeapEnter(void)
92{
93 int rc = RTSemFastMutexRequest(g_hMtxHGCMHandleData);
94
95 VBGL_HGCM_ASSERT_MSG(RT_SUCCESS(rc), ("Failed to request handle heap mutex, rc = %Rrc\n", rc));
96
97 return rc;
98}
99
100DECLINLINE(void) vbglR0HandleHeapLeave(void)
101{
102 RTSemFastMutexRelease(g_hMtxHGCMHandleData);
103}
104
105struct VBGLHGCMHANDLEDATA *vbglR0HGCMHandleAlloc(void)
106{
107 struct VBGLHGCMHANDLEDATA *p = NULL;
108 int rc = vbglR0HandleHeapEnter();
109 if (RT_SUCCESS(rc))
110 {
111 uint32_t i;
112
113 /* Simple linear search in array. This will be called not so often, only connect/disconnect. */
114 /** @todo bitmap for faster search and other obvious optimizations. */
115 for (i = 0; i < RT_ELEMENTS(g_aHGCMHandleData); i++)
116 {
117 if (!g_aHGCMHandleData[i].fAllocated)
118 {
119 p = &g_aHGCMHandleData[i];
120 p->fAllocated = 1;
121 break;
122 }
123 }
124
125 vbglR0HandleHeapLeave();
126
127 VBGL_HGCM_ASSERT_MSG(p != NULL, ("Not enough HGCM handles.\n"));
128 }
129 return p;
130}
131
132void vbglR0HGCMHandleFree(struct VBGLHGCMHANDLEDATA *pHandle)
133{
134 if (pHandle)
135 {
136 int rc = vbglR0HandleHeapEnter();
137 if (RT_SUCCESS(rc))
138 {
139 VBGL_HGCM_ASSERT_MSG(pHandle->fAllocated, ("Freeing not allocated handle.\n"));
140
141 RT_ZERO(*pHandle);
142 vbglR0HandleHeapLeave();
143 }
144 }
145}
146
147DECLR0VBGL(int) VbglR0HGCMConnect(VBGLHGCMHANDLE *pHandle, const char *pszServiceName, HGCMCLIENTID *pidClient)
148{
149 int rc;
150 if (pHandle && pszServiceName && pidClient)
151 {
152 struct VBGLHGCMHANDLEDATA *pHandleData = vbglR0HGCMHandleAlloc();
153 if (pHandleData)
154 {
155 rc = VbglR0IdcOpen(&pHandleData->IdcHandle,
156 VBGL_IOC_VERSION /*uReqVersion*/,
157 VBGL_IOC_VERSION & UINT32_C(0xffff0000) /*uMinVersion*/,
158 NULL /*puSessionVersion*/, NULL /*puDriverVersion*/, NULL /*uDriverRevision*/);
159 if (RT_SUCCESS(rc))
160 {
161 VBGLIOCHGCMCONNECT Info;
162 RT_ZERO(Info);
163 VBGLREQHDR_INIT(&Info.Hdr, HGCM_CONNECT);
164 Info.u.In.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
165 rc = RTStrCopy(Info.u.In.Loc.u.host.achName, sizeof(Info.u.In.Loc.u.host.achName), pszServiceName);
166 if (RT_SUCCESS(rc))
167 {
168 rc = VbglR0IdcCall(&pHandleData->IdcHandle, VBGL_IOCTL_HGCM_CONNECT, &Info.Hdr, sizeof(Info));
169 if (RT_SUCCESS(rc))
170 {
171 *pidClient = Info.u.Out.idClient;
172 *pHandle = pHandleData;
173 return rc;
174 }
175 }
176
177 VbglR0IdcClose(&pHandleData->IdcHandle);
178 }
179
180 vbglR0HGCMHandleFree(pHandleData);
181 }
182 else
183 rc = VERR_NO_MEMORY;
184 }
185 else
186 rc = VERR_INVALID_PARAMETER;
187 return rc;
188}
189
190DECLR0VBGL(int) VbglR0HGCMDisconnect(VBGLHGCMHANDLE handle, HGCMCLIENTID idClient)
191{
192 int rc;
193 VBGLIOCHGCMDISCONNECT Info;
194
195 RT_ZERO(Info);
196 VBGLREQHDR_INIT(&Info.Hdr, HGCM_DISCONNECT);
197 Info.u.In.idClient = idClient;
198 rc = VbglR0IdcCall(&handle->IdcHandle, VBGL_IOCTL_HGCM_DISCONNECT, &Info.Hdr, sizeof(Info));
199
200 VbglR0IdcClose(&handle->IdcHandle);
201
202 vbglR0HGCMHandleFree(handle);
203
204 return rc;
205}
206
207DECLR0VBGL(int) VbglR0HGCMCallRaw(VBGLHGCMHANDLE handle, PVBGLIOCHGCMCALL pData, uint32_t cbData)
208{
209 VBGL_HGCM_ASSERT_MSG(cbData >= sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(HGCMFunctionParameter),
210 ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->cParms,
211 sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(VBGLIOCHGCMCALL)));
212
213 return VbglR0IdcCallRaw(&handle->IdcHandle, VBGL_IOCTL_HGCM_CALL(cbData), &pData->Hdr, cbData);
214}
215
216DECLR0VBGL(int) VbglR0HGCMCall(VBGLHGCMHANDLE handle, PVBGLIOCHGCMCALL pData, uint32_t cbData)
217{
218 int rc = VbglR0HGCMCallRaw(handle, pData, cbData);
219 if (RT_SUCCESS(rc))
220 rc = pData->Hdr.rc;
221 return rc;
222}
223
224DECLR0VBGL(int) VbglR0HGCMCallUserDataRaw(VBGLHGCMHANDLE handle, PVBGLIOCHGCMCALL pData, uint32_t cbData)
225{
226 VBGL_HGCM_ASSERT_MSG(cbData >= sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(HGCMFunctionParameter),
227 ("cbData = %d, cParms = %d (calculated size %d)\n", cbData, pData->cParms,
228 sizeof(VBGLIOCHGCMCALL) + pData->cParms * sizeof(VBGLIOCHGCMCALL)));
229
230 return VbglR0IdcCallRaw(&handle->IdcHandle, VBGL_IOCTL_HGCM_CALL_WITH_USER_DATA(cbData), &pData->Hdr, cbData);
231}
232
233
234DECLR0VBGL(int) VbglR0HGCMFastCall(VBGLHGCMHANDLE hHandle, PVBGLIOCIDCHGCMFASTCALL pCallReq, uint32_t cbCallReq)
235{
236 /* pCallReq->Hdr.rc and pCallReq->HgcmCallReq.header.header.rc; are not used by this IDC. */
237 return VbglR0IdcCallRaw(&hHandle->IdcHandle, VBGL_IOCTL_IDC_HGCM_FAST_CALL, &pCallReq->Hdr, cbCallReq);
238}
239
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