VirtualBox

Changeset 86591 in vbox for trunk/src


Ignore:
Timestamp:
Oct 15, 2020 1:42:24 PM (4 years ago)
Author:
vboxsync
Message:

Devices/HPET: Fix timer count.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/DevHPET.cpp

    r82968 r86591  
    142142
    143143/** Extract the timer count from the capabilities. */
    144 #define HPET_CAP_GET_TIMERS(a_u32)      ( ((a_u32) >> 8) & 0x1f )
     144#define HPET_CAP_GET_TIMERS(a_u32)              ((((a_u32) >> 8) + 1) & 0x1f)
     145/** Revision ID. */
     146#define HPET_CAP_GET_REV_ID(a_u32)              ((a_u32) & 0xff)
     147/** Counter size. */
     148#define HPET_CAP_HAS_64BIT_COUNT_SIZE(a_u32)    RT_BOOL((a_u32) & RT_BIT(13))
     149/** Legacy Replacement Route. */
     150#define HPET_CAP_HAS_LEG_RT(a_u32)              RT_BOOL((a_u32) & RT_BIT(15))
     151
    145152
    146153/** The version of the saved state. */
    147 #define HPET_SAVED_STATE_VERSION       2
     154#define HPET_SAVED_STATE_VERSION                3
     155/** The version of the saved state prior to the off-by-1 timer count fix. */
     156#define HPET_SAVED_STATE_VERSION_PRE_TIMER      2
    148157/** Empty saved state */
    149 #define HPET_SAVED_STATE_VERSION_EMPTY 1
     158#define HPET_SAVED_STATE_VERSION_EMPTY          1
    150159
    151160
     
    12161225     */
    12171226    uint32_t const cTimers = HPET_CAP_GET_TIMERS(pThis->u32Capabilities);
     1227    AssertReturn(cTimers <= RT_ELEMENTS(pThis->aTimers), VERR_OUT_OF_RANGE);
    12181228    for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
    12191229    {
     
    12491259    if (uVersion == HPET_SAVED_STATE_VERSION_EMPTY)
    12501260        return VINF_SUCCESS;
    1251     if (uVersion != HPET_SAVED_STATE_VERSION)
     1261    if (   uVersion != HPET_SAVED_STATE_VERSION
     1262        && uVersion != HPET_SAVED_STATE_VERSION_PRE_TIMER)
    12521263        return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
    12531264
     
    12871298    if (RT_FAILURE(rc))
    12881299        return rc;
    1289     if (HPET_CAP_GET_TIMERS(RT_LO_U32(u64CapPer)) != cTimers)
     1300
     1301    /* Older saved state have an off-by-1 timer count bug. */
     1302    uint8_t cCapTimers = HPET_CAP_GET_TIMERS(RT_LO_U32(u64CapPer));
     1303    if (   uVersion <= HPET_SAVED_STATE_VERSION_PRE_TIMER
     1304        && cCapTimers > 0 /* Paranoia */)
     1305        --cCapTimers;
     1306
     1307    /* Verify capability reported timer count matches timer count in the saved state field. */
     1308    if (cCapTimers != cTimers)
    12901309        return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Capabilities does not match timer count: cTimers=%#x caps=%#x"),
    1291                                        cTimers, (unsigned)HPET_CAP_GET_TIMERS(u64CapPer));
     1310                                       cTimers, cCapTimers);
     1311    if (HPET_CAP_GET_TIMERS(RT_LO_U32(u64CapPer)) > RT_ELEMENTS(pThis->aTimers))
     1312        return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - too many timers in capability register: CAP=%#x => %u times, max %u"),
     1313                                       RT_LO_U32(u64CapPer), (unsigned)HPET_CAP_GET_TIMERS(RT_LO_U32(u64CapPer)), RT_ELEMENTS(pThis->aTimers));
     1314
    12921315    pThis->u32Capabilities  = RT_LO_U32(u64CapPer);
    12931316    pThis->u32Period        = RT_HI_U32(u64CapPer);
     
    14551478     */
    14561479    hpetR3Reset(pDevIns);
     1480
     1481    uint32_t const fCaps = pThis->u32Capabilities;
     1482    LogRel(("HPET: Capabilities=%#RX32 (LegacyRt=%RTbool CounterSize=%s Timers=%u Revision=%#x)\n",
     1483            fCaps, HPET_CAP_HAS_LEG_RT(fCaps), HPET_CAP_HAS_64BIT_COUNT_SIZE(fCaps) ? "64-bit" : "32-bit",
     1484            HPET_CAP_GET_TIMERS(fCaps), HPET_CAP_GET_REV_ID(fCaps)));
    14571485
    14581486    /*
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