VirtualBox

Changeset 58159 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Oct 9, 2015 5:31:28 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
103267
Message:

VMMDev: Positive thinking, Doxygen, and some heartbeat cleanups.

Location:
trunk/src/VBox/Devices/VMMDev
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/VMMDev/VMMDev.cpp

    r58156 r58159  
    1414 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1515 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     16 */
     17
     18/** @page pg_vmmdev   The VMM Device.
     19 *
     20 * The VMM device is a custom hardware device emulation for communicating with
     21 * the guest additions.
     22 *
     23 * Whenever host wants to inform guest about something an IRQ notification will
     24 * be raised.
     25 *
     26 * VMMDev PDM interface will contain the guest notification method.
     27 *
     28 * There is a 32 bit event mask which will be read by guest on an interrupt.  A
     29 * non zero bit in the mask means that the specific event occurred and requires
     30 * processing on guest side.
     31 *
     32 * After reading the event mask guest must issue a generic request
     33 * AcknowlegdeEvents.
     34 *
     35 * IRQ line is set to 1 (request) if there are unprocessed events, that is the
     36 * event mask is not zero.
     37 *
     38 * After receiving an interrupt and checking event mask, the guest must process
     39 * events using the event specific mechanism.
     40 *
     41 * That is if mouse capabilities were changed, guest will use
     42 * VMMDev_GetMouseStatus generic request.
     43 *
     44 * Event mask is only a set of flags indicating that guest must proceed with a
     45 * procedure.
     46 *
     47 * Unsupported events are therefore ignored. The guest additions must inform
     48 * host which events they want to receive, to avoid unnecessary IRQ processing.
     49 * By default no events are signalled to guest.
     50 *
     51 * This seems to be fast method. It requires only one context switch for an
     52 * event processing.
     53 *
    1654 */
    1755
     
    6098*   Defined Constants And Macros                                                                                                 *
    6199*********************************************************************************************************************************/
    62 #define VBOX_GUEST_INTERFACE_VERSION_1_03(s) \
     100#define VMMDEV_INTERFACE_VERSION_IS_1_03(s) \
    63101    (   RT_HIWORD((s)->guestInfo.interfaceVersion) == 1 \
    64102     && RT_LOWORD((s)->guestInfo.interfaceVersion) == 3 )
    65103
    66 #define VBOX_GUEST_INTERFACE_VERSION_OK(additionsVersion) \
     104#define VMMDEV_INTERFACE_VERSION_IS_OK(additionsVersion) \
    67105      (   RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
    68106       && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION) )
    69107
    70 #define VBOX_GUEST_INTERFACE_VERSION_OLD(additionsVersion) \
     108#define VMMDEV_INTERFACE_VERSION_IS_OLD(additionsVersion) \
    71109      (   (RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) \
    72110       || (   RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
    73111           && RT_LOWORD(additionsVersion) <= RT_LOWORD(VMMDEV_VERSION) ) )
    74112
    75 #define VBOX_GUEST_INTERFACE_VERSION_TOO_OLD(additionsVersion) \
     113#define VMMDEV_INTERFACE_VERSION_IS_TOO_OLD(additionsVersion) \
    76114      ( RT_HIWORD(additionsVersion) < RT_HIWORD(VMMDEV_VERSION) )
    77115
    78 #define VBOX_GUEST_INTERFACE_VERSION_NEW(additionsVersion) \
     116#define VMMDEV_INTERFACE_VERSION_IS_NEW(additionsVersion) \
    79117      (   RT_HIWORD(additionsVersion) > RT_HIWORD(VMMDEV_VERSION) \
    80118       || (   RT_HIWORD(additionsVersion) == RT_HIWORD(VMMDEV_VERSION) \
     
    93131 *  Used when no HeartbeatInterval is set in CFGM and for setting
    94132 *  HB check timer if the guest's heartbeat frequency is less than 1Hz. */
    95 #define HEARTBEAT_DEFAULT_INTERVAL            UINT64_C(2000000000)
     133#define VMMDEV_HEARTBEAT_DEFAULT_INTERVAL                       (2U*RT_NS_1SEC_64)
    96134
    97135
    98136#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    99137
    100 /** @page pg_vmmdev   VMMDev
    101  *
    102  * Whenever host wants to inform guest about something an IRQ notification will
    103  * be raised.
    104  *
    105  * VMMDev PDM interface will contain the guest notification method.
    106  *
    107  * There is a 32 bit event mask which will be read by guest on an interrupt.  A
    108  * non zero bit in the mask means that the specific event occurred and requires
    109  * processing on guest side.
    110  *
    111  * After reading the event mask guest must issue a generic request
    112  * AcknowlegdeEvents.
    113  *
    114  * IRQ line is set to 1 (request) if there are unprocessed events, that is the
    115  * event mask is not zero.
    116  *
    117  * After receiving an interrupt and checking event mask, the guest must process
    118  * events using the event specific mechanism.
    119  *
    120  * That is if mouse capabilities were changed, guest will use
    121  * VMMDev_GetMouseStatus generic request.
    122  *
    123  * Event mask is only a set of flags indicating that guest must proceed with a
    124  * procedure.
    125  *
    126  * Unsupported events are therefore ignored. The guest additions must inform
    127  * host which events they want to receive, to avoid unnecessary IRQ processing.
    128  * By default no events are signalled to guest.
    129  *
    130  * This seems to be fast method. It requires only one context switch for an
    131  * event processing.
    132  *
    133  */
    134 
    135 
    136138/* -=-=-=-=- Misc Helpers -=-=-=-=- */
    137139
     
    143145static void vmmdevLogGuestOsInfo(VBoxGuestInfo *pGuestInfo)
    144146{
    145     const char *pcszOs;
     147    const char *pszOs;
    146148    switch (pGuestInfo->osType & ~VBOXOSTYPE_x64)
    147149    {
    148         case VBOXOSTYPE_DOS:                              pcszOs = "DOS";            break;
    149         case VBOXOSTYPE_Win31:                            pcszOs = "Windows 3.1";    break;
    150         case VBOXOSTYPE_Win9x:                            pcszOs = "Windows 9x";     break;
    151         case VBOXOSTYPE_Win95:                            pcszOs = "Windows 95";     break;
    152         case VBOXOSTYPE_Win98:                            pcszOs = "Windows 98";     break;
    153         case VBOXOSTYPE_WinMe:                            pcszOs = "Windows Me";     break;
    154         case VBOXOSTYPE_WinNT:                            pcszOs = "Windows NT";     break;
    155         case VBOXOSTYPE_WinNT4:                           pcszOs = "Windows NT4";    break;
    156         case VBOXOSTYPE_Win2k:                            pcszOs = "Windows 2k";     break;
    157         case VBOXOSTYPE_WinXP:                            pcszOs = "Windows XP";     break;
    158         case VBOXOSTYPE_Win2k3:                           pcszOs = "Windows 2k3";    break;
    159         case VBOXOSTYPE_WinVista:                         pcszOs = "Windows Vista";  break;
    160         case VBOXOSTYPE_Win2k8:                           pcszOs = "Windows 2k8";    break;
    161         case VBOXOSTYPE_Win7:                             pcszOs = "Windows 7";      break;
    162         case VBOXOSTYPE_Win8:                             pcszOs = "Windows 8";      break;
    163         case VBOXOSTYPE_Win2k12_x64 & ~VBOXOSTYPE_x64:    pcszOs = "Windows 2k12";   break;
    164         case VBOXOSTYPE_Win81:                            pcszOs = "Windows 8.1";    break;
    165         case VBOXOSTYPE_Win10:                            pcszOs = "Windows 10";     break;
    166         case VBOXOSTYPE_OS2:                              pcszOs = "OS/2";           break;
    167         case VBOXOSTYPE_OS2Warp3:                         pcszOs = "OS/2 Warp 3";    break;
    168         case VBOXOSTYPE_OS2Warp4:                         pcszOs = "OS/2 Warp 4";    break;
    169         case VBOXOSTYPE_OS2Warp45:                        pcszOs = "OS/2 Warp 4.5";  break;
    170         case VBOXOSTYPE_ECS:                              pcszOs = "OS/2 ECS";       break;
    171         case VBOXOSTYPE_OS21x:                            pcszOs = "OS/2 2.1x";      break;
    172         case VBOXOSTYPE_Linux:                            pcszOs = "Linux";          break;
    173         case VBOXOSTYPE_Linux22:                          pcszOs = "Linux 2.2";      break;
    174         case VBOXOSTYPE_Linux24:                          pcszOs = "Linux 2.4";      break;
    175         case VBOXOSTYPE_Linux26:                          pcszOs = "Linux >= 2.6";   break;
    176         case VBOXOSTYPE_ArchLinux:                        pcszOs = "ArchLinux";      break;
    177         case VBOXOSTYPE_Debian:                           pcszOs = "Debian";         break;
    178         case VBOXOSTYPE_OpenSUSE:                         pcszOs = "openSUSE";       break;
    179         case VBOXOSTYPE_FedoraCore:                       pcszOs = "Fedora";         break;
    180         case VBOXOSTYPE_Gentoo:                           pcszOs = "Gentoo";         break;
    181         case VBOXOSTYPE_Mandriva:                         pcszOs = "Mandriva";       break;
    182         case VBOXOSTYPE_RedHat:                           pcszOs = "RedHat";         break;
    183         case VBOXOSTYPE_Turbolinux:                       pcszOs = "TurboLinux";     break;
    184         case VBOXOSTYPE_Ubuntu:                           pcszOs = "Ubuntu";         break;
    185         case VBOXOSTYPE_Xandros:                          pcszOs = "Xandros";        break;
    186         case VBOXOSTYPE_Oracle:                           pcszOs = "Oracle Linux";   break;
    187         case VBOXOSTYPE_FreeBSD:                          pcszOs = "FreeBSD";        break;
    188         case VBOXOSTYPE_OpenBSD:                          pcszOs = "OpenBSD";        break;
    189         case VBOXOSTYPE_NetBSD:                           pcszOs = "NetBSD";         break;
    190         case VBOXOSTYPE_Netware:                          pcszOs = "Netware";        break;
    191         case VBOXOSTYPE_Solaris:                          pcszOs = "Solaris";        break;
    192         case VBOXOSTYPE_OpenSolaris:                      pcszOs = "OpenSolaris";    break;
    193         case VBOXOSTYPE_Solaris11_x64 & ~VBOXOSTYPE_x64:  pcszOs = "Solaris 11";     break;
    194         case VBOXOSTYPE_MacOS:                            pcszOs = "Mac OS X";       break;
    195         case VBOXOSTYPE_MacOS106:                         pcszOs = "Mac OS X 10.6";  break;
    196         case VBOXOSTYPE_MacOS107_x64 & ~VBOXOSTYPE_x64:   pcszOs = "Mac OS X 10.7";  break;
    197         case VBOXOSTYPE_MacOS108_x64 & ~VBOXOSTYPE_x64:   pcszOs = "Mac OS X 10.8";  break;
    198         case VBOXOSTYPE_MacOS109_x64 & ~VBOXOSTYPE_x64:   pcszOs = "Mac OS X 10.9";  break;
    199         case VBOXOSTYPE_MacOS1010_x64 & ~VBOXOSTYPE_x64:  pcszOs = "Mac OS X 10.10"; break;
    200         case VBOXOSTYPE_MacOS1011_x64 & ~VBOXOSTYPE_x64:  pcszOs = "Mac OS X 10.11"; break;
    201         case VBOXOSTYPE_Haiku:                            pcszOs = "Haiku";          break;
    202         default:                                          pcszOs = "unknown";        break;
     150        case VBOXOSTYPE_DOS:                              pszOs = "DOS";            break;
     151        case VBOXOSTYPE_Win31:                            pszOs = "Windows 3.1";    break;
     152        case VBOXOSTYPE_Win9x:                            pszOs = "Windows 9x";     break;
     153        case VBOXOSTYPE_Win95:                            pszOs = "Windows 95";     break;
     154        case VBOXOSTYPE_Win98:                            pszOs = "Windows 98";     break;
     155        case VBOXOSTYPE_WinMe:                            pszOs = "Windows Me";     break;
     156        case VBOXOSTYPE_WinNT:                            pszOs = "Windows NT";     break;
     157        case VBOXOSTYPE_WinNT4:                           pszOs = "Windows NT4";    break;
     158        case VBOXOSTYPE_Win2k:                            pszOs = "Windows 2k";     break;
     159        case VBOXOSTYPE_WinXP:                            pszOs = "Windows XP";     break;
     160        case VBOXOSTYPE_Win2k3:                           pszOs = "Windows 2k3";    break;
     161        case VBOXOSTYPE_WinVista:                         pszOs = "Windows Vista";  break;
     162        case VBOXOSTYPE_Win2k8:                           pszOs = "Windows 2k8";    break;
     163        case VBOXOSTYPE_Win7:                             pszOs = "Windows 7";      break;
     164        case VBOXOSTYPE_Win8:                             pszOs = "Windows 8";      break;
     165        case VBOXOSTYPE_Win2k12_x64 & ~VBOXOSTYPE_x64:    pszOs = "Windows 2k12";   break;
     166        case VBOXOSTYPE_Win81:                            pszOs = "Windows 8.1";    break;
     167        case VBOXOSTYPE_Win10:                            pszOs = "Windows 10";     break;
     168        case VBOXOSTYPE_OS2:                              pszOs = "OS/2";           break;
     169        case VBOXOSTYPE_OS2Warp3:                         pszOs = "OS/2 Warp 3";    break;
     170        case VBOXOSTYPE_OS2Warp4:                         pszOs = "OS/2 Warp 4";    break;
     171        case VBOXOSTYPE_OS2Warp45:                        pszOs = "OS/2 Warp 4.5";  break;
     172        case VBOXOSTYPE_ECS:                              pszOs = "OS/2 ECS";       break;
     173        case VBOXOSTYPE_OS21x:                            pszOs = "OS/2 2.1x";      break;
     174        case VBOXOSTYPE_Linux:                            pszOs = "Linux";          break;
     175        case VBOXOSTYPE_Linux22:                          pszOs = "Linux 2.2";      break;
     176        case VBOXOSTYPE_Linux24:                          pszOs = "Linux 2.4";      break;
     177        case VBOXOSTYPE_Linux26:                          pszOs = "Linux >= 2.6";   break;
     178        case VBOXOSTYPE_ArchLinux:                        pszOs = "ArchLinux";      break;
     179        case VBOXOSTYPE_Debian:                           pszOs = "Debian";         break;
     180        case VBOXOSTYPE_OpenSUSE:                         pszOs = "openSUSE";       break;
     181        case VBOXOSTYPE_FedoraCore:                       pszOs = "Fedora";         break;
     182        case VBOXOSTYPE_Gentoo:                           pszOs = "Gentoo";         break;
     183        case VBOXOSTYPE_Mandriva:                         pszOs = "Mandriva";       break;
     184        case VBOXOSTYPE_RedHat:                           pszOs = "RedHat";         break;
     185        case VBOXOSTYPE_Turbolinux:                       pszOs = "TurboLinux";     break;
     186        case VBOXOSTYPE_Ubuntu:                           pszOs = "Ubuntu";         break;
     187        case VBOXOSTYPE_Xandros:                          pszOs = "Xandros";        break;
     188        case VBOXOSTYPE_Oracle:                           pszOs = "Oracle Linux";   break;
     189        case VBOXOSTYPE_FreeBSD:                          pszOs = "FreeBSD";        break;
     190        case VBOXOSTYPE_OpenBSD:                          pszOs = "OpenBSD";        break;
     191        case VBOXOSTYPE_NetBSD:                           pszOs = "NetBSD";         break;
     192        case VBOXOSTYPE_Netware:                          pszOs = "Netware";        break;
     193        case VBOXOSTYPE_Solaris:                          pszOs = "Solaris";        break;
     194        case VBOXOSTYPE_OpenSolaris:                      pszOs = "OpenSolaris";    break;
     195        case VBOXOSTYPE_Solaris11_x64 & ~VBOXOSTYPE_x64:  pszOs = "Solaris 11";     break;
     196        case VBOXOSTYPE_MacOS:                            pszOs = "Mac OS X";       break;
     197        case VBOXOSTYPE_MacOS106:                         pszOs = "Mac OS X 10.6";  break;
     198        case VBOXOSTYPE_MacOS107_x64 & ~VBOXOSTYPE_x64:   pszOs = "Mac OS X 10.7";  break;
     199        case VBOXOSTYPE_MacOS108_x64 & ~VBOXOSTYPE_x64:   pszOs = "Mac OS X 10.8";  break;
     200        case VBOXOSTYPE_MacOS109_x64 & ~VBOXOSTYPE_x64:   pszOs = "Mac OS X 10.9";  break;
     201        case VBOXOSTYPE_MacOS1010_x64 & ~VBOXOSTYPE_x64:  pszOs = "Mac OS X 10.10"; break;
     202        case VBOXOSTYPE_MacOS1011_x64 & ~VBOXOSTYPE_x64:  pszOs = "Mac OS X 10.11"; break;
     203        case VBOXOSTYPE_Haiku:                            pszOs = "Haiku";          break;
     204        default:                                          pszOs = "unknown";        break;
    203205    }
    204206    LogRel(("VMMDev: Guest Additions information report: Interface = 0x%08X osType = 0x%08X (%s, %u-bit)\n",
    205             pGuestInfo->interfaceVersion, pGuestInfo->osType, pcszOs,
     207            pGuestInfo->interfaceVersion, pGuestInfo->osType, pszOs,
    206208            pGuestInfo->osType & VBOXOSTYPE_x64 ? 64 : 32));
    207209}
     
    216218static void vmmdevSetIRQ_Legacy(PVMMDEV pThis)
    217219{
    218     if (!pThis->fu32AdditionsOk)
    219     {
     220    if (pThis->fu32AdditionsOk)
     221    {
     222        /* Filter unsupported events */
     223        uint32_t fEvents = pThis->u32HostEventFlags & pThis->pVMMDevRAMR3->V.V1_03.u32GuestEventMask;
     224
     225        Log(("vmmdevSetIRQ: fEvents=%#010x, u32HostEventFlags=%#010x, u32GuestEventMask=%#010x.\n",
     226             fEvents, pThis->u32HostEventFlags, pThis->pVMMDevRAMR3->V.V1_03.u32GuestEventMask));
     227
     228        /* Move event flags to VMMDev RAM */
     229        pThis->pVMMDevRAMR3->V.V1_03.u32HostEvents = fEvents;
     230
     231        uint32_t uIRQLevel = 0;
     232        if (fEvents)
     233        {
     234            /* Clear host flags which will be delivered to guest. */
     235            pThis->u32HostEventFlags &= ~fEvents;
     236            Log(("vmmdevSetIRQ: u32HostEventFlags=%#010x\n", pThis->u32HostEventFlags));
     237            uIRQLevel = 1;
     238        }
     239
     240        /* Set IRQ level for pin 0 (see NoWait comment in vmmdevMaybeSetIRQ). */
     241        /** @todo make IRQ pin configurable, at least a symbolic constant */
     242        PDMDevHlpPCISetIrqNoWait(pThis->pDevIns, 0, uIRQLevel);
     243        Log(("vmmdevSetIRQ: IRQ set %d\n", uIRQLevel));
     244    }
     245    else
    220246        Log(("vmmdevSetIRQ: IRQ is not generated, guest has not yet reported to us.\n"));
    221         return;
    222     }
    223 
    224     /* Filter unsupported events */
    225     uint32_t u32EventFlags = pThis->u32HostEventFlags
    226                            & pThis->pVMMDevRAMR3->V.V1_03.u32GuestEventMask;
    227 
    228     Log(("vmmdevSetIRQ: u32EventFlags=%#010x, u32HostEventFlags=%#010x, u32GuestEventMask=%#010x.\n",
    229          u32EventFlags, pThis->u32HostEventFlags, pThis->pVMMDevRAMR3->V.V1_03.u32GuestEventMask));
    230 
    231     /* Move event flags to VMMDev RAM */
    232     pThis->pVMMDevRAMR3->V.V1_03.u32HostEvents = u32EventFlags;
    233 
    234     uint32_t u32IRQLevel = 0;
    235     if (u32EventFlags)
    236     {
    237         /* Clear host flags which will be delivered to guest. */
    238         pThis->u32HostEventFlags &= ~u32EventFlags;
    239         Log(("vmmdevSetIRQ: u32HostEventFlags=%#010x\n", pThis->u32HostEventFlags));
    240         u32IRQLevel = 1;
    241     }
    242 
    243     /* Set IRQ level for pin 0 (see NoWait comment in vmmdevMaybeSetIRQ). */
    244     /** @todo make IRQ pin configurable, at least a symbolic constant */
    245     PPDMDEVINS pDevIns = pThis->pDevIns;
    246     PDMDevHlpPCISetIrqNoWait(pDevIns, 0, u32IRQLevel);
    247     Log(("vmmdevSetIRQ: IRQ set %d\n", u32IRQLevel));
    248247}
    249248
     
    286285    Assert(PDMCritSectIsOwner(&pThis->CritSect));
    287286
    288     if (VBOX_GUEST_INTERFACE_VERSION_1_03(pThis))
     287    if (!VMMDEV_INTERFACE_VERSION_IS_1_03(pThis))
     288    {
     289        Log3(("vmmdevNotifyGuestWorker: New additions detected.\n"));
     290
     291        if (pThis->fu32AdditionsOk)
     292        {
     293            const bool fHadEvents = (pThis->u32HostEventFlags & pThis->u32GuestFilterMask) != 0;
     294
     295            Log3(("vmmdevNotifyGuestWorker: fHadEvents=%d, u32HostEventFlags=%#010x, u32GuestFilterMask=%#010x.\n",
     296                  fHadEvents, pThis->u32HostEventFlags, pThis->u32GuestFilterMask));
     297
     298            pThis->u32HostEventFlags |= fAddEvents;
     299
     300            if (!fHadEvents)
     301                vmmdevMaybeSetIRQ(pThis);
     302        }
     303        else
     304        {
     305            pThis->u32HostEventFlags |= fAddEvents;
     306            Log(("vmmdevNotifyGuestWorker: IRQ is not generated, guest has not yet reported to us.\n"));
     307        }
     308    }
     309    else
    289310    {
    290311        Log3(("vmmdevNotifyGuestWorker: Old additions detected.\n"));
     
    292313        pThis->u32HostEventFlags |= fAddEvents;
    293314        vmmdevSetIRQ_Legacy(pThis);
    294     }
    295     else
    296     {
    297         Log3(("vmmdevNotifyGuestWorker: New additions detected.\n"));
    298 
    299         if (!pThis->fu32AdditionsOk)
    300         {
    301             pThis->u32HostEventFlags |= fAddEvents;
    302             Log(("vmmdevNotifyGuestWorker: IRQ is not generated, guest has not yet reported to us.\n"));
    303             return;
    304         }
    305 
    306         const bool fHadEvents = (pThis->u32HostEventFlags & pThis->u32GuestFilterMask) != 0;
    307 
    308         Log3(("vmmdevNotifyGuestWorker: fHadEvents=%d, u32HostEventFlags=%#010x, u32GuestFilterMask=%#010x.\n",
    309               fHadEvents, pThis->u32HostEventFlags, pThis->u32GuestFilterMask));
    310 
    311         pThis->u32HostEventFlags |= fAddEvents;
    312 
    313         if (!fHadEvents)
    314             vmmdevMaybeSetIRQ(pThis);
    315315    }
    316316}
     
    334334
    335335    /*
    336      * Drop notifications if the VM is not running yet/anymore.
     336     * Only notify the VM when it's running.
    337337     */
    338338    VMSTATE enmVMState = PDMDevHlpVMState(pThis->pDevIns);
    339     if (    enmVMState != VMSTATE_RUNNING
    340         &&  enmVMState != VMSTATE_RUNNING_LS)
    341         return;
    342 
    343     PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
    344     vmmdevNotifyGuestWorker(pThis, fAddEvents);
    345     PDMCritSectLeave(&pThis->CritSect);
     339/** @todo r=bird: Shouldn't there be more states here?  Wouldn't we drop
     340 *        notifications now when we're in the process of suspending or
     341 *        similar? */
     342    if (   enmVMState == VMSTATE_RUNNING
     343        || enmVMState == VMSTATE_RUNNING_LS)
     344    {
     345        PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
     346        vmmdevNotifyGuestWorker(pThis, fAddEvents);
     347        PDMCritSectLeave(&pThis->CritSect);
     348    }
    346349}
    347350
     
    408411
    409412        /* Check additions interface version. */
    410         pThis->fu32AdditionsOk = VBOX_GUEST_INTERFACE_VERSION_OK(pThis->guestInfo.interfaceVersion);
     413        pThis->fu32AdditionsOk = VMMDEV_INTERFACE_VERSION_IS_OK(pThis->guestInfo.interfaceVersion);
    411414
    412415        vmmdevLogGuestOsInfo(&pThis->guestInfo);
     
    427430
    428431/**
    429  * Resets heartbeat timer.
    430  *
    431  * @param   pThis           The VMMDev state.
    432  * @returns VBox status code.
    433  */
    434 static int vmmDevHeartbeatTimerReset(PVMMDEV pThis)
    435 {
     432 * Handles VMMDevReq_GuestHeartbeat.
     433 *
     434 * @returns VBox status code that the guest should see.
     435 * @param   pThis    The VMMDev instance data.
     436 */
     437static int vmmDevReqHandler_GuestHeartbeat(PVMMDEV pThis)
     438{
     439    int rc;
    436440    if (pThis->fHBCheckEnabled)
    437         return TMTimerSetNano(pThis->pHBCheckTimer, pThis->u64HeartbeatTimeout);
    438 
    439     return VINF_SUCCESS;
    440 }
    441 
    442 
    443 /**
    444  * Handles VMMDevReq_GuestHeartbeat.
    445  *
    446  * @returns VBox status code that the guest should see.
    447  * @param   pThis    The VMMDev instance data.
    448  */
    449 static int vmmDevReqHandler_GuestHeartbeat(PVMMDEV pThis)
    450 {
    451     int rc = VINF_SUCCESS;
    452 
     441    {
     442        uint64_t const nsNowTS = TMTimerGetNano(pThis->pHearbeatFlatlinedTimer);
     443        if (!pThis->fHasMissedHB)
     444        { /* likely */ }
     445        else
     446        {
     447            LogRel(("VMMDev: GuestHeartBeat: Guest is alive (gone %'llu ns)\n", nsNowTS - pThis->nsLastHeartbeatTS));
     448            ASMAtomicWriteBool(&pThis->fHasMissedHB, false);
     449        }
     450        ASMAtomicWriteU64(&pThis->nsLastHeartbeatTS, nsNowTS);
     451
     452        /* Postpone (or restart if we missed a beat) the timeout timer. */
     453        rc = TMTimerSetNano(pThis->pHearbeatFlatlinedTimer, pThis->cNsHeartbeatTimeout);
     454    }
     455    else
     456        rc = VINF_SUCCESS;
     457    return rc;
     458}
     459
     460
     461/**
     462 * Timer that fires when where have been no heartbeats for a given time.
     463 *
     464 * @remarks Does not take the VMMDev critsect.
     465 */
     466static DECLCALLBACK(void) vmmDevHeartbeatFlatlinedTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     467{
     468    PVMMDEV pThis = (PVMMDEV)pvUser;
    453469    if (pThis->fHBCheckEnabled)
    454470    {
    455         ASMAtomicWriteU64(&pThis->uLastHBTime, TMTimerGetNano(pThis->pHBCheckTimer));
    456         if (pThis->fHasMissedHB)
    457         {
    458             LogRel(("VMMDev: GuestHeartBeat: Guest is alive\n"));
    459             ASMAtomicWriteBool(&pThis->fHasMissedHB, false);
    460         }
    461         rc = vmmDevHeartbeatTimerReset(pThis);
    462     }
    463     return rc;
    464 }
    465 
    466 
    467 /**
    468  * Guest heartbeat check timer. Fires if there are no heartbeats for certain time.
    469  * Timer is set in vmmDevHeartbeatTimerReset.
    470  */
    471 static DECLCALLBACK(void) vmmDevHeartBeatCheckTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    472 {
    473     PVMMDEV pThis = (PVMMDEV) pvUser;
    474     if (pThis->fHBCheckEnabled)
    475     {
    476         uint64_t uIntervalNs = TMTimerGetNano(pTimer) - pThis->uLastHBTime;
    477         if (!pThis->fHasMissedHB && uIntervalNs >= pThis->u64HeartbeatInterval)
    478         {
    479             LogRel(("VMMDev: HeartBeatCheckTimer: Guest seems to be unresponsive. Last heartbeat received %RU64 seconds ago\n",
    480                     uIntervalNs / RT_NS_1SEC_64));
     471        uint64_t cNsElapsed = TMTimerGetNano(pTimer) - pThis->nsLastHeartbeatTS;
     472        if (   !pThis->fHasMissedHB
     473            && cNsElapsed >= pThis->cNsHeartbeatInterval)
     474        {
     475            LogRel(("VMMDev: vmmDevHeartbeatFlatlinedTimer: Guest seems to be unresponsive. Last heartbeat received %RU64 seconds ago\n",
     476                    cNsElapsed / RT_NS_1SEC));
    481477            ASMAtomicWriteBool(&pThis->fHasMissedHB, true);
    482478        }
     
    498494    int rc;
    499495
    500     pReq->cNsInterval = pThis->u64HeartbeatInterval;
     496    pReq->cNsInterval = pThis->cNsHeartbeatInterval;
    501497
    502498    if (pReq->fEnabled != pThis->fHBCheckEnabled)
     
    505501        if (pReq->fEnabled)
    506502        {
    507             /* set first timer explicitly */
    508             rc = vmmDevHeartbeatTimerReset(pThis);
     503            /* Start the countdown. */
     504            rc = TMTimerSetNano(pThis->pHearbeatFlatlinedTimer, pThis->cNsHeartbeatTimeout);
    509505            if (RT_SUCCESS(rc))
    510506                LogRel(("VMMDev: Heartbeat checking timer set to trigger every %RU64 milliseconds\n",
    511                         pThis->u64HeartbeatTimeout / RT_NS_1MS));
     507                        pThis->cNsHeartbeatTimeout / RT_NS_1MS));
    512508            else
    513509                LogRel(("VMMDev: Cannot create heartbeat check timer, rc=%Rrc\n", rc));
     
    515511        else
    516512        {
    517             rc = TMTimerStop(pThis->pHBCheckTimer);
     513            rc = TMTimerStop(pThis->pHearbeatFlatlinedTimer);
    518514            LogRel(("VMMDev: Heartbeat checking timer has been stopped, rc=%Rrc\n", rc));
    519515        }
     
    15761572    AssertMsgReturn(pReq->header.size == sizeof(*pReq), ("%u\n", pReq->header.size), VERR_INVALID_PARAMETER);
    15771573
    1578     if (VBOX_GUEST_INTERFACE_VERSION_1_03(pThis))
     1574    if (VMMDEV_INTERFACE_VERSION_IS_1_03(pThis))
    15791575    {
    15801576        vmmdevSetIRQ_Legacy(pThis);
     
    40044000                                N_("Configuration error: Failed querying \"GuestCoreDumpCount\" as a 32-bit unsigned integer"));
    40054001
    4006     rc = CFGMR3QueryU64Def(pCfg, "HeartbeatInterval", &pThis->u64HeartbeatInterval, HEARTBEAT_DEFAULT_INTERVAL);
     4002    rc = CFGMR3QueryU64Def(pCfg, "HeartbeatInterval", &pThis->cNsHeartbeatInterval, VMMDEV_HEARTBEAT_DEFAULT_INTERVAL);
    40074003    if (RT_FAILURE(rc))
    40084004        return PDMDEV_SET_ERROR(pDevIns, rc,
    40094005                                N_("Configuration error: Failed querying \"HeartbeatInterval\" as a 64-bit unsigned integer"));
    4010     if (pThis->u64HeartbeatInterval < RT_NS_100MS/2)
     4006    if (pThis->cNsHeartbeatInterval < RT_NS_100MS / 2)
    40114007        return PDMDEV_SET_ERROR(pDevIns, rc,
    40124008                                N_("Configuration error: Heartbeat interval \"HeartbeatInterval\" too small"));
    40134009
    4014     rc = CFGMR3QueryU64Def(pCfg, "HeartbeatTimeout", &pThis->u64HeartbeatTimeout, pThis->u64HeartbeatInterval * 2);
     4010    rc = CFGMR3QueryU64Def(pCfg, "HeartbeatTimeout", &pThis->cNsHeartbeatTimeout, pThis->cNsHeartbeatInterval * 2);
    40154011    if (RT_FAILURE(rc))
    40164012        return PDMDEV_SET_ERROR(pDevIns, rc,
    40174013                                N_("Configuration error: Failed querying \"HeartbeatTimeout\" as a 64-bit unsigned integer"));
    4018     if (pThis->u64HeartbeatTimeout < RT_NS_100MS)
     4014    if (pThis->cNsHeartbeatTimeout < RT_NS_100MS)
    40194015        return PDMDEV_SET_ERROR(pDevIns, rc,
    4020                                 N_("Configuration error: Heartbeat timeout timer interval \"HeartbeatTimeout\" too small"));
     4016                                N_("Configuration error: Heartbeat timeout \"HeartbeatTimeout\" too small"));
     4017    if (pThis->cNsHeartbeatTimeout <= pThis->cNsHeartbeatInterval + RT_NS_10MS)
     4018        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     4019                                   N_("Configuration error: Heartbeat timeout \"HeartbeatTimeout\" value (%'ull ns) is too close to the interval (%'ull ns)"),
     4020                                   pThis->cNsHeartbeatTimeout, pThis->cNsHeartbeatInterval);
    40214021
    40224022#ifndef VBOX_WITHOUT_TESTING_FEATURES
     
    41694169     * Create heartbeat checking timer.
    41704170     */
    4171     rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vmmDevHeartBeatCheckTimer, pThis,
    4172                         TMTIMER_FLAGS_NO_CRIT_SECT, "HB Check Timer", &pThis->pHBCheckTimer);
     4171    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vmmDevHeartbeatFlatlinedTimer, pThis,
     4172                                TMTIMER_FLAGS_NO_CRIT_SECT, "Heartbeat flatlined", &pThis->pHearbeatFlatlinedTimer);
    41734173    AssertRCReturn(rc, rc);
    41744174
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r56292 r58159  
    361361
    362362    /** Timestamp of the last heartbeat from guest in nanosec. */
    363     uint64_t volatile   uLastHBTime;
     363    uint64_t volatile   nsLastHeartbeatTS;
    364364    /** Indicates whether we missed HB from guest on last check. */
    365365    bool volatile       fHasMissedHB;
     
    368368    /** Alignment padding. */
    369369    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;
     370    /** Guest heartbeat interval in nanoseconds.
     371     * This is the interval the guest is told to produce heartbeats at. */
     372    uint64_t            cNsHeartbeatInterval;
     373    /** The amount of time without a heartbeat (nanoseconds) before we
     374     * conclude the guest is doing a Dixie Flatline (Neuromancer) impression. */
     375    uint64_t            cNsHeartbeatTimeout;
     376    /** Timer for signalling a flatlined guest. */
     377    PTMTIMERR3          pHearbeatFlatlinedTimer;
    376378} VMMDevState;
    377379typedef VMMDevState VMMDEV;
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