VirtualBox

Changeset 39890 in vbox for trunk/src/VBox/Devices/VMMDev


Ignore:
Timestamp:
Jan 26, 2012 7:42:19 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
75940
Message:

VMMDev,IGuest,IAdditionsFacility,VBoxGuest,iprt/types.h: VMMDev must track the guest facility reports so they can be saved and restored correctly. Also fixed a reset bug related to guestInfo2. Restrict who can report the status of which facilities. Recalc the runlevel based on which facilities are active. Restrict the number of facilities main tracks.

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

Legend:

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

    r39882 r39890  
    8787
    8888/** The saved state version. */
    89 #define VMMDEV_SAVED_STATE_VERSION                          14
     89#define VMMDEV_SAVED_STATE_VERSION                              15
     90/** The saved state version which is missing the guest facility statuses. */
     91#define VMMDEV_SAVED_STATE_VERSION_MISSING_FACILITY_STATUSES    14
    9092/** The saved state version which is missing the guestInfo2 bits. */
    91 #define VMMDEV_SAVED_STATE_VERSION_MISSING_GUEST_INFO_2     13
     93#define VMMDEV_SAVED_STATE_VERSION_MISSING_GUEST_INFO_2         13
    9294/** The saved state version used by VirtualBox 3.0.
    9395 *  This doesn't have the config part. */
    94 #define VMMDEV_SAVED_STATE_VERSION_VBOX_30                  11
     96#define VMMDEV_SAVED_STATE_VERSION_VBOX_30                      11
    9597
    9698
     
    532534
    533535    pThis->pDrv->pfnUpdateGuestInfo2(pThis->pDrv, uFullVersion, pszName, pInfo2->additionsRevision, pInfo2->additionsFeatures);
     536
     537    return VINF_SUCCESS;
     538}
     539
     540/**
     541 * Allocates a new facility status entry, initializing it to inactive.
     542 *
     543 * @returns Pointer to a facility status entry on success, NULL on failure
     544 *          (table full).
     545 * @param   pThis           The VMMDev instance data.
     546 * @param   uFacility       The facility type code - VBoxGuestFacilityType.
     547 * @param   fFixed          This is set when allocating the standard entries
     548 *                          from the constructor.
     549 * @param   pTimeSpecNow    Optionally giving the entry timestamp to use (ctor).
     550 */
     551static PVMMDEVFACILITYSTATUSENTRY
     552vmmdevAllocFacilityStatusEntry(VMMDevState *pThis, uint32_t uFacility, bool fFixed, PCRTTIMESPEC pTimeSpecNow)
     553{
     554    /* If full, expunge one inactive entry. */
     555    if (pThis->cFacilityStatuses == RT_ELEMENTS(pThis->aFacilityStatuses))
     556    {
     557        uint32_t i = pThis->cFacilityStatuses;
     558        while (i-- > 0)
     559        {
     560            if (   pThis->aFacilityStatuses[i].uStatus == VBoxGuestFacilityStatus_Inactive
     561                && !pThis->aFacilityStatuses[i].fFixed)
     562            {
     563                pThis->cFacilityStatuses--;
     564                int cToMove = pThis->cFacilityStatuses - i;
     565                if (cToMove)
     566                    memmove(&pThis->aFacilityStatuses[i], &pThis->aFacilityStatuses[i + 1],
     567                            cToMove * sizeof(pThis->aFacilityStatuses[i]));
     568                RT_ZERO(pThis->aFacilityStatuses[pThis->cFacilityStatuses]);
     569                break;
     570            }
     571        }
     572
     573        if (pThis->cFacilityStatuses == RT_ELEMENTS(pThis->aFacilityStatuses))
     574            return NULL;
     575    }
     576
     577    /* Find location in array (it's sorted). */
     578    uint32_t i = pThis->cFacilityStatuses;
     579    while (i-- > 0)
     580        if (pThis->aFacilityStatuses[i].uFacility < uFacility)
     581            break;
     582    i++;
     583
     584    /* Move. */
     585    int cToMove = pThis->cFacilityStatuses - i;
     586    if (cToMove > 0)
     587        memmove(&pThis->aFacilityStatuses[i + 1], &pThis->aFacilityStatuses[i],
     588                cToMove * sizeof(pThis->aFacilityStatuses[i]));
     589    pThis->cFacilityStatuses++;
     590
     591    /* Initialize. */
     592    pThis->aFacilityStatuses[i].uFacility   = uFacility;
     593    pThis->aFacilityStatuses[i].uStatus     = VBoxGuestFacilityStatus_Inactive;
     594    pThis->aFacilityStatuses[i].fFixed      = fFixed;
     595    pThis->aFacilityStatuses[i].fPadding    = 0;
     596    pThis->aFacilityStatuses[i].fFlags      = 0;
     597    pThis->aFacilityStatuses[i].uPadding    = 0;
     598    if (pTimeSpecNow)
     599        pThis->aFacilityStatuses[i].TimeSpecTS = *pTimeSpecNow;
     600    else
     601        RTTimeSpecSetNano(&pThis->aFacilityStatuses[i].TimeSpecTS, 0);
     602
     603    return &pThis->aFacilityStatuses[i];
     604
     605}
     606
     607/**
     608 * Gets a facility status entry, allocating a new one if not already present.
     609 *
     610 * @returns Pointer to a facility status entry on success, NULL on failure
     611 *          (table full).
     612 * @param   pThis           The VMMDev instance data.
     613 * @param   uFacility       The facility type code - VBoxGuestFacilityType.
     614 */
     615static PVMMDEVFACILITYSTATUSENTRY vmmdevGetFacilityStatusEntry(VMMDevState *pThis, uint32_t uFacility)
     616{
     617    /** @todo change to binary search. */
     618    uint32_t i = pThis->cFacilityStatuses;
     619    while (i-- > 0)
     620    {
     621        if (pThis->aFacilityStatuses[i].uFacility == uFacility)
     622            return &pThis->aFacilityStatuses[i];
     623        if (pThis->aFacilityStatuses[i].uFacility < uFacility)
     624            break;
     625    }
     626    return vmmdevAllocFacilityStatusEntry(pThis, uFacility, false /*fFixed*/, NULL);
     627}
     628
     629/**
     630 * Handles VMMDevReq_ReportGuestStatus.
     631 *
     632 * @returns VBox status code that the guest should see.
     633 * @param   pThis           The VMMDev instance data.
     634 * @param   pRequestHeader  The header of the request to handle.
     635 */
     636static int vmmdevReqHandler_ReportGuestStatus(VMMDevState *pThis, VMMDevRequestHeader *pRequestHeader)
     637{
     638    /*
     639     * Validate input.
     640     */
     641    AssertMsgReturn(pRequestHeader->size == sizeof(VMMDevReportGuestStatus), ("%u\n", pRequestHeader->size), VERR_INVALID_PARAMETER);
     642    VBoxGuestStatus *pStatus = &((VMMDevReportGuestStatus *)pRequestHeader)->guestStatus;
     643    AssertMsgReturn(   pStatus->facility > VBoxGuestFacilityType_Unknown
     644                    && pStatus->facility <= VBoxGuestFacilityType_All,
     645                    ("%d\n", pStatus->facility),
     646                    VERR_INVALID_PARAMETER);
     647    AssertMsgReturn(pStatus->status == (VBoxGuestFacilityStatus)(uint16_t)pStatus->status,
     648                    ("%#x (%u)\n", pStatus->status, pStatus->status),
     649                    VERR_OUT_OF_RANGE);
     650
     651    /*
     652     * Do the update.
     653     */
     654    RTTIMESPEC Now;
     655    RTTimeNow(&Now);
     656    if (pStatus->facility == VBoxGuestFacilityType_All)
     657    {
     658        uint32_t i = pThis->cFacilityStatuses;
     659        while (i-- > 0)
     660        {
     661            pThis->aFacilityStatuses[i].TimeSpecTS = Now;
     662            pThis->aFacilityStatuses[i].uStatus    = (uint16_t)pStatus->status;
     663            pThis->aFacilityStatuses[i].fFlags     = pStatus->flags;
     664        }
     665    }
     666    else
     667    {
     668        PVMMDEVFACILITYSTATUSENTRY pEntry = vmmdevGetFacilityStatusEntry(pThis, pStatus->facility);
     669        if (!pEntry)
     670        {
     671            static int g_cLogEntries = 0;
     672            if (g_cLogEntries++ < 10)
     673                LogRel(("VMM: Facility table is full - facility=%u status=%u.\n", pStatus->facility, pStatus->status));
     674            return VERR_OUT_OF_RESOURCES;
     675        }
     676
     677        pEntry->TimeSpecTS = Now;
     678        pEntry->uStatus    = (uint16_t)pStatus->status;
     679        pEntry->fFlags     = pStatus->flags;
     680    }
     681
     682    if (pThis->pDrv)
     683        pThis->pDrv->pfnUpdateGuestStatus(pThis->pDrv, pStatus->facility, pStatus->status, pStatus->flags, &Now);
    534684
    535685    return VINF_SUCCESS;
     
    727877
    728878        case VMMDevReq_ReportGuestStatus:
    729         {
    730             if (pRequestHeader->size != sizeof(VMMDevReportGuestStatus))
    731             {
    732                 AssertMsgFailed(("VMMDev guest status structure has an invalid size!\n"));
    733                 pRequestHeader->rc = VERR_INVALID_PARAMETER;
    734             }
    735             else
    736             {
    737                 /** @todo r=bird: VMMDev (or GuestImpl.cpp) needs to remember this stuff and
    738                  *        tell Main after a state restore! */
    739                 VBoxGuestStatus *guestStatus = &((VMMDevReportGuestStatus*)pRequestHeader)->guestStatus;
    740                 pThis->pDrv->pfnUpdateGuestStatus(pThis->pDrv, guestStatus);
    741 
    742                 pRequestHeader->rc = VINF_SUCCESS;
    743             }
    744             break;
    745         }
     879            pRequestHeader->rc = vmmdevReqHandler_ReportGuestStatus(pThis, pRequestHeader);
     880            break;
    746881
    747882        /* Report guest capabilities */
     
    27192854    SSMR3PutU32(pSSM, pThis->guestInfo2.fFeatures);
    27202855    SSMR3PutStrZ(pSSM, pThis->guestInfo2.szName);
     2856    SSMR3PutU32(pSSM, pThis->cFacilityStatuses);
     2857    for (uint32_t i = 0; i < pThis->cFacilityStatuses; i++)
     2858    {
     2859        SSMR3PutU32(pSSM, pThis->aFacilityStatuses[i].uFacility);
     2860        SSMR3PutU32(pSSM, pThis->aFacilityStatuses[i].fFlags);
     2861        SSMR3PutU16(pSSM, pThis->aFacilityStatuses[i].uStatus);
     2862        SSMR3PutS64(pSSM, RTTimeSpecGetNano(&pThis->aFacilityStatuses[i].TimeSpecTS));
     2863    }
    27212864
    27222865    return VINF_SUCCESS;
     
    28122955    }
    28132956
     2957    if (uVersion > VMMDEV_SAVED_STATE_VERSION_MISSING_FACILITY_STATUSES)
     2958    {
     2959        uint32_t cFacilityStatuses;
     2960        rc = SSMR3GetU32(pSSM, &cFacilityStatuses);
     2961        AssertRCReturn(rc, rc);
     2962
     2963        for (uint32_t i = 0; i < cFacilityStatuses; i++)
     2964        {
     2965            uint32_t uFacility, fFlags;
     2966            uint16_t uStatus;
     2967            int64_t  iTimeStampNano;
     2968
     2969            SSMR3GetU32(pSSM, &uFacility);
     2970            SSMR3GetU32(pSSM, &fFlags);
     2971            SSMR3GetU16(pSSM, &uStatus);
     2972            rc = SSMR3GetS64(pSSM, &iTimeStampNano);
     2973            AssertRCReturn(rc, rc);
     2974
     2975            PVMMDEVFACILITYSTATUSENTRY pEntry = vmmdevGetFacilityStatusEntry(pThis, uFacility);
     2976            AssertLogRelMsgReturn(pEntry,
     2977                                  ("VMMDev: Ran out of entries restoring the guest facility statuses. Saved state has %u.\n", cFacilityStatuses),
     2978                                  VERR_OUT_OF_RESOURCES);
     2979            pEntry->uStatus = uStatus;
     2980            pEntry->fFlags  = fFlags;
     2981            RTTimeSpecSetNano(&pEntry->TimeSpecTS, iTimeStampNano);
     2982        }
     2983    }
     2984
     2985
    28142986    /*
    28152987     * On a resume, we send the capabilities changed message so
     
    28483020            pThis->pDrv->pfnUpdateGuestInfo(pThis->pDrv, &pThis->guestInfo);
    28493021        }
     3022
     3023        for (uint32_t i = 0; i < pThis->cFacilityStatuses; i++) /* ascending order! */
     3024            if (   pThis->aFacilityStatuses[i].uStatus != VBoxGuestFacilityStatus_Inactive
     3025                || !pThis->aFacilityStatuses[i].fFixed)
     3026                pThis->pDrv->pfnUpdateGuestStatus(pThis->pDrv,
     3027                                                  pThis->aFacilityStatuses[i].uFacility,
     3028                                                  pThis->aFacilityStatuses[i].uStatus,
     3029                                                  pThis->aFacilityStatuses[i].fFlags,
     3030                                                  &pThis->aFacilityStatuses[i].TimeSpecTS);
    28503031    }
    28513032    if (pThis->pDrv)
     
    29383119    pThis->fu32AdditionsOk = false;
    29393120    memset (&pThis->guestInfo, 0, sizeof (pThis->guestInfo));
     3121    RT_ZERO(pThis->guestInfo2);
     3122
     3123    /* Clear facilities. No need to tell Main as it will get a
     3124       pfnUpdateGuestInfo callback. */
     3125    RTTIMESPEC TimeStampNow;
     3126    RTTimeNow(&TimeStampNow);
     3127    uint32_t iFacility = pThis->cFacilityStatuses;
     3128    while (iFacility-- > 0)
     3129    {
     3130        pThis->aFacilityStatuses[iFacility].uStatus    = VBoxGuestFacilityStatus_Inactive;
     3131        pThis->aFacilityStatuses[iFacility].TimeSpecTS = TimeStampNow;
     3132    }
    29403133
    29413134    /* clear pending display change request. */
     
    30563249    /* interrupt on pin 0 */
    30573250    PCIDevSetInterruptPin(&pThis->dev, 0x01);
     3251
     3252    RTTIMESPEC TimeStampNow;
     3253    RTTimeNow(&TimeStampNow);
     3254    vmmdevAllocFacilityStatusEntry(pThis, VBoxGuestFacilityType_VBoxGuestDriver, true /*fFixed*/, &TimeStampNow);
     3255    vmmdevAllocFacilityStatusEntry(pThis, VBoxGuestFacilityType_VBoxService,     true /*fFixed*/, &TimeStampNow);
     3256    vmmdevAllocFacilityStatusEntry(pThis, VBoxGuestFacilityType_VBoxTrayClient,  true /*fFixed*/, &TimeStampNow);
     3257    vmmdevAllocFacilityStatusEntry(pThis, VBoxGuestFacilityType_Seamless,        true /*fFixed*/, &TimeStampNow);
     3258    vmmdevAllocFacilityStatusEntry(pThis, VBoxGuestFacilityType_Graphics,        true /*fFixed*/, &TimeStampNow);
     3259    Assert(pThis->cFacilityStatuses == 5);
    30583260
    30593261    /*
  • trunk/src/VBox/Devices/VMMDev/VMMDevState.h

    r39882 r39890  
    7979    } Judge;
    8080} VMMDEVCREDS;
     81
     82
     83/**
     84 * Facility status entry.
     85 */
     86typedef struct VMMDEVFACILITYSTATUSENTRY
     87{
     88    /** The facility, see VBoxGuestFacilityType. */
     89    uint32_t    uFacility;
     90    /** The status, see VBoxGuestFacilityStatus. */
     91    uint16_t    uStatus;
     92    /** Whether this entry is fixed and cannot be reused when inactive. */
     93    bool        fFixed;
     94    /** Explicit alignment padding / reserved for future use. MBZ. */
     95    bool        fPadding;
     96    /** The facility flags (yet to be defined). */
     97    uint32_t    fFlags;
     98    /** Explicit alignment padding / reserved for future use. MBZ. */
     99    uint32_t    uPadding;
     100    /** Last update timestamp. */
     101    RTTIMESPEC  TimeSpecTS;
     102} VMMDEVFACILITYSTATUSENTRY;
     103/** Pointer to a facility status entry. */
     104typedef VMMDEVFACILITYSTATUSENTRY *PVMMDEVFACILITYSTATUSENTRY;
    81105
    82106
     
    170194        uint32_t uRevision;
    171195        uint32_t fFeatures;
    172         uint32_t uPadding;
    173196        char     szName[128];
    174197    } guestInfo2;
     198
     199    /** Array of guest facility statuses. */
     200    VMMDEVFACILITYSTATUSENTRY   aFacilityStatuses[32];
     201    /** The number of valid entries in the facility status array. */
     202    uint32_t                    cFacilityStatuses;
    175203
    176204    /** Information reported by guest via VMMDevReportGuestCapabilities. */
     
    320348AssertCompileMemberAlignment(VMMDevState, cbGuestRAM, 8);
    321349AssertCompileMemberAlignment(VMMDevState, enmCpuHotPlugEvent, 4);
     350AssertCompileMemberAlignment(VMMDevState, aFacilityStatuses, 8);
    322351#ifndef VBOX_WITHOUT_TESTING_FEATURES
    323352AssertCompileMemberAlignment(VMMDevState, TestingData.Value.u64Value, 8);
Note: See TracChangeset for help on using the changeset viewer.

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