VirtualBox

Changeset 75705 in vbox for trunk/src


Ignore:
Timestamp:
Nov 25, 2018 1:44:41 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
126904
Message:

VBoxGuest/darwin: Implemented straight forward interrupt handling. Enabled test signing. Adjustments. bugref:4686

Location:
trunk/src/VBox/Additions/common/VBoxGuest
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/Makefile.kmk

    r75552 r75705  
    181181 INSTALLS += VBoxGuest.kext
    182182 VBoxGuest.kext_INST     = $(INST_ADDITIONS)/VBoxGuest.kext/Contents/
    183  VBoxGuest.kext_SOURCES  = $(VBoxGuest.kext_0_OUTDIR)/Info.plist
    184  VBoxGuest.kext_CLEAN    = $(VBoxGuest.kext_0_OUTDIR)/Info.plist
    185 
    186 $$(VBoxGuest.kext_0_OUTDIR)/Info.plist: \
     183 VBoxGuest.kext_SOURCES  = $(VBoxGuest.kext_0_OUTDIR)/Contents/Info.plist
     184 VBoxGuest.kext_CLEAN    = $(VBoxGuest.kext_0_OUTDIR)/Contents/Info.plist
     185 VBoxGuest.kext_BLDDIRS  = $(VBoxGuest.kext_0_OUTDIR)/Contents/
     186
     187$$(VBoxGuest.kext_0_OUTDIR)/Contents/Info.plist: \
    187188                $(PATH_SUB_CURRENT)/darwin/Info.plist \
    188189                $(VBOX_VERSION_MK) | $$(dir $$@)
     
    199200                --output $@ \
    200201                $<
     202
     203$(evalcall2 VBOX_TEST_SIGN_KEXT,VBoxGuest)
    201204endif # darwin
    202205
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp

    r70873 r75705  
    4646#include <iprt/initterm.h>
    4747#include <iprt/mem.h>
     48#include <iprt/power.h>
    4849#include <iprt/process.h>
    49 #include <iprt/power.h>
    5050#include <iprt/semaphore.h>
    5151#include <iprt/spinlock.h>
     
    7474*   Defined Constants And Macros                                                                                                 *
    7575*********************************************************************************************************************************/
    76 
    7776/** The system device node name. */
    7877#define DEVICE_NAME_SYS     "vboxguest"
    7978/** The user device node name. */
    8079#define DEVICE_NAME_USR     "vboxguestu"
     80
     81
     82/** @name For debugging/whatever, now permanent.
     83 * @{  */
     84#define VBOX_PROC_SELFNAME_LEN              31
     85#define VBOX_RETRIEVE_CUR_PROC_NAME(a_Name) char a_Name[VBOX_PROC_SELFNAME_LEN + 1]; \
     86                                            proc_selfname(a_Name, VBOX_PROC_SELFNAME_LEN)
     87/** @} */
    8188
    8289
     
    122129
    123130protected:
     131#ifdef USE_INTERRUPT_SOURCE
    124132    IOWorkLoop                *m_pWorkLoop;
     133#else
     134    /** Non-NULL if interrupts are registered.  Probably same as getProvider(). */
     135    IOService                 *m_pInterruptProvider;
     136#endif
    125137
    126138public:
     139    virtual bool init(OSDictionary *pDictionary = 0);
     140    virtual void free(void);
     141    virtual IOService *probe(IOService *pProvider, SInt32 *pi32Score);
    127142    virtual bool start(IOService *pProvider);
    128143    virtual void stop(IOService *pProvider);
    129144    virtual bool terminate(IOOptionBits fOptions);
     145#ifdef USE_INTERRUPT_SOURCE
    130146    IOWorkLoop * getWorkLoop();
     147#else
     148    static void  vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc);
     149
     150#endif
    131151};
    132152
     
    146166
    147167private:
     168    /** Guard against the parent class growing and us using outdated headers. */
     169    uint8_t m_abSafetyPadding[256];
     170
    148171    PVBOXGUESTSESSION           m_pSession;     /**< The session. */
    149172    task_t                      m_Task;         /**< The client task. */
     
    155178    static  void sessionClose(RTPROCESS Process);
    156179    virtual IOReturn clientClose(void);
     180    virtual IOReturn clientDied(void);
     181    virtual bool terminate(IOOptionBits fOptions = 0);
     182    virtual bool finalize(IOOptionBits fOptions);
     183    virtual void stop(IOService *pProvider);
     184
     185    RTR0MEMEF_NEW_AND_DELETE_OPERATORS_IOKIT();
    157186};
    158187
     
    205234
    206235/** Major device number. */
    207 static int                  g_iMajorDeviceNo    = -1;
     236static int                  g_iMajorDeviceNo = -1;
    208237/** Registered devfs device handle. */
    209 static void                *g_hDevFsDeviceSys   = NULL;
     238static void                *g_hDevFsDeviceSys = NULL;
    210239/** Registered devfs device handle for the user device. */
    211 static void                *g_hDevFsDeviceUsr   = NULL; /**< @todo 4 later */
     240static void                *g_hDevFsDeviceUsr = NULL; /**< @todo 4 later */
    212241
    213242/** Spinlock protecting g_apSessionHashTab. */
    214 static RTSPINLOCK           g_Spinlock          = NIL_RTSPINLOCK;
     243static RTSPINLOCK           g_Spinlock = NIL_RTSPINLOCK;
    215244/** Hash table */
    216245static PVBOXGUESTSESSION    g_apSessionHashTab[19];
     
    218247#define SESSION_HASH(pid)   ((pid) % RT_ELEMENTS(g_apSessionHashTab))
    219248/** The number of open sessions. */
    220 static int32_t volatile     g_cSessions         = 0;
    221 /** The number of IOService class instances. */
    222 static bool volatile        g_fInstantiated     = 0;
     249static int32_t volatile     g_cSessions = 0;
     250/** Makes sure there is only one org_virtualbox_VBoxGuest instance. */
     251static bool volatile        g_fInstantiated = 0;
    223252/** The notifier handle for the sleep callback handler. */
    224 static IONotifier          *g_pSleepNotifier    = NULL;
    225 
     253static IONotifier          *g_pSleepNotifier = NULL;
     254
     255#ifdef USE_INTERRUPT_SOURCE
    226256/* States of atimic variable aimed to protect dynamic object allocation in SMP environment. */
    227257#define VBOXGUEST_OBJECT_UNINITIALIZED  (0)
     
    231261/** Atomic variable used to protect work loop allocation when multiple threads attempt to obtain it. */
    232262static uint8_t volatile     g_fWorkLoopCreated  = VBOXGUEST_OBJECT_UNINITIALIZED;
     263#endif
    233264
    234265
     
    239270{
    240271    RT_NOREF(pKModInfo, pvData);
     272#ifdef DEBUG
     273    printf("vgdrvDarwinStart\n");
     274#endif
     275#if 0
     276    gIOKitDebug |= 0x001 //kIOLogAttach
     277                |  0x002 //kIOLogProbe
     278                |  0x004 //kIOLogStart
     279                |  0x008 //kIOLogRegister
     280                |  0x010 //kIOLogMatch
     281                |  0x020 //kIOLogConfig
     282                ;
     283#endif
    241284
    242285    /*
     
    250293    }
    251294
     295    RTLogBackdoorPrintf("VBoxGuest: RTR0Init failed with rc=%Rrc\n", rc);
    252296    printf("VBoxGuest: RTR0Init failed with rc=%d\n", rc);
    253297    return KMOD_RETURN_FAILURE;
     298}
     299
     300
     301/**
     302 * Stop the kernel module.
     303 */
     304static kern_return_t vgdrvDarwinStop(struct kmod_info *pKModInfo, void *pvData)
     305{
     306    RT_NOREF(pKModInfo, pvData);
     307
     308    /** @todo we need to check for VBoxSF clients? */
     309
     310    RTLogBackdoorPrintf("VBoxGuest: calling RTR0TermForced ...\n");
     311    RTR0TermForced();
     312
     313    RTLogBackdoorPrintf("VBoxGuest: vgdrvDarwinStop returns.\n");
     314    printf("VBoxGuest: driver unloaded\n");
     315    return KMOD_RETURN_SUCCESS;
    254316}
    255317
     
    269331        if (g_iMajorDeviceNo >= 0)
    270332        {
     333            /** @todo limit /dev/vboxguest access. */
    271334            g_hDevFsDeviceSys = devfs_make_node(makedev(g_iMajorDeviceNo, 0), DEVFS_CHAR,
    272335                                                UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_SYS);
     
    274337            {
    275338                /*
    276                  * Register a sleep/wakeup notification callback.
     339                 * And a all-user device.
    277340                 */
    278                 g_pSleepNotifier = registerPrioritySleepWakeInterest(&vgdrvDarwinSleepHandler, &g_DevExt, NULL);
    279                 if (g_pSleepNotifier != NULL)
     341                g_hDevFsDeviceUsr = devfs_make_node(makedev(g_iMajorDeviceNo, 1), DEVFS_CHAR,
     342                                                    UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_USR);
     343                if (g_hDevFsDeviceUsr != NULL)
    280344                {
    281                     return KMOD_RETURN_SUCCESS;
     345                    /*
     346                     * Register a sleep/wakeup notification callback.
     347                     */
     348                    g_pSleepNotifier = registerPrioritySleepWakeInterest(&vgdrvDarwinSleepHandler, &g_DevExt, NULL);
     349                    if (g_pSleepNotifier != NULL)
     350                        return KMOD_RETURN_SUCCESS;
    282351                }
    283352            }
     
    290359
    291360/**
    292  * Stop the kernel module.
    293  */
    294 static kern_return_t vgdrvDarwinStop(struct kmod_info *pKModInfo, void *pvData)
    295 {
    296     RT_NOREF(pKModInfo, pvData);
    297     RTR0TermForced();
    298 
    299     printf("VBoxGuest: driver unloaded\n");
    300     return KMOD_RETURN_SUCCESS;
    301 }
    302 
    303 
    304 /* Unregister VBoxGuest char device */
     361 * Unregister VBoxGuest char devices and associated session spinlock.
     362 */
    305363static int vgdrvDarwinCharDevRemove(void)
    306364{
    307     int rc = KMOD_RETURN_SUCCESS;
    308 
    309365    if (g_pSleepNotifier)
    310366    {
     
    338394    }
    339395
    340     return rc;
     396    return KMOD_RETURN_SUCCESS;
    341397}
    342398
     
    361417
    362418    /*
     419     * The process issuing the request must be the current process.
     420     */
     421    RTPROCESS Process = RTProcSelf();
     422    if ((int)Process != proc_pid(pProcess))
     423        return EIO;
     424
     425    /*
    363426     * Find the session created by org_virtualbox_VBoxGuestClient, fail
    364427     * if no such session, and mark it as opened. We set the uid & gid
    365428     * here too, since that is more straight forward at this point.
    366429     */
    367     //const bool          fUnrestricted = minor(Dev) == 0;
     430    const bool          fUnrestricted = minor(Dev) == 0;
    368431    int                 rc = VINF_SUCCESS;
    369432    PVBOXGUESTSESSION   pSession = NULL;
     
    371434    if (pCred)
    372435    {
    373         RTPROCESS       Process = RTProcSelf();
    374436        unsigned        iHash = SESSION_HASH(Process);
    375437        RTSpinlockAcquire(g_Spinlock);
     
    383445            {
    384446                pSession->fOpened = true;
    385                 /*pSession->fUnrestricted = fUnrestricted; - later */
     447                pSession->fUserSession = !fUnrestricted;
    386448            }
    387449            else
     
    431493 * @param   Dev         The device number (major+minor).
    432494 * @param   iCmd        The IOCtl command.
    433  * @param   pData     Pointer to the request data.
     495 * @param   pData       Pointer to the request data.
    434496 * @param   fFlags      Flag saying we're a character device (like we didn't know already).
    435497 * @param   pProcess    The process issuing this request.
     
    438500{
    439501    RT_NOREF(Dev, fFlags);
    440     //const bool          fUnrestricted = minor(Dev) == 0;
     502    const bool          fUnrestricted = minor(Dev) == 0;
    441503    const RTPROCESS     Process = proc_pid(pProcess);
    442504    const unsigned      iHash = SESSION_HASH(Process);
     
    448510    RTSpinlockAcquire(g_Spinlock);
    449511    pSession = g_apSessionHashTab[iHash];
    450     while (pSession && pSession->Process != Process && (/*later: pSession->fUnrestricted != fUnrestricted ||*/ !pSession->fOpened))
     512    while (pSession && (pSession->Process != Process || pSession->fUserSession == fUnrestricted || !pSession->fOpened))
    451513        pSession = pSession->pNextHash;
     514
     515    //if (RT_LIKELY(pSession))
     516    //    supdrvSessionRetain(pSession);
     517
    452518    RTSpinlockRelease(g_Spinlock);
    453519    if (!pSession)
    454520    {
    455         Log(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n", (int)Process, iCmd));
     521        Log(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n",
     522             (int)Process, iCmd));
    456523        return EINVAL;
    457524    }
     
    460527     * Deal with the high-speed IOCtl.
    461528     */
     529    int rc;
    462530    if (VBGL_IOCTL_IS_FAST(iCmd))
    463         return VGDrvCommonIoCtlFast(iCmd, &g_DevExt, pSession);
    464 
    465     return vgdrvDarwinIOCtlSlow(pSession, iCmd, pData, pProcess);
     531        rc = VGDrvCommonIoCtlFast(iCmd, &g_DevExt, pSession);
     532    else
     533        rc = vgdrvDarwinIOCtlSlow(pSession, iCmd, pData, pProcess);
     534
     535    //supdrvSessionRelease(pSession);
     536    return rc;
    466537}
    467538
     
    679750/**
    680751 * Callback for blah blah blah.
     752 *
     753 * @todo move to IPRT.
    681754 */
    682755static IOReturn vgdrvDarwinSleepHandler(void *pvTarget, void *pvRefCon, UInt32 uMessageType,
     
    727800 * org_virtualbox_VBoxGuest
    728801 *
    729  */
    730 
     802 * - IOService diff resync -
     803 * - IOService diff resync -
     804 * - IOService diff resync -
     805 *
     806 */
     807
     808
     809/**
     810 * Initialize the object.
     811 */
     812bool org_virtualbox_VBoxGuest::init(OSDictionary *pDictionary)
     813{
     814    LogFlow(("IOService::init([%p], %p)\n", this, pDictionary));
     815    if (IOService::init(pDictionary))
     816    {
     817        /* init members. */
     818        return true;
     819    }
     820    return false;
     821}
     822
     823
     824/**
     825 * Free the object.
     826 */
     827void org_virtualbox_VBoxGuest::free(void)
     828{
     829    RTLogBackdoorPrintf("IOService::free([%p])\n", this); /* might got sideways if we use LogFlow() here. weird. */
     830    IOService::free();
     831}
     832
     833
     834/**
     835 * Check if it's ok to start this service.
     836 * It's always ok by us, so it's up to IOService to decide really.
     837 */
     838IOService *org_virtualbox_VBoxGuest::probe(IOService *pProvider, SInt32 *pi32Score)
     839{
     840    LogFlow(("IOService::probe([%p])\n", this));
     841    IOService *pRet = IOService::probe(pProvider, pi32Score);
     842    LogFlow(("IOService::probe([%p]) returns %p *pi32Score=%d\n", this, pRet, pi32Score ? *pi32Score : -1));
     843    return pRet;
     844}
     845
     846
     847/**
     848 * Start this service.
     849 */
     850bool org_virtualbox_VBoxGuest::start(IOService *pProvider)
     851{
     852    LogFlow(("IOService::start([%p])\n", this));
     853
     854    /*
     855     * Low level initialization / device initialization should be performed only once.
     856     */
     857    if (ASMAtomicCmpXchgBool(&g_fInstantiated, true, false))
     858    {
     859        /*
     860         * Make sure it's a PCI device.
     861         */
     862        m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider);
     863        if (m_pIOPCIDevice)
     864        {
     865            /*
     866             * Call parent.
     867             */
     868            if (IOService::start(pProvider))
     869            {
     870                /*
     871                 * Is it the VMM device?
     872                 */
     873                if (isVmmDev(m_pIOPCIDevice))
     874                {
     875                    /*
     876                     * Enable I/O port and memory regions on the device.
     877                     */
     878                    m_pIOPCIDevice->setMemoryEnable(true);
     879                    m_pIOPCIDevice->setIOEnable(true);
     880
     881                    /*
     882                     * Region #0: I/O ports. Mandatory.
     883                     */
     884                    IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0);
     885                    if (pMem)
     886                    {
     887                        IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress();
     888                        if ((IOPortBasePhys >> 16) == 0)
     889                        {
     890                            RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys;
     891                            void    *pvMMIOBase = NULL;
     892                            uint32_t cbMMIO     = 0;
     893
     894                            /*
     895                             * Region #1: Shared Memory.  Technically optional.
     896                             */
     897                            m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1);
     898                            if (m_pMap)
     899                            {
     900                                pvMMIOBase = (void *)m_pMap->getVirtualAddress();
     901                                cbMMIO     = m_pMap->getLength();
     902                            }
     903
     904                            /*
     905                             * Initialize the device extension.
     906                             */
     907                            int rc = VGDrvCommonInitDevExt(&g_DevExt, IOPortBase, pvMMIOBase, cbMMIO,
     908                                                           ARCH_BITS == 64 ? VBOXOSTYPE_MacOS_x64 : VBOXOSTYPE_MacOS, 0);
     909                            if (RT_SUCCESS(rc))
     910                            {
     911                                /*
     912                                 * Register the device nodes and enable interrupts.
     913                                 */
     914                                rc = vgdrvDarwinCharDevInit();
     915                                if (rc == KMOD_RETURN_SUCCESS)
     916                                {
     917                                    if (setupVmmDevInterrupts(pProvider))
     918                                    {
     919                                        /*
     920                                         * Read host configuration.
     921                                         */
     922                                        VGDrvCommonProcessOptionsFromHost(&g_DevExt);
     923
     924                                        /*
     925                                         * Just register the service and we're done!
     926                                         */
     927                                        registerService();
     928
     929                                        LogRel(("VBoxGuest: IOService started\n"));
     930                                        return true;
     931                                    }
     932
     933                                    LogRel(("VBoxGuest: Failed to set up interrupts\n"));
     934                                    vgdrvDarwinCharDevRemove();
     935                                }
     936                                else
     937                                    LogRel(("VBoxGuest: Failed to initialize character devices (rc=%#x).\n", rc));
     938
     939                                VGDrvCommonDeleteDevExt(&g_DevExt);
     940                            }
     941                            else
     942                                LogRel(("VBoxGuest: Failed to initialize common code (rc=%Rrc).\n", rc));
     943
     944                            if (m_pMap)
     945                            {
     946                                m_pMap->release();
     947                                m_pMap = NULL;
     948                            }
     949                        }
     950                        else
     951                            LogRel(("VBoxGuest: Bad I/O port address: %#RX64\n", (uint64_t)IOPortBasePhys));
     952                    }
     953                    else
     954                        LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n"));
     955                }
     956                else
     957                    LogRel(("VBoxGuest: Not the VMMDev (%#x:%#x).\n",
     958                           m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID), m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID)));
     959
     960                IOService::stop(pProvider);
     961            }
     962        }
     963        else
     964            LogRel(("VBoxGuest: Provider is not an instance of IOPCIDevice.\n"));
     965
     966        ASMAtomicXchgBool(&g_fInstantiated, false);
     967    }
     968    return false;
     969}
     970
     971
     972/**
     973 * Stop this service.
     974 */
     975void org_virtualbox_VBoxGuest::stop(IOService *pProvider)
     976{
     977#ifdef LOG_ENABLED
     978    RTLogBackdoorPrintf("org_virtualbox_VBoxGuest::stop([%p], %p)\n", this, pProvider); /* Being cautious here, no Log(). */
     979#endif
     980    AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated));
     981
     982    /* Low level termination should be performed only once */
     983    if (!disableVmmDevInterrupts())
     984        printf("VBoxGuest: unable to unregister interrupt handler\n");
     985
     986    vgdrvDarwinCharDevRemove();
     987    VGDrvCommonDeleteDevExt(&g_DevExt);
     988
     989    if (m_pMap)
     990    {
     991        m_pMap->release();
     992        m_pMap = NULL;
     993    }
     994
     995    IOService::stop(pProvider);
     996
     997    ASMAtomicWriteBool(&g_fInstantiated, false);
     998
     999    printf("VBoxGuest: IOService stopped\n");
     1000    RTLogBackdoorPrintf("org_virtualbox_VBoxGuest::stop: returning\n"); /* Being cautious here, no Log(). */
     1001}
     1002
     1003
     1004/**
     1005 * Termination request.
     1006 *
     1007 * @return  true if we're ok with shutting down now, false if we're not.
     1008 * @param   fOptions        Flags.
     1009 */
     1010bool org_virtualbox_VBoxGuest::terminate(IOOptionBits fOptions)
     1011{
     1012#ifdef LOG_ENABLED
     1013    RTLogBackdoorPrintf("org_virtualbox_VBoxGuest::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n",
     1014                        KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions); /* Being cautious here, no Log(). */
     1015#endif
     1016
     1017    bool fRc;
     1018    if (   KMOD_INFO_NAME.reference_count != 0
     1019        || ASMAtomicUoReadS32(&g_cSessions))
     1020        fRc = false;
     1021    else
     1022        fRc = IOService::terminate(fOptions);
     1023
     1024#ifdef LOG_ENABLED
     1025    RTLogBackdoorPrintf("org_virtualbox_SupDrv::terminate: returns %d\n", fRc); /* Being cautious here, no Log(). */
     1026#endif
     1027    return fRc;
     1028}
     1029
     1030#ifdef USE_INTERRUPT_SOURCE
    7311031
    7321032/**
     
    8501150}
    8511151
    852 
     1152#else  /* !USE_INTERRUPT_SOURCE */
     1153
     1154/**
     1155 * Implementes a IOInterruptHandler, called by provider when an interrupt occurs.
     1156 */
     1157/*static*/ void org_virtualbox_VBoxGuest::vgdrvDarwinIrqHandler(OSObject *pTarget, void *pvRefCon, IOService *pNub, int iSrc)
     1158{
     1159    RTLogBackdoorPrintf("vgdrvDarwinIrqHandler: %p %p %p %d\n", pTarget, pvRefCon, pNub, iSrc);
     1160    RT_NOREF(pvRefCon, pNub, iSrc);
     1161
     1162    bool fTaken = VGDrvCommonISR(&g_DevExt);
     1163    if (fTaken)
     1164    {
     1165        RTLogBackdoorPrintf("VBoxGuest: our interrupt!\n");
     1166# ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP /* Turns out this isn't needed.  Will ditch it later. */
     1167        /*
     1168         * This is essentially what IOFilterInterruptEventSource does, only it
     1169         * disables after the filter returns true and re-enables again after
     1170         * the workloop job has called the handler.
     1171         */
     1172        org_virtualbox_VBoxGuest *pThis = (org_virtualbox_VBoxGuest *)pTarget;
     1173        if (pThis)
     1174        {
     1175            IOService *pProvider = pThis->m_pInterruptProvider;
     1176            if (pProvider)
     1177            {
     1178                pProvider->disableInterrupt(0);
     1179                VGDrvCommonWaitDoWakeUps(&g_DevExt); /* Could we perhaps do theses elsewhere? */
     1180                pProvider->enableInterrupt(0);
     1181                return;
     1182            }
     1183        }
     1184        VGDrvCommonWaitDoWakeUps(&g_DevExt);
     1185# endif
     1186    }
     1187}
     1188
     1189
     1190/**
     1191 * Sets up and enables interrupts on the device.
     1192 *
     1193 * Interrupts are handled directly, no messing around with workloops.  The
     1194 * rational here is is that the main job of our interrupt handler is waking up
     1195 * other threads currently sitting in HGCM calls, i.e. little more effort than
     1196 * waking up the workloop thread.
     1197 *
     1198 * @returns success indicator.  Failures are fully logged.
     1199 */
     1200bool org_virtualbox_VBoxGuest::setupVmmDevInterrupts(IOService *pProvider)
     1201{
     1202    AssertReturn(pProvider, false);
     1203
     1204    if (m_pInterruptProvider != pProvider)
     1205    {
     1206        pProvider->retain();
     1207        if (m_pInterruptProvider)
     1208            m_pInterruptProvider->release();
     1209        m_pInterruptProvider = pProvider;
     1210    }
     1211
     1212    IOReturn rc = pProvider->registerInterrupt(0 /*intIndex*/, this, vgdrvDarwinIrqHandler, this);
     1213    if (rc == kIOReturnSuccess)
     1214    {
     1215        rc = pProvider->enableInterrupt(0 /*intIndex*/);
     1216        if (rc == kIOReturnSuccess)
     1217            return true;
     1218
     1219        LogRel(("VBoxGuest: Failed to enable interrupt: %#x\n", rc));
     1220        m_pInterruptProvider->unregisterInterrupt(0 /*intIndex*/);
     1221    }
     1222    else
     1223        LogRel(("VBoxGuest: Failed to register interrupt: %#x\n", rc));
     1224    return false;
     1225}
     1226
     1227
     1228/**
     1229 * Counterpart to setupVmmDevInterrupts().
     1230 */
     1231bool org_virtualbox_VBoxGuest::disableVmmDevInterrupts(void)
     1232{
     1233    if (m_pInterruptProvider)
     1234    {
     1235        IOReturn rc = m_pInterruptProvider->disableInterrupt(0 /*intIndex*/);
     1236        AssertMsg(rc == kIOReturnSuccess, ("%#x\n", rc));
     1237        rc = m_pInterruptProvider->unregisterInterrupt(0 /*intIndex*/);
     1238        AssertMsg(rc == kIOReturnSuccess, ("%#x\n", rc));
     1239        RT_NOREF_PV(rc);
     1240
     1241        m_pInterruptProvider->release();
     1242        m_pInterruptProvider = NULL;
     1243    }
     1244
     1245    return true;
     1246}
     1247
     1248#endif /* !USE_INTERRUPT_SOURCE */
     1249
     1250/**
     1251 * Checks if it's the VMM device.
     1252 *
     1253 * @returns true if it is, false if it isn't.
     1254 * @param   pIOPCIDevice    The PCI device we think might be the VMM device.
     1255 */
    8531256bool org_virtualbox_VBoxGuest::isVmmDev(IOPCIDevice *pIOPCIDevice)
    8541257{
    855     UInt16 uVendorId, uDeviceId;
    856 
    857     if (!pIOPCIDevice)
    858         return false;
    859 
    860     uVendorId = m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID);
    861     uDeviceId = m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID);
    862 
    863     if (uVendorId == VMMDEV_VENDORID && uDeviceId == VMMDEV_DEVICEID)
    864         return true;
    865 
    866     return true;
    867 }
    868 
    869 
    870 /**
    871  * Start this service.
    872  */
    873 bool org_virtualbox_VBoxGuest::start(IOService *pProvider)
    874 {
    875     /*
    876      * Low level initialization / device initialization should be performed only once.
    877      */
    878     if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false))
    879         return false;
    880 
    881     if (!IOService::start(pProvider))
    882         return false;
    883 
    884     m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider);
    885     if (m_pIOPCIDevice)
    886     {
    887         if (isVmmDev(m_pIOPCIDevice))
    888         {
    889             /* Enable memory response from VMM device */
    890             m_pIOPCIDevice->setMemoryEnable(true);
    891             m_pIOPCIDevice->setIOEnable(true);
    892 
    893             IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0);
    894             if (pMem)
    895             {
    896                 IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress();
    897                 /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */
    898                 if((IOPortBasePhys >> 16) == 0)
    899                 {
    900 
    901                     RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys;
    902                     void    *pvMMIOBase = NULL;
    903                     uint32_t cbMMIO     = 0;
    904                     m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1);
    905                     if (m_pMap)
    906                     {
    907                         pvMMIOBase = (void *)m_pMap->getVirtualAddress();
    908                         cbMMIO     = m_pMap->getLength();
    909                     }
    910 
    911                     int rc = VGDrvCommonInitDevExt(&g_DevExt,
    912                                                    IOPortBase,
    913                                                    pvMMIOBase,
    914                                                    cbMMIO,
    915 #if ARCH_BITS == 64
    916                                                    VBOXOSTYPE_MacOS_x64,
    917 #else
    918                                                    VBOXOSTYPE_MacOS,
    919 #endif
    920                                                    0);
    921                     if (RT_SUCCESS(rc))
    922                     {
    923                         rc = vgdrvDarwinCharDevInit();
    924                         if (rc == KMOD_RETURN_SUCCESS)
    925                         {
    926                             if (setupVmmDevInterrupts(pProvider))
    927                             {
    928                                 /*
    929                                  * Read host configuration.
    930                                  */
    931                                 VGDrvCommonProcessOptionsFromHost(&g_DevExt);
    932 
    933                                 /*
    934                                  * Register the service.
    935                                  */
    936                                 registerService();
    937                                 LogRel(("VBoxGuest: IOService started\n"));
    938                                 return true;
    939                             }
    940 
    941                             LogRel(("VBoxGuest: Failed to set up interrupts\n"));
    942                             vgdrvDarwinCharDevRemove();
    943                         }
    944                         else
    945                             LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc));
    946 
    947                         VGDrvCommonDeleteDevExt(&g_DevExt);
    948                     }
    949                     else
    950                         LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc));
    951 
    952                     if (m_pMap)
    953                     {
    954                         m_pMap->release();
    955                         m_pMap = NULL;
    956                     }
    957                 }
    958             }
    959             else
    960                 LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n"));
    961         }
    962         else
    963             LogRel(("VBoxGuest: Not the VMMDev (%#x:%#x).\n",
    964                    m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID), m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID)));
    965     }
    966     else
    967         LogRel(("VBoxGuest: Provider is not an instance of IOPCIDevice.\n"));
    968 
    969     ASMAtomicXchgBool(&g_fInstantiated, false);
    970     IOService::stop(pProvider);
     1258    if (pIOPCIDevice)
     1259    {
     1260        uint16_t idVendor = m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID);
     1261        if (idVendor == VMMDEV_VENDORID)
     1262        {
     1263            uint16_t idDevice = m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID);
     1264            if (idDevice == VMMDEV_DEVICEID)
     1265                return true;
     1266        }
     1267    }
    9711268    return false;
    9721269}
    9731270
    974 
    975 /**
    976  * Stop this service.
    977  */
    978 void org_virtualbox_VBoxGuest::stop(IOService *pProvider)
    979 {
    980     /* Do not use Log*() here (in IOService instance) because its instance
    981      * already terminated in BSD's module unload callback! */
    982     Log(("org_virtualbox_VBoxGuest::stop([%p], %p)\n", this, pProvider));
    983 
    984     AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated));
    985 
    986     /* Low level termination should be performed only once */
    987     if (!disableVmmDevInterrupts())
    988         printf("VBoxGuest: unable to unregister interrupt handler\n");
    989 
    990     vgdrvDarwinCharDevRemove();
    991     VGDrvCommonDeleteDevExt(&g_DevExt);
    992 
    993     if (m_pMap)
    994     {
    995         m_pMap->release();
    996         m_pMap = NULL;
    997     }
    998 
    999     IOService::stop(pProvider);
    1000 
    1001     ASMAtomicWriteBool(&g_fInstantiated, false);
    1002 
    1003     printf("VBoxGuest: IOService stopped\n");
    1004 }
    1005 
    1006 
    1007 /**
    1008  * Termination request.
    1009  *
    1010  * @return  true if we're ok with shutting down now, false if we're not.
    1011  * @param   fOptions        Flags.
    1012  */
    1013 bool org_virtualbox_VBoxGuest::terminate(IOOptionBits fOptions)
    1014 {
    1015     /* Do not use Log*() here (in IOService instance) because its instance
    1016      * already terminated in BSD's module unload callback! */
    1017 #ifdef LOG_ENABLED
    1018     printf("org_virtualbox_VBoxGuest::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n",
    1019            KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions);
    1020 #endif
    1021 
    1022     bool fRc;
    1023     if (    KMOD_INFO_NAME.reference_count != 0
    1024         ||  ASMAtomicUoReadS32(&g_cSessions))
    1025         fRc = false;
    1026     else
    1027         fRc = IOService::terminate(fOptions);
    1028 
    1029 #ifdef LOG_ENABLED
    1030     printf("org_virtualbox_SupDrv::terminate: returns %d\n", fRc);
    1031 #endif
    1032     return fRc;
    1033 }
    10341271
    10351272
     
    10551292    if (u32Type != VBOXGUEST_DARWIN_IOSERVICE_COOKIE)
    10561293    {
    1057         Log(("org_virtualbox_VBoxGuestClient::initWithTask: Bad cookie %#x\n", u32Type));
     1294        VBOX_RETRIEVE_CUR_PROC_NAME(szProcName);
     1295        LogRelMax(10, ("org_virtualbox_VBoxGuestClient::initWithTask: Bad cookie %#x (%s)\n", u32Type, szProcName));
    10581296        return false;
    10591297    }
     
    11011339            {
    11021340                m_pSession->fOpened = false;
    1103                 /* The fUnrestricted field is set on open. */
     1341                /* The Uid, Gid and fUnrestricted fields are set on open. */
    11041342
    11051343                /*
     
    11111349
    11121350                PVBOXGUESTSESSION pCur = g_apSessionHashTab[iHash];
    1113                 if (pCur && pCur->Process != m_pSession->Process)
    1114                 {
    1115                     do pCur = pCur->pNextHash;
    1116                     while (pCur && pCur->Process != m_pSession->Process);
    1117                 }
     1351                while (pCur && pCur->Process != m_pSession->Process)
     1352                    pCur = pCur->pNextHash;
    11181353                if (!pCur)
    11191354                {
     
    11351370
    11361371                LogFlow(("org_virtualbox_VBoxGuestClient::start: already got a session for this process (%p)\n", pCur));
    1137                 VGDrvCommonCloseSession(&g_DevExt, m_pSession);
     1372                VGDrvCommonCloseSession(&g_DevExt, m_pSession);  //supdrvSessionRelease(m_pSession);
    11381373            }
    11391374
     
    12111446     * Close the session.
    12121447     */
    1213     VGDrvCommonCloseSession(&g_DevExt, pSession);
     1448    VGDrvCommonCloseSession(&g_DevExt, pSession); // supdrvSessionRelease(m_pSession);
    12141449}
    12151450
     
    12411476}
    12421477
     1478
     1479/**
     1480 * The client exits abnormally / forgets to do cleanups. (logging)
     1481 */
     1482IOReturn org_virtualbox_VBoxGuestClient::clientDied(void)
     1483{
     1484    LogFlow(("IOService::clientDied([%p]) m_Task=%p R0Process=%p Process=%d\n", this, m_Task, RTR0ProcHandleSelf(), RTProcSelf()));
     1485
     1486    /* IOUserClient::clientDied() calls clientClose, so we'll just do the work there. */
     1487    return IOUserClient::clientDied();
     1488}
     1489
     1490
     1491/**
     1492 * Terminate the service (initiate the destruction). (logging)
     1493 */
     1494bool org_virtualbox_VBoxGuestClient::terminate(IOOptionBits fOptions)
     1495{
     1496    LogFlow(("IOService::terminate([%p], %#x)\n", this, fOptions));
     1497    return IOUserClient::terminate(fOptions);
     1498}
     1499
     1500
     1501/**
     1502 * The final stage of the client service destruction. (logging)
     1503 */
     1504bool org_virtualbox_VBoxGuestClient::finalize(IOOptionBits fOptions)
     1505{
     1506    LogFlow(("IOService::finalize([%p], %#x)\n", this, fOptions));
     1507    return IOUserClient::finalize(fOptions);
     1508}
     1509
     1510
     1511/**
     1512 * Stop the client service. (logging)
     1513 */
     1514void org_virtualbox_VBoxGuestClient::stop(IOService *pProvider)
     1515{
     1516    LogFlow(("IOService::stop([%p])\n", this));
     1517    IOUserClient::stop(pProvider);
     1518}
     1519
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r75588 r75705  
    44824482#endif
    44834483
    4484 #if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_DARWIN) && !defined(RT_OS_WINDOWS)
     4484#if defined(VBOXGUEST_USE_DEFERRED_WAKE_UP) && !defined(RT_OS_WINDOWS)
    44854485    /*
    44864486     * Do wake-ups.
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r75588 r75705  
    3939/** @def VBOXGUEST_USE_DEFERRED_WAKE_UP
    4040 * Defer wake-up of waiting thread when defined. */
    41 #if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
     41#if defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) || defined(DOXYGEN_RUNNING)
    4242# define VBOXGUEST_USE_DEFERRED_WAKE_UP
    4343#endif
  • trunk/src/VBox/Additions/common/VBoxGuest/darwin/Info.plist

    r45459 r75705  
    2525            <key>IOKitDebug</key>               <integer>65535</integer>
    2626            <key>IOProviderClass</key>          <string>IOPCIDevice</string>
    27             <key>IONameMatch</key>              <string>pci80ee,cafe</string>
     27            <key>IOPCIPrimaryMatch</key>        <string>0xcafe80ee</string>
     28            <!-- <key>IONameMatch</key>              <string>pci80ee,cafe</string> -->
    2829        </dict>
    2930    </dict>
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3Lib.cpp

    r69500 r75705  
    219219     * before we open it via the BSD device node.
    220220     */
     221   /* IOKit */
    221222    mach_port_t MasterPort;
    222223    kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort);
    223224    if (kr != kIOReturnSuccess)
     225    {
     226        LogRel(("IOMasterPort -> %d\n", kr));
    224227        return VERR_GENERAL_FAILURE;
     228    }
    225229
    226230    CFDictionaryRef ClassToMatch = IOServiceMatching("org_virtualbox_VBoxGuest");
    227231    if (!ClassToMatch)
     232    {
     233        LogRel(("IOServiceMatching(\"org_virtualbox_VBoxGuest\") failed.\n"));
    228234        return VERR_GENERAL_FAILURE;
     235    }
    229236
    230237    io_service_t ServiceObject = IOServiceGetMatchingService(kIOMasterPortDefault, ClassToMatch);
    231238    if (!ServiceObject)
     239    {
     240        LogRel(("IOServiceGetMatchingService returned NULL\n"));
    232241        return VERR_NOT_FOUND;
     242    }
    233243
    234244    io_connect_t uConnection;
     
    236246    IOObjectRelease(ServiceObject);
    237247    if (kr != kIOReturnSuccess)
     248    {
     249        LogRel(("IOServiceOpen returned %d. Driver open failed.\n", kr));
    238250        return VERR_OPEN_FAILED;
    239 
     251    }
     252
     253    /* Regular unix FD. */
    240254    RTFILE hFile;
    241255    int rc = RTFileOpen(&hFile, pszDeviceName, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    242256    if (RT_FAILURE(rc))
    243257    {
     258        LogRel(("RTFileOpen(%s) returned %Rrc. Driver open failed.\n", pszDeviceName, rc));
    244259        IOServiceClose(uConnection);
    245260        return rc;
Note: See TracChangeset for help on using the changeset viewer.

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