VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp@ 90520

Last change on this file since 90520 was 87700, checked in by vboxsync, 4 years ago

SUPDrv,++: Experimental support for wrapping .r0 modules in native kernel modules on linux, so that perf and similar tools work better. Minor IOC version increase as SUP_IOCTL_LDR_OPEN now support just opening a module w/o preparing the loading. SUPDrv must export all the symbols in g_aFunctions the linux way now, or linux won't see them, so introduced a SUPR0_EXPORT_SYMBOL macro similar to RT_EXPORT_SYMBOL. bugref:9937

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.6 KB
Line 
1/* $Id: SUPDrv-os2.cpp 87700 2021-02-10 20:21:04Z vboxsync $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - OS/2 specifics.
4 */
5
6/*
7 * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
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#define LOG_GROUP LOG_GROUP_SUP_DRV
36#define __STDC_CONSTANT_MACROS
37#define __STDC_LIMIT_MACROS
38
39#include <os2ddk/bsekee.h>
40#undef RT_MAX
41
42#include "SUPDrvInternal.h"
43#include <VBox/version.h>
44#include <iprt/initterm.h>
45#include <iprt/string.h>
46#include <iprt/spinlock.h>
47#include <iprt/process.h>
48#include <iprt/assert.h>
49#include <VBox/log.h>
50#include <iprt/param.h>
51
52
53/*********************************************************************************************************************************
54* Global Variables *
55*********************************************************************************************************************************/
56/**
57 * Device extention & session data association structure.
58 */
59static SUPDRVDEVEXT g_DevExt;
60/** Spinlock protecting g_apSessionHashTab. */
61static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
62/** Hash table */
63static PSUPDRVSESSION g_apSessionHashTab[19];
64/** Calculates the index into g_apSessionHashTab.*/
65#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
66
67RT_C_DECLS_BEGIN
68/* Defined in SUPDrvA-os2.asm */
69extern uint16_t g_offLogHead;
70extern uint16_t volatile g_offLogTail;
71extern uint16_t const g_cchLogMax;
72extern char g_szLog[];
73/* (init only:) */
74extern char g_szInitText[];
75extern uint16_t g_cchInitText;
76extern uint16_t g_cchInitTextMax;
77RT_C_DECLS_END
78
79
80/*********************************************************************************************************************************
81* Internal Functions *
82*********************************************************************************************************************************/
83
84
85
86/**
87 * 32-bit Ring-0 initialization.
88 *
89 * @returns 0 on success, non-zero on failure.
90 * @param pszArgs Pointer to the device arguments.
91 */
92DECLASM(int) VBoxDrvInit(const char *pszArgs)
93{
94 /*
95 * Initialize the runtime.
96 */
97 int rc = RTR0Init(0);
98 if (RT_SUCCESS(rc))
99 {
100 Log(("VBoxDrvInit: pszArgs=%s\n", pszArgs));
101
102 /*
103 * Initialize the device extension.
104 */
105 rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION));
106 if (RT_SUCCESS(rc))
107 {
108 /*
109 * Initialize the session hash table.
110 */
111 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvOS2");
112 if (RT_SUCCESS(rc))
113 {
114 /*
115 * Process the commandline. Later.
116 */
117 bool fVerbose = true;
118
119 /*
120 * Success
121 */
122 if (fVerbose)
123 {
124 strcpy(&g_szInitText[0],
125 "\r\n"
126 "VirtualBox.org Support Driver for OS/2 version " VBOX_VERSION_STRING "\r\n"
127 "Copyright (C) 2007 Knut St. Osmundsen\r\n"
128 "Copyright (C) 2007-2020 Oracle Corporation\r\n");
129 g_cchInitText = strlen(&g_szInitText[0]);
130 }
131 return VINF_SUCCESS;
132 }
133 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTSpinlockCreate failed, rc=%Rrc\n", rc);
134 supdrvDeleteDevExt(&g_DevExt);
135 }
136 else
137 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: supdrvInitDevExt failed, rc=%Rrc\n", rc);
138 RTR0Term();
139 }
140 else
141 g_cchInitText = RTStrPrintf(&g_szInitText[0], g_cchInitTextMax, "VBoxDrv.sys: RTR0Init failed, rc=%Rrc\n", rc);
142 return rc;
143}
144
145
146DECLASM(int) VBoxDrvOpen(uint16_t sfn)
147{
148 int rc;
149 PSUPDRVSESSION pSession;
150
151 /*
152 * Create a new session.
153 */
154 rc = supdrvCreateSession(&g_DevExt, true /* fUser */, true /*fUnrestricted*/, &pSession);
155 if (RT_SUCCESS(rc))
156 {
157 pSession->sfn = sfn;
158
159 /*
160 * Insert it into the hash table.
161 */
162 unsigned iHash = SESSION_HASH(sfn);
163 RTSpinlockAcquire(g_Spinlock);
164 pSession->pNextHash = g_apSessionHashTab[iHash];
165 g_apSessionHashTab[iHash] = pSession;
166 RTSpinlockRelease(g_Spinlock);
167 }
168
169 Log(("VBoxDrvOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, (int)RTProcSelf()));
170 return rc;
171}
172
173
174DECLASM(int) VBoxDrvClose(uint16_t sfn)
175{
176 Log(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn));
177
178 /*
179 * Remove from the hash table.
180 */
181 PSUPDRVSESSION pSession;
182 const RTPROCESS Process = RTProcSelf();
183 const unsigned iHash = SESSION_HASH(sfn);
184 RTSpinlockAcquire(g_Spinlock);
185
186 pSession = g_apSessionHashTab[iHash];
187 if (pSession)
188 {
189 if ( pSession->sfn == sfn
190 && pSession->Process == Process)
191 {
192 g_apSessionHashTab[iHash] = pSession->pNextHash;
193 pSession->pNextHash = NULL;
194 }
195 else
196 {
197 PSUPDRVSESSION pPrev = pSession;
198 pSession = pSession->pNextHash;
199 while (pSession)
200 {
201 if ( pSession->sfn == sfn
202 && pSession->Process == Process)
203 {
204 pPrev->pNextHash = pSession->pNextHash;
205 pSession->pNextHash = NULL;
206 break;
207 }
208
209 /* next */
210 pPrev = pSession;
211 pSession = pSession->pNextHash;
212 }
213 }
214 }
215 RTSpinlockRelease(g_Spinlock);
216 if (!pSession)
217 {
218 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn));
219 return VERR_INVALID_PARAMETER;
220 }
221
222 /*
223 * Close the session.
224 */
225 supdrvSessionRelease(pSession);
226 return 0;
227}
228
229
230DECLASM(int) VBoxDrvIOCtlFast(uint16_t sfn, uint8_t iFunction)
231{
232 /*
233 * Find the session.
234 */
235 const RTPROCESS Process = RTProcSelf();
236 const unsigned iHash = SESSION_HASH(sfn);
237 PSUPDRVSESSION pSession;
238
239 RTSpinlockAcquire(g_Spinlock);
240 pSession = g_apSessionHashTab[iHash];
241 if (pSession && pSession->Process != Process)
242 {
243 do pSession = pSession->pNextHash;
244 while ( pSession
245 && ( pSession->sfn != sfn
246 || pSession->Process != Process));
247
248 if (RT_LIKELY(pSession))
249 supdrvSessionRetain(pSession);
250 }
251 RTSpinlockRelease(g_Spinlock);
252 if (RT_UNLIKELY(!pSession))
253 {
254 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
255 return VERR_INVALID_PARAMETER;
256 }
257
258 /*
259 * Dispatch the fast IOCtl.
260 */
261 int rc;
262 if ((unsigned)(iFunction - SUP_IOCTL_FAST_DO_FIRST) < (unsigned)32)
263 rc = supdrvIOCtlFast(iFunction, 0, &g_DevExt, pSession);
264 else
265 rc = VERR_INVALID_FUNCTION;
266 supdrvSessionRelease(pSession);
267 return rc;
268}
269
270
271DECLASM(int) VBoxDrvIOCtl(uint16_t sfn, uint8_t iCat, uint8_t iFunction, void *pvParm, void *pvData, uint16_t *pcbParm, uint16_t *pcbData)
272{
273 /*
274 * Find the session.
275 */
276 const RTPROCESS Process = RTProcSelf();
277 const unsigned iHash = SESSION_HASH(sfn);
278 PSUPDRVSESSION pSession;
279
280 RTSpinlockAcquire(g_Spinlock);
281 pSession = g_apSessionHashTab[iHash];
282 if (pSession && pSession->Process != Process)
283 {
284 do pSession = pSession->pNextHash;
285 while ( pSession
286 && ( pSession->sfn != sfn
287 || pSession->Process != Process));
288
289 if (RT_LIKELY(pSession))
290 supdrvSessionRetain(pSession);
291 }
292 RTSpinlockRelease(g_Spinlock);
293 if (!pSession)
294 {
295 OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d\n", (int)Process));
296 return VERR_INVALID_PARAMETER;
297 }
298
299 /*
300 * Verify the category and dispatch the IOCtl.
301 */
302 if (RT_LIKELY(iCat == SUP_CTL_CATEGORY))
303 {
304 Log(("VBoxDrvIOCtl: pSession=%p iFunction=%#x pvParm=%p pvData=%p *pcbParm=%d *pcbData=%d\n", pSession, iFunction, pvParm, pvData, *pcbParm, *pcbData));
305 Assert(pvParm);
306 Assert(!pvData);
307
308 /*
309 * Lock the header.
310 */
311 PSUPREQHDR pHdr = (PSUPREQHDR)pvParm;
312 AssertReturn(*pcbParm == sizeof(*pHdr), VERR_INVALID_PARAMETER);
313 KernVMLock_t Lock;
314 int rc = KernVMLock(VMDHL_WRITE, pHdr, *pcbParm, &Lock, (KernPageList_t *)-1, NULL);
315 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, *pcbParm, &Lock, rc), VERR_LOCK_FAILED);
316
317 /*
318 * Validate the header.
319 */
320 if (RT_LIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) == SUPREQHDR_FLAGS_MAGIC))
321 {
322 uint32_t cbReq = RT_MAX(pHdr->cbIn, pHdr->cbOut);
323 if (RT_LIKELY( pHdr->cbIn >= sizeof(*pHdr)
324 && pHdr->cbOut >= sizeof(*pHdr)
325 && cbReq <= _1M*16))
326 {
327 /*
328 * Lock the rest of the buffer if necessary.
329 */
330 if (((uintptr_t)pHdr & PAGE_OFFSET_MASK) + cbReq > PAGE_SIZE)
331 {
332 rc = KernVMUnlock(&Lock);
333 AssertMsgReturn(!rc, ("KernVMUnlock(Lock) -> %#x\n", rc), VERR_LOCK_FAILED);
334
335 rc = KernVMLock(VMDHL_WRITE, pHdr, cbReq, &Lock, (KernPageList_t *)-1, NULL);
336 AssertMsgReturn(!rc, ("KernVMLock(VMDHL_WRITE, %p, %#x, &p, NULL, NULL) -> %d\n", pHdr, cbReq, &Lock, rc), VERR_LOCK_FAILED);
337 }
338
339 /*
340 * Process the IOCtl.
341 */
342 rc = supdrvIOCtl(iFunction, &g_DevExt, pSession, pHdr, cbReq);
343 }
344 else
345 {
346 OSDBGPRINT(("VBoxDrvIOCtl: max(%#x,%#x); iCmd=%#x\n", pHdr->cbIn, pHdr->cbOut, iFunction));
347 rc = VERR_INVALID_PARAMETER;
348 }
349 }
350 else
351 {
352 OSDBGPRINT(("VBoxDrvIOCtl: bad magic fFlags=%#x; iCmd=%#x\n", pHdr->fFlags, iFunction));
353 rc = VERR_INVALID_PARAMETER;
354 }
355
356 /*
357 * Unlock and return.
358 */
359 int rc2 = KernVMUnlock(&Lock);
360 AssertMsg(!rc2, ("rc2=%d\n", rc2)); NOREF(rc2);s
361 }
362 else
363 rc = VERR_NOT_SUPPORTED;
364
365 supdrvSessionRelease(pSession);
366 Log2(("VBoxDrvIOCtl: returns %d\n", rc));
367 return rc;
368}
369
370
371void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
372{
373 NOREF(pDevExt);
374 NOREF(pSession);
375}
376
377
378void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
379{
380 NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
381}
382
383
384void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
385{
386 NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
387}
388
389
390void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
391{
392 NOREF(pObj);
393 NOREF(pSession);
394}
395
396
397bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
398{
399 NOREF(pObj);
400 NOREF(pSession);
401 NOREF(pszObjName);
402 NOREF(prc);
403 return false;
404}
405
406
407bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
408{
409 NOREF(pDevExt);
410 return false;
411}
412
413
414bool VBOXCALL supdrvOSAreCpusOfflinedOnSuspend(void)
415{
416 return false;
417}
418
419
420bool VBOXCALL supdrvOSAreTscDeltasInSync(void)
421{
422 NOREF(pDevExt);
423 return false;
424}
425
426
427int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
428{
429 NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
430 return VERR_NOT_SUPPORTED;
431}
432
433
434int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv,
435 const uint8_t *pbImageBits, const char *pszSymbol)
436{
437 NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol);
438 return VERR_NOT_SUPPORTED;
439}
440
441
442int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
443{
444 NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
445 return VERR_NOT_SUPPORTED;
446}
447
448
449void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
450{
451 NOREF(pDevExt); NOREF(pImage);
452}
453
454
455void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
456{
457 NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
458}
459
460
461void VBOXCALL supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
462{
463 NOREF(pDevExt); NOREF(pImage);
464}
465
466
467int VBOXCALL supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
468 const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
469{
470 RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
471 return VERR_WRONG_ORDER;
472}
473
474
475void VBOXCALL supdrvOSLdrRetainWrapperModule(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
476{
477 RT_NOREF(pDevExt, pImage);
478 AssertFailed();
479}
480
481
482void VBOXCALL supdrvOSLdrReleaseWrapperModule(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
483{
484 RT_NOREF(pDevExt, pImage);
485 AssertFailed();
486}
487
488#ifdef SUPDRV_WITH_MSR_PROBER
489
490int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
491{
492 NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
493 return VERR_NOT_SUPPORTED;
494}
495
496
497int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
498{
499 NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
500 return VERR_NOT_SUPPORTED;
501}
502
503
504int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
505{
506 NOREF(idCpu); NOREF(pReq);
507 return VERR_NOT_SUPPORTED;
508}
509
510#endif /* SUPDRV_WITH_MSR_PROBER */
511
512
513/**
514 * Callback for writing to the log buffer.
515 *
516 * @returns number of bytes written.
517 * @param pvArg Unused.
518 * @param pachChars Pointer to an array of utf-8 characters.
519 * @param cbChars Number of bytes in the character array pointed to by pachChars.
520 */
521static DECLCALLBACK(size_t) VBoxDrvLogOutput(void *pvArg, const char *pachChars, size_t cbChars)
522{
523 size_t cchWritten = 0;
524 while (cbChars-- > 0)
525 {
526 const uint16_t offLogHead = g_offLogHead;
527 const uint16_t offLogHeadNext = (offLogHead + 1) & (g_cchLogMax - 1);
528 if (offLogHeadNext == g_offLogTail)
529 break; /* no */
530 g_szLog[offLogHead] = *pachChars++;
531 g_offLogHead = offLogHeadNext;
532 cchWritten++;
533 }
534 return cchWritten;
535}
536
537
538SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
539{
540 va_list va;
541
542#if 0 //def DEBUG_bird
543 va_start(va, pszFormat);
544 RTLogComPrintfV(pszFormat, va);
545 va_end(va);
546#endif
547
548 va_start(va, pszFormat);
549 int cch = RTLogFormatV(VBoxDrvLogOutput, NULL, pszFormat, va);
550 va_end(va);
551
552 return cch;
553}
554
555
556SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
557{
558 return 0;
559}
560
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