VirtualBox

Changeset 36837 in vbox


Ignore:
Timestamp:
Apr 25, 2011 8:41:44 AM (14 years ago)
Author:
vboxsync
Message:

HPET: cleanup, ICH9-specific HPET behavior

Location:
trunk/src/VBox
Files:
2 edited

Legend:

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

    r36649 r36837  
    5050 */
    5151#define HPET_NUM_TIMERS             3
     52#define HPET_NUM_TIMERS_ICH9        4
    5253
    5354/*
     
    5556 */
    5657#define HPET_CLK_PERIOD             10000000UL
     58
     59/*
     60 * 69841279 femtoseconds == 69.84 ns
     61 */
     62#define HPET_CLK_PERIOD_ICH9        69841279UL
    5763
    5864/*
     
    130136    RCPTRTYPE(struct HpetState *)    pHpetRC;
    131137
    132     /* timer number*/
     138    /* Timer number. */
    133139    uint8_t                          u8TimerNumber;
    134      /* Wrap */
     140     /* Wrap. */
    135141    uint8_t                          u8Wrap;
    136     /* Alignment */
     142    /* Alignment. */
    137143    uint32_t                         alignment0;
    138     /* Memory-mapped, software visible timer registers */
    139     /* Configuration/capabilities */
     144    /* Memory-mapped, software visible timer registers. */
     145    /* Configuration/capabilities. */
    140146    uint64_t                         u64Config;
    141     /* comparator */
     147    /* comparator. */
    142148    uint64_t                         u64Cmp;
    143     /* FSB route, not supported now */
     149    /* FSB route, not supported now. */
    144150    uint64_t                         u64Fsb;
    145151
    146     /* Hidden register state */
    147     /* Last value written to comparator */
     152    /* Hidden register state. */
     153    /* Last value written to comparator. */
    148154    uint64_t                         u64Period;
    149155} HpetTimer;
     
    166172    PCPDMHPETHLPRC       pHpetHlpRC;
    167173
    168     /* Timer structures */
     174    /* Timer structures. */
    169175    HpetTimer            aTimers[HPET_NUM_TIMERS];
    170176
    171     /* Offset realtive to the system clock */
     177    /* Offset realtive to the system clock. */
    172178    uint64_t             u64HpetOffset;
    173179
    174180    /* Memory-mapped, software visible registers */
    175     /* capabilities */
     181    /* capabilities. */
    176182    uint64_t             u64Capabilities;
    177     /* configuration */
     183    /* Configuration. */
    178184    uint64_t             u64HpetConfig;
    179     /* interrupt status register */
     185    /* Interrupt status register. */
    180186    uint64_t             u64Isr;
    181     /* main counter */
     187    /* Main counter. */
    182188    uint64_t             u64HpetCounter;
    183189
    184     /* Global device lock */
     190    /* Global device lock. */
    185191    PDMCRITSECT          csLock;
     192
     193    /* If we emulate ICH9 HPET (different frequency and counter rollover behavior
     194       in 32-bit mode). */
     195    uint8_t              fIch9;
     196    uint8_t              padding0[7];
    186197} HpetState;
    187198
     
    232243}
    233244
    234 static uint64_t hpetTicksToNs(uint64_t value)
    235 {
    236     return (ASMMultU64ByU32DivByU32(value, HPET_CLK_PERIOD, FS_PER_NS));
    237 }
    238 
    239 static uint64_t nsToHpetTicks(uint64_t u64Value)
    240 {
    241     return (ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, HPET_CLK_PERIOD));
     245static uint64_t hpetTicksToNs(HpetState* pThis, uint64_t value)
     246{
     247    return (ASMMultU64ByU32DivByU32(value,  (uint32_t)(pThis->u64Capabilities >> 32), FS_PER_NS));
     248}
     249
     250static uint64_t nsToHpetTicks(HpetState* pThis, uint64_t u64Value)
     251{
     252    return (ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, (uint32_t)(pThis->u64Capabilities >> 32)));
    242253}
    243254
     
    248259     * with the same speed.
    249260     */
    250     return nsToHpetTicks(TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer)) +
    251                          pThis->u64HpetOffset);
     261    return  nsToHpetTicks(pThis, TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer)) +
     262                          pThis->u64HpetOffset);
    252263}
    253264
     
    329340    u64Diff = hpetComputeDiff(pTimer, u64Ticks);
    330341
    331     /* Spec says in one-shot 32-bit mode, generate an interrupt when
     342    /* HPET spec says in one-shot 32-bit mode, generate an interrupt when
    332343     * counter wraps in addition to an interrupt with comparator match.
     344     *
     345     * ICH9 spec doesn't mention that, so we disable wraparound behavior for ICH9,
     346     * see public trac defect #8707.
    333347     */
    334     if ((pTimer->u64Config & HPET_TN_32BIT) && !(pTimer->u64Config & HPET_TN_PERIODIC))
    335     {
    336         u32TillWrap = 0xffffffff - (uint32_t)u64Ticks;
    337         if (u32TillWrap < (uint32_t)u64Diff)
    338         {
    339             u64Diff = u32TillWrap;
    340             pTimer->u8Wrap = 1;
     348    if (!pTimer->CTX_SUFF(pHpet)->fIch9)
     349    {
     350        if ((pTimer->u64Config & HPET_TN_32BIT) && !(pTimer->u64Config & HPET_TN_PERIODIC))
     351        {
     352            u32TillWrap = 0xffffffff - (uint32_t)u64Ticks;
     353            if (u32TillWrap < (uint32_t)u64Diff)
     354            {
     355                u64Diff = u32TillWrap;
     356                pTimer->u8Wrap = 1;
     357            }
    341358        }
    342359    }
     
    349366#endif
    350367
    351     Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(u64Diff)));
    352 
    353     TMTimerSetNano(pTimer->CTX_SUFF(pTimer), hpetTicksToNs(u64Diff));
     368    Log4(("HPET: next IRQ in %lld ticks (%lld ns)\n", u64Diff, hpetTicksToNs(pTimer->CTX_SUFF(pHpet), u64Diff)));
     369
     370    TMTimerSetNano(pTimer->CTX_SUFF(pTimer), hpetTicksToNs(pTimer->CTX_SUFF(pHpet), u64Diff));
    354371}
    355372
     
    410427        default:
    411428            LogRel(("invalid HPET register read %d on %d\n", iTimerReg, pTimer->u8TimerNumber));
     429            *pValue = 0;
    412430            break;
    413431        }
     
    442460        {
    443461            uint64_t u64Ticks;
    444             Log(("read HPET_COUNTER\n"));
    445462            if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
    446463                u64Ticks = hpetGetTicks(pThis);
     
    449466            /** @todo: is it correct? */
    450467            *pValue = (iIndex == HPET_COUNTER) ? (uint32_t)u64Ticks : (uint32_t)(u64Ticks >> 32);
     468            Log(("read HPET_COUNTER: %s part value %x\n", (iIndex == HPET_COUNTER) ? "low" : "high", *pValue));
    451469            break;
    452470        }
     
    457475        default:
    458476            Log(("invalid HPET register read: %x\n", iIndex));
     477            *pValue = 0;
    459478            break;
    460479    }
     
    488507        case HPET_TN_CFG:
    489508        {
    490             Log(("write HPET_TN_CFG: %d\n", iTimerNo));
    491             if (iNewValue & HPET_TN_32BIT)
    492             {
     509            Log(("write HPET_TN_CFG: %d: %x\n", iTimerNo, iNewValue));
     510            if ((iNewValue & HPET_TN_32BIT) != 0)
     511            {
     512                Log(("setting timer to 32-bit mode\n"));
    493513                pTimer->u64Cmp = (uint32_t)pTimer->u64Cmp;
    494514                pTimer->u64Period = (uint32_t)pTimer->u64Period;
     
    497517            {
    498518                LogRel(("level-triggered config not yet supported\n"));
    499                 Assert(false);
     519                AssertFailed();
    500520            }
    501521            /** We only care about lower 32-bits so far */
     
    574594        {
    575595            LogRel(("invalid timer register write: %d\n", iTimerReg));
    576             Assert(false);
     596            AssertFailed();
    577597            break;
    578598        }
     
    636656            {
    637657                /* Enable main counter and interrupt generation. */
    638                 pThis->u64HpetOffset = hpetTicksToNs(pThis->u64HpetCounter)
     658                pThis->u64HpetOffset = hpetTicksToNs(pThis, pThis->u64HpetCounter)
    639659                        - TMTimerGet(pThis->aTimers[0].CTX_SUFF(pTimer));
    640660                for (i = 0; i < HPET_NUM_TIMERS; i++)
     
    745765                uint32_t iTimer = (iIndex - 0x100) / 0x20;
    746766                uint32_t iTimerReg = (iIndex - 0x100) % 0x20;
    747                
     767
    748768                /* for most 8-byte accesses we just split them, happens under lock anyway. */
    749769                rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg, &value.u32[0]);
     
    756776                if (iIndex == HPET_COUNTER)
    757777                {
    758                     /* When reading HPET counter we must read it in a single read, 
     778                    /* When reading HPET counter we must read it in a single read,
    759779                       to avoid unexpected time jumps on 32-bit overflow. */
    760                     value.u64 = 
    761                             (pThis->u64HpetConfig & HPET_CFG_ENABLE) != 0 
     780                    value.u64 =
     781                            (pThis->u64HpetConfig & HPET_CFG_ENABLE) != 0
    762782                            ?
    763783                            hpetGetTicks(pThis)
     
    769789                {
    770790                    /* for most 8-byte accesses we just split them, happens under lock anyway. */
    771                    
     791
    772792                    rc = hpetConfigRegRead32(pThis, iIndex, &value.u32[0]);
    773793                    if (RT_UNLIKELY(rc != VINF_SUCCESS))
     
    10111031            pThis->pHpetHlpR3->pfnSetIrq(pThis->CTX_SUFF(pDevIns), irq, PDM_IRQ_LEVEL_FLIP_FLOP);
    10121032        else
    1013             Assert(false);
     1033            AssertFailed();
    10141034        /* @todo: implement IRQs in level-triggered mode */
    10151035    }
     
    10481068        u64Diff = hpetComputeDiff(pTimer, u64CurTick);
    10491069
    1050         Log4(("HPET: periodical: next in %lld\n",  hpetTicksToNs(u64Diff)));
    1051         TMTimerSetNano(pTmTimer, hpetTicksToNs(u64Diff));
     1070        Log4(("HPET: periodical: next in %lld\n",  hpetTicksToNs(pThis, u64Diff)));
     1071        TMTimerSetNano(pTmTimer, hpetTicksToNs(pThis, u64Diff));
    10521072    }
    10531073    else if ((pTimer->u64Config & HPET_TN_32BIT) &&
     
    10571077        {
    10581078            u64Diff = hpetComputeDiff(pTimer, u64CurTick);
    1059             TMTimerSetNano(pTmTimer, hpetTicksToNs(u64Diff));
     1079            TMTimerSetNano(pTmTimer, hpetTicksToNs(pThis, u64Diff));
    10601080            pTimer->u8Wrap = 0;
    10611081        }
     
    11221142    pThis->u64HpetCounter = 0ULL;
    11231143    pThis->u64HpetOffset = 0ULL;
     1144
     1145    uint32_t u32Vendor = 0x8086;
    11241146    /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
    1125     uint32_t u32Vendor = 0x8086;
    11261147    uint32_t u32Caps =
    11271148      (1 << 15) /* LEG_RT_CAP, LegacyReplacementRoute capable */ |
    11281149      (1 << 13) /* COUNTER_SIZE_CAP, main counter is 64-bit capable */ |
    1129       ((HPET_NUM_TIMERS-1) << 8) /* NUM_TIM_CAP, number of timers -1 */ |
     1150      /* Actually ICH9 has 4 timers, but to avoid breaking saved state we'll stick with 3 so far. */
     1151      (HPET_NUM_TIMERS << 8) /* NUM_TIM_CAP, number of timers -1 */ |
    11301152      1 /* REV_ID, revision, must not be 0 */;
    11311153    pThis->u64Capabilities = (u32Vendor << 16) | u32Caps;
    1132     pThis->u64Capabilities |= ((uint64_t)(HPET_CLK_PERIOD) << 32);
     1154    pThis->u64Capabilities |= ((uint64_t)(pThis->fIch9 ? HPET_CLK_PERIOD_ICH9 : HPET_CLK_PERIOD) << 32);
    11331155
    11341156    /* Notify PIT/RTC devices */
     
    11471169    int        rc;
    11481170    HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
    1149 
    1150     memset(pThis, 0, sizeof(*pThis));
    11511171
    11521172    pThis->pDevInsR3 = pDevIns;
     
    12181238    bool         fRCEnabled = false;
    12191239    bool         fR0Enabled = false;
     1240    bool         fIch9      = false;
    12201241    PDMHPETREG   HpetReg;
    12211242
    1222     /* Only one HPET device now */
     1243    /* Only one HPET device now, as we use fixed MMIO region. */
    12231244    Assert(iInstance == 0);
    12241245
     
    12261247     * Validate configuration.
    12271248     */
    1228     if (!CFGMR3AreValuesValid(pCfg, "GCEnabled\0" "R0Enabled\0"))
     1249    if (!CFGMR3AreValuesValid(pCfg,
     1250                              "GCEnabled\0"
     1251                              "R0Enabled\0"
     1252                              "ICH9\0"))
    12291253        return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
    12301254
     
    12391263        return PDMDEV_SET_ERROR(pDevIns, rc,
    12401264                                N_("Configuration error: failed to read R0Enabled as boolean"));
     1265    rc = CFGMR3QueryBoolDef(pCfg, "ICH9", &fIch9, false);
     1266    if (RT_FAILURE(rc))
     1267        return PDMDEV_SET_ERROR(pDevIns, rc,
     1268                                N_("Configuration error: failed to read ICH9 as boolean"));
     1269
    12411270    /* Initialize the device state */
     1271    memset(pThis, 0, sizeof(*pThis));
     1272
     1273    pThis->fIch9 = (uint8_t)fIch9;
     1274
    12421275    rc = hpetInit(pDevIns);
    12431276    if (RT_FAILURE(rc))
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r36703 r36837  
    10721072            InsertConfigNode(pDev,     "0", &pInst);
    10731073            InsertConfigInteger(pInst, "Trusted",   1); /* boolean */
     1074            InsertConfigNode(pInst,    "Config", &pCfg);
     1075            InsertConfigInteger(pCfg,  "ICH9", (chipsetType == ChipsetType_ICH9) ? 1 : 0);  /* boolean */
    10741076        }
    10751077
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