VirtualBox

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

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