Logo Search packages:      
Sourcecode: virtualbox-ose version File versions

VMInternal.h

Go to the documentation of this file.
/* $Id: VMInternal.h 13791 2008-11-04 16:12:57Z vboxsync $ */
/** @file
 * VM - Internal header file.
 */

/*
 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License (GPL) as published by the Free Software
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
 * Clara, CA 95054 USA or visit http://www.sun.com if you need
 * additional information or have any questions.
 */

#ifndef ___VMInternal_h
#define ___VMInternal_h

#include <VBox/cdefs.h>
#include <VBox/vmapi.h>
#include <setjmp.h>



/** @defgroup grp_vm_int   Internals
 * @ingroup grp_vm
 * @internal
 * @{
 */


/**
 * At-reset callback type.
 */
00041 typedef enum VMATRESETTYPE
{
    /** Device callback. */
00044     VMATRESETTYPE_DEV = 1,
    /** Internal callback . */
00046     VMATRESETTYPE_INTERNAL,
    /** External callback. */
00048     VMATRESETTYPE_EXTERNAL
} VMATRESETTYPE;


/** Pointer to at-reset callback. */
00053 typedef struct VMATRESET *PVMATRESET;

/**
 * At reset callback.
 */
00058 typedef struct VMATRESET
{
    /** Pointer to the next one in the list. */
00061     PVMATRESET                      pNext;
    /** Callback type. */
00063     VMATRESETTYPE                   enmType;
    /** User argument for the callback. */
00065     void                           *pvUser;
    /** Description. */
00067     const char                     *pszDesc;
    /** Type specific data. */
    union
    {
        /** VMATRESETTYPE_DEV. */
        struct
        {
            /** Callback. */
00075             PFNVMATRESET            pfnCallback;
            /** Device instance. */
00077             PPDMDEVINS              pDevIns;
        } Dev;

        /** VMATRESETTYPE_INTERNAL. */
        struct
        {
            /** Callback. */
00084             PFNVMATRESETINT         pfnCallback;
        } Internal;

        /** VMATRESETTYPE_EXTERNAL. */
        struct
        {
            /** Callback. */
00091             PFNVMATRESETEXT         pfnCallback;
        } External;
    } u;
} VMATRESET;


/**
 * VM state change callback.
 */
00100 typedef struct VMATSTATE
{
    /** Pointer to the next one. */
00103     struct VMATSTATE               *pNext;
    /** Pointer to the callback. */
00105     PFNVMATSTATE                    pfnAtState;
    /** The user argument. */
00107     void                           *pvUser;
} VMATSTATE;
/** Pointer to a VM state change callback. */
00110 typedef VMATSTATE *PVMATSTATE;


/**
 * VM error callback.
 */
00116 typedef struct VMATERROR
{
    /** Pointer to the next one. */
00119     struct VMATERROR               *pNext;
    /** Pointer to the callback. */
00121     PFNVMATERROR                    pfnAtError;
    /** The user argument. */
00123     void                           *pvUser;
} VMATERROR;
/** Pointer to a VM error callback. */
00126 typedef VMATERROR *PVMATERROR;


/**
 * Chunk of memory allocated off the hypervisor heap in which
 * we copy the error details.
 */
00133 typedef struct VMERROR
{
    /** The size of the chunk. */
00136     uint32_t                        cbAllocated;
    /** The current offset into the chunk.
     * We start by putting the filename and function immediatly
     * after the end of the buffer. */
00140     uint32_t                        off;
    /** Offset from the start of this structure to the file name. */
00142     uint32_t                        offFile;
    /** The line number. */
00144     uint32_t                        iLine;
    /** Offset from the start of this structure to the function name. */
00146     uint32_t                        offFunction;
    /** Offset from the start of this structure to the formatted message text. */
00148     uint32_t                        offMessage;
    /** The VBox status code. */
00150     int32_t                         rc;
} VMERROR, *PVMERROR;


/**
 * VM runtime error callback.
 */
00157 typedef struct VMATRUNTIMEERROR
{
    /** Pointer to the next one. */
00160     struct VMATRUNTIMEERROR         *pNext;
    /** Pointer to the callback. */
00162     PFNVMATRUNTIMEERROR              pfnAtRuntimeError;
    /** The user argument. */
00164     void                            *pvUser;
} VMATRUNTIMEERROR;
/** Pointer to a VM error callback. */
00167 typedef VMATRUNTIMEERROR *PVMATRUNTIMEERROR;


/**
 * Chunk of memory allocated off the hypervisor heap in which
 * we copy the runtime error details.
 */
00174 typedef struct VMRUNTIMEERROR
{
    /** The size of the chunk. */
00177     uint32_t                        cbAllocated;
    /** The current offset into the chunk.
     * We start by putting the error ID immediatly
     * after the end of the buffer. */
00181     uint32_t                        off;
    /** Offset from the start of this structure to the error ID. */
00183     uint32_t                        offErrorID;
    /** Offset from the start of this structure to the formatted message text. */
00185     uint32_t                        offMessage;
    /** Whether the error is fatal or not */
00187     bool                            fFatal;
} VMRUNTIMEERROR, *PVMRUNTIMEERROR;

/** The halt method. */
00191 typedef enum
{
    /** The usual invalid value. */
00194     VMHALTMETHOD_INVALID = 0,
    /** Use the method used during bootstrapping. */
00196     VMHALTMETHOD_BOOTSTRAP,
    /** Use the default method. */
00198     VMHALTMETHOD_DEFAULT,
    /** The old spin/yield/block method. */
00200     VMHALTMETHOD_OLD,
    /** The first go at a block/spin method. */
00202     VMHALTMETHOD_1,
    /** The first go at a more global approach. */
00204     VMHALTMETHOD_GLOBAL_1,
    /** The end of valid methods. (not inclusive of course) */
00206     VMHALTMETHOD_END,
    /** The usual 32-bit max value. */
00208     VMHALTMETHOD_32BIT_HACK = 0x7fffffff
} VMHALTMETHOD;


/**
 * VM Internal Data (part of the VM structure).
 *
 * @todo Move this and all related things to VMM. The VM component was, to some
 *       extent at least, a bad ad hoc design which should all have been put in
 *       VMM. @see pg_vm.
 */
00219 typedef struct VMINT
{
    /** VM Error Message. */
    R3PTRTYPE(PVMERROR)             pErrorR3;
    /** VM Runtime Error Message. */
    R3PTRTYPE(PVMRUNTIMEERROR)      pRuntimeErrorR3;
    /** Set by VMR3SuspendNoSave; cleared by VMR3Resume; signals the VM is in an
     * inconsistent state and saving is not allowed. */
00227     bool                            fPreventSaveState;
} VMINT;
/** Pointer to the VM Internal Data (part of the VM structure). */
00230 typedef VMINT *PVMINT;


/**
 * VM internal data kept in the UVM.
 */
00236 typedef struct VMINTUSERPERVM
{
    /** Head of the request queue. Atomic. */
00239     volatile PVMREQ                 pReqs;
    /** The last index used during alloc/free. */
00241     volatile uint32_t               iReqFree;
    /** Number of free request packets. */
00243     volatile uint32_t               cReqFree;
    /** Array of pointers to lists of free request packets. Atomic. */
00245     volatile PVMREQ                 apReqFree[9];

#ifdef VBOX_WITH_STATISTICS
    /** Number of VMR3ReqAlloc returning a new packet. */
    STAMCOUNTER                     StatReqAllocNew;
    /** Number of VMR3ReqAlloc causing races. */
    STAMCOUNTER                     StatReqAllocRaces;
    /** Number of VMR3ReqAlloc returning a recycled packet. */
    STAMCOUNTER                     StatReqAllocRecycled;
    /** Number of VMR3ReqFree calls. */
    STAMCOUNTER                     StatReqFree;
    /** Number of times the request was actually freed. */
    STAMCOUNTER                     StatReqFreeOverflow;
#endif

    /** Pointer to the support library session.
     * Mainly for creation and destruction.. */
00262     PSUPDRVSESSION                  pSession;

    /** Wait event semaphore. */
00265     RTSEMEVENT                      EventSemWait;
    /** Wait/Idle indicator. */
00267     bool volatile                   fWait;
    /** Force EMT to terminate. */
00269     bool volatile                   fTerminateEMT;
    /** If set the EMT does the final VM cleanup when it exits.
     * If clear the VMR3Destroy() caller does so. */
00272     bool                            fEMTDoesTheCleanup;

    /** @name Generic Halt data
     * @{
     */
    /** The current halt method.
     * Can be selected by CFGM option 'VM/HaltMethod'. */
00279     VMHALTMETHOD                    enmHaltMethod;
    /** The index into g_aHaltMethods of the current halt method. */
00281     uint32_t volatile               iHaltMethod;
    /** The average time (ns) between two halts in the last second. (updated once per second) */
00283     uint32_t                        HaltInterval;
    /** The average halt frequency for the last second. (updated once per second) */
00285     uint32_t                        HaltFrequency;
    /** The number of halts in the current period. */
00287     uint32_t                        cHalts;
00288     uint32_t                        padding; /**< alignment padding. */
    /** When we started counting halts in cHalts (RTTimeNanoTS). */
00290     uint64_t                        u64HaltsStartTS;
    /** @} */

    /** Union containing data and config for the different halt algorithms. */
    union
    {
       /**
        * Method 1 & 2 - Block whenever possible, and when lagging behind
        * switch to spinning with regular blocking every 5-200ms (defaults)
        * depending on the accumulated lag. The blocking interval is adjusted
        * with the average oversleeping of the last 64 times.
        *
        * The difference between 1 and 2 is that we use native absolute
        * time APIs for the blocking instead of the millisecond based IPRT
        * interface.
        */
        struct
        {
            /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
00309             uint32_t                cBlocks;
            /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
00311             uint64_t                cNSBlockedTooLongAvg;
            /** Total time spend oversleeping when blocking. */
00313             uint64_t                cNSBlockedTooLong;
            /** Total time spent blocking. */
00315             uint64_t                cNSBlocked;
            /** The timestamp (RTTimeNanoTS) of the last block. */
00317             uint64_t                u64LastBlockTS;

            /** When we started spinning relentlessly in order to catch up some of the oversleeping.
             * This is 0 when we're not spinning. */
00321             uint64_t                u64StartSpinTS;

            /** The max interval without blocking (when spinning). */
00324             uint32_t                u32MinBlockIntervalCfg;
            /** The minimum interval between blocking (when spinning). */
00326             uint32_t                u32MaxBlockIntervalCfg;
            /** The value to divide the current lag by to get the raw blocking interval (when spinning). */
00328             uint32_t                u32LagBlockIntervalDivisorCfg;
            /** When to start spinning (lag / nano secs). */
00330             uint32_t                u32StartSpinningCfg;
            /** When to stop spinning (lag / nano secs). */
00332             uint32_t                u32StopSpinningCfg;
        }                           Method12;

#if 0
       /**
        * Method 3 & 4 - Same as method 1 & 2 respectivly, except that we
        * sprinkle it with yields.
        */
       struct
       {
           /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
           uint32_t                 cBlocks;
           /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
           uint64_t                 cBlockedTooLongNSAvg;
           /** Total time spend oversleeping when blocking. */
           uint64_t                 cBlockedTooLongNS;
           /** Total time spent blocking. */
           uint64_t                 cBlockedNS;
           /** The timestamp (RTTimeNanoTS) of the last block. */
           uint64_t                 u64LastBlockTS;

           /** How many times we've yielded while cBlockedNS and cBlockedTooLongNS has been accumulating. */
           uint32_t                 cYields;
           /** Avg. time spend oversleeping when yielding. */
           uint32_t                 cYieldTooLongNSAvg;
           /** Total time spend oversleeping when yielding. */
           uint64_t                 cYieldTooLongNS;
           /** Total time spent yielding. */
           uint64_t                 cYieldedNS;
           /** The timestamp (RTTimeNanoTS) of the last block. */
           uint64_t                 u64LastYieldTS;

           /** When we started spinning relentlessly in order to catch up some of the oversleeping. */
           uint64_t                 u64StartSpinTS;
       }                            Method34;
#endif
    }                               Halt;

    /** Profiling the halted state; yielding vs blocking.
     * @{ */
00372     STAMPROFILE                     StatHaltYield;
    STAMPROFILE                     StatHaltBlock;
    STAMPROFILE                     StatHaltTimers;
    STAMPROFILE                     StatHaltPoll;
    /** @} */


    /** List of registered reset callbacks. */
00380     PVMATRESET                      pAtReset;
    /** List of registered reset callbacks. */
00382     PVMATRESET                     *ppAtResetNext;

    /** List of registered state change callbacks. */
00385     PVMATSTATE                      pAtState;
    /** List of registered state change callbacks. */
00387     PVMATSTATE                     *ppAtStateNext;

    /** List of registered error callbacks. */
00390     PVMATERROR                      pAtError;
    /** List of registered error callbacks. */
00392     PVMATERROR                     *ppAtErrorNext;

    /** List of registered error callbacks. */
00395     PVMATRUNTIMEERROR               pAtRuntimeError;
    /** List of registered error callbacks. */
00397     PVMATRUNTIMEERROR              *ppAtRuntimeErrorNext;

    /** Pointer to the DBGC instance data. */
00400     void                           *pvDBGC;

    /* TLS index for the VMINTUSERPERVMCPU pointer. */
    RTTLS                           idxTLS;
} VMINTUSERPERVM;

/** Pointer to the VM internal data kept in the UVM. */
00407 typedef VMINTUSERPERVM *PVMINTUSERPERVM;


/**
 * VMCPU internal data kept in the UVM.
 *
 * Almost a copy of VMINTUSERPERVM. Separate data properly later on.
 */
00415 typedef struct VMINTUSERPERVMCPU
{
    /** Head of the request queue. Atomic. */
00418     volatile PVMREQ                 pReqs;

    /** The handle to the EMT thread. */
00421     RTTHREAD                        ThreadEMT;
    /** The native of the EMT thread. */
00423     RTNATIVETHREAD                  NativeThreadEMT;
    /** Wait event semaphore. */
00425     RTSEMEVENT                      EventSemWait;
    /** Wait/Idle indicator. */
00427     bool volatile                   fWait;
    /** Force EMT to terminate. */
00429     bool volatile                   fTerminateEMT;
    /** If set the EMT does the final VM cleanup when it exits.
     * If clear the VMR3Destroy() caller does so. */
00432     bool                            fEMTDoesTheCleanup;

    /** @name Generic Halt data
     * @{
     */
    /** The current halt method.
     * Can be selected by CFGM option 'VM/HaltMethod'. */
00439     VMHALTMETHOD                    enmHaltMethod;
    /** The index into g_aHaltMethods of the current halt method. */
00441     uint32_t volatile               iHaltMethod;
    /** The average time (ns) between two halts in the last second. (updated once per second) */
00443     uint32_t                        HaltInterval;
    /** The average halt frequency for the last second. (updated once per second) */
00445     uint32_t                        HaltFrequency;
    /** The number of halts in the current period. */
00447     uint32_t                        cHalts;
00448     uint32_t                        padding; /**< alignment padding. */
    /** When we started counting halts in cHalts (RTTimeNanoTS). */
00450     uint64_t                        u64HaltsStartTS;
    /** @} */

    /** Union containing data and config for the different halt algorithms. */
    union
    {
       /**
        * Method 1 & 2 - Block whenever possible, and when lagging behind
        * switch to spinning with regular blocking every 5-200ms (defaults)
        * depending on the accumulated lag. The blocking interval is adjusted
        * with the average oversleeping of the last 64 times.
        *
        * The difference between 1 and 2 is that we use native absolute
        * time APIs for the blocking instead of the millisecond based IPRT
        * interface.
        */
        struct
        {
            /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
00469             uint32_t                cBlocks;
            /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
00471             uint64_t                cNSBlockedTooLongAvg;
            /** Total time spend oversleeping when blocking. */
00473             uint64_t                cNSBlockedTooLong;
            /** Total time spent blocking. */
00475             uint64_t                cNSBlocked;
            /** The timestamp (RTTimeNanoTS) of the last block. */
00477             uint64_t                u64LastBlockTS;

            /** When we started spinning relentlessly in order to catch up some of the oversleeping.
             * This is 0 when we're not spinning. */
00481             uint64_t                u64StartSpinTS;

            /** The max interval without blocking (when spinning). */
00484             uint32_t                u32MinBlockIntervalCfg;
            /** The minimum interval between blocking (when spinning). */
00486             uint32_t                u32MaxBlockIntervalCfg;
            /** The value to divide the current lag by to get the raw blocking interval (when spinning). */
00488             uint32_t                u32LagBlockIntervalDivisorCfg;
            /** When to start spinning (lag / nano secs). */
00490             uint32_t                u32StartSpinningCfg;
            /** When to stop spinning (lag / nano secs). */
00492             uint32_t                u32StopSpinningCfg;
        }                           Method12;

#if 0
       /**
        * Method 3 & 4 - Same as method 1 & 2 respectivly, except that we
        * sprinkle it with yields.
        */
       struct
       {
           /** How many times we've blocked while cBlockedNS and cBlockedTooLongNS has been accumulating. */
           uint32_t                 cBlocks;
           /** Avg. time spend oversleeping when blocking. (Re-calculated every so often.) */
           uint64_t                 cBlockedTooLongNSAvg;
           /** Total time spend oversleeping when blocking. */
           uint64_t                 cBlockedTooLongNS;
           /** Total time spent blocking. */
           uint64_t                 cBlockedNS;
           /** The timestamp (RTTimeNanoTS) of the last block. */
           uint64_t                 u64LastBlockTS;

           /** How many times we've yielded while cBlockedNS and cBlockedTooLongNS has been accumulating. */
           uint32_t                 cYields;
           /** Avg. time spend oversleeping when yielding. */
           uint32_t                 cYieldTooLongNSAvg;
           /** Total time spend oversleeping when yielding. */
           uint64_t                 cYieldTooLongNS;
           /** Total time spent yielding. */
           uint64_t                 cYieldedNS;
           /** The timestamp (RTTimeNanoTS) of the last block. */
           uint64_t                 u64LastYieldTS;

           /** When we started spinning relentlessly in order to catch up some of the oversleeping. */
           uint64_t                 u64StartSpinTS;
       }                            Method34;
#endif
    }                               Halt;

    /** Profiling the halted state; yielding vs blocking.
     * @{ */
00532     STAMPROFILE                     StatHaltYield;
    STAMPROFILE                     StatHaltBlock;
    STAMPROFILE                     StatHaltTimers;
    STAMPROFILE                     StatHaltPoll;
    /** @} */

    /** Pointer to the DBGC instance data. */
00539     void                           *pvDBGC;

    /** vmR3EmulationThread longjmp buffer. Must be last in the structure. */
00542     jmp_buf                         emtJumpEnv;
} VMINTUSERPERVMCPU;

/** Pointer to the VM internal data kept in the UVM. */
00546 typedef VMINTUSERPERVMCPU *PVMINTUSERPERVMCPU;

DECLCALLBACK(int)   vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArg);
int                 vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod);
DECLCALLBACK(int)   vmR3Destroy(PVM pVM);
DECLCALLBACK(void)  vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);
void                vmSetErrorCopy(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
DECLCALLBACK(void)  vmR3SetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list *args);
void                vmSetRuntimeErrorCopy(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list args);
void                vmR3DestroyFinalBitFromEMT(PUVM pUVM);
void                vmR3SetState(PVM pVM, VMSTATE enmStateNew);


/** @} */

#endif


Generated by  Doxygen 1.6.0   Back to index