VirtualBox

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

Last change on this file since 107252 was 107252, checked in by vboxsync, 6 weeks ago

Add,HostDrivers: More parfait/solaris kludges. [fix]

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