VirtualBox

Changeset 52789 in vbox


Ignore:
Timestamp:
Sep 18, 2014 4:08:18 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
96175
Message:

VMMDev/Main, Additions: Guest heartbeat implementation. VMMDev reports to host log if missed heartbeat from the guest.

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VMMDev.h

    r50512 r52789  
    44
    55/*
    6  * Copyright (C) 2006-2013 Oracle Corporation
     6 * Copyright (C) 2006-2014 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    212212    VMMDevReq_GetSessionId               = 217, /* since version 3.2.8 */
    213213    VMMDevReq_WriteCoreDump              = 218,
     214    VMMDevReq_GuestHeartbeat             = 219,
     215    VMMDevReq_HeartbeatConfigure         = 220,
    214216    VMMDevReq_SizeHack                   = 0x7fffffff
    215217} VMMDevRequestType;
     
    14941496} VMMDevReqWriteCoreDump;
    14951497AssertCompileSize(VMMDevReqWriteCoreDump, 24+4);
     1498
     1499/** Heart beat check state structure.
     1500 *  Used by VMMDevReq_HeartbeatConfigure. */
     1501typedef struct
     1502{
     1503    /** Header. */
     1504    VMMDevRequestHeader header;
     1505    /** OUT: Guest heartbeat interval in nanosec. */
     1506    uint64_t    cNsInterval;
     1507    /** Heartbeat check flag. */
     1508    bool fEnabled;
     1509} VMMDevReqHeartbeat;
     1510AssertCompileSize(VMMDevReqHeartbeat, 24+12);
    14961511
    14971512
     
    20142029        case VMMDevReq_GetSessionId:
    20152030            return sizeof(VMMDevReqSessionId);
     2031        case VMMDevReq_HeartbeatConfigure:
     2032            return sizeof(VMMDevReqHeartbeat);
     2033        case VMMDevReq_GuestHeartbeat:
     2034            return sizeof(VMMDevRequestHeader);
    20162035        default:
    20172036            break;
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp

    r52701 r52789  
    4343#include <iprt/assert.h>
    4444#include <iprt/param.h>
     45#include <iprt/timer.h>
    4546#ifdef VBOX_WITH_HGCM
    4647# include <iprt/thread.h>
     
    686687
    687688/**
     689 * Sends heartbeat to host.
     690 *
     691 * @returns VBox status code.
     692 */
     693static int VBoxGuestHeartbeatSend(void)
     694{
     695    VMMDevRequestHeader *pReq;
     696    int rc = VbglGRAlloc(&pReq, sizeof(*pReq), VMMDevReq_GuestHeartbeat);
     697    Log(("VBoxGuestHeartbeatSend: VbglGRAlloc VBoxGuestHeartbeatSend completed with rc=%Rrc\n", rc));
     698    if (RT_SUCCESS(rc))
     699    {
     700        rc = VbglGRPerform(pReq);
     701        Log(("VBoxGuestHeartbeatSend: VbglGRPerform VBoxGuestHeartbeatSend completed with rc=%Rrc\n", rc));
     702        VbglGRFree(pReq);
     703    }
     704    return rc;
     705}
     706
     707
     708/**
     709 * Configure the host to check guest's heartbeat
     710 * and get heartbeat interval from the host.
     711 *
     712 * @returns VBox status code.
     713 * @param   pDevExt         The device extension.
     714 * @param   fEnabled        Set true to enable guest heartbeat checks on host.
     715 */
     716static int VBoxGuestHeartbeatHostConfigure(PVBOXGUESTDEVEXT pDevExt, bool fEnabled)
     717{
     718    VMMDevReqHeartbeat *pReq;
     719    int rc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof(*pReq), VMMDevReq_HeartbeatConfigure);
     720    Log(("VBoxGuestHeartbeatHostConfigure: VbglGRAlloc VBoxGuestHeartbeatHostConfigure completed with rc=%Rrc\n", rc));
     721    if (RT_SUCCESS(rc))
     722    {
     723        pReq->fEnabled = fEnabled;
     724        pReq->cNsInterval = 0;
     725        rc = VbglGRPerform(&pReq->header);
     726        Log(("VBoxGuestHeartbeatHostConfigure: VbglGRPerform VBoxGuestHeartbeatHostConfigure completed with rc=%Rrc\n", rc));
     727        pDevExt->cNsHeartbeatInterval = pReq->cNsInterval;
     728        VbglGRFree(&pReq->header);
     729    }
     730    return rc;
     731}
     732
     733
     734/**
     735 * Callback for heartbeat timer.
     736 */
     737static DECLCALLBACK(void) VBoxGuestHeartbeatTimerHandler(PRTTIMER p1, void *p2, uint64_t p3)
     738{
     739    NOREF(p1);
     740    NOREF(p2);
     741    NOREF(p3);
     742
     743    int rc = VBoxGuestHeartbeatSend();
     744    if (RT_FAILURE(rc))
     745    {
     746        Log(("HB Timer: VBoxGuestHeartbeatSend terminated with rc=%Rrc\n", rc));
     747    }
     748}
     749
     750
     751/**
    688752 * Helper to reinit the VBoxVMM communication after hibernation.
    689753 *
     
    10471111                        LogRelFunc(("VBoxReportGuestDriverStatus failed, rc=%Rrc\n", rc));
    10481112
     1113                    /* Make sure that heartbeat checking is disabled. */
     1114                    rc = VBoxGuestHeartbeatHostConfigure(pDevExt, false);
     1115                    if (RT_SUCCESS(rc))
     1116                    {
     1117                        rc = VBoxGuestHeartbeatHostConfigure(pDevExt, true);
     1118                        if (RT_SUCCESS(rc))
     1119                        {
     1120                            LogFlowFunc(("Setting up heartbeat to trigger every %RU64 sec\n", pDevExt->cNsHeartbeatInterval / 1000000000));
     1121                            rc = RTTimerCreateEx(&pDevExt->pHeartbeatTimer, pDevExt->cNsHeartbeatInterval,
     1122                                                 0, (PFNRTTIMER)VBoxGuestHeartbeatTimerHandler, NULL);
     1123                            if (RT_SUCCESS(rc))
     1124                            {
     1125                                rc = RTTimerStart(pDevExt->pHeartbeatTimer, 0);
     1126                                if (RT_FAILURE(rc))
     1127                                    LogRelFunc(("Heartbeat timer failed to start, rc=%Rrc\n", rc));
     1128                            }
     1129                            if (RT_FAILURE(rc))
     1130                            {
     1131                                LogRelFunc(("Failed to set up the timer, guest heartbeat is disabled\n"));
     1132                                /* Disable host heartbeat check if we failed */
     1133                                VBoxGuestHeartbeatHostConfigure(pDevExt, false);
     1134                            }
     1135                        }
     1136                        else
     1137                            LogRelFunc(("Failed to configure host for heartbeat checking, rc=%Rrc\n", rc));
     1138                    }
     1139
    10491140                    LogFlowFunc(("VBoxGuestInitDevExt: returns success\n"));
    10501141                    return VINF_SUCCESS;
     
    11101201    Log(("VBoxGuestDeleteDevExt:\n"));
    11111202    Log(("VBoxGuest: The additions driver is terminating.\n"));
     1203
     1204    /*
     1205     * Stop and destroy HB timer and
     1206     * disable host heartbeat checking.
     1207     */
     1208    if (pDevExt->pHeartbeatTimer)
     1209    {
     1210        RTTimerDestroy(pDevExt->pHeartbeatTimer);
     1211        VBoxGuestHeartbeatHostConfigure(pDevExt, false);
     1212    }
    11121213
    11131214    /*
  • trunk/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h

    r52700 r52789  
    55
    66/*
    7  * Copyright (C) 2010-2012 Oracle Corporation
     7 * Copyright (C) 2010-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3232#include <iprt/semaphore.h>
    3333#include <iprt/spinlock.h>
     34#include <iprt/timer.h>
    3435#include <VBox/VMMDev.h>
    3536#include <VBox/VBoxGuest.h>
     
    179180     * and as such reported to the host. */
    180181    uint32_t                    u32GuestCaps;
     182    /** Heartbeat timer which fires with interval
     183      * cNsHearbeatInterval and its handler sends
     184      * VMMDevReq_GuestHeartbeat to VMMDev. */
     185    PRTTIMER                    pHeartbeatTimer;
     186    /** Heartbeat timer interval in nanoseconds. */
     187    uint64_t                    cNsHeartbeatInterval;
    181188} VBOXGUESTDEVEXT;
    182189/** Pointer to the VBoxGuest driver data. */
  • trunk/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile

    r44528 r52789  
    55
    66#
    7 # Copyright (C) 2006-2012 Oracle Corporation
     7# Copyright (C) 2006-2014 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    150150        thread-r0drv-freebsd.c \
    151151        thread2-r0drv-freebsd.c \
    152         time-r0drv-freebsd.c
     152        time-r0drv-freebsd.c \
     153        timer-r0drv-freebsd.c
    153154
    154155.PATH:  ${.CURDIR}/r0drv/generic
  • trunk/src/VBox/Additions/common/VBoxGuest/linux/Makefile

    r52421 r52789  
    55
    66#
    7 # Copyright (C) 2006-2012 Oracle Corporation
     7# Copyright (C) 2006-2014 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    5353        r0drv/linux/thread2-r0drv-linux.o \
    5454        r0drv/linux/time-r0drv-linux.o \
     55        r0drv/linux/timer-r0drv-linux.o \
    5556        r0drv/linux/RTLogWriteDebugger-r0drv-linux.o \
    5657        r0drv/generic/semspinmutex-r0drv-generic.o \
  • trunk/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest

    r44528 r52789  
    66
    77#
    8 # Copyright (C) 2007-2012 Oracle Corporation
     8# Copyright (C) 2007-2014 Oracle Corporation
    99#
    1010# This file is part of VirtualBox Open Source Edition (OSE), as
     
    5252    ${PATH_ROOT}/include/iprt/thread.h=>include/iprt/thread.h \
    5353    ${PATH_ROOT}/include/iprt/time.h=>include/iprt/time.h \
     54    ${PATH_ROOT}/include/iprt/timer.h=>include/iprt/timer.h \
    5455    ${PATH_ROOT}/include/iprt/types.h=>include/iprt/types.h \
    5556    ${PATH_ROOT}/include/iprt/uni.h=>include/iprt/uni.h \
     
    171172    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/thread2-r0drv-linux.c=>r0drv/linux/thread2-r0drv-linux.c \
    172173    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/time-r0drv-linux.c=>r0drv/linux/time-r0drv-linux.c \
     174    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c=>r0drv/linux/timer-r0drv-linux.c \
    173175    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/waitqueue-r0drv-linux.h=>r0drv/linux/waitqueue-r0drv-linux.h \
    174176    ${PATH_ROOT}/src/VBox/Runtime/r0drv/linux/RTLogWriteDebugger-r0drv-linux.c=>r0drv/linux/RTLogWriteDebugger-r0drv-linux.c \
  • trunk/src/VBox/Devices/VMMDev/VMMDev.cpp

    r52667 r52789  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    9090 *  This doesn't have the config part. */
    9191#define VMMDEV_SAVED_STATE_VERSION_VBOX_30                      11
     92/** Default interval in nanoseconds between guest heartbeats.
     93 *  Used when no HeartbeatInterval is set in CFGM and for setting
     94 *  HB check timer if the guest's heartbeat frequency is less than 1Hz. */
     95#define HEARTBEAT_DEFAULT_INTERVAL            UINT64_C(2000000000)
    9296
    9397
     
    350354
    351355    return VINF_SUCCESS;
     356}
     357
     358
     359/**
     360 * Resets heartbeat timer.
     361 *
     362 * @param   pThis           The VMMDev state.
     363 * @returns VBox status code.
     364 */
     365static int vmmDevHeartbeatTimerReset(PVMMDEV pThis)
     366{
     367    if (pThis->fHBCheckEnabled)
     368        return TMTimerSetNano(pThis->pHBCheckTimer, pThis->u64HeartbeatTimeout);
     369
     370    return VINF_SUCCESS;
     371}
     372
     373
     374/**
     375 * Handles VMMDevReq_GuestHeartbeat.
     376 *
     377 * @returns VBox status code that the guest should see.
     378 * @param   pThis    The VMMDev instance data.
     379 */
     380static int vmmDevReqHandler_GuestHeartbeat(PVMMDEV pThis)
     381{
     382    int rc = VINF_SUCCESS;
     383
     384    if (pThis->fHBCheckEnabled)
     385    {
     386        ASMAtomicWriteU64(&pThis->uLastHBTime, TMTimerGetNano(pThis->pHBCheckTimer));
     387        if (pThis->fHasMissedHB)
     388        {
     389            LogRel(("vmmDevReqHandler_GuestHeartBeat: guest is alive\n"));
     390            ASMAtomicWriteBool(&pThis->fHasMissedHB, false);
     391        }
     392        rc = vmmDevHeartbeatTimerReset(pThis);
     393    }
     394    return rc;
     395}
     396
     397
     398/**
     399 * Guest heartbeat check timer. Fires if there are no heartbeats for certain time.
     400 * Timer is set in vmmDevHeartbeatTimerReset.
     401 */
     402static DECLCALLBACK(void) vmmDevHeartBeatCheckTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     403{
     404    PVMMDEV pThis = (PVMMDEV) pvUser;
     405    if (pThis->fHBCheckEnabled)
     406    {
     407        uint64_t interval = TMTimerGetNano(pTimer) - pThis->uLastHBTime;
     408        if (!pThis->fHasMissedHB && interval >= pThis->u64HeartbeatInterval)
     409        {
     410            LogRel(("vmmDevHeartBeatCheckTimer: guest seems to be not responding, last heartbeat received %RU64 sec ago\n", interval / 1000000000));
     411            ASMAtomicWriteBool(&pThis->fHasMissedHB, true);
     412        }
     413    }
     414}
     415
     416
     417/**
     418 * Handles VMMDevReq_HeartbeatConfigure.
     419 *
     420 * @returns VBox status code that the guest should see.
     421 * @param   pThis     The VMMDev instance data.
     422 * @param   pReqHdr   The header of the request to handle.
     423 */
     424static int vmmDevReqHandler_HeartbeatConfigure(PVMMDEV pThis, VMMDevRequestHeader *pReqHdr)
     425{
     426    AssertMsgReturn(pReqHdr->size == sizeof(VMMDevReqHeartbeat), ("%u\n", pReqHdr->size), VERR_INVALID_PARAMETER);
     427    VMMDevReqHeartbeat *pReq = (VMMDevReqHeartbeat *)pReqHdr;
     428    int rc;
     429
     430    pReq->cNsInterval = pThis->u64HeartbeatInterval;
     431
     432    if (pReq->fEnabled != pThis->fHBCheckEnabled)
     433    {
     434        ASMAtomicWriteBool(&pThis->fHBCheckEnabled, pReq->fEnabled);
     435        if (pReq->fEnabled)
     436        {
     437            /* set first timer explicitly */
     438            rc = vmmDevHeartbeatTimerReset(pThis);
     439            if (RT_SUCCESS(rc))
     440            {
     441                LogRel(("Heartbeat checking timer has been set to trigger every %RU64 sec\n", pThis->u64HeartbeatInterval / 500000000));
     442            }
     443            else
     444                LogRel(("Cannot create heartbeat check timer, rc=%Rrc\n", rc));
     445        }
     446        else
     447        {
     448            rc = TMTimerStop(pThis->pHBCheckTimer);
     449            LogRel(("Heartbeat checking timer has been stopped, rc=%Rrc\n", rc));
     450        }
     451    }
     452    else
     453    {
     454        LogRel(("vmmDevReqHandler_HeartbeatConfigure: enabled=%d\n", pThis->fHBCheckEnabled));
     455        rc = VINF_SUCCESS;
     456    }
     457
     458    return rc;
    352459}
    353460
     
    25172624        }
    25182625
     2626        case VMMDevReq_GuestHeartbeat:
     2627            pReqHdr->rc = vmmDevReqHandler_GuestHeartbeat(pThis);
     2628            break;
     2629
     2630        case VMMDevReq_HeartbeatConfigure:
     2631            pReqHdr->rc = vmmDevReqHandler_HeartbeatConfigure(pThis, pReqHdr);
     2632            break;
     2633
    25192634        default:
    25202635        {
     
    38233938                                N_("Configuration error: Failed querying \"GuestCoreDumpCount\" as a 32-bit unsigned integer"));
    38243939
     3940    rc = CFGMR3QueryU64Def(pCfg, "HeartbeatInterval", &pThis->u64HeartbeatInterval, HEARTBEAT_DEFAULT_INTERVAL);
     3941    if (RT_FAILURE(rc))
     3942        return PDMDEV_SET_ERROR(pDevIns, rc,
     3943                                N_("Configuration error: Failed querying \"HeartbeatInterval\" as a 64-bit unsigned integer"));
     3944
     3945    rc = CFGMR3QueryU64Def(pCfg, "HeartbeatTimeout", &pThis->u64HeartbeatTimeout, pThis->u64HeartbeatInterval * 2);
     3946    if (RT_FAILURE(rc))
     3947        return PDMDEV_SET_ERROR(pDevIns, rc,
     3948                                N_("Configuration error: Failed querying \"HeartbeatTimeout\" as a 64-bit unsigned integer"));
     3949
    38253950#ifndef VBOX_WITHOUT_TESTING_FEATURES
    38263951    rc = CFGMR3QueryBoolDef(pCfg, "TestingEnabled", &pThis->fTestingEnabled, false);
     
    39674092                                NULL, vmmdevSaveExec, NULL,
    39684093                                NULL, vmmdevLoadExec, vmmdevLoadStateDone);
     4094    AssertRCReturn(rc, rc);
     4095
     4096    /*
     4097     * Create heartbeat checking timer.
     4098     */
     4099    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vmmDevHeartBeatCheckTimer, pThis,
     4100                        TMTIMER_FLAGS_NO_CRIT_SECT, "HB Check Timer", &pThis->pHBCheckTimer);
    39694101    AssertRCReturn(rc, rc);
    39704102
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r51520 r52789  
    359359    RTTEST                  hTestingTest;
    360360#endif /* !VBOX_WITHOUT_TESTING_FEATURES */
     361
     362    /** Timestamp of the last heartbeat from guest in nanosec. */
     363    uint64_t volatile   uLastHBTime;
     364    /** Indicates whether we missed HB from guest on last check. */
     365    bool volatile       fHasMissedHB;
     366    /** Indicates whether heartbeat check is active. */
     367    bool volatile       fHBCheckEnabled;
     368    /** Alignment padding. */
     369    bool                afAlignment8[6];
     370    /** Guest heartbeat interval in nanoseconds. */
     371    uint64_t            u64HeartbeatInterval;
     372    /** Guest heartbeat timeout in nanoseconds. */
     373    uint64_t            u64HeartbeatTimeout;
     374    /** Timer for checking guest heart beat. */
     375    PTMTIMERR3          pHBCheckTimer;
    361376} VMMDevState;
    362377typedef VMMDevState VMMDEV;
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r52508 r52789  
    88
    99/*
    10  * Copyright (C) 2006-2012 Oracle Corporation
     10 * Copyright (C) 2006-2014 Oracle Corporation
    1111 *
    1212 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    16591659    GEN_CHECK_OFF(VMMDEV, TestingData.Value.u32Unit);
    16601660    GEN_CHECK_OFF(VMMDEV, TestingData.Value.szName);
     1661    GEN_CHECK_OFF(VMMDEV, uLastHBTime);
     1662    GEN_CHECK_OFF(VMMDEV, fHasMissedHB);
     1663    GEN_CHECK_OFF(VMMDEV, fHBCheckEnabled);
     1664    GEN_CHECK_OFF(VMMDEV, u64HeartbeatInterval);
     1665    GEN_CHECK_OFF(VMMDEV, u64HeartbeatTimeout);
     1666    GEN_CHECK_OFF(VMMDEV, pHBCheckTimer);
    16611667
    16621668#ifdef VBOX_WITH_BUSLOGIC
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