VirtualBox

Changeset 44629 in vbox for trunk/src/VBox/Devices/PC


Ignore:
Timestamp:
Feb 11, 2013 11:59:14 AM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83717
Message:

DevHEP: MMIO changes and other cleanups.

File:
1 edited

Legend:

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

    r44528 r44629  
    11/* $Id$ */
    22/** @file
    3  * HPET virtual device - High Precision Event Timer emulation
     3 * HPET virtual device - High Precision Event Timer emulation.
    44 */
    55
    66/*
    7  * Copyright (C) 2009-2012 Oracle Corporation
     7 * Copyright (C) 2009-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4545 */
    4646
    47 /** Base address for MMIO. */
    48 /* On ICH9, it is 0xFED0x000 where 'x' is 0-3, default 0. We do not support
     47/** Base address for MMIO.
     48 * On ICH9, it is 0xFED0x000 where 'x' is 0-3, default 0. We do not support
    4949 * relocation as the platform firmware is responsible for configuring the
    5050 * HPET base address and the OS isn't expected to move it.
     
    5252#define HPET_BASE                   0xfed00000
    5353
    54 /* HPET reserves a 1K range. */
     54/** HPET reserves a 1K range. */
    5555#define HPET_BAR_SIZE               0x1000
    5656
     
    7070#define HPET_CLK_PERIOD_ICH9        UINT32_C(69841279)
    7171
    72 /*
     72/**
    7373 * Femtosecods in a nanosecond
    7474 */
    7575#define FS_PER_NS                   1000000
    7676
    77 /*
    78  * Interrupt type
    79  */
     77/** @name Interrupt type
     78 * @{ */
    8079#define HPET_TIMER_TYPE_LEVEL       1
    8180#define HPET_TIMER_TYPE_EDGE        0
    82 
    83 /* Delivery mode */
    84 #define HPET_TIMER_DELIVERY_APIC    0   /* Delivery through APIC. */
    85 #define HPET_TIMER_DELIVERY_FSB     1   /* Delivery through FSB. */
     81/** @} */
     82
     83/** @name Delivery mode
     84 * @{ */
     85#define HPET_TIMER_DELIVERY_APIC    0   /**< Delivery through APIC. */
     86#define HPET_TIMER_DELIVERY_FSB     1   /**< Delivery through FSB. */
     87/** @} */
    8688
    8789#define HPET_TIMER_CAP_FSB_INT_DEL (1 << 15)
    8890#define HPET_TIMER_CAP_PER_INT     (1 << 4)
    8991
    90 #define HPET_CFG_ENABLE          0x001 /* ENABLE_CNF */
    91 #define HPET_CFG_LEGACY          0x002 /* LEG_RT_CNF */
    92 
    93 /* Register offsets in HPET space. */
    94 #define HPET_ID                  0x000  /* Device ID. */
    95 #define HPET_PERIOD              0x004  /* Clock period in femtoseconds. */
    96 #define HPET_CFG                 0x010  /* Configuration register. */
    97 #define HPET_STATUS              0x020  /* Status register. */
    98 #define HPET_COUNTER             0x0f0  /* Main HPET counter. */
    99 
    100 /* Timer N offsets (within each timer's space). */
    101 #define HPET_TN_CFG              0x000  /* Timer N configuration. */
    102 #define HPET_TN_CMP              0x008  /* Timer N comparator. */
    103 #define HPET_TN_ROUTE            0x010  /* Timer N interrupt route. */
     92#define HPET_CFG_ENABLE          0x001  /**< ENABLE_CNF */
     93#define HPET_CFG_LEGACY          0x002  /**< LEG_RT_CNF */
     94
     95/** @name Register offsets in HPET space.
     96 * @{ */
     97#define HPET_ID                  0x000  /**< Device ID. */
     98#define HPET_PERIOD              0x004  /**< Clock period in femtoseconds. */
     99#define HPET_CFG                 0x010  /**< Configuration register. */
     100#define HPET_STATUS              0x020  /**< Status register. */
     101#define HPET_COUNTER             0x0f0  /**< Main HPET counter. */
     102/** @} */
     103
     104/** @name Timer N offsets (within each timer's space).
     105 * @{ */
     106#define HPET_TN_CFG              0x000  /**< Timer N configuration. */
     107#define HPET_TN_CMP              0x008  /**< Timer N comparator. */
     108#define HPET_TN_ROUTE            0x010  /**< Timer N interrupt route. */
     109/** @} */
    104110
    105111#define HPET_CFG_WRITE_MASK      0x3
     
    133139#define DEVHPET_LOCK_RETURN(a_pThis, a_rcBusy)  \
    134140    do { \
    135         int rcLock = PDMCritSectEnter(&(a_pThis)->csLock, (a_rcBusy)); \
     141        int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \
    136142        if (rcLock != VINF_SUCCESS) \
    137143            return rcLock; \
     
    142148 */
    143149#define DEVHPET_UNLOCK(a_pThis) \
    144     do { PDMCritSectLeave(&(a_pThis)->csLock); } while (0)
     150    do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0)
    145151
    146152
     
    153159        if (rcLock != VINF_SUCCESS) \
    154160            return rcLock; \
    155         rcLock = PDMCritSectEnter(&(a_pThis)->csLock, (a_rcBusy)); \
     161        rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \
    156162        if (rcLock != VINF_SUCCESS) \
    157163        { \
     
    167173#define DEVHPET_UNLOCK_BOTH(a_pThis) \
    168174    do { \
    169         PDMCritSectLeave(&(a_pThis)->csLock); \
     175        PDMCritSectLeave(&(a_pThis)->CritSect); \
    170176        TMTimerUnlock((a_pThis)->aTimers[0].CTX_SUFF(pTimer)); \
    171177    } while (0)
     
    175181*   Structures and Typedefs                                                    *
    176182*******************************************************************************/
    177 struct HpetState;
    178 typedef struct HpetTimer
     183/**
     184 * A HPET timer.
     185 */
     186typedef struct HPETTIMER
    179187{
    180188    /** The HPET timer - R3 Ptr. */
    181     PTMTIMERR3                       pTimerR3;
     189    PTMTIMERR3                  pTimerR3;
    182190    /** Pointer to the instance data - R3 Ptr. */
    183     R3PTRTYPE(struct HpetState *)    pHpetR3;
     191    R3PTRTYPE(struct HPET *)    pHpetR3;
    184192
    185193    /** The HPET timer - R0 Ptr. */
    186     PTMTIMERR0                       pTimerR0;
     194    PTMTIMERR0                  pTimerR0;
    187195    /** Pointer to the instance data - R0 Ptr. */
    188     R0PTRTYPE(struct HpetState *)    pHpetR0;
     196    R0PTRTYPE(struct HPET *)    pHpetR0;
    189197
    190198    /** The HPET timer - RC Ptr. */
    191     PTMTIMERRC                       pTimerRC;
     199    PTMTIMERRC                  pTimerRC;
    192200    /** Pointer to the instance data - RC Ptr. */
    193     RCPTRTYPE(struct HpetState *)    pHpetRC;
     201    RCPTRTYPE(struct HPET *)    pHpetRC;
    194202
    195203    /** Timer index. */
    196     uint8_t                          idxTimer;
     204    uint8_t                     idxTimer;
    197205    /** Wrap. */
    198     uint8_t                          u8Wrap;
     206    uint8_t                     u8Wrap;
    199207    /** Alignment. */
    200     uint32_t                         alignment0;
     208    uint32_t                    alignment0;
    201209
    202210    /** @name Memory-mapped, software visible timer registers.
    203211     * @{ */
    204212    /** Configuration/capabilities. */
    205     uint64_t                         u64Config;
     213    uint64_t                    u64Config;
    206214    /** Comparator. */
    207     uint64_t                         u64Cmp;
     215    uint64_t                    u64Cmp;
    208216    /** FSB route, not supported now. */
    209     uint64_t                         u64Fsb;
     217    uint64_t                    u64Fsb;
    210218    /** @} */
    211219
     
    213221     * @{ */
    214222    /** Last value written to comparator. */
    215     uint64_t                         u64Period;
     223    uint64_t                    u64Period;
    216224    /** @} */
    217 } HpetTimer;
    218 AssertCompileMemberAlignment(HpetTimer, u64Config, sizeof(uint64_t));
    219 
    220 typedef struct HpetState
     225} HPETTIMER;
     226AssertCompileMemberAlignment(HPETTIMER, u64Config, sizeof(uint64_t));
     227
     228/**
     229 * The HPET state.
     230 */
     231typedef struct HPET
    221232{
    222233    /** Pointer to the device instance. - R3 ptr. */
    223     PPDMDEVINSR3         pDevInsR3;
     234    PPDMDEVINSR3                pDevInsR3;
    224235    /** The HPET helpers - R3 Ptr. */
    225     PCPDMHPETHLPR3       pHpetHlpR3;
     236    PCPDMHPETHLPR3              pHpetHlpR3;
    226237
    227238    /** Pointer to the device instance. - R0 ptr. */
    228     PPDMDEVINSR0         pDevInsR0;
     239    PPDMDEVINSR0                pDevInsR0;
    229240    /** The HPET helpers - R0 Ptr. */
    230     PCPDMHPETHLPR0       pHpetHlpR0;
     241    PCPDMHPETHLPR0              pHpetHlpR0;
    231242
    232243    /** Pointer to the device instance. - RC ptr. */
    233     PPDMDEVINSRC         pDevInsRC;
     244    PPDMDEVINSRC                pDevInsRC;
    234245    /** The HPET helpers - RC Ptr. */
    235     PCPDMHPETHLPRC       pHpetHlpRC;
     246    PCPDMHPETHLPRC              pHpetHlpRC;
    236247
    237248    /** Timer structures. */
    238     HpetTimer            aTimers[RT_MAX(HPET_NUM_TIMERS_PIIX, HPET_NUM_TIMERS_ICH9)];
     249    HPETTIMER                   aTimers[RT_MAX(HPET_NUM_TIMERS_PIIX, HPET_NUM_TIMERS_ICH9)];
    239250
    240251    /** Offset realtive to the virtual sync clock. */
    241     uint64_t             u64HpetOffset;
     252    uint64_t                    u64HpetOffset;
    242253
    243254    /** @name Memory-mapped, software visible registers
    244255     * @{ */
    245256    /** Capabilities. */
    246     uint32_t             u32Capabilities;
     257    uint32_t                    u32Capabilities;
    247258    /** HPET_PERIOD - . */
    248     uint32_t             u32Period;
     259    uint32_t                    u32Period;
    249260    /** Configuration. */
    250     uint64_t             u64HpetConfig;
     261    uint64_t                    u64HpetConfig;
    251262    /** Interrupt status register. */
    252     uint64_t             u64Isr;
     263    uint64_t                    u64Isr;
    253264    /** Main counter. */
    254     uint64_t             u64HpetCounter;
     265    uint64_t                    u64HpetCounter;
    255266    /** @}  */
    256267
    257268    /** Global device lock. */
    258     PDMCRITSECT          csLock;
     269    PDMCRITSECT                 CritSect;
    259270
    260271    /** Whether we emulate ICH9 HPET (different frequency & timer count). */
    261     bool                 fIch9;
    262     uint8_t              padding0[7];
    263 } HpetState;
     272    bool                        fIch9;
     273    /** Size alignment padding. */
     274    uint8_t                     abPadding0[7];
     275} HPET;
    264276
    265277
     
    267279
    268280
    269 DECLINLINE(bool) hpet32bitTimer(HpetTimer *pHpetTimer)
     281DECLINLINE(bool) hpet32bitTimer(HPETTIMER *pHpetTimer)
    270282{
    271283    uint64_t u64Cfg = pHpetTimer->u64Config;
     
    274286}
    275287
    276 DECLINLINE(uint64_t) hpetInvalidValue(HpetTimer *pHpetTimer)
     288DECLINLINE(uint64_t) hpetInvalidValue(HPETTIMER *pHpetTimer)
    277289{
    278290    return hpet32bitTimer(pHpetTimer) ? UINT32_MAX : UINT64_MAX;
    279291}
    280292
    281 DECLINLINE(uint64_t) hpetTicksToNs(HpetState *pThis, uint64_t value)
     293DECLINLINE(uint64_t) hpetTicksToNs(HPET *pThis, uint64_t value)
    282294{
    283295    return ASMMultU64ByU32DivByU32(value,  pThis->u32Period, FS_PER_NS);
    284296}
    285297
    286 DECLINLINE(uint64_t) nsToHpetTicks(HpetState const *pThis, uint64_t u64Value)
     298DECLINLINE(uint64_t) nsToHpetTicks(HPET const *pThis, uint64_t u64Value)
    287299{
    288300    return ASMMultU64ByU32DivByU32(u64Value, FS_PER_NS, pThis->u32Period);
    289301}
    290302
    291 DECLINLINE(uint64_t) hpetGetTicks(HpetState const *pThis)
     303DECLINLINE(uint64_t) hpetGetTicks(HPET const *pThis)
    292304{
    293305    /*
     
    300312}
    301313
    302 DECLINLINE(uint64_t) hpetUpdateMasked(uint64_t u64NewValue,
    303                                       uint64_t u64OldValue,
    304                                       uint64_t u64Mask)
     314DECLINLINE(uint64_t) hpetUpdateMasked(uint64_t u64NewValue, uint64_t u64OldValue, uint64_t u64Mask)
    305315{
    306316    u64NewValue &= u64Mask;
     
    309319}
    310320
    311 DECLINLINE(bool) hpetBitJustSet(uint64_t u64OldValue,
    312                                 uint64_t u64NewValue,
    313                                 uint64_t u64Mask)
     321DECLINLINE(bool) hpetBitJustSet(uint64_t u64OldValue, uint64_t u64NewValue, uint64_t u64Mask)
    314322{
    315323    return !(u64OldValue & u64Mask)
     
    317325}
    318326
    319 DECLINLINE(bool) hpetBitJustCleared(uint64_t u64OldValue,
    320                                     uint64_t u64NewValue,
    321                                     uint64_t u64Mask)
     327DECLINLINE(bool) hpetBitJustCleared(uint64_t u64OldValue, uint64_t u64NewValue, uint64_t u64Mask)
    322328{
    323329    return !!(u64OldValue & u64Mask)
     
    325331}
    326332
    327 DECLINLINE(uint64_t) hpetComputeDiff(HpetTimer *pHpetTimer,
    328                                      uint64_t   u64Now)
     333DECLINLINE(uint64_t) hpetComputeDiff(HPETTIMER *pHpetTimer, uint64_t u64Now)
    329334{
    330335
     
    348353
    349354
    350 static void hpetAdjustComparator(HpetTimer *pHpetTimer, uint64_t u64Now)
     355static void hpetAdjustComparator(HPETTIMER *pHpetTimer, uint64_t u64Now)
    351356{
    352357    uint64_t    u64Period = pHpetTimer->u64Period;
     
    367372 * @param   pHpetTimer  The timer.
    368373 */
    369 DECLINLINE(void) hpetTimerSetFrequencyHint(HpetState *pThis, HpetTimer *pHpetTimer)
     374DECLINLINE(void) hpetTimerSetFrequencyHint(HPET *pThis, HPETTIMER *pHpetTimer)
    370375{
    371376    if (pHpetTimer->u64Config & HPET_TN_PERIODIC)
     
    379384
    380385
    381 static void hpetProgramTimer(HpetTimer *pHpetTimer)
     386static void hpetProgramTimer(HPETTIMER *pHpetTimer)
    382387{
    383388    /* no wrapping on new timers */
     
    434439 * @remarks ASSUMES the caller holds the HPET lock.
    435440 */
    436 static int hpetTimerRegRead32(HpetState const *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t *pu32Value)
    437 {
    438     Assert(PDMCritSectIsOwner(&pThis->csLock));
     441static int hpetTimerRegRead32(HPET const *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t *pu32Value)
     442{
     443    Assert(PDMCritSectIsOwner(&pThis->CritSect));
    439444
    440445    if (   iTimerNo >= HPET_CAP_GET_TIMERS(pThis->u32Capabilities)  /* The second check is only to satisfy Parfait; */
     
    448453    }
    449454
    450     HpetTimer const *pHpetTimer = &pThis->aTimers[iTimerNo];
     455    HPETTIMER const *pHpetTimer = &pThis->aTimers[iTimerNo];
    451456    uint32_t u32Value;
    452457    switch (iTimerReg)
     
    503508 *          the TM lock.
    504509 */
    505 static int hpetTimerRegWrite32(HpetState *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t u32NewValue)
    506 {
    507     Assert(!PDMCritSectIsOwner(&pThis->csLock) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer)));
     510static int hpetTimerRegWrite32(HPET *pThis, uint32_t iTimerNo, uint32_t iTimerReg, uint32_t u32NewValue)
     511{
     512    Assert(!PDMCritSectIsOwner(&pThis->CritSect) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer)));
    508513
    509514    if (   iTimerNo >= HPET_CAP_GET_TIMERS(pThis->u32Capabilities)
     
    515520        return VINF_SUCCESS;
    516521    }
    517     HpetTimer *pHpetTimer = &pThis->aTimers[iTimerNo];
     522    HPETTIMER *pHpetTimer = &pThis->aTimers[iTimerNo];
    518523
    519524    switch (iTimerReg)
     
    635640 * @remarks The caller must not own the device lock if HPET_COUNTER is read.
    636641 */
    637 static int hpetConfigRegRead32(HpetState *pThis, uint32_t idxReg, uint32_t *pu32Value)
    638 {
    639     Assert(!PDMCritSectIsOwner(&pThis->csLock) || (idxReg != HPET_COUNTER && idxReg != HPET_COUNTER + 4));
     642static int hpetConfigRegRead32(HPET *pThis, uint32_t idxReg, uint32_t *pu32Value)
     643{
     644    Assert(!PDMCritSectIsOwner(&pThis->CritSect) || (idxReg != HPET_COUNTER && idxReg != HPET_COUNTER + 4));
    640645
    641646    uint32_t u32Value;
     
    720725 *          the TM lock.
    721726 */
    722 static int hpetConfigRegWrite32(HpetState *pThis, uint32_t idxReg, uint32_t u32NewValue)
    723 {
    724     Assert(!PDMCritSectIsOwner(&pThis->csLock) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer)));
     727static int hpetConfigRegWrite32(HPET *pThis, uint32_t idxReg, uint32_t u32NewValue)
     728{
     729    Assert(!PDMCritSectIsOwner(&pThis->CritSect) || TMTimerIsLockOwner(pThis->aTimers[0].CTX_SUFF(pTimer)));
    725730
    726731    int rc = VINF_SUCCESS;
     
    856861PDMBOTHCBDECL(int)  hpetMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    857862{
    858     HpetState      *pThis  = PDMINS_2_DATA(pDevIns, HpetState*);
     863    HPET      *pThis  = PDMINS_2_DATA(pDevIns, HPET*);
    859864    uint32_t const  idxReg = (uint32_t)(GCPhysAddr - HPET_BASE);
    860865    NOREF(pvUser);
     866    Assert(cb == 4 || cb == 8);
    861867
    862868    LogFlow(("hpetMMIORead (%d): %llx (%x)\n", cb, (uint64_t)GCPhysAddr, idxReg));
    863869
    864     int rc = VINF_SUCCESS;
    865     switch (cb)
    866     {
    867         case 4:
     870    int rc;
     871    if (cb == 4)
     872    {
     873        /*
     874         * 4-byte access.
     875         */
     876        if (idxReg >= 0x100 && idxReg < 0x400)
     877        {
     878            DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
     879            rc = hpetTimerRegRead32(pThis,
     880                                    (idxReg - 0x100) / 0x20,
     881                                    (idxReg - 0x100) % 0x20,
     882                                    (uint32_t *)pv);
     883            DEVHPET_UNLOCK(pThis);
     884        }
     885        else
     886            rc = hpetConfigRegRead32(pThis, idxReg, (uint32_t *)pv);
     887    }
     888    else
     889    {
     890        /*
     891         * 8-byte access - Split the access except for timing sensitive registers.
     892         * The others assume the protection of the lock.
     893         */
     894        PRTUINT64U pValue = (PRTUINT64U)pv;
     895        if (idxReg == HPET_COUNTER)
     896        {
     897            /* When reading HPET counter we must read it in a single read,
     898               to avoid unexpected time jumps on 32-bit overflow. */
     899            DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
     900            if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
     901                pValue->u = hpetGetTicks(pThis);
     902            else
     903                pValue->u = pThis->u64HpetCounter;
     904            DEVHPET_UNLOCK_BOTH(pThis);
     905            rc = VINF_SUCCESS;
     906        }
     907        else
     908        {
     909            DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
    868910            if (idxReg >= 0x100 && idxReg < 0x400)
    869911            {
    870                 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
    871                 rc = hpetTimerRegRead32(pThis,
    872                                         (idxReg - 0x100) / 0x20,
    873                                         (idxReg - 0x100) % 0x20,
    874                                         (uint32_t *)pv);
    875                 DEVHPET_UNLOCK(pThis);
    876             }
    877             else
    878                 rc = hpetConfigRegRead32(pThis, idxReg, (uint32_t *)pv);
    879             break;
    880 
    881         case 8:
    882         {
    883             /* Unaligned accesses not allowed */
    884             if (RT_UNLIKELY(idxReg % 8 != 0))
    885             {
    886                 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "idxReg=%#x cb=8\n", idxReg);
    887                 break;
    888             }
    889 
    890             /* Split the access except for timing sensitive registers.  The
    891                others assume the protection of the lock. */
    892             PRTUINT64U pValue = (PRTUINT64U)pv;
    893             if (idxReg == HPET_COUNTER)
    894             {
    895                 /* When reading HPET counter we must read it in a single read,
    896                    to avoid unexpected time jumps on 32-bit overflow. */
    897                 DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
    898                 if (pThis->u64HpetConfig & HPET_CFG_ENABLE)
    899                     pValue->u = hpetGetTicks(pThis);
    900                 else
    901                     pValue->u = pThis->u64HpetCounter;
    902                 DEVHPET_UNLOCK_BOTH(pThis);
     912                uint32_t iTimer    = (idxReg - 0x100) / 0x20;
     913                uint32_t iTimerReg = (idxReg - 0x100) % 0x20;
     914                rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg, &pValue->s.Lo);
     915                if (rc == VINF_SUCCESS)
     916                    rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg + 4, &pValue->s.Hi);
    903917            }
    904918            else
    905919            {
    906                 DEVHPET_LOCK_RETURN(pThis, VINF_IOM_R3_MMIO_READ);
    907                 if (idxReg >= 0x100 && idxReg < 0x400)
    908                 {
    909                     uint32_t iTimer    = (idxReg - 0x100) / 0x20;
    910                     uint32_t iTimerReg = (idxReg - 0x100) % 0x20;
    911                     rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg, &pValue->s.Lo);
    912                     if (rc == VINF_SUCCESS)
    913                         rc = hpetTimerRegRead32(pThis, iTimer, iTimerReg + 4, &pValue->s.Hi);
    914                 }
    915                 else
    916                 {
    917                     /* for most 8-byte accesses we just split them, happens under lock anyway. */
    918                     rc = hpetConfigRegRead32(pThis, idxReg, &pValue->s.Lo);
    919                     if (rc == VINF_SUCCESS)
    920                         rc = hpetConfigRegRead32(pThis, idxReg + 4, &pValue->s.Hi);
    921                 }
    922                 DEVHPET_UNLOCK(pThis);
     920                /* for most 8-byte accesses we just split them, happens under lock anyway. */
     921                rc = hpetConfigRegRead32(pThis, idxReg, &pValue->s.Lo);
     922                if (rc == VINF_SUCCESS)
     923                    rc = hpetConfigRegRead32(pThis, idxReg + 4, &pValue->s.Hi);
    923924            }
    924             break;
    925         }
    926 
    927         case 1:
    928         case 2:
    929             Log(("Narrow read: %d\n", cb));
    930             rc = VINF_SUCCESS;
    931             break;
    932 
    933         default:
    934             AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
    935             rc = VINF_SUCCESS;
    936     }
    937 
     925            DEVHPET_UNLOCK(pThis);
     926        }
     927    }
    938928    return rc;
    939929}
     
    945935PDMBOTHCBDECL(int) hpetMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    946936{
    947     HpetState  *pThis  = PDMINS_2_DATA(pDevIns, HpetState*);
     937    HPET  *pThis  = PDMINS_2_DATA(pDevIns, HPET*);
    948938    uint32_t    idxReg = (uint32_t)(GCPhysAddr - HPET_BASE);
    949939    LogFlow(("hpetMMIOWrite: cb=%u reg=%03x (%RGp) val=%llx\n",
    950940             cb, idxReg, GCPhysAddr, cb == 4 ? *(uint32_t *)pv : cb == 8 ? *(uint64_t *)pv : 0xdeadbeef));
    951941    NOREF(pvUser);
     942    Assert(cb == 4 || cb == 8);
    952943
    953944    int rc;
    954     switch (cb)
    955     {
    956         case 4:
    957             if (idxReg >= 0x100 && idxReg < 0x400)
    958                 rc = hpetTimerRegWrite32(pThis,
    959                                          (idxReg - 0x100) / 0x20,
    960                                          (idxReg - 0x100) % 0x20,
    961                                          *(uint32_t const *)pv);
    962             else
    963                 rc = hpetConfigRegWrite32(pThis, idxReg, *(uint32_t const *)pv);
    964             break;
    965 
    966         case 8:
    967         {
    968             /* Unaligned accesses are not allowed. */
    969             if (RT_UNLIKELY(idxReg % 8 != 0))
    970             {
    971                 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "idxReg=%#x cb=8\n", idxReg);
    972                 break;
    973             }
    974 
    975             /* Split the access and rely on the locking to prevent trouble. */
    976             DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
    977             RTUINT64U uValue;
    978             uValue.u = *(uint64_t const *)pv;
    979             if (idxReg >= 0x100 && idxReg < 0x400)
    980             {
    981                 uint32_t iTimer    = (idxReg - 0x100) / 0x20;
    982                 uint32_t iTimerReg = (idxReg - 0x100) % 0x20;
    983 /** @todo Consider handling iTimerReg == HPET_TN_CMP specially here */
    984                 rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg, uValue.s.Lo);
    985                 if (RT_LIKELY(rc == VINF_SUCCESS))
    986                     rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg + 4, uValue.s.Hi);
    987             }
    988             else
    989             {
    990                 rc = hpetConfigRegWrite32(pThis, idxReg, uValue.s.Lo);
    991                 if (RT_LIKELY(rc == VINF_SUCCESS))
    992                     rc = hpetConfigRegWrite32(pThis, idxReg + 4, uValue.s.Hi);
    993             }
    994             DEVHPET_UNLOCK_BOTH(pThis);
    995             break;
    996         }
    997 
    998         case 1:
    999         case 2:
    1000             Log(("Narrow write: %d\n", cb));
    1001             rc = VINF_SUCCESS;
    1002             break;
    1003 
    1004         default:
    1005             AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
    1006             rc = VERR_INTERNAL_ERROR;
    1007             break;
     945    if (cb == 4)
     946    {
     947        if (idxReg >= 0x100 && idxReg < 0x400)
     948            rc = hpetTimerRegWrite32(pThis,
     949                                     (idxReg - 0x100) / 0x20,
     950                                     (idxReg - 0x100) % 0x20,
     951                                     *(uint32_t const *)pv);
     952        else
     953            rc = hpetConfigRegWrite32(pThis, idxReg, *(uint32_t const *)pv);
     954    }
     955    else
     956    {
     957        /*
     958         * 8-byte access.
     959         */
     960        /* Split the access and rely on the locking to prevent trouble. */
     961        DEVHPET_LOCK_BOTH_RETURN(pThis, VINF_IOM_R3_MMIO_WRITE);
     962        RTUINT64U uValue;
     963        uValue.u = *(uint64_t const *)pv;
     964        if (idxReg >= 0x100 && idxReg < 0x400)
     965        {
     966            uint32_t iTimer    = (idxReg - 0x100) / 0x20;
     967            uint32_t iTimerReg = (idxReg - 0x100) % 0x20;
     968    /** @todo Consider handling iTimerReg == HPET_TN_CMP specially here */
     969            rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg, uValue.s.Lo);
     970            if (RT_LIKELY(rc == VINF_SUCCESS))
     971                rc = hpetTimerRegWrite32(pThis, iTimer, iTimerReg + 4, uValue.s.Hi);
     972        }
     973        else
     974        {
     975            rc = hpetConfigRegWrite32(pThis, idxReg, uValue.s.Lo);
     976            if (RT_LIKELY(rc == VINF_SUCCESS))
     977                rc = hpetConfigRegWrite32(pThis, idxReg + 4, uValue.s.Hi);
     978        }
     979        DEVHPET_UNLOCK_BOTH(pThis);
    1008980    }
    1009981
     
    1021993 * @param   pHpetTimer          The HPET timer.
    1022994 */
    1023 static uint32_t hpetTimerCbGetIrq(struct HpetTimer const *pHpetTimer)
     995static uint32_t hpetR3TimerGetIrq(struct HPETTIMER const *pHpetTimer)
    1024996{
    1025997    /*
     
    10401012
    10411013/**
    1042  * Used by hpetTimerCb to update the IRQ status.
     1014 * Used by hpetR3Timer to update the IRQ status.
    10431015 *
    10441016 * @param   pThis               The HPET device state.
    10451017 * @param   pHpetTimer          The HPET timer.
    10461018 */
    1047 static void hpetTimerCbUpdateIrq(HpetState *pThis, struct HpetTimer *pHpetTimer)
     1019static void hpetR3TimerUpdateIrq(HPET *pThis, struct HPETTIMER *pHpetTimer)
    10481020{
    10491021    /** @todo: is it correct? */
     
    10511023        && !!(pThis->u64HpetConfig & HPET_CFG_ENABLE))
    10521024    {
    1053         uint32_t irq = hpetTimerCbGetIrq(pHpetTimer);
     1025        uint32_t irq = hpetR3TimerGetIrq(pHpetTimer);
    10541026        Log4(("HPET: raising IRQ %d\n", irq));
    10551027
     
    10751047 * @param   pvUser          Pointer to the HPET timer state.
    10761048 */
    1077 static DECLCALLBACK(void) hpetTimerCb(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    1078 {
    1079     HpetState *pThis      = PDMINS_2_DATA(pDevIns, HpetState *);
    1080     HpetTimer *pHpetTimer = (HpetTimer *)pvUser;
     1049static DECLCALLBACK(void) hpetR3Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     1050{
     1051    HPET *pThis      = PDMINS_2_DATA(pDevIns, HPET *);
     1052    HPETTIMER *pHpetTimer = (HPETTIMER *)pvUser;
    10811053    uint64_t   u64Period  = pHpetTimer->u64Period;
    10821054    uint64_t   u64CurTick = hpetGetTicks(pThis);
     
    11061078
    11071079    /* Should it really be under lock, does it really matter? */
    1108     hpetTimerCbUpdateIrq(pThis, pHpetTimer);
     1080    hpetR3TimerUpdateIrq(pThis, pHpetTimer);
    11091081}
    11101082
     
    11161088 * @callback_method_impl{FNDBGFHANDLERDEV}
    11171089 */
    1118 static DECLCALLBACK(void) hpetInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    1119 {
    1120     HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
     1090static DECLCALLBACK(void) hpetR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     1091{
     1092    HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
    11211093    NOREF(pszArgs);
    11221094
     
    11491121 * @callback_method_impl{FNSSMDEVLIVEEXEC}
    11501122 */
    1151 static DECLCALLBACK(int) hpetLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
    1152 {
    1153     HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
     1123static DECLCALLBACK(int) hpetR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
     1124{
     1125    HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
    11541126    NOREF(uPass);
    11551127
     
    11631135 * @callback_method_impl{FNSSMDEVSAVEEXEC}
    11641136 */
    1165 static DECLCALLBACK(int) hpetSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    1166 {
    1167     HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
     1137static DECLCALLBACK(int) hpetR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
     1138{
     1139    HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
    11681140
    11691141    /*
    11701142     * The config.
    11711143     */
    1172     hpetLiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
     1144    hpetR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
    11731145
    11741146    /*
     
    11781150    for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
    11791151    {
    1180         HpetTimer *pHpetTimer = &pThis->aTimers[iTimer];
     1152        HPETTIMER *pHpetTimer = &pThis->aTimers[iTimer];
    11811153        TMR3TimerSave(pHpetTimer->pTimerR3, pSSM);
    11821154        SSMR3PutU8(pSSM,  pHpetTimer->u8Wrap);
     
    11991171 * @callback_method_impl{FNSSMDEVLOADEXEC}
    12001172 */
    1201 static DECLCALLBACK(int) hpetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    1202 {
    1203     HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
     1173static DECLCALLBACK(int) hpetR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
     1174{
     1175    HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
    12041176
    12051177    /*
     
    12291201    for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
    12301202    {
    1231         HpetTimer *pHpetTimer = &pThis->aTimers[iTimer];
     1203        HPETTIMER *pHpetTimer = &pThis->aTimers[iTimer];
    12321204        TMR3TimerLoad(pHpetTimer->pTimerR3, pSSM);
    12331205        SSMR3GetU8(pSSM,  &pHpetTimer->u8Wrap);
     
    12551227     * Set the timer frequency hints.
    12561228     */
    1257     PDMCritSectEnter(&pThis->csLock, VERR_IGNORED);
     1229    PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
    12581230    for (uint32_t iTimer = 0; iTimer < cTimers; iTimer++)
    12591231    {
    1260         HpetTimer *pHpetTimer = &pThis->aTimers[iTimer];
     1232        HPETTIMER *pHpetTimer = &pThis->aTimers[iTimer];
    12611233        if (TMTimerIsActive(pHpetTimer->CTX_SUFF(pTimer)))
    12621234            hpetTimerSetFrequencyHint(pThis, pHpetTimer);
    12631235    }
    1264     PDMCritSectLeave(&pThis->csLock);
     1236    PDMCritSectLeave(&pThis->CritSect);
    12651237    return VINF_SUCCESS;
    12661238}
     
    12731245 * @interface_method_impl{PDMDEVREG,pfnRelocate}
    12741246 */
    1275 static DECLCALLBACK(void) hpetRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    1276 {
    1277     HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
    1278     LogFlow(("hpetRelocate:\n"));
     1247static DECLCALLBACK(void) hpetR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
     1248{
     1249    HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
     1250    LogFlow(("hpetR3Relocate:\n"));
    12791251    NOREF(offDelta);
    12801252
     
    12841256    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
    12851257    {
    1286         HpetTimer *pTm = &pThis->aTimers[i];
     1258        HPETTIMER *pTm = &pThis->aTimers[i];
    12871259        if (pTm->pTimerR3)
    12881260            pTm->pTimerRC = TMTimerRCPtr(pTm->pTimerR3);
     
    12951267 * @interface_method_impl{PDMDEVREG,pfnReset}
    12961268 */
    1297 static DECLCALLBACK(void) hpetReset(PPDMDEVINS pDevIns)
    1298 {
    1299     HpetState *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
    1300     LogFlow(("hpetReset:\n"));
     1269static DECLCALLBACK(void) hpetR3Reset(PPDMDEVINS pDevIns)
     1270{
     1271    HPET *pThis = PDMINS_2_DATA(pDevIns, HPET *);
     1272    LogFlow(("hpetR3Reset:\n"));
    13011273
    13021274    /*
     
    13061278    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
    13071279    {
    1308         HpetTimer *pHpetTimer = &pThis->aTimers[i];
     1280        HPETTIMER *pHpetTimer = &pThis->aTimers[i];
    13091281        Assert(pHpetTimer->idxTimer == i);
    13101282        TMTimerStop(pHpetTimer->pTimerR3);
     
    13591331 * @interface_method_impl{PDMDEVREG,pfnConstruct}
    13601332 */
    1361 static DECLCALLBACK(int) hpetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
     1333static DECLCALLBACK(int) hpetR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
    13621334{
    13631335    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    1364     HpetState   *pThis = PDMINS_2_DATA(pDevIns, HpetState *);
     1336    HPET   *pThis = PDMINS_2_DATA(pDevIns, HPET *);
    13651337
    13661338    /* Only one HPET device now, as we use fixed MMIO region. */
    13671339    Assert(iInstance == 0);
     1340
     1341    /*
     1342     * Initialize the device state.
     1343     */
     1344    pThis->pDevInsR3 = pDevIns;
     1345    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     1346    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1347
     1348    /* Init the HPET timers (init all regardless of how many we expose). */
     1349    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
     1350    {
     1351        HPETTIMER *pHpetTimer = &pThis->aTimers[i];
     1352
     1353        pHpetTimer->idxTimer = i;
     1354        pHpetTimer->pHpetR3  = pThis;
     1355        pHpetTimer->pHpetR0  = PDMINS_2_DATA_R0PTR(pDevIns);
     1356        pHpetTimer->pHpetRC  = PDMINS_2_DATA_RCPTR(pDevIns);
     1357    }
    13681358
    13691359    /*
     
    13891379                                N_("Configuration error: failed to read ICH9 as boolean"));
    13901380
    1391     /*
    1392      * Initialize the device state.
    1393      */
    1394     pThis->pDevInsR3 = pDevIns;
    1395     pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    1396     pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    1397 
    1398     rc = PDMDevHlpCritSectInit(pDevIns, &pThis->csLock, RT_SRC_POS, "HPET#%u", pDevIns->iInstance);
     1381
     1382    /*
     1383     * Create critsect and timers.
     1384     * Note! We don't use the default critical section of the device, but our own.
     1385     */
     1386    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "HPET");
    13991387    AssertRCReturn(rc, rc);
    14001388
    1401     /* No automatic locking. */
    14021389    rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
    14031390    AssertRCReturn(rc, rc);
     
    14061393    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aTimers); i++)
    14071394    {
    1408         HpetTimer *pHpetTimer = &pThis->aTimers[i];
    1409 
    1410         pHpetTimer->idxTimer = i;
    1411         pHpetTimer->pHpetR3  = pThis;
    1412         pHpetTimer->pHpetR0  = PDMINS_2_DATA_R0PTR(pDevIns);
    1413         pHpetTimer->pHpetRC  = PDMINS_2_DATA_RCPTR(pDevIns);
    1414 
    1415         rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hpetTimerCb, pHpetTimer,
     1395        HPETTIMER *pHpetTimer = &pThis->aTimers[i];
     1396
     1397        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, hpetR3Timer, pHpetTimer,
    14161398                                    TMTIMER_FLAGS_NO_CRIT_SECT, "HPET Timer",
    14171399                                    &pThis->aTimers[i].pTimerR3);
     
    14191401        pThis->aTimers[i].pTimerRC = TMTimerRCPtr(pThis->aTimers[i].pTimerR3);
    14201402        pThis->aTimers[i].pTimerR0 = TMTimerR0Ptr(pThis->aTimers[i].pTimerR3);
    1421         rc = TMR3TimerSetCritSect(pThis->aTimers[i].pTimerR3, &pThis->csLock);
     1403        rc = TMR3TimerSetCritSect(pThis->aTimers[i].pTimerR3, &pThis->CritSect);
    14221404        AssertRCReturn(rc, rc);
    14231405    }
    14241406
    1425     /* This must be done prior to registering the HPET, right? */
    1426     hpetReset(pDevIns);
     1407    /*
     1408     * This must be done prior to registering the HPET, right?
     1409     */
     1410    hpetR3Reset(pDevIns);
    14271411
    14281412    /*
     
    14391423     */
    14401424    rc = PDMDevHlpMMIORegister(pDevIns, HPET_BASE, HPET_BAR_SIZE, pThis,
    1441                                IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
     1425                               IOMMMIO_FLAGS_READ_DWORD_QWORD | IOMMMIO_FLAGS_WRITE_ONLY_DWORD_QWORD,
    14421426                               hpetMMIOWrite, hpetMMIORead, "HPET Memory");
    14431427    AssertRCReturn(rc, rc);
     
    14631447
    14641448    /* Register SSM callbacks */
    1465     rc = PDMDevHlpSSMRegister3(pDevIns, HPET_SAVED_STATE_VERSION, sizeof(*pThis), hpetLiveExec, hpetSaveExec, hpetLoadExec);
     1449    rc = PDMDevHlpSSMRegister3(pDevIns, HPET_SAVED_STATE_VERSION, sizeof(*pThis), hpetR3LiveExec, hpetR3SaveExec, hpetR3LoadExec);
    14661450    AssertRCReturn(rc, rc);
    14671451
    14681452    /* Register an info callback. */
    1469     PDMDevHlpDBGFInfoRegister(pDevIns, "hpet", "Display HPET status. (no arguments)", hpetInfo);
     1453    PDMDevHlpDBGFInfoRegister(pDevIns, "hpet", "Display HPET status. (no arguments)", hpetR3Info);
    14701454
    14711455    return VINF_SUCCESS;
     
    14891473    " High Precision Event Timer (HPET) Device",
    14901474    /* fFlags */
    1491     PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
     1475    PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36
     1476    | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
    14921477    /* fClass */
    14931478    PDM_DEVREG_CLASS_PIT,
     
    14951480    1,
    14961481    /* cbInstance */
    1497     sizeof(HpetState),
     1482    sizeof(HPET),
    14981483    /* pfnConstruct */
    1499     hpetConstruct,
     1484    hpetR3Construct,
    15001485    /* pfnDestruct */
    15011486    NULL,
    15021487    /* pfnRelocate */
    1503     hpetRelocate,
     1488    hpetR3Relocate,
    15041489    /* pfnIOCtl */
    15051490    NULL,
     
    15071492    NULL,
    15081493    /* pfnReset */
    1509     hpetReset,
     1494    hpetR3Reset,
    15101495    /* pfnSuspend */
    15111496    NULL,
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