VirtualBox

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

Last change on this file since 82590 was 82590, checked in by vboxsync, 5 years ago

SUPDrv,IPRT: Adding SUPR0HCPhysToVirt to linux & solaris; introducing IPRT_WITHOUT_EFLAGS_AC_PRESERVING and VBOX_WITHOUT_EFLAGS_AC_SET_IN_VBOXDRV config macros for disabling EFLAGS.AC hacks (not active). bugref:9627

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette