VirtualBox

Changeset 234 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 23, 2007 1:04:38 PM (18 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
17760
Message:

VMM: Added support for runtime error notifications (VMSetRuntimeError and friends).

Location:
trunk/src/VBox/VMM
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/EM.cpp

    r23 r234  
    33853385                 */
    33863386                case EMSTATE_REM:
     3387#if 0
     3388                    /* simulate a runtime error */
     3389                    VMSetRuntimeError (pVM, true, "simulatedError", "pVM=%p", pVM);
     3390#endif
    33873391                    rc = emR3RemExecute(pVM, &fFFDone);
    33883392                    Log2(("EMR3ExecuteVM: emR3RemExecute -> %Vrc\n", rc));
  • trunk/src/VBox/VMM/VM.cpp

    r226 r234  
    116116static DECLCALLBACK(int) vmR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
    117117static DECLCALLBACK(int) vmR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
     118static DECLCALLBACK(int) vmR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
     119static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
    118120
    119121
     
    202204            pVM->vm.s.ppAtStateNext = &pVM->vm.s.pAtState;
    203205            pVM->vm.s.ppAtErrorNext = &pVM->vm.s.pAtError;
     206            pVM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;
    204207            rc = RTSemEventCreate(&pVM->vm.s.EventSemWait);
    205208            if (VBOX_FAILURE(rc))
     
    24802483        if (pErr->offFile)
    24812484            pszFile = (const char *)pErr + pErr->offFile;
     2485        iLine = pErr->iLine;
    24822486        if (pErr->offFunction)
    24832487            pszFunction = (const char *)pErr + pErr->offFunction;
     
    25272531}
    25282532
     2533
     2534/**
     2535 * Registers a VM runtime error callback.
     2536 *
     2537 * @returns VBox status code.
     2538 * @param   pVM                 The VM handle.
     2539 * @param   pfnAtRuntimeError   Pointer to callback.
     2540 * @param   pvUser              User argument.
     2541 * @thread  Any.
     2542 */
     2543VMR3DECL(int)   VMR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
     2544{
     2545    LogFlow(("VMR3AtRuntimeErrorRegister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
     2546
     2547    /*
     2548     * Validate input.
     2549     */
     2550    if (!pfnAtRuntimeError)
     2551    {
     2552        AssertMsgFailed(("callback is required\n"));
     2553        return VERR_INVALID_PARAMETER;
     2554    }
     2555
     2556    /*
     2557     * Make sure we're in EMT (to avoid the logging).
     2558     */
     2559    PVMREQ pReq;
     2560    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorRegister, 3, pVM, pfnAtRuntimeError, pvUser);
     2561    if (VBOX_FAILURE(rc))
     2562        return rc;
     2563    rc = pReq->iStatus;
     2564    VMR3ReqFree(pReq);
     2565
     2566    LogFlow(("VMR3AtRuntimeErrorRegister: returns %Vrc\n", rc));
     2567    return rc;
     2568}
     2569
     2570
     2571/**
     2572 * Registers a VM runtime error callback.
     2573 *
     2574 * @returns VBox status code.
     2575 * @param   pVM                 The VM handle.
     2576 * @param   pfnAtRuntimeError   Pointer to callback.
     2577 * @param   pvUser              User argument.
     2578 * @thread  EMT
     2579 */
     2580static DECLCALLBACK(int)    vmR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
     2581{
     2582    /*
     2583     * Allocate a new record.
     2584     */
     2585
     2586    PVMATRUNTIMEERROR pNew = (PVMATRUNTIMEERROR)MMR3HeapAlloc(pVM, MM_TAG_VM, sizeof(*pNew));
     2587    if (!pNew)
     2588        return VERR_NO_MEMORY;
     2589
     2590    /* fill */
     2591    pNew->pfnAtRuntimeError = pfnAtRuntimeError;
     2592    pNew->pvUser            = pvUser;
     2593    pNew->pNext             = NULL;
     2594
     2595    /* insert */
     2596    *pVM->vm.s.ppAtRuntimeErrorNext = pNew;
     2597    pVM->vm.s.ppAtRuntimeErrorNext = &pNew->pNext;
     2598
     2599    return VINF_SUCCESS;
     2600}
     2601
     2602
     2603/**
     2604 * Deregisters a VM runtime error callback.
     2605 *
     2606 * @returns VBox status code.
     2607 * @param   pVM                 The VM handle.
     2608 * @param   pfnAtRuntimeError   Pointer to callback.
     2609 * @param   pvUser              User argument.
     2610 * @thread  Any.
     2611 */
     2612VMR3DECL(int)   VMR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
     2613{
     2614    LogFlow(("VMR3AtRuntimeErrorDeregister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
     2615
     2616    /*
     2617     * Validate input.
     2618     */
     2619    if (!pfnAtRuntimeError)
     2620    {
     2621        AssertMsgFailed(("callback is required\n"));
     2622        return VERR_INVALID_PARAMETER;
     2623    }
     2624
     2625    /*
     2626     * Make sure we're in EMT (to avoid the logging).
     2627     */
     2628    PVMREQ pReq;
     2629    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorDeregister, 3, pVM, pfnAtRuntimeError, pvUser);
     2630    if (VBOX_FAILURE(rc))
     2631        return rc;
     2632    rc = pReq->iStatus;
     2633    VMR3ReqFree(pReq);
     2634
     2635    LogFlow(("VMR3AtRuntimeErrorDeregister: returns %Vrc\n", rc));
     2636    return rc;
     2637}
     2638
     2639
     2640/**
     2641 * Deregisters a VM runtime error callback.
     2642 *
     2643 * @returns VBox status code.
     2644 * @param   pVM                 The VM handle.
     2645 * @param   pfnAtRuntimeError   Pointer to callback.
     2646 * @param   pvUser              User argument.
     2647 * @thread  EMT
     2648 */
     2649static DECLCALLBACK(int)    vmR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
     2650{
     2651    LogFlow(("vmR3AtRuntimeErrorDeregister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
     2652
     2653    /*
     2654     * Search the list for the entry.
     2655     */
     2656    PVMATRUNTIMEERROR pPrev = NULL;
     2657    PVMATRUNTIMEERROR pCur = pVM->vm.s.pAtRuntimeError;
     2658    while (     pCur
     2659           &&   pCur->pfnAtRuntimeError == pfnAtRuntimeError
     2660           &&   pCur->pvUser == pvUser)
     2661    {
     2662        pPrev = pCur;
     2663        pCur = pCur->pNext;
     2664    }
     2665    if (!pCur)
     2666    {
     2667        AssertMsgFailed(("pfnAtRuntimeError=%p was not found\n", pfnAtRuntimeError));
     2668        return VERR_FILE_NOT_FOUND;
     2669    }
     2670
     2671    /*
     2672     * Unlink it.
     2673     */
     2674    if (pPrev)
     2675    {
     2676        pPrev->pNext = pCur->pNext;
     2677        if (!pCur->pNext)
     2678            pVM->vm.s.ppAtRuntimeErrorNext = &pPrev->pNext;
     2679    }
     2680    else
     2681    {
     2682        pVM->vm.s.pAtRuntimeError = pCur->pNext;
     2683        if (!pCur->pNext)
     2684            pVM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;
     2685    }
     2686
     2687    /*
     2688     * Free it.
     2689     */
     2690    pCur->pfnAtRuntimeError = NULL;
     2691    pCur->pNext = NULL;
     2692    MMR3HeapFree(pCur);
     2693
     2694    return VINF_SUCCESS;
     2695}
     2696
     2697
     2698/**
     2699 * Ellipsis to va_list wrapper for calling pfnAtRuntimeError.
     2700 */
     2701static void vmR3SetRuntimeErrorWorkerDoCall(PVM pVM, PVMATRUNTIMEERROR pCur, bool fFatal,
     2702                                            const char *pszErrorID,
     2703                                            const char *pszFormat, ...)
     2704{
     2705    va_list va;
     2706    va_start(va, pszFormat);
     2707    pCur->pfnAtRuntimeError(pVM, pCur->pvUser, fFatal, pszErrorID, pszFormat, va);
     2708    va_end(va);
     2709}
     2710
     2711
     2712/**
     2713 * This is a worker function for GC and Ring-0 calls to VMSetError and VMSetErrorV.
     2714 * The message is found in VMINT.
     2715 *
     2716 * @param   pVM             The VM handle.
     2717 * @thread  EMT.
     2718 */
     2719VMR3DECL(void) VMR3SetRuntimeErrorWorker(PVM pVM)
     2720{
     2721    VM_ASSERT_EMT(pVM);
     2722    AssertReleaseMsgFailed(("And we have a winner! You get to implement Ring-0 and GC VMSetRuntimeErrorV! Contrats!\n"));
     2723
     2724    /*
     2725     * Unpack the error (if we managed to format one).
     2726     */
     2727    PVMRUNTIMEERROR pErr = pVM->vm.s.pRuntimeErrorR3;
     2728    const char *pszErrorID = NULL;
     2729    const char *pszMessage;
     2730    bool        fFatal = false;
     2731    if (pErr)
     2732    {
     2733        AssertCompile(sizeof(const char) == sizeof(uint8_t));
     2734        if (pErr->offErrorID)
     2735            pszErrorID = (const char *)pErr + pErr->offErrorID;
     2736        if (pErr->offMessage)
     2737            pszMessage = (const char *)pErr + pErr->offMessage;
     2738        else
     2739            pszMessage = "No message!";
     2740        fFatal = pErr->fFatal;
     2741    }
     2742    else
     2743        pszMessage = "No message! (Failed to allocate memory to put the error message in!)";
     2744
     2745    /*
     2746     * Call the at runtime error callbacks.
     2747     */
     2748    for (PVMATRUNTIMEERROR pCur = pVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
     2749        vmR3SetRuntimeErrorWorkerDoCall(pVM, pCur, fFatal, pszErrorID, "%s", pszMessage);
     2750}
     2751
     2752
     2753/**
     2754 * Worker which calls everyone listening to the VM runtime error messages.
     2755 *
     2756 * @param   pVM             The VM handle.
     2757 * @param   fFatal          Whether it is a fatal error or not.
     2758 * @param   pszErrorID      Error ID string.
     2759 * @param   pszFormat       Format string.
     2760 * @param   pArgs           Pointer to the format arguments.
     2761 * @thread  EMT
     2762 */
     2763DECLCALLBACK(void) vmR3SetRuntimeErrorV(PVM pVM, bool fFatal,
     2764                                        const char *pszErrorID,
     2765                                        const char *pszFormat, va_list *pArgs)
     2766{
     2767    /*
     2768     * Make a copy of the message.
     2769     */
     2770    vmSetRuntimeErrorCopy(pVM, fFatal, pszErrorID, pszFormat, *pArgs);
     2771
     2772    /*
     2773     * Call the at error callbacks.
     2774     */
     2775    for (PVMATRUNTIMEERROR pCur = pVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
     2776    {
     2777        va_list va2;
     2778        va_copy(va2, *pArgs);
     2779        pCur->pfnAtRuntimeError(pVM, pCur->pvUser, fFatal, pszErrorID, pszFormat, va2);
     2780        va_end(va2);
     2781    }
     2782}
     2783
  • trunk/src/VBox/VMM/VMInternal.h

    r23 r234  
    156156
    157157/**
     158 * VM runtime error callback.
     159 */
     160typedef struct VMATRUNTIMEERROR
     161{
     162    /** Pointer to the next one. */
     163    struct VMATRUNTIMEERROR *pNext;
     164    /** Pointer to the callback. */
     165    PFNVMATRUNTIMEERROR      pfnAtRuntimeError;
     166    /** The user argument. */
     167    void                    *pvUser;
     168} VMATRUNTIMEERROR;
     169/** Pointer to a VM error callback. */
     170typedef VMATRUNTIMEERROR *PVMATRUNTIMEERROR;
     171
     172
     173/**
     174 * Chunk of memory allocated off the hypervisor heap in which
     175 * we copy the runtime error details.
     176 */
     177typedef struct VMRUNTIMEERROR
     178{
     179    /** The size of the chunk. */
     180    uint32_t                cbAllocated;
     181    /** The current offset into the chunk.
     182     * We start by putting the error ID immediatly
     183     * after the end of the buffer. */
     184    uint32_t                off;
     185    /** Offset from the start of this structure to the error ID. */
     186    uint32_t                offErrorID;
     187    /** Offset from the start of this structure to the formatted message text. */
     188    uint32_t                offMessage;
     189    /** Whether the error is fatal or not */
     190    bool                    fFatal;
     191} VMRUNTIMEERROR, *PVMRUNTIMEERROR;
     192
     193
     194/**
    158195 * Converts a VMM pointer into a VM pointer.
    159196 * @returns Pointer to the VM structure the VMM is part of.
     
    186223    /** List of registered error callbacks. */
    187224    HCPTRTYPE(PVMATERROR *)         ppAtErrorNext;
     225
     226    /** List of registered error callbacks. */
     227    HCPTRTYPE(PVMATRUNTIMEERROR)    pAtRuntimeError;
     228    /** List of registered error callbacks. */
     229    HCPTRTYPE(PVMATRUNTIMEERROR *)  ppAtRuntimeErrorNext;
    188230
    189231    /** Head of the request queue. Atomic. */
     
    203245    /** VM Error Message. */
    204246    R3PTRTYPE(PVMERROR)             pErrorR3;
     247
     248    /** VM Runtime Error Message. */
     249    R3PTRTYPE(PVMRUNTIMEERROR)      pRuntimeErrorR3;
    205250
    206251    /** Pointer to the DBGC instance data. */
     
    245290DECLCALLBACK(void) vmR3SetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);
    246291void vmSetErrorCopy(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
     292DECLCALLBACK(void) vmR3SetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list *args);
     293void vmSetRuntimeErrorCopy(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list args);
    247294void vmR3DestroyFinalBit(PVM pVM);
    248295
  • trunk/src/VBox/VMM/VMM.cpp

    r161 r234  
    21212121            break;
    21222122
     2123        /*
     2124         * Set the VM runtime error message.
     2125         */
     2126        case VMMCALLHOST_VM_SET_RUNTIME_ERROR:
     2127            VMR3SetRuntimeErrorWorker(pVM);
     2128            break;
     2129
    21232130        default:
    21242131            AssertMsgFailed(("enmCallHostOperation=%d\n", pVM->vmm.s.enmCallHostOperation));
  • trunk/src/VBox/VMM/VMMAll/VMAll.cpp

    r23 r234  
    4141 *    @code
    4242 *    return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
    43  *    @codeend
     43 *    @endcode
    4444 * @param   pVM             VM handle. Must be non-NULL.
    4545 * @param   rc              VBox status code.
     
    6565 *    @code
    6666 *    return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
    67  *    @codeend
     67 *    @endcode
    6868 * @param   pVM             VM handle. Must be non-NULL.
    6969 * @param   rc              VBox status code.
     
    178178}
    179179
     180
     181/**
     182 * Sets the runtime error message.
     183 * As opposed VMSetError(), this method is intended to inform the VM user about
     184 * errors and error-like conditions that happen at an arbitrary point during VM
     185 * execution (like "host memory low" or "out of host disk space").
     186 *
     187 * The @a fFatal parameter defines whether the error is fatal or not. If it is
     188 * true, then it is expected that the caller has already paused the VM execution
     189 * before calling this method. The VM user is supposed to power off the VM
     190 * immediately after it has received the runtime error notification via the
     191 * FNVMATRUNTIMEERROR callback.
     192 *
     193 * If @a fFatal is false, then the paused state of the VM defines the kind of
     194 * the error. If the VM is paused before calling this method, it means that
     195 * the VM user may try to fix the error condition (i.e. free more host memory)
     196 * and then resume the VM execution. If the VM is not paused before calling
     197 * this method, it means that the given error is a warning about an error
     198 * condition that may happen soon but that doesn't directly affect the
     199 * VM execution by the time of the call.
     200 *
     201 * The @a pszErrorID parameter defines an unique error identificator.
     202 * It is used by the front-ends to show a proper message to the end user
     203 * containig possible actions (for example, Retry/Ignore). For this reason,
     204 * an error ID assigned once to some particular error condition should not
     205 * change in the future. The format of this parameter is "someErrorCondition".
     206 *
     207 * @param   pVM             VM handle. Must be non-NULL.
     208 * @param   fFatal          Whether it is a fatal error or not.
     209 * @param   pszErrorID      Error ID string.
     210 * @param   pszFormat       Error message format string.
     211 * @param   ...             Error message arguments.
     212 *
     213 * @return  VBox status code (whether the error has been successfully set
     214 *          and delivered to callbacks or not).
     215 *
     216 * @thread  Any
     217 */
     218VMDECL(int) VMSetRuntimeError(PVM pVM, bool fFatal, const char *pszErrorID,
     219                              const char *pszFormat, ...)
     220{
     221    va_list args;
     222    va_start(args, pszFormat);
     223    int rc = VMSetRuntimeErrorV(pVM, fFatal, pszErrorID, pszFormat, args);
     224    va_end(args);
     225    return rc;
     226}
     227
     228
     229/**
     230 * va_list version of VMSetRuntimeError.
     231 *
     232 * @param   pVM             VM handle. Must be non-NULL.
     233 * @param   fFatal          Whether it is a fatal error or not.
     234 * @param   pszErrorID      Error ID string.
     235 * @param   pszFormat       Error message format string.
     236 * @param   args            Error message arguments.
     237 *
     238 * @return  VBox status code (whether the error has been successfully set
     239 *          and delivered to callbacks or not).
     240 *
     241 * @thread  Any
     242 */
     243VMDECL(int) VMSetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID,
     244                               const char *pszFormat, va_list args)
     245{
     246#ifdef IN_RING3
     247    /*
     248     * Switch to EMT.
     249     */
     250    PVMREQ pReq;
     251    VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3SetRuntimeErrorV, 5,
     252                pVM, fFatal, pszErrorID, pszFormat, &args);
     253    VMR3ReqFree(pReq);
     254
     255#else
     256    /*
     257     * We're already on the EMT thread and can safely create a VMRUNTIMEERROR chunk.
     258     */
     259    vmSetRuntimeErrorCopy(pVM, fFatal, pszErrorID, pszFormat, args);
     260
     261# ifdef IN_GC
     262    VMMGCCallHost(pVM, VMMCALLHOST_VM_SET_RUNTIME_ERROR, 0);
     263# elif defined(IN_RING0)
     264    VMMR0CallHost(pVM, VMMCALLHOST_VM_SET_RUNTIME_ERROR, 0);
     265# else
     266# endif
     267#endif
     268    return VINF_SUCCESS;
     269}
     270
     271
     272/**
     273 * Copies the error to a VMRUNTIMEERROR structure.
     274 *
     275 * This is mainly intended for Ring-0 and GC where the error must be copied to
     276 * memory accessible from ring-3. But it's just possible that we might add
     277 * APIs for retrieving the VMRUNTIMEERROR copy later.
     278 *
     279 * @param   pVM             VM handle. Must be non-NULL.
     280 * @param   fFatal          Whether it is a fatal error or not.
     281 * @param   pszErrorID      Error ID string.
     282 * @param   pszFormat       Error message format string.
     283 * @param   args            Error message arguments.
     284 * @thread  EMT
     285 */
     286void vmSetRuntimeErrorCopy(PVM pVM, bool fFatal, const char *pszErrorID,
     287                           const char *pszFormat, va_list args)
     288{
     289#if 0 /// @todo implement Ring-0 and GC VMSetError
     290    /*
     291     * Create the untranslated message copy.
     292     */
     293    /* free any old message. */
     294    MMHyperFree(pVM, MMHyperR32Ctx(pVM, pVM->vm.s.pRuntimeErrorR3));
     295    pVM->vm.s.pRuntimeErrorR3 = NULL;
     296
     297    /* calc reasonable start size. */
     298    size_t cchErrorID = pszErrorID ? strlen(pszErrorID) : 0;
     299    size_t cchFormat = strlen(pszFormat);
     300    size_t cb = sizeof(VMRUNTIMEERROR)
     301              + cchErrorID + 1
     302              + cchFormat + 32;
     303
     304    /* allocate it */
     305    void *pv;
     306    int rc2 = MMHyperAlloc(pVM, cb, 0, MM_TAG_VM, &pv);
     307    if (VBOX_SUCCESS(rc2))
     308    {
     309        /* initialize it. */
     310        PVMRUNTIMEERROR pErr = (PVMRUNTIMEERROR)pv;
     311        pErr->cbAllocated = cb;
     312        pErr->off = sizeof(PVMRUNTIMEERROR);
     313        pErr->offErrorID = = 0;
     314
     315        if (cchErrorID)
     316        {
     317            pErr->offErrorID = pErr->off;
     318            memcpy((uint8_t *)pErr + pErr->off, pszErrorID, cchErrorID + 1);
     319            pErr->off += cchErrorID + 1;
     320        }
     321
     322        pErr->offMessage = pErr->off;
     323
     324        /* format the message (pErr might be reallocated) */
     325        VMSETRUNTIMEERRORFMTARGS Args;
     326        Args.pVM = pVM;
     327        Args.pErr = pErr;
     328
     329        va_list va2;
     330        va_copy(va2, args);
     331        RTStrFormatV(vmSetRuntimeErrorFmtOut, &pErr, NULL, NULL, &pszFormatTmp, args);
     332        va_end(va2);
     333
     334        /* done. */
     335        pVM->vm.s.pErrorRuntimeR3 = MMHyper2HC(pVM, (uintptr_t)pArgs.pErr);
     336    }
     337#endif
     338}
     339
  • trunk/src/VBox/VMM/VMMInternal.h

    r161 r234  
    302302    STAMCOUNTER                 StatGCRetRemReplay;
    303303    STAMCOUNTER                 StatGCRetVMSetError;
     304    STAMCOUNTER                 StatGCRetVMSetRuntimeError;
    304305    STAMCOUNTER                 StatGCRetPGMLock;
    305306
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r140 r234  
    365365                case VMMCALLHOST_VM_SET_ERROR:
    366366                    STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetVMSetError);
     367                    break;
     368                case VMMCALLHOST_VM_SET_RUNTIME_ERROR:
     369                    STAM_COUNTER_INC(&pVM->vmm.s.StatGCRetVMSetRuntimeError);
    367370                    break;
    368371                default:
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