VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use