VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c@ 90520

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

SUPDrv: Build fix when compiling Solaris with VBOX_WITH_NATIVE_SOLARIS_LOADING enabled: remove call to the obsolete and now non-nonexistent VMMR0EntryInt() routine which was nuked in r102142.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 40.0 KB
Line 
1/* $Id: SUPDrv-solaris.c 88169 2021-03-17 19:35:16Z vboxsync $ */
2/** @file
3 * VBoxDrv - The VirtualBox Support Driver - Solaris specifics.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP LOG_GROUP_SUP_DRV
32#include <sys/types.h>
33#include <sys/param.h>
34#include <sys/errno.h>
35#include <sys/uio.h>
36#include <sys/buf.h>
37#include <sys/modctl.h>
38#include <sys/kobj.h>
39#include <sys/kobj_impl.h>
40#include <sys/open.h>
41#include <sys/conf.h>
42#include <sys/cmn_err.h>
43#include <sys/stat.h>
44#include <sys/ddi.h>
45#include <sys/sunddi.h>
46#include <sys/file.h>
47#include <sys/priv_names.h>
48#include <vm/hat.h>
49#undef u /* /usr/include/sys/user.h:249:1 is where this is defined to (curproc->p_user). very cool. */
50
51#include "../SUPDrvInternal.h"
52#include <VBox/log.h>
53#include <VBox/param.h>
54#include <VBox/version.h>
55#include <iprt/semaphore.h>
56#include <iprt/spinlock.h>
57#include <iprt/mp.h>
58#include <iprt/path.h>
59#include <iprt/power.h>
60#include <iprt/process.h>
61#include <iprt/thread.h>
62#include <iprt/initterm.h>
63#include <iprt/alloc.h>
64#include <iprt/string.h>
65#include <iprt/err.h>
66
67#include "dtrace/SUPDrv.h"
68
69extern caddr_t hat_kpm_pfn2va(pfn_t); /* Found in vm/hat.h on solaris 11.3, but not on older like 10u7. */
70
71
72/*********************************************************************************************************************************
73* Defined Constants And Macros *
74*********************************************************************************************************************************/
75/** The system device name. */
76#define DEVICE_NAME_SYS "vboxdrv"
77/** The user device name. */
78#define DEVICE_NAME_USR "vboxdrvu"
79/** The module description as seen in 'modinfo'. */
80#define DEVICE_DESC "VirtualBox HostDrv"
81/** Maximum number of driver instances. */
82#define DEVICE_MAXINSTANCES 16
83
84
85/*********************************************************************************************************************************
86* Internal Functions *
87*********************************************************************************************************************************/
88static int VBoxDrvSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred);
89static int VBoxDrvSolarisClose(dev_t Dev, int fFlag, int fType, cred_t *pCred);
90static int VBoxDrvSolarisRead(dev_t Dev, struct uio *pUio, cred_t *pCred);
91static int VBoxDrvSolarisWrite(dev_t Dev, struct uio *pUio, cred_t *pCred);
92static int VBoxDrvSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArgs, int mode, cred_t *pCred, int *pVal);
93
94static int VBoxDrvSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t Cmd);
95static int VBoxDrvSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t Cmd);
96static int VBoxDrvSolarisQuiesceNotNeeded(dev_info_t *pDip);
97
98static int VBoxSupDrvErr2SolarisErr(int rc);
99static int VBoxDrvSolarisIOCtlSlow(PSUPDRVSESSION pSession, int Cmd, int Mode, intptr_t pArgs);
100
101
102/*********************************************************************************************************************************
103* Global Variables *
104*********************************************************************************************************************************/
105/**
106 * cb_ops: for drivers that support char/block entry points
107 */
108static struct cb_ops g_VBoxDrvSolarisCbOps =
109{
110 VBoxDrvSolarisOpen,
111 VBoxDrvSolarisClose,
112 nodev, /* b strategy */
113 nodev, /* b dump */
114 nodev, /* b print */
115 VBoxDrvSolarisRead,
116 VBoxDrvSolarisWrite,
117 VBoxDrvSolarisIOCtl,
118 nodev, /* c devmap */
119 nodev, /* c mmap */
120 nodev, /* c segmap */
121 nochpoll, /* c poll */
122 ddi_prop_op, /* property ops */
123 NULL, /* streamtab */
124 D_NEW | D_MP, /* compat. flag */
125 CB_REV /* revision */
126};
127
128/**
129 * dev_ops: for driver device operations
130 */
131static struct dev_ops g_VBoxDrvSolarisDevOps =
132{
133 DEVO_REV, /* driver build revision */
134 0, /* ref count */
135 nulldev, /* get info */
136 nulldev, /* identify */
137 nulldev, /* probe */
138 VBoxDrvSolarisAttach,
139 VBoxDrvSolarisDetach,
140 nodev, /* reset */
141 &g_VBoxDrvSolarisCbOps,
142 (struct bus_ops *)0,
143 nodev, /* power */
144 VBoxDrvSolarisQuiesceNotNeeded
145};
146
147/**
148 * modldrv: export driver specifics to the kernel
149 */
150static struct modldrv g_VBoxDrvSolarisModule =
151{
152 &mod_driverops, /* extern from kernel */
153 DEVICE_DESC " " VBOX_VERSION_STRING "r" RT_XSTR(VBOX_SVN_REV),
154 &g_VBoxDrvSolarisDevOps
155};
156
157/**
158 * modlinkage: export install/remove/info to the kernel
159 */
160static struct modlinkage g_VBoxDrvSolarisModLinkage =
161{
162 MODREV_1, /* loadable module system revision */
163 {
164 &g_VBoxDrvSolarisModule,
165 NULL /* terminate array of linkage structures */
166 }
167};
168
169#ifndef USE_SESSION_HASH
170/**
171 * State info for each open file handle.
172 */
173typedef struct
174{
175 /**< Pointer to the session data. */
176 PSUPDRVSESSION pSession;
177} vbox_devstate_t;
178#else
179/** State info. for each driver instance. */
180typedef struct
181{
182 dev_info_t *pDip; /* Device handle */
183} vbox_devstate_t;
184#endif
185
186/** Opaque pointer to list of state */
187static void *g_pVBoxDrvSolarisState;
188
189/** Device extention & session data association structure */
190static SUPDRVDEVEXT g_DevExt;
191
192/** Hash table */
193static PSUPDRVSESSION g_apSessionHashTab[19];
194/** Spinlock protecting g_apSessionHashTab. */
195static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK;
196/** Calculates bucket index into g_apSessionHashTab.*/
197#define SESSION_HASH(sfn) ((sfn) % RT_ELEMENTS(g_apSessionHashTab))
198
199/**
200 * Kernel entry points
201 */
202int _init(void)
203{
204#if 0 /* No IPRT logging before RTR0Init() is done! */
205 LogFlowFunc(("vboxdrv:_init\n"));
206#endif
207
208 /*
209 * Prevent module autounloading.
210 */
211 modctl_t *pModCtl = mod_getctl(&g_VBoxDrvSolarisModLinkage);
212 if (pModCtl)
213 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD;
214 else
215 cmn_err(CE_NOTE, "vboxdrv: failed to disable autounloading!\n");
216
217 /*
218 * Initialize IPRT R0 driver, which internally calls OS-specific r0 init.
219 */
220 int rc = RTR0Init(0);
221 if (RT_SUCCESS(rc))
222 {
223 /*
224 * Initialize the device extension
225 */
226 rc = supdrvInitDevExt(&g_DevExt, sizeof(SUPDRVSESSION));
227 if (RT_SUCCESS(rc))
228 {
229 cmn_err(CE_CONT, "!tsc::mode %s @ tentative %lu Hz\n", SUPGetGIPModeName(g_DevExt.pGip), g_DevExt.pGip->u64CpuHz);
230
231 /*
232 * Initialize the session hash table.
233 */
234 memset(g_apSessionHashTab, 0, sizeof(g_apSessionHashTab));
235 rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxDrvSol");
236 if (RT_SUCCESS(rc))
237 {
238 rc = ddi_soft_state_init(&g_pVBoxDrvSolarisState, sizeof(vbox_devstate_t), 8);
239 if (!rc)
240 {
241 rc = mod_install(&g_VBoxDrvSolarisModLinkage);
242 if (!rc)
243 return rc; /* success */
244
245 ddi_soft_state_fini(&g_pVBoxDrvSolarisState);
246 LogRel(("vboxdrv: mod_install failed! rc=%d\n", rc));
247 }
248 else
249 LogRel(("vboxdrv: failed to initialize soft state.\n"));
250
251 RTSpinlockDestroy(g_Spinlock);
252 g_Spinlock = NIL_RTSPINLOCK;
253 }
254 else
255 {
256 LogRel(("VBoxDrvSolarisAttach: RTSpinlockCreate failed\n"));
257 rc = RTErrConvertToErrno(rc);
258 }
259 supdrvDeleteDevExt(&g_DevExt);
260 }
261 else
262 {
263 LogRel(("VBoxDrvSolarisAttach: supdrvInitDevExt failed\n"));
264 rc = EINVAL;
265 }
266 RTR0TermForced();
267 }
268 else
269 {
270 LogRel(("VBoxDrvSolarisAttach: failed to init R0Drv\n"));
271 rc = RTErrConvertToErrno(rc);
272 }
273 memset(&g_DevExt, 0, sizeof(g_DevExt));
274
275 return rc;
276}
277
278
279int _fini(void)
280{
281 LogFlowFunc(("vboxdrv:_fini\n"));
282
283 /*
284 * Undo the work we did at start (in the reverse order).
285 */
286 int rc = mod_remove(&g_VBoxDrvSolarisModLinkage);
287 if (rc != 0)
288 return rc;
289
290 supdrvDeleteDevExt(&g_DevExt);
291
292 rc = RTSpinlockDestroy(g_Spinlock);
293 AssertRC(rc);
294 g_Spinlock = NIL_RTSPINLOCK;
295
296 RTR0TermForced();
297
298 memset(&g_DevExt, 0, sizeof(g_DevExt));
299
300 ddi_soft_state_fini(&g_pVBoxDrvSolarisState);
301 return 0;
302}
303
304
305int _info(struct modinfo *pModInfo)
306{
307#if 0 /* No IPRT logging before RTR0Init() is done! And yes this is called before _init()!*/
308 LogFlowFunc(("vboxdrv:_init\n"));
309#endif
310 int e = mod_info(&g_VBoxDrvSolarisModLinkage, pModInfo);
311 return e;
312}
313
314
315/**
316 * Attach entry point, to attach a device to the system or resume it.
317 *
318 * @param pDip The module structure instance.
319 * @param enmCmd Operation type (attach/resume).
320 *
321 * @return corresponding solaris error code.
322 */
323static int VBoxDrvSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
324{
325 LogFlowFunc(("VBoxDrvSolarisAttach\n"));
326
327 switch (enmCmd)
328 {
329 case DDI_ATTACH:
330 {
331 int rc;
332#ifdef USE_SESSION_HASH
333 int instance = ddi_get_instance(pDip);
334 vbox_devstate_t *pState;
335
336 if (ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, instance) != DDI_SUCCESS)
337 {
338 LogRel(("VBoxDrvSolarisAttach: state alloc failed\n"));
339 return DDI_FAILURE;
340 }
341
342 pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
343#endif
344
345 /*
346 * Register for suspend/resume notifications
347 */
348 rc = ddi_prop_create(DDI_DEV_T_NONE, pDip, DDI_PROP_CANSLEEP /* kmem alloc can sleep */,
349 "pm-hardware-state", "needs-suspend-resume", sizeof("needs-suspend-resume"));
350 if (rc != DDI_PROP_SUCCESS)
351 LogRel(("vboxdrv: Suspend/Resume notification registration failed.\n"));
352
353 /*
354 * Register ourselves as a character device, pseudo-driver
355 */
356#ifdef VBOX_WITH_HARDENING
357 rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME_SYS, S_IFCHR, 0 /*minor*/, DDI_PSEUDO,
358 0, NULL, NULL, 0600);
359#else
360 rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME_SYS, S_IFCHR, 0 /*minor*/, DDI_PSEUDO,
361 0, "none", "none", 0666);
362#endif
363 if (rc == DDI_SUCCESS)
364 {
365 rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME_USR, S_IFCHR, 1 /*minor*/, DDI_PSEUDO,
366 0, "none", "none", 0666);
367 if (rc == DDI_SUCCESS)
368 {
369#ifdef USE_SESSION_HASH
370 pState->pDip = pDip;
371#endif
372 ddi_report_dev(pDip);
373 return DDI_SUCCESS;
374 }
375 ddi_remove_minor_node(pDip, NULL);
376 }
377
378 return DDI_FAILURE;
379 }
380
381 case DDI_RESUME:
382 {
383#if 0
384 RTSemFastMutexRequest(g_DevExt.mtxGip);
385 if (g_DevExt.pGipTimer)
386 RTTimerStart(g_DevExt.pGipTimer, 0);
387
388 RTSemFastMutexRelease(g_DevExt.mtxGip);
389#endif
390 RTPowerSignalEvent(RTPOWEREVENT_RESUME);
391 LogFlow(("vboxdrv: Awakened from suspend.\n"));
392 return DDI_SUCCESS;
393 }
394
395 default:
396 return DDI_FAILURE;
397 }
398
399 return DDI_FAILURE;
400}
401
402
403/**
404 * Detach entry point, to detach a device to the system or suspend it.
405 *
406 * @param pDip The module structure instance.
407 * @param enmCmd Operation type (detach/suspend).
408 *
409 * @return corresponding solaris error code.
410 */
411static int VBoxDrvSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
412{
413 LogFlowFunc(("VBoxDrvSolarisDetach\n"));
414 switch (enmCmd)
415 {
416 case DDI_DETACH:
417 {
418#ifndef USE_SESSION_HASH
419 ddi_remove_minor_node(pDip, NULL);
420#else
421 int instance = ddi_get_instance(pDip);
422 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
423 ddi_remove_minor_node(pDip, NULL);
424 ddi_soft_state_free(g_pVBoxDrvSolarisState, instance);
425#endif
426 ddi_prop_remove_all(pDip);
427 return DDI_SUCCESS;
428 }
429
430 case DDI_SUSPEND:
431 {
432#if 0
433 RTSemFastMutexRequest(g_DevExt.mtxGip);
434 if (g_DevExt.pGipTimer && g_DevExt.cGipUsers > 0)
435 RTTimerStop(g_DevExt.pGipTimer);
436
437 RTSemFastMutexRelease(g_DevExt.mtxGip);
438#endif
439 RTPowerSignalEvent(RTPOWEREVENT_SUSPEND);
440 LogFlow(("vboxdrv: Falling to suspend mode.\n"));
441 return DDI_SUCCESS;
442
443 }
444
445 default:
446 return DDI_FAILURE;
447 }
448}
449
450
451/**
452 * Quiesce not-needed entry point, as Solaris 10 doesn't have any
453 * ddi_quiesce_not_needed() function.
454 *
455 * @param pDip The module structure instance.
456 *
457 * @return corresponding solaris error code.
458 */
459static int VBoxDrvSolarisQuiesceNotNeeded(dev_info_t *pDip)
460{
461 return DDI_SUCCESS;
462}
463
464
465/**
466 * open() worker.
467 */
468static int VBoxDrvSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred)
469{
470 const bool fUnrestricted = getminor(*pDev) == 0;
471 PSUPDRVSESSION pSession;
472 int rc;
473
474 LogFlowFunc(("VBoxDrvSolarisOpen: pDev=%p:%#x\n", pDev, *pDev));
475
476 /*
477 * Validate input
478 */
479 if ( (getminor(*pDev) != 0 && getminor(*pDev) != 1)
480 || fType != OTYP_CHR)
481 return EINVAL; /* See mmopen for precedent. */
482
483#ifndef USE_SESSION_HASH
484 /*
485 * Locate a new device open instance.
486 *
487 * For each open call we'll allocate an item in the soft state of the device.
488 * The item index is stored in the dev_t. I hope this is ok...
489 */
490 vbox_devstate_t *pState = NULL;
491 unsigned iOpenInstance;
492 for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
493 {
494 if ( !ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance) /* faster */
495 && ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, iOpenInstance) == DDI_SUCCESS)
496 {
497 pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance);
498 break;
499 }
500 }
501 if (!pState)
502 {
503 LogRel(("VBoxDrvSolarisOpen: too many open instances.\n"));
504 return ENXIO;
505 }
506
507 /*
508 * Create a new session.
509 */
510 rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession);
511 if (RT_SUCCESS(rc))
512 {
513 pSession->Uid = crgetruid(pCred);
514 pSession->Gid = crgetrgid(pCred);
515
516 pState->pSession = pSession;
517 *pDev = makedevice(getmajor(*pDev), iOpenInstance);
518 LogFlow(("VBoxDrvSolarisOpen: Dev=%#x pSession=%p pid=%d r0proc=%p thread=%p\n",
519 *pDev, pSession, RTProcSelf(), RTR0ProcHandleSelf(), RTThreadNativeSelf() ));
520 return 0;
521 }
522
523 /* failed - clean up */
524 ddi_soft_state_free(g_pVBoxDrvSolarisState, iOpenInstance);
525
526#else
527 /*
528 * Create a new session.
529 * Sessions in Solaris driver are mostly useless. It's however needed
530 * in VBoxDrvSolarisIOCtlSlow() while calling supdrvIOCtl()
531 */
532 rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession);
533 if (RT_SUCCESS(rc))
534 {
535 unsigned iHash;
536
537 pSession->Uid = crgetruid(pCred);
538 pSession->Gid = crgetrgid(pCred);
539
540 /*
541 * Insert it into the hash table.
542 */
543# error "Only one entry per process!"
544 iHash = SESSION_HASH(pSession->Process);
545 RTSpinlockAcquire(g_Spinlock);
546 pSession->pNextHash = g_apSessionHashTab[iHash];
547 g_apSessionHashTab[iHash] = pSession;
548 RTSpinlockRelease(g_Spinlock);
549 LogFlow(("VBoxDrvSolarisOpen success\n"));
550 }
551
552 int instance;
553 for (instance = 0; instance < DEVICE_MAXINSTANCES; instance++)
554 {
555 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
556 if (pState)
557 break;
558 }
559
560 if (instance >= DEVICE_MAXINSTANCES)
561 {
562 LogRel(("VBoxDrvSolarisOpen: All instances exhausted\n"));
563 return ENXIO;
564 }
565
566 *pDev = makedevice(getmajor(*pDev), instance);
567#endif
568
569 return VBoxSupDrvErr2SolarisErr(rc);
570}
571
572
573static int VBoxDrvSolarisClose(dev_t Dev, int flag, int otyp, cred_t *cred)
574{
575 LogFlowFunc(("VBoxDrvSolarisClose: Dev=%#x\n", Dev));
576
577#ifndef USE_SESSION_HASH
578 /*
579 * Get the session and free the soft state item.
580 */
581 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev));
582 if (!pState)
583 {
584 LogRel(("VBoxDrvSolarisClose: no state data for %#x (%d)\n", Dev, getminor(Dev)));
585 return EFAULT;
586 }
587
588 PSUPDRVSESSION pSession = pState->pSession;
589 pState->pSession = NULL;
590 ddi_soft_state_free(g_pVBoxDrvSolarisState, getminor(Dev));
591
592 if (!pSession)
593 {
594 LogRel(("VBoxDrvSolarisClose: no session in state data for %#x (%d)\n", Dev, getminor(Dev)));
595 return EFAULT;
596 }
597 LogFlow(("VBoxDrvSolarisClose: Dev=%#x pSession=%p pid=%d r0proc=%p thread=%p\n",
598 Dev, pSession, RTProcSelf(), RTR0ProcHandleSelf(), RTThreadNativeSelf() ));
599
600#else
601 const RTPROCESS Process = RTProcSelf();
602 const unsigned iHash = SESSION_HASH(Process);
603 PSUPDRVSESSION pSession;
604
605 /*
606 * Remove from the hash table.
607 */
608 RTSpinlockAcquire(g_Spinlock);
609 pSession = g_apSessionHashTab[iHash];
610 if (pSession)
611 {
612 if (pSession->Process == Process)
613 {
614 g_apSessionHashTab[iHash] = pSession->pNextHash;
615 pSession->pNextHash = NULL;
616 }
617 else
618 {
619 PSUPDRVSESSION pPrev = pSession;
620 pSession = pSession->pNextHash;
621 while (pSession)
622 {
623 if (pSession->Process == Process)
624 {
625 pPrev->pNextHash = pSession->pNextHash;
626 pSession->pNextHash = NULL;
627 break;
628 }
629
630 /* next */
631 pPrev = pSession;
632 pSession = pSession->pNextHash;
633 }
634 }
635 }
636 RTSpinlockRelease(g_Spinlock);
637 if (!pSession)
638 {
639 LogRel(("VBoxDrvSolarisClose: WHAT?!? pSession == NULL! This must be a mistake... pid=%d (close)\n", (int)Process));
640 return EFAULT;
641 }
642#endif
643
644 /*
645 * Close the session.
646 */
647 supdrvSessionRelease(pSession);
648 return 0;
649}
650
651
652static int VBoxDrvSolarisRead(dev_t Dev, struct uio *pUio, cred_t *pCred)
653{
654 LogFlowFunc(("VBoxDrvSolarisRead"));
655 return 0;
656}
657
658
659static int VBoxDrvSolarisWrite(dev_t Dev, struct uio *pUio, cred_t *pCred)
660{
661 LogFlowFunc(("VBoxDrvSolarisWrite"));
662 return 0;
663}
664
665
666/**
667 * Driver ioctl, an alternate entry point for this character driver.
668 *
669 * @param Dev Device number
670 * @param iCmd Operation identifier
671 * @param pArgs Arguments from user to driver
672 * @param Mode Information bitfield (read/write, address space etc.)
673 * @param pCred User credentials
674 * @param pVal Return value for calling process.
675 *
676 * @return corresponding solaris error code.
677 */
678static int VBoxDrvSolarisIOCtl(dev_t Dev, int iCmd, intptr_t pArgs, int Mode, cred_t *pCred, int *pVal)
679{
680#ifndef USE_SESSION_HASH
681 /*
682 * Get the session from the soft state item.
683 */
684 vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev));
685 if (!pState)
686 {
687 LogRel(("VBoxDrvSolarisIOCtl: no state data for %#x (%d)\n", Dev, getminor(Dev)));
688 return EINVAL;
689 }
690
691 PSUPDRVSESSION pSession = pState->pSession;
692 if (!pSession)
693 {
694 LogRel(("VBoxDrvSolarisIOCtl: no session in state data for %#x (%d)\n", Dev, getminor(Dev)));
695 return DDI_SUCCESS;
696 }
697#else
698 const RTPROCESS Process = RTProcSelf();
699 const unsigned iHash = SESSION_HASH(Process);
700 PSUPDRVSESSION pSession;
701 const bool fUnrestricted = getminor(Dev) == 0;
702
703 /*
704 * Find the session.
705 */
706 RTSpinlockAcquire(g_Spinlock);
707 pSession = g_apSessionHashTab[iHash];
708 while (pSession && pSession->Process != Process && pSession->fUnrestricted == fUnrestricted);
709 pSession = pSession->pNextHash;
710 RTSpinlockRelease(g_Spinlock);
711 if (!pSession)
712 {
713 LogRel(("VBoxSupDrvIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x Dev=%#x\n",
714 (int)Process, iCmd, (int)Dev));
715 return EINVAL;
716 }
717#endif
718
719 /*
720 * Deal with the two high-speed IOCtl that takes it's arguments from
721 * the session and iCmd, and only returns a VBox status code.
722 */
723 AssertCompile((SUP_IOCTL_FAST_DO_FIRST & 0xff) == (SUP_IOCTL_FLAG | 64));
724 if ( (unsigned)(iCmd - SUP_IOCTL_FAST_DO_FIRST) < (unsigned)32
725 && pSession->fUnrestricted)
726 {
727 *pVal = supdrvIOCtlFast(iCmd - SUP_IOCTL_FAST_DO_FIRST, pArgs, &g_DevExt, pSession);
728 return 0;
729 }
730
731 return VBoxDrvSolarisIOCtlSlow(pSession, iCmd, Mode, pArgs);
732}
733
734
735/** @def IOCPARM_LEN
736 * Gets the length from the ioctl number.
737 * This is normally defined by sys/ioccom.h on BSD systems...
738 */
739#ifndef IOCPARM_LEN
740# define IOCPARM_LEN(x) ( ((x) >> 16) & IOCPARM_MASK )
741#endif
742
743
744/**
745 * Worker for VBoxSupDrvIOCtl that takes the slow IOCtl functions.
746 *
747 * @returns Solaris errno.
748 *
749 * @param pSession The session.
750 * @param iCmd The IOCtl command.
751 * @param Mode Information bitfield (for specifying ownership of data)
752 * @param iArg User space address of the request buffer.
753 */
754static int VBoxDrvSolarisIOCtlSlow(PSUPDRVSESSION pSession, int iCmd, int Mode, intptr_t iArg)
755{
756 int rc;
757 uint32_t cbBuf = 0;
758 union
759 {
760 SUPREQHDR Hdr;
761 uint8_t abBuf[64];
762 } StackBuf;
763 PSUPREQHDR pHdr;
764
765
766 /*
767 * Read the header.
768 */
769 if (RT_UNLIKELY(IOCPARM_LEN(iCmd) != sizeof(StackBuf.Hdr)))
770 {
771 LogRel(("VBoxDrvSolarisIOCtlSlow: iCmd=%#x len %d expected %d\n", iCmd, IOCPARM_LEN(iCmd), sizeof(StackBuf.Hdr)));
772 return EINVAL;
773 }
774 rc = ddi_copyin((void *)iArg, &StackBuf.Hdr, sizeof(StackBuf.Hdr), Mode);
775 if (RT_UNLIKELY(rc))
776 {
777 LogRel(("VBoxDrvSolarisIOCtlSlow: ddi_copyin(,%#lx,) failed; iCmd=%#x. rc=%d\n", iArg, iCmd, rc));
778 return EFAULT;
779 }
780 if (RT_UNLIKELY((StackBuf.Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
781 {
782 LogRel(("VBoxDrvSolarisIOCtlSlow: bad header magic %#x; iCmd=%#x\n", StackBuf.Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK, iCmd));
783 return EINVAL;
784 }
785 cbBuf = RT_MAX(StackBuf.Hdr.cbIn, StackBuf.Hdr.cbOut);
786 if (RT_UNLIKELY( StackBuf.Hdr.cbIn < sizeof(StackBuf.Hdr)
787 || StackBuf.Hdr.cbOut < sizeof(StackBuf.Hdr)
788 || cbBuf > _1M*16))
789 {
790 LogRel(("VBoxDrvSolarisIOCtlSlow: max(%#x,%#x); iCmd=%#x\n", StackBuf.Hdr.cbIn, StackBuf.Hdr.cbOut, iCmd));
791 return EINVAL;
792 }
793
794 /*
795 * Buffer the request.
796 */
797 if (cbBuf <= sizeof(StackBuf))
798 pHdr = &StackBuf.Hdr;
799 else
800 {
801 pHdr = RTMemTmpAlloc(cbBuf);
802 if (RT_UNLIKELY(!pHdr))
803 {
804 LogRel(("VBoxDrvSolarisIOCtlSlow: failed to allocate buffer of %d bytes for iCmd=%#x.\n", cbBuf, iCmd));
805 return ENOMEM;
806 }
807 }
808 rc = ddi_copyin((void *)iArg, pHdr, cbBuf, Mode);
809 if (RT_UNLIKELY(rc))
810 {
811 LogRel(("VBoxDrvSolarisIOCtlSlow: copy_from_user(,%#lx, %#x) failed; iCmd=%#x. rc=%d\n", iArg, cbBuf, iCmd, rc));
812 if (pHdr != &StackBuf.Hdr)
813 RTMemFree(pHdr);
814 return EFAULT;
815 }
816
817 /*
818 * Process the IOCtl.
819 */
820 rc = supdrvIOCtl(iCmd, &g_DevExt, pSession, pHdr, cbBuf);
821
822 /*
823 * Copy ioctl data and output buffer back to user space.
824 */
825 if (RT_LIKELY(!rc))
826 {
827 uint32_t cbOut = pHdr->cbOut;
828 if (RT_UNLIKELY(cbOut > cbBuf))
829 {
830 LogRel(("VBoxDrvSolarisIOCtlSlow: too much output! %#x > %#x; iCmd=%#x!\n", cbOut, cbBuf, iCmd));
831 cbOut = cbBuf;
832 }
833 rc = ddi_copyout(pHdr, (void *)iArg, cbOut, Mode);
834 if (RT_UNLIKELY(rc != 0))
835 {
836 /* this is really bad */
837 LogRel(("VBoxDrvSolarisIOCtlSlow: ddi_copyout(,%p,%d) failed. rc=%d\n", (void *)iArg, cbBuf, rc));
838 rc = EFAULT;
839 }
840 }
841 else
842 rc = EINVAL;
843
844 if (pHdr != &StackBuf.Hdr)
845 RTMemTmpFree(pHdr);
846 return rc;
847}
848
849
850/**
851 * The SUPDRV IDC entry point.
852 *
853 * @returns VBox status code, see supdrvIDC.
854 * @param uReq The request code.
855 * @param pReq The request.
856 */
857int VBOXCALL SUPDrvSolarisIDC(uint32_t uReq, PSUPDRVIDCREQHDR pReq)
858{
859 PSUPDRVSESSION pSession;
860
861 /*
862 * Some quick validations.
863 */
864 if (RT_UNLIKELY(!VALID_PTR(pReq)))
865 return VERR_INVALID_POINTER;
866
867 pSession = pReq->pSession;
868 if (pSession)
869 {
870 if (RT_UNLIKELY(!VALID_PTR(pSession)))
871 return VERR_INVALID_PARAMETER;
872 if (RT_UNLIKELY(pSession->pDevExt != &g_DevExt))
873 return VERR_INVALID_PARAMETER;
874 }
875 else if (RT_UNLIKELY(uReq != SUPDRV_IDC_REQ_CONNECT))
876 return VERR_INVALID_PARAMETER;
877
878 /*
879 * Do the job.
880 */
881 return supdrvIDC(uReq, &g_DevExt, pSession, pReq);
882}
883
884
885/**
886 * Converts an supdrv error code to a solaris error code.
887 *
888 * @returns corresponding solaris error code.
889 * @param rc IPRT status code.
890 */
891static int VBoxSupDrvErr2SolarisErr(int rc)
892{
893 switch (rc)
894 {
895 case VINF_SUCCESS: return 0;
896 case VERR_GENERAL_FAILURE: return EACCES;
897 case VERR_INVALID_PARAMETER: return EINVAL;
898 case VERR_INVALID_MAGIC: return EILSEQ;
899 case VERR_INVALID_HANDLE: return ENXIO;
900 case VERR_INVALID_POINTER: return EFAULT;
901 case VERR_LOCK_FAILED: return ENOLCK;
902 case VERR_ALREADY_LOADED: return EEXIST;
903 case VERR_PERMISSION_DENIED: return EPERM;
904 case VERR_VERSION_MISMATCH: return ENOSYS;
905 }
906
907 return EPERM;
908}
909
910
911void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
912{
913 NOREF(pDevExt);
914 NOREF(pSession);
915}
916
917
918void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
919{
920 NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
921}
922
923
924void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
925{
926 NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
927}
928
929
930/**
931 * Initializes any OS specific object creator fields.
932 */
933void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
934{
935 NOREF(pObj);
936 NOREF(pSession);
937}
938
939
940/**
941 * Checks if the session can access the object.
942 *
943 * @returns true if a decision has been made.
944 * @returns false if the default access policy should be applied.
945 *
946 * @param pObj The object in question.
947 * @param pSession The session wanting to access the object.
948 * @param pszObjName The object name, can be NULL.
949 * @param prc Where to store the result when returning true.
950 */
951bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
952{
953 NOREF(pObj);
954 NOREF(pSession);
955 NOREF(pszObjName);
956 NOREF(prc);
957 return false;
958}
959
960
961bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
962{
963 return false;
964}
965
966
967bool VBOXCALL supdrvOSAreCpusOfflinedOnSuspend(void)
968{
969 /** @todo verify this. */
970 return false;
971}
972
973
974bool VBOXCALL supdrvOSAreTscDeltasInSync(void)
975{
976 return false;
977}
978
979
980#if defined(VBOX_WITH_NATIVE_SOLARIS_LOADING) \
981 && !defined(VBOX_WITHOUT_NATIVE_R0_LOADER)
982
983int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
984{
985 pImage->idSolMod = -1;
986 pImage->pSolModCtl = NULL;
987
988# if 1 /* This approach requires _init/_fini/_info stubs. */
989 /*
990 * Construct a filename that escapes the module search path and let us
991 * specify a root path.
992 */
993 /** @todo change this to use modctl and use_path=0. */
994 const char *pszName = RTPathFilename(pszFilename);
995 AssertReturn(pszName, VERR_INVALID_PARAMETER);
996 char *pszSubDir = RTStrAPrintf2("../../../../../../../../../../..%.*s", pszName - pszFilename - 1, pszFilename);
997 if (!pszSubDir)
998 return VERR_NO_STR_MEMORY;
999 int idMod = modload(pszSubDir, pszName);
1000 if (idMod == -1)
1001 {
1002 /* This is an horrible hack for avoiding the mod-present check in
1003 modrload on S10. Fortunately, nobody else seems to be using that
1004 variable... */
1005 extern int swaploaded;
1006 int saved_swaploaded = swaploaded;
1007 swaploaded = 0;
1008 idMod = modload(pszSubDir, pszName);
1009 swaploaded = saved_swaploaded;
1010 }
1011 RTStrFree(pszSubDir);
1012 if (idMod == -1)
1013 {
1014 LogRel(("modload(,%s): failed, could be anything...\n", pszFilename));
1015 return VERR_LDR_GENERAL_FAILURE;
1016 }
1017
1018 modctl_t *pModCtl = mod_hold_by_id(idMod);
1019 if (!pModCtl)
1020 {
1021 LogRel(("mod_hold_by_id(,%s): failed, weird.\n", pszFilename));
1022 /* No point in calling modunload. */
1023 return VERR_LDR_GENERAL_FAILURE;
1024 }
1025 pModCtl->mod_loadflags |= MOD_NOAUTOUNLOAD | MOD_NOUNLOAD; /* paranoia */
1026
1027# else
1028
1029 const int idMod = -1;
1030 modctl_t *pModCtl = mod_hold_by_name(pszFilename);
1031 if (!pModCtl)
1032 {
1033 LogRel(("mod_hold_by_name failed for '%s'\n", pszFilename));
1034 return VERR_LDR_GENERAL_FAILURE;
1035 }
1036
1037 int rc = kobj_load_module(pModCtl, 0 /*use_path*/);
1038 if (rc != 0)
1039 {
1040 LogRel(("kobj_load_module failed with rc=%d for '%s'\n", rc, pszFilename));
1041 mod_release_mod(pModCtl);
1042 return RTErrConvertFromErrno(rc);
1043 }
1044# endif
1045
1046 /*
1047 * Get the module info.
1048 *
1049 * Note! The text section is actually not at mi_base, but and the next
1050 * alignment boundrary and there seems to be no easy way of
1051 * getting at this address. This sabotages supdrvOSLdrLoad.
1052 * Bastards!
1053 */
1054 struct modinfo ModInfo;
1055 kobj_getmodinfo(pModCtl->mod_mp, &ModInfo);
1056 pImage->pvImage = ModInfo.mi_base;
1057 pImage->idSolMod = idMod;
1058 pImage->pSolModCtl = pModCtl;
1059
1060 mod_release_mod(pImage->pSolModCtl);
1061 LogRel(("supdrvOSLdrOpen: succeeded for '%s' (mi_base=%p mi_size=%#x), id=%d ctl=%p\n",
1062 pszFilename, ModInfo.mi_base, ModInfo.mi_size, idMod, pModCtl));
1063 return VINF_SUCCESS;
1064}
1065
1066
1067int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv,
1068 const uint8_t *pbImageBits, const char *pszSymbol)
1069{
1070 NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol);
1071 if (kobj_addrcheck(pImage->pSolModCtl->mod_mp, pv))
1072 return VERR_INVALID_PARAMETER;
1073 return VINF_SUCCESS;
1074}
1075
1076
1077/**
1078 * Resolves a module entry point address.
1079 *
1080 * @returns VBox status code.
1081 * @param pImage The image.
1082 * @param pszSymbol The symbol name.
1083 * @param ppvValue Where to store the value. On input this holds
1084 * the symbol value SUPLib calculated.
1085 */
1086static int supdrvSolLdrResolvEp(PSUPDRVLDRIMAGE pImage, const char *pszSymbol, void **ppvValue)
1087{
1088 /* Don't try resolve symbols which, according to SUPLib, aren't there. */
1089 if (!*ppvValue)
1090 return VINF_SUCCESS;
1091
1092 uintptr_t uValue = modlookup_by_modctl(pImage->pSolModCtl, pszSymbol);
1093 if (!uValue)
1094 {
1095 LogRel(("supdrvOSLdrLoad on %s failed to resolve %s\n", pImage->szName, pszSymbol));
1096 return VERR_SYMBOL_NOT_FOUND;
1097 }
1098 *ppvValue = (void *)uValue;
1099 return VINF_SUCCESS;
1100}
1101
1102
1103int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
1104{
1105#if 0 /* This doesn't work because of text alignment. */
1106 /*
1107 * Comparing is very very difficult since text and data may be allocated
1108 * separately.
1109 */
1110 size_t cbCompare = RT_MIN(pImage->cbImageBits, 64);
1111 if (memcmp(pImage->pvImage, pbImageBits, cbCompare))
1112 {
1113 LogRel(("Image mismatch: %s (%p)\n", pImage->szName, pImage->pvImage));
1114 LogRel(("Native: %.*Rhxs\n", cbCompare, pImage->pvImage));
1115 LogRel(("SUPLib: %.*Rhxs\n", cbCompare, pbImageBits));
1116 return VERR_LDR_MISMATCH_NATIVE;
1117 }
1118#endif
1119
1120 /*
1121 * Get the exported symbol addresses.
1122 */
1123 int rc;
1124 modctl_t *pModCtl = mod_hold_by_id(pImage->idSolMod);
1125 if (pModCtl && pModCtl == pImage->pSolModCtl)
1126 {
1127 uint32_t iSym = pImage->cSymbols;
1128 while (iSym-- > 0)
1129 {
1130 const char *pszSymbol = &pImage->pachStrTab[pImage->paSymbols[iSym].offName];
1131 uintptr_t uValue = modlookup_by_modctl(pImage->pSolModCtl, pszSymbol);
1132 if (!uValue)
1133 {
1134 LogRel(("supdrvOSLdrLoad on %s failed to resolve the exported symbol: '%s'\n", pImage->szName, pszSymbol));
1135 break;
1136 }
1137 uintptr_t offSymbol = uValue - (uintptr_t)pImage->pvImage;
1138 pImage->paSymbols[iSym].offSymbol = offSymbol;
1139 if (pImage->paSymbols[iSym].offSymbol != (int32_t)offSymbol)
1140 {
1141 LogRel(("supdrvOSLdrLoad on %s symbol out of range: %p (%s) \n", pImage->szName, offSymbol, pszSymbol));
1142 break;
1143 }
1144 }
1145
1146 rc = iSym == UINT32_MAX ? VINF_SUCCESS : VERR_LDR_GENERAL_FAILURE;
1147
1148 /*
1149 * Get the standard module entry points.
1150 */
1151 if (RT_SUCCESS(rc))
1152 {
1153 rc = supdrvSolLdrResolvEp(pImage, "ModuleInit", (void **)&pImage->pfnModuleInit);
1154 if (RT_SUCCESS(rc))
1155 rc = supdrvSolLdrResolvEp(pImage, "ModuleTerm", (void **)&pImage->pfnModuleTerm);
1156
1157 switch (pReq->u.In.eEPType)
1158 {
1159 case SUPLDRLOADEP_VMMR0:
1160 {
1161 if (RT_SUCCESS(rc))
1162 rc = supdrvSolLdrResolvEp(pImage, "VMMR0EntryFast", (void **)&pReq->u.In.EP.VMMR0.pvVMMR0EntryFast);
1163 if (RT_SUCCESS(rc))
1164 rc = supdrvSolLdrResolvEp(pImage, "VMMR0EntryEx", (void **)&pReq->u.In.EP.VMMR0.pvVMMR0EntryEx);
1165 break;
1166 }
1167
1168 case SUPLDRLOADEP_SERVICE:
1169 {
1170 /** @todo we need the name of the entry point. */
1171 return VERR_NOT_SUPPORTED;
1172 }
1173 }
1174 }
1175
1176 mod_release_mod(pImage->pSolModCtl);
1177 }
1178 else
1179 {
1180 LogRel(("mod_hold_by_id failed in supdrvOSLdrLoad on %s: %p\n", pImage->szName, pModCtl));
1181 rc = VERR_LDR_MISMATCH_NATIVE;
1182 }
1183 return rc;
1184}
1185
1186
1187void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
1188{
1189# if 1
1190 pImage->pSolModCtl->mod_loadflags &= ~MOD_NOUNLOAD;
1191 int rc = modunload(pImage->idSolMod);
1192 if (rc)
1193 LogRel(("modunload(%u (%s)) failed: %d\n", pImage->idSolMod, pImage->szName, rc));
1194# else
1195 kobj_unload_module(pImage->pSolModCtl);
1196# endif
1197 pImage->pSolModCtl = NULL;
1198 pImage->idSolMod = NULL;
1199}
1200
1201#else /* !VBOX_WITH_NATIVE_SOLARIS_LOADING */
1202
1203int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
1204{
1205 NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
1206 return VERR_NOT_SUPPORTED;
1207}
1208
1209
1210int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv,
1211 const uint8_t *pbImageBits, const char *pszSymbol)
1212{
1213 NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol);
1214 return VERR_NOT_SUPPORTED;
1215}
1216
1217
1218int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
1219{
1220 NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
1221 return VERR_NOT_SUPPORTED;
1222}
1223
1224
1225void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
1226{
1227 NOREF(pDevExt); NOREF(pImage);
1228}
1229
1230#endif /* !VBOX_WITH_NATIVE_SOLARIS_LOADING */
1231
1232
1233void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
1234{
1235 NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
1236}
1237
1238
1239void VBOXCALL supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
1240{
1241 NOREF(pDevExt); NOREF(pImage);
1242}
1243
1244
1245int VBOXCALL supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
1246 const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
1247{
1248 RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
1249 return VERR_WRONG_ORDER;
1250}
1251
1252
1253void VBOXCALL supdrvOSLdrRetainWrapperModule(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
1254{
1255 RT_NOREF(pDevExt, pImage);
1256 AssertFailed();
1257}
1258
1259
1260void VBOXCALL supdrvOSLdrReleaseWrapperModule(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
1261{
1262 RT_NOREF(pDevExt, pImage);
1263 AssertFailed();
1264}
1265
1266#ifdef SUPDRV_WITH_MSR_PROBER
1267
1268int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
1269{
1270/** @todo cmi_hdl_rdmsr can safely do this. there is also the on_trap() fun
1271 * for catching traps that could possibly be used directly. */
1272 NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
1273 return VERR_NOT_SUPPORTED;
1274}
1275
1276
1277int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
1278{
1279/** @todo cmi_hdl_wrmsr can safely do this. */
1280 NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
1281 return VERR_NOT_SUPPORTED;
1282}
1283
1284
1285int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
1286{
1287 NOREF(idCpu); NOREF(pReq);
1288 return VERR_NOT_SUPPORTED;
1289}
1290
1291#endif /* SUPDRV_WITH_MSR_PROBER */
1292
1293
1294SUPR0DECL(int) SUPR0HCPhysToVirt(RTHCPHYS HCPhys, void **ppv)
1295{
1296 AssertReturn(!(HCPhys & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
1297 AssertReturn(HCPhys != NIL_RTHCPHYS, VERR_INVALID_POINTER);
1298 HCPhys >>= PAGE_SHIFT;
1299 AssertReturn(HCPhys <= physmax, VERR_INVALID_POINTER);
1300 *ppv = hat_kpm_pfn2va(HCPhys);
1301 return VINF_SUCCESS;
1302}
1303
1304
1305RTDECL(int) SUPR0Printf(const char *pszFormat, ...)
1306{
1307 va_list args;
1308 char szMsg[512];
1309
1310 /* cmn_err() acquires adaptive mutexes. Not preemption safe, see @bugref{6657}. */
1311 if (!RTThreadPreemptIsEnabled(NIL_RTTHREAD))
1312 return 0;
1313
1314 va_start(args, pszFormat);
1315 RTStrPrintfV(szMsg, sizeof(szMsg) - 1, pszFormat, args);
1316 va_end(args);
1317
1318 szMsg[sizeof(szMsg) - 1] = '\0';
1319 cmn_err(CE_CONT, "%s", szMsg);
1320 return 0;
1321}
1322
1323
1324SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
1325{
1326 return 0;
1327}
1328
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