VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibInit.cpp@ 75893

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

VBoxGuestLib.h: Forgot to commit VbglR0QueryHostFeatures.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.9 KB
Line 
1/* $Id: VBoxGuestR0LibInit.cpp 75600 2018-11-19 21:15:16Z vboxsync $ */
2/** @file
3 * VBoxGuestLibR0 - Library initialization.
4 */
5
6/*
7 * Copyright (C) 2006-2018 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include "VBoxGuestR0LibInternal.h"
36
37#include <iprt/string.h>
38#include <iprt/assert.h>
39#include <iprt/semaphore.h>
40
41
42/*********************************************************************************************************************************
43* Global Variables *
44*********************************************************************************************************************************/
45/** The global VBGL instance data. */
46VBGLDATA g_vbgldata;
47
48
49/**
50 * Used by vbglR0QueryDriverInfo and VbglInit to try get the host feature mask
51 * and version information (g_vbgldata::hostVersion).
52 *
53 * This was first implemented by the host in 3.1 and we quietly ignore failures
54 * for that reason.
55 */
56static void vbglR0QueryHostVersion(void)
57{
58 VMMDevReqHostVersion *pReq;
59 int rc = VbglR0GRAlloc((VMMDevRequestHeader **) &pReq, sizeof (*pReq), VMMDevReq_GetHostVersion);
60 if (RT_SUCCESS(rc))
61 {
62 rc = VbglR0GRPerform(&pReq->header);
63 if (RT_SUCCESS(rc))
64 {
65 g_vbgldata.hostVersion = *pReq;
66 Log(("vbglR0QueryHostVersion: %u.%u.%ur%u %#x\n",
67 pReq->major, pReq->minor, pReq->build, pReq->revision, pReq->features));
68 }
69
70 VbglR0GRFree(&pReq->header);
71 }
72}
73
74
75#ifndef VBGL_VBOXGUEST
76/**
77 * The guest library uses lazy initialization for VMMDev port and memory,
78 * because these values are provided by the VBoxGuest driver and it might
79 * be loaded later than other drivers.
80 *
81 * The VbglEnter checks the current library status, tries to retrieve these
82 * values and fails if they are unavailable.
83 */
84static int vbglR0QueryDriverInfo(void)
85{
86# ifdef VBGLDATA_USE_FAST_MUTEX
87 int rc = RTSemFastMutexRequest(g_vbgldata.hMtxIdcSetup);
88# else
89 int rc = RTSemMutexRequest(g_vbgldata.hMtxIdcSetup, RT_INDEFINITE_WAIT);
90# endif
91 if (RT_SUCCESS(rc))
92 {
93 if (g_vbgldata.status == VbglStatusReady)
94 { /* likely */ }
95 else
96 {
97 rc = VbglR0IdcOpen(&g_vbgldata.IdcHandle,
98 VBGL_IOC_VERSION /*uReqVersion*/,
99 VBGL_IOC_VERSION & UINT32_C(0xffff0000) /*uMinVersion*/,
100 NULL /*puSessionVersion*/, NULL /*puDriverVersion*/, NULL /*puDriverRevision*/);
101 if (RT_SUCCESS(rc))
102 {
103 /*
104 * Try query the port info.
105 */
106 VBGLIOCGETVMMDEVIOINFO PortInfo;
107 RT_ZERO(PortInfo);
108 VBGLREQHDR_INIT(&PortInfo.Hdr, GET_VMMDEV_IO_INFO);
109 rc = VbglR0IdcCall(&g_vbgldata.IdcHandle, VBGL_IOCTL_GET_VMMDEV_IO_INFO, &PortInfo.Hdr, sizeof(PortInfo));
110 if (RT_SUCCESS(rc))
111 {
112 dprintf(("Port I/O = 0x%04x, MMIO = %p\n", PortInfo.u.Out.IoPort, PortInfo.u.Out.pvVmmDevMapping));
113
114 g_vbgldata.portVMMDev = PortInfo.u.Out.IoPort;
115 g_vbgldata.pVMMDevMemory = (VMMDevMemory *)PortInfo.u.Out.pvVmmDevMapping;
116 g_vbgldata.status = VbglStatusReady;
117
118 vbglR0QueryHostVersion();
119 }
120 }
121
122 dprintf(("vbglQueryDriverInfo rc = %Rrc\n", rc));
123 }
124
125# ifdef VBGLDATA_USE_FAST_MUTEX
126 RTSemFastMutexRelease(g_vbgldata.hMtxIdcSetup);
127# else
128 RTSemMutexRelease(g_vbgldata.hMtxIdcSetup);
129# endif
130 }
131 return rc;
132}
133#endif /* !VBGL_VBOXGUEST */
134
135/**
136 * Checks if VBGL has been initialized.
137 *
138 * The client library, this will lazily complete the initialization.
139 *
140 * @return VINF_SUCCESS or VERR_VBGL_NOT_INITIALIZED.
141 */
142int vbglR0Enter(void)
143{
144 if (g_vbgldata.status == VbglStatusReady)
145 return VINF_SUCCESS;
146
147#ifndef VBGL_VBOXGUEST
148 if (g_vbgldata.status == VbglStatusInitializing)
149 {
150 vbglR0QueryDriverInfo();
151 if (g_vbgldata.status == VbglStatusReady)
152 return VINF_SUCCESS;
153 }
154#endif
155 return VERR_VBGL_NOT_INITIALIZED;
156}
157
158
159static int vbglR0InitCommon(void)
160{
161 int rc;
162
163 RT_ZERO(g_vbgldata);
164 g_vbgldata.status = VbglStatusInitializing;
165
166 rc = VbglR0PhysHeapInit();
167 if (RT_SUCCESS(rc))
168 {
169 dprintf(("vbglR0InitCommon: returns rc = %d\n", rc));
170 return rc;
171 }
172
173 LogRel(("vbglR0InitCommon: VbglR0PhysHeapInit failed: rc=%Rrc\n", rc));
174 g_vbgldata.status = VbglStatusNotInitialized;
175 return rc;
176}
177
178
179static void vbglR0TerminateCommon(void)
180{
181 VbglR0PhysHeapTerminate();
182 g_vbgldata.status = VbglStatusNotInitialized;
183}
184
185#ifdef VBGL_VBOXGUEST
186
187DECLR0VBGL(int) VbglR0InitPrimary(RTIOPORT portVMMDev, VMMDevMemory *pVMMDevMemory, uint32_t *pfFeatures)
188{
189 int rc;
190
191# ifdef RT_OS_WINDOWS /** @todo r=bird: this doesn't make sense. Is there something special going on on windows? */
192 dprintf(("vbglInit: starts g_vbgldata.status %d\n", g_vbgldata.status));
193
194 if ( g_vbgldata.status == VbglStatusInitializing
195 || g_vbgldata.status == VbglStatusReady)
196 {
197 /* Initialization is already in process. */
198 return VINF_SUCCESS;
199 }
200# else
201 dprintf(("vbglInit: starts\n"));
202# endif
203
204 rc = vbglR0InitCommon();
205 if (RT_SUCCESS(rc))
206 {
207 g_vbgldata.portVMMDev = portVMMDev;
208 g_vbgldata.pVMMDevMemory = pVMMDevMemory;
209 g_vbgldata.status = VbglStatusReady;
210
211 vbglR0QueryHostVersion();
212 *pfFeatures = g_vbgldata.hostVersion.features;
213 return VINF_SUCCESS;
214 }
215
216 g_vbgldata.status = VbglStatusNotInitialized;
217 return rc;
218}
219
220DECLR0VBGL(void) VbglR0TerminatePrimary(void)
221{
222 vbglR0TerminateCommon();
223}
224
225
226#else /* !VBGL_VBOXGUEST */
227
228DECLR0VBGL(int) VbglR0InitClient(void)
229{
230 int rc;
231
232 /** @todo r=bird: explain why we need to be doing this, please... */
233 if ( g_vbgldata.status == VbglStatusInitializing
234 || g_vbgldata.status == VbglStatusReady)
235 {
236 /* Initialization is already in process. */
237 return VINF_SUCCESS;
238 }
239
240 rc = vbglR0InitCommon();
241 if (RT_SUCCESS(rc))
242 {
243# ifdef VBGLDATA_USE_FAST_MUTEX
244 rc = RTSemFastMutexCreate(&g_vbgldata.hMtxIdcSetup);
245# else
246 rc = RTSemMutexCreate(&g_vbgldata.hMtxIdcSetup);
247# endif
248 if (RT_SUCCESS(rc))
249 {
250 /* Try to obtain VMMDev port via IOCTL to VBoxGuest main driver. */
251 vbglR0QueryDriverInfo();
252
253# ifdef VBOX_WITH_HGCM
254 rc = VbglR0HGCMInit();
255# endif
256 if (RT_SUCCESS(rc))
257 return VINF_SUCCESS;
258
259# ifdef VBGLDATA_USE_FAST_MUTEX
260 RTSemFastMutexDestroy(g_vbgldata.hMtxIdcSetup);
261 g_vbgldata.hMtxIdcSetup = NIL_RTSEMFASTMUTEX;
262# else
263 RTSemMutexDestroy(g_vbgldata.hMtxIdcSetup);
264 g_vbgldata.hMtxIdcSetup = NIL_RTSEMMUTEX;
265# endif
266 }
267 vbglR0TerminateCommon();
268 }
269
270 return rc;
271}
272
273DECLR0VBGL(void) VbglR0TerminateClient(void)
274{
275# ifdef VBOX_WITH_HGCM
276 VbglR0HGCMTerminate();
277# endif
278
279 /* driver open could fail, which does not prevent VbglInit from succeeding,
280 * close the driver only if it is opened */
281 VbglR0IdcClose(&g_vbgldata.IdcHandle);
282# ifdef VBGLDATA_USE_FAST_MUTEX
283 RTSemFastMutexDestroy(g_vbgldata.hMtxIdcSetup);
284 g_vbgldata.hMtxIdcSetup = NIL_RTSEMFASTMUTEX;
285# else
286 RTSemMutexDestroy(g_vbgldata.hMtxIdcSetup);
287 g_vbgldata.hMtxIdcSetup = NIL_RTSEMMUTEX;
288# endif
289
290 /* note: do vbglR0TerminateCommon as a last step since it zeroez up the g_vbgldata
291 * conceptually, doing vbglR0TerminateCommon last is correct
292 * since this is the reverse order to how init is done */
293 vbglR0TerminateCommon();
294}
295
296
297int VBOXCALL vbglR0QueryIdcHandle(PVBGLIDCHANDLE *ppIdcHandle)
298{
299 if (g_vbgldata.status == VbglStatusReady)
300 { /* likely */ }
301 else
302 {
303 vbglR0QueryDriverInfo();
304 if (g_vbgldata.status != VbglStatusReady)
305 {
306 *ppIdcHandle = NULL;
307 return VERR_TRY_AGAIN;
308 }
309 }
310
311 *ppIdcHandle = &g_vbgldata.IdcHandle;
312 return VINF_SUCCESS;
313}
314
315
316DECLR0VBGL(int) VbglR0QueryHostFeatures(uint32_t *pfHostFeatures)
317{
318 if (g_vbgldata.status == VbglStatusReady)
319 *pfHostFeatures = g_vbgldata.hostVersion.features;
320 else
321 {
322 int rc = vbglR0QueryDriverInfo();
323 if (g_vbgldata.status != VbglStatusReady)
324 return rc;
325 *pfHostFeatures = g_vbgldata.hostVersion.features;
326 }
327
328 return VINF_SUCCESS;
329}
330
331#endif /* !VBGL_VBOXGUEST */
332
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