VirtualBox

Changeset 63632 in vbox


Ignore:
Timestamp:
Aug 25, 2016 10:58:22 AM (8 years ago)
Author:
vboxsync
Message:

VMM/APIC: Initial Hyper-V support for synthetic interrupts, Hyper-V interface for direct TPR, EOI, ICR accesses.
Support for Hyper-V compatibility mode (x2APIC interface while operating in xAPIC mode).

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/apic.h

    r61794 r63632  
    141141#define XAPIC_OFF_LVT_EXT_END                XAPIC_OFF_LVT_CMCI
    142142
     143/** @name xAPIC Interrupt Command Register bits.
     144 * See Intel spec. 10.6.1 "Interrupt Command Register (ICR)".
     145 * See Intel spec. 10.5.1 "Local Vector Table".
     146 * @{ */
     147/**
     148 * xAPIC trigger mode.
     149 */
     150typedef enum XAPICTRIGGERMODE
     151{
     152    XAPICTRIGGERMODE_EDGE = 0,
     153    XAPICTRIGGERMODE_LEVEL
     154} XAPICTRIGGERMODE;
     155
    143156RT_C_DECLS_BEGIN
    144157
     
    148161 */
    149162VMMR3_INT_DECL(void)        APICR3InitIpi(PVMCPU pVCpu);
     163VMMR3_INT_DECL(void)        APICR3HvEnable(PVM pVM);
    150164/** @} */
    151165#endif /* IN_RING3 */
     
    165179VMMDECL(bool)               APICGetHighestPendingInterrupt(PVMCPU pVCpu, uint8_t *pu8PendingIntr);
    166180
     181/** @name Hyper-V interface (Ring-3 and all-context API).
     182 * @{ */
     183#ifdef IN_RING3
     184VMMR3_INT_DECL(void)        APICR3HvSetCompatMode(PVM pVM, bool fHyperVCompatMode);
     185#endif
     186VMM_INT_DECL(void)          APICHvSendInterrupt(PVMCPU pVCpu, uint8_t uVector, bool fAutoEoi, XAPICTRIGGERMODE enmTriggerMode);
     187VMM_INT_DECL(VBOXSTRICTRC)  APICHvSetTpr(PVMCPU pVCpu, uint8_t uTpr);
     188VMM_INT_DECL(uint8_t)       APICHvGetTpr(PVMCPU pVCpu);
     189VMM_INT_DECL(VBOXSTRICTRC)  APICHvSetIcr(PVMCPU pVCpu, uint64_t uIcr);
     190VMM_INT_DECL(uint64_t)      APICHvGetIcr(PVMCPU pVCpu);
     191VMM_INT_DECL(VBOXSTRICTRC)  APICHvSetEoi(PVMCPU pVCpu, uint32_t uEoi);
     192/** @} */
     193
    167194RT_C_DECLS_END
    168195
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSize.cpp

    r62576 r63632  
    291291#ifdef VBOX_WITH_NEW_APIC
    292292    CHECK_MEMBER_ALIGNMENT(APICDEV, pDevInsR0, 8);
     293    CHECK_MEMBER_ALIGNMENT(APICDEV, pCritSectR0, 8);
    293294    CHECK_MEMBER_ALIGNMENT(APICDEV, pDevInsRC, 8);
     295    CHECK_MEMBER_ALIGNMENT(APICDEV, pCritSectRC, 8);
    294296#else
    295297# ifdef VBOX_WITH_STATISTICS
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp

    r62957 r63632  
    773773    GEN_CHECK_OFF(APICCPU, StatTimerIcrWrite);
    774774    GEN_CHECK_OFF(APICCPU, StatIcrLoWrite);
     775    GEN_CHECK_OFF(APICCPU, StatIcrHiWrite);
     776    GEN_CHECK_OFF(APICCPU, StatIcrFullWrite);
    775777# endif /* VBOX_WITH_STATISTICS */
    776778#else
  • trunk/src/VBox/VMM/VMMAll/APICAll.cpp

    r63525 r63632  
    10551055    PXAPICPAGE pXApicPage = VMCPU_TO_XAPICPAGE(pVCpu);
    10561056    pXApicPage->icr_hi.all.u32IcrHi = uIcrHi & XAPIC_ICR_HI_DEST;
     1057    STAM_COUNTER_INC(&pVCpu->apic.s.StatIcrHiWrite);
    10571058    Log2(("APIC%u: apicSetIcrHi: uIcrHi=%#RX32\n", pVCpu->idCpu, pXApicPage->icr_hi.all.u32IcrHi));
    10581059
     
    10911092 * @param   rcRZ            The return code if the operation cannot be performed
    10921093 *                          in the current context.
     1094 *
     1095 * @remarks This function is used by both x2APIC interface and the Hyper-V
     1096 *          interface, see APICHvSetIcr(). The Hyper-V spec isn't clear what
     1097 *          happens when invalid bits are set. For the time being, it will #GP
     1098 *          like a regular x2APIC access.
    10931099 */
    10941100static VBOXSTRICTRC apicSetIcr(PVMCPU pVCpu, uint64_t u64Icr, int rcRZ)
    10951101{
    10961102    VMCPU_ASSERT_EMT(pVCpu);
    1097     Assert(XAPIC_IN_X2APIC_MODE(pVCpu));
    10981103
    10991104    /* Validate. */
     
    11041109        PX2APICPAGE pX2ApicPage = VMCPU_TO_X2APICPAGE(pVCpu);
    11051110        pX2ApicPage->icr_hi.u32IcrHi = RT_HI_U32(u64Icr);
    1106         return apicSetIcrLo(pVCpu, uLo,  rcRZ);
     1111        STAM_COUNTER_INC(&pVCpu->apic.s.StatIcrHiWrite);
     1112        STAM_COUNTER_INC(&pVCpu->apic.s.StatIcrFullWrite);
     1113        return apicSetIcrLo(pVCpu, uLo, rcRZ);
    11071114    }
    11081115    return apicMsrAccessError(pVCpu, MSR_IA32_X2APIC_ICR, APICMSRACCESS_WRITE_RSVD_BITS);
     
    11891196 *
    11901197 * @returns Strict VBox status code.
    1191  * @param   pVCpu           The cross context virtual CPU structure.
    1192  * @param   uTpr            The TPR value.
    1193  */
    1194 static VBOXSTRICTRC apicSetTpr(PVMCPU pVCpu, uint32_t uTpr)
     1198 * @param   pVCpu                   The cross context virtual CPU structure.
     1199 * @param   uTpr                    The TPR value.
     1200 * @param   fForceX2ApicBehaviour   Pretend the APIC is in x2APIC mode during
     1201 *                                  this write.
     1202 */
     1203static VBOXSTRICTRC apicSetTprEx(PVMCPU pVCpu, uint32_t uTpr, bool fForceX2ApicBehaviour)
    11951204{
    11961205    VMCPU_ASSERT_EMT(pVCpu);
    11971206
    1198     Log2(("APIC%u: apicSetTpr: uTpr=%#RX32\n", pVCpu->idCpu, uTpr));
     1207    Log2(("APIC%u: apicSetTprEx: uTpr=%#RX32\n", pVCpu->idCpu, uTpr));
    11991208    STAM_COUNTER_INC(&pVCpu->apic.s.StatTprWrite);
    12001209
    1201     if (   XAPIC_IN_X2APIC_MODE(pVCpu)
     1210    bool const fX2ApicMode = XAPIC_IN_X2APIC_MODE(pVCpu) || fForceX2ApicBehaviour;
     1211    if (   fX2ApicMode
    12021212        && (uTpr & ~XAPIC_TPR_VALID))
    12031213        return apicMsrAccessError(pVCpu, MSR_IA32_X2APIC_TPR, APICMSRACCESS_WRITE_RSVD_BITS);
     
    12151225 *
    12161226 * @returns Strict VBox status code.
    1217  * @param   pVCpu           The cross context virtual CPU structure.
    1218  * @param   uEoi            The EOI value.
    1219  */
    1220 static VBOXSTRICTRC apicSetEoi(PVMCPU pVCpu, uint32_t uEoi)
     1227 * @param   pVCpu                   The cross context virtual CPU structure.
     1228 * @param   uEoi                    The EOI value.
     1229 * @param   fForceX2ApicBehaviour   Pretend the APIC is in x2APIC mode during
     1230 *                                  this write.
     1231 */
     1232static VBOXSTRICTRC apicSetEoi(PVMCPU pVCpu, uint32_t uEoi, bool fForceX2ApicBehaviour)
    12211233{
    12221234    VMCPU_ASSERT_EMT(pVCpu);
     
    12251237    STAM_COUNTER_INC(&pVCpu->apic.s.StatEoiWrite);
    12261238
    1227     if (   XAPIC_IN_X2APIC_MODE(pVCpu)
     1239    bool const fX2ApicMode = XAPIC_IN_X2APIC_MODE(pVCpu) || fForceX2ApicBehaviour;
     1240    if (   fX2ApicMode
    12281241        && (uEoi & ~XAPIC_EOI_WO_VALID))
    12291242        return apicMsrAccessError(pVCpu, MSR_IA32_X2APIC_EOI, APICMSRACCESS_WRITE_RSVD_BITS);
     
    12491262            { /* likely */ }
    12501263            else
    1251                 return XAPIC_IN_X2APIC_MODE(pVCpu) ? VINF_CPUM_R3_MSR_WRITE : VINF_IOM_R3_MMIO_WRITE;
     1264                return fX2ApicMode ? VINF_CPUM_R3_MSR_WRITE : VINF_IOM_R3_MMIO_WRITE;
    12521265
    12531266            /*
     
    13111324{
    13121325    VMCPU_ASSERT_EMT(pVCpu);
    1313     Assert(!XAPIC_IN_X2APIC_MODE(pVCpu));
     1326    PCAPIC pApic = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
     1327    Assert(!XAPIC_IN_X2APIC_MODE(pVCpu) || pApic->fHyperVCompatMode); RT_NOREF_PV(pApic);
    13141328
    13151329    Log2(("APIC%u: apicSetLdr: uLdr=%#RX32\n", pVCpu->idCpu, uLdr));
     
    16011615        pApicCpu->uHintedTimerShift = uTimerShift;
    16021616    }
     1617}
     1618
     1619
     1620/**
     1621 * Gets the Interrupt Command Register (ICR), without performing any interface
     1622 * checks.
     1623 *
     1624 * @returns The ICR value.
     1625 * @param   pVCpu           The cross context virtual CPU structure.
     1626 */
     1627DECLINLINE(uint64_t) apicGetIcrNoCheck(PVMCPU pVCpu)
     1628{
     1629    PCX2APICPAGE pX2ApicPage = VMCPU_TO_CX2APICPAGE(pVCpu);
     1630    uint64_t const uHi  = pX2ApicPage->icr_hi.u32IcrHi;
     1631    uint64_t const uLo  = pX2ApicPage->icr_lo.all.u32IcrLo;
     1632    uint64_t const uIcr = RT_MAKE_U64(uLo, uHi);
     1633    return uIcr;
    16031634}
    16041635
     
    17191750        case XAPIC_OFF_TPR:
    17201751        {
    1721             rcStrict = apicSetTpr(pVCpu, uValue);
     1752            rcStrict = apicSetTprEx(pVCpu, uValue, false /* fForceX2ApicBehaviour */);
    17221753            break;
    17231754        }
     
    17441775        case XAPIC_OFF_EOI:
    17451776        {
    1746             rcStrict = apicSetEoi(pVCpu, uValue);
     1777            rcStrict = apicSetEoi(pVCpu, uValue, false /* fForceX2ApicBehaviour */);
    17471778            break;
    17481779        }
     
    18431874    RT_NOREF_PV(pDevIns);
    18441875
     1876    PCAPIC pApic = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
    18451877#ifndef IN_RING3
    1846     PCAPIC pApic = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
    18471878    if (pApic->fRZEnabled)
    18481879    { /* likely */}
     
    18541885
    18551886    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    1856     if (RT_LIKELY(XAPIC_IN_X2APIC_MODE(pVCpu)))
     1887    if (RT_LIKELY(   XAPIC_IN_X2APIC_MODE(pVCpu)
     1888                  || pApic->fHyperVCompatMode))
    18571889    {
    18581890        switch (u32Reg)
     
    18611893            case MSR_IA32_X2APIC_ICR:
    18621894            {
    1863                 PCX2APICPAGE pX2ApicPage = VMCPU_TO_CX2APICPAGE(pVCpu);
    1864                 uint64_t const uHi = pX2ApicPage->icr_hi.u32IcrHi;
    1865                 uint64_t const uLo = pX2ApicPage->icr_lo.all.u32IcrLo;
    1866                 *pu64Value = RT_MAKE_U64(uLo, uHi);
     1895                *pu64Value = apicGetIcrNoCheck(pVCpu);
    18671896                break;
    18681897            }
     
    19481977    RT_NOREF_PV(pDevIns);
    19491978
     1979    PCAPIC pApic = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
    19501980#ifndef IN_RING3
    1951     PCAPIC pApic = VM_TO_APIC(pVCpu->CTX_SUFF(pVM));
    19521981    if (pApic->fRZEnabled)
    19531982    { /* likely */ }
     
    19732002    uint32_t     u32Value = RT_LO_U32(u64Value);
    19742003    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
    1975     if (RT_LIKELY(XAPIC_IN_X2APIC_MODE(pVCpu)))
     2004    if (RT_LIKELY(   XAPIC_IN_X2APIC_MODE(pVCpu)
     2005                  || pApic->fHyperVCompatMode))
    19762006    {
    19772007        switch (u32Reg)
     
    19792009            case MSR_IA32_X2APIC_TPR:
    19802010            {
    1981                 rcStrict = apicSetTpr(pVCpu, u32Value);
     2011                rcStrict = apicSetTprEx(pVCpu, u32Value, false /* fForceX2ApicBehaviour */);
    19822012                break;
    19832013            }
     
    20352065            case MSR_IA32_X2APIC_EOI:
    20362066            {
    2037                 rcStrict = apicSetEoi(pVCpu, u32Value);
     2067                rcStrict = apicSetEoi(pVCpu, u32Value, false /* fForceX2ApicBehaviour */);
    20382068                break;
    20392069            }
    20402070
     2071            /*
     2072             * Windows guest using Hyper-V x2APIC MSR compatibility mode tries to write the "high"
     2073             * LDR bits, which is quite absurd (as it's a 32-bit register) using this invalid MSR
     2074             * index (0x80E). The write value was 0xffffffff on a Windows 8.1 64-bit guest. We can
     2075             * safely ignore this nonsense, See @bugref{8382#c7}.
     2076             */
     2077            case MSR_IA32_X2APIC_LDR + 1:
     2078            {
     2079                if (pApic->fHyperVCompatMode)
     2080                    rcStrict = VINF_SUCCESS;
     2081                else
     2082                    rcStrict = apicMsrAccessError(pVCpu, u32Reg, APICMSRACCESS_WRITE_RSVD_OR_UNKNOWN);
     2083                break;
     2084            }
     2085
     2086            /* Special-treament (read-only normally, but not with Hyper-V) */
     2087            case MSR_IA32_X2APIC_LDR:
     2088            {
     2089                if (pApic->fHyperVCompatMode)
     2090                {
     2091                    rcStrict = apicSetLdr(pVCpu, u32Value);
     2092                    break;
     2093                }
     2094                /* fallthru */
     2095            }
    20412096            /* Read-only MSRs: */
    20422097            case MSR_IA32_X2APIC_ID:
    20432098            case MSR_IA32_X2APIC_VERSION:
    20442099            case MSR_IA32_X2APIC_PPR:
    2045             case MSR_IA32_X2APIC_LDR:
    20462100            case MSR_IA32_X2APIC_ISR0:  case MSR_IA32_X2APIC_ISR1:  case MSR_IA32_X2APIC_ISR2:  case MSR_IA32_X2APIC_ISR3:
    20472101            case MSR_IA32_X2APIC_ISR4:  case MSR_IA32_X2APIC_ISR5:  case MSR_IA32_X2APIC_ISR6:  case MSR_IA32_X2APIC_ISR7:
     
    22322286{
    22332287    RT_NOREF_PV(pDevIns);
    2234     apicSetTpr(pVCpu, u8Tpr);
     2288    apicSetTprEx(pVCpu, u8Tpr, false /* fForceX2ApicBehaviour */);
    22352289}
    22362290
     
    28792933            break;
    28802934
    2881         AssertCompile(RT_ELEMENTS(pXApicPage->irr.u) == 2 * RT_ELEMENTS(pPib->aVectorBitmap));
    2882         for (size_t idxPib = 0, idxReg = 0; idxPib < RT_ELEMENTS(pPib->aVectorBitmap); idxPib++, idxReg += 2)
    2883         {
    2884             uint64_t const u64Fragment = ASMAtomicXchgU64(&pPib->aVectorBitmap[idxPib], 0);
     2935        AssertCompile(RT_ELEMENTS(pXApicPage->irr.u) == 2 * RT_ELEMENTS(pPib->au64VectorBitmap));
     2936        for (size_t idxPib = 0, idxReg = 0; idxPib < RT_ELEMENTS(pPib->au64VectorBitmap); idxPib++, idxReg += 2)
     2937        {
     2938            uint64_t const u64Fragment = ASMAtomicXchgU64(&pPib->au64VectorBitmap[idxPib], 0);
    28852939            if (u64Fragment)
    28862940            {
     
    29062960            break;
    29072961
    2908         AssertCompile(RT_ELEMENTS(pXApicPage->irr.u) == 2 * RT_ELEMENTS(pPib->aVectorBitmap));
    2909         for (size_t idxPib = 0, idxReg = 0; idxPib < RT_ELEMENTS(pPib->aVectorBitmap); idxPib++, idxReg += 2)
    2910         {
    2911             uint64_t const u64Fragment = ASMAtomicXchgU64(&pPib->aVectorBitmap[idxPib], 0);
     2962        AssertCompile(RT_ELEMENTS(pXApicPage->irr.u) == 2 * RT_ELEMENTS(pPib->au64VectorBitmap));
     2963        for (size_t idxPib = 0, idxReg = 0; idxPib < RT_ELEMENTS(pPib->au64VectorBitmap); idxPib++, idxReg += 2)
     2964        {
     2965            uint64_t const u64Fragment = ASMAtomicXchgU64(&pPib->au64VectorBitmap[idxPib], 0);
    29122966            if (u64Fragment)
    29132967            {
     
    29483002}
    29493003
     3004
     3005/**
     3006 * Posts an interrupt to a target APIC, Hyper-V interface.
     3007 *
     3008 * @returns true if the interrupt was accepted, false otherwise.
     3009 * @param   pVCpu               The cross context virtual CPU structure.
     3010 * @param   uVector             The vector of the interrupt to be posted.
     3011 * @param   fAutoEoi            Whether this interrupt has automatic EOI
     3012 *                              treatment.
     3013 * @param   enmTriggerMode      The trigger mode of the interrupt.
     3014 *
     3015 * @thread  Any.
     3016 */
     3017VMM_INT_DECL(void) APICHvSendInterrupt(PVMCPU pVCpu, uint8_t uVector, bool fAutoEoi, XAPICTRIGGERMODE enmTriggerMode)
     3018{
     3019    Assert(pVCpu);
     3020    Assert(!fAutoEoi);    /** @todo AutoEOI.  */
     3021    apicPostInterrupt(pVCpu, uVector, enmTriggerMode);
     3022}
     3023
     3024
     3025/**
     3026 * Sets the Task Priority Register (TPR), Hyper-V interface.
     3027 *
     3028 * @returns Strict VBox status code.
     3029 * @param   pVCpu       The cross context virtual CPU structure.
     3030 * @param   uTpr        The TPR value to set.
     3031 *
     3032 * @remarks Validates like in x2APIC mode.
     3033 */
     3034VMM_INT_DECL(VBOXSTRICTRC) APICHvSetTpr(PVMCPU pVCpu, uint8_t uTpr)
     3035{
     3036    Assert(pVCpu);
     3037    VMCPU_ASSERT_EMT(pVCpu);
     3038    return apicSetTprEx(pVCpu, uTpr, true /* fForceX2ApicBehaviour */);
     3039}
     3040
     3041
     3042/**
     3043 * Gets the Task Priority Register (TPR), Hyper-V interface.
     3044 *
     3045 * @returns The TPR value.
     3046 * @param   pVCpu           The cross context virtual CPU structure.
     3047 */
     3048VMM_INT_DECL(uint8_t) APICHvGetTpr(PVMCPU pVCpu)
     3049{
     3050    Assert(pVCpu);
     3051    VMCPU_ASSERT_EMT(pVCpu);
     3052
     3053    /*
     3054     * The APIC could be operating in xAPIC mode and thus we should not use the apicReadMsr()
     3055     * interface which validates the APIC mode and will throw a #GP(0) if not in x2APIC mode.
     3056     * We could use the apicReadRegister() MMIO interface, but why bother getting the PDMDEVINS
     3057     * pointer, so just directly read the APIC page.
     3058     */
     3059    PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
     3060    return apicReadRaw32(pXApicPage, XAPIC_OFF_TPR);
     3061}
     3062
     3063
     3064/**
     3065 * Sets the Interrupt Command Register (ICR), Hyper-V interface.
     3066 *
     3067 * @returns Strict VBox status code.
     3068 * @param   pVCpu       The cross context virtual CPU structure.
     3069 * @param   uIcr        The ICR value to set.
     3070 */
     3071VMM_INT_DECL(VBOXSTRICTRC) APICHvSetIcr(PVMCPU pVCpu, uint64_t uIcr)
     3072{
     3073    Assert(pVCpu);
     3074    VMCPU_ASSERT_EMT(pVCpu);
     3075    return apicSetIcr(pVCpu, uIcr, VINF_CPUM_R3_MSR_WRITE);
     3076}
     3077
     3078
     3079/**
     3080 * Gets the Interrupt Command Register (ICR), Hyper-V interface.
     3081 *
     3082 * @returns The ICR value.
     3083 * @param   pVCpu           The cross context virtual CPU structure.
     3084 */
     3085VMM_INT_DECL(uint64_t) APICHvGetIcr(PVMCPU pVCpu)
     3086{
     3087    Assert(pVCpu);
     3088    VMCPU_ASSERT_EMT(pVCpu);
     3089    return apicGetIcrNoCheck(pVCpu);
     3090}
     3091
     3092
     3093/**
     3094 * Sets the End-Of-Interrupt (EOI) register, Hyper-V interface.
     3095 *
     3096 * @returns Strict VBox status code.
     3097 * @param   pVCpu           The cross context virtual CPU structure.
     3098 * @param   uEoi            The EOI value.
     3099 */
     3100VMM_INT_DECL(VBOXSTRICTRC) APICHvSetEoi(PVMCPU pVCpu, uint32_t uEoi)
     3101{
     3102    Assert(pVCpu);
     3103    VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu);
     3104    return apicSetEoi(pVCpu, uEoi, true /* fForceX2ApicBehaviour */);
     3105}
     3106
  • trunk/src/VBox/VMM/VMMR3/APIC.cpp

    r62658 r63632  
    355355
    356356/**
     357 * Sets whether Hyper-V compatibile x2APIC mode is enabled or not.
     358 *
     359 * @param   pVM                 The cross context VM structure.
     360 * @param   fHyperVCompatMode   Whether the compatibility mode is enabled.
     361 */
     362VMMR3_INT_DECL(void) APICR3HvSetCompatMode(PVM pVM, bool fHyperVCompatMode)
     363{
     364    Assert(pVM);
     365    PAPIC pApic = VM_TO_APIC(pVM);
     366    pApic->fHyperVCompatMode = fHyperVCompatMode;
     367}
     368
     369
     370/**
    357371 * Helper for dumping an APIC 256-bit sparse register.
    358372 *
     
    413427    RT_ZERO(ApicReg);
    414428    ssize_t const cFragmentsDst = RT_ELEMENTS(ApicReg.u);
    415     ssize_t const cFragmentsSrc = RT_ELEMENTS(pApicPib->aVectorBitmap);
    416     AssertCompile(RT_ELEMENTS(ApicReg.u) == 2 * RT_ELEMENTS(pApicPib->aVectorBitmap));
     429    ssize_t const cFragmentsSrc = RT_ELEMENTS(pApicPib->au64VectorBitmap);
     430    AssertCompile(RT_ELEMENTS(ApicReg.u) == 2 * RT_ELEMENTS(pApicPib->au64VectorBitmap));
    417431    for (ssize_t idxPib = cFragmentsSrc - 1, idxReg = cFragmentsDst - 1; idxPib >= 0; idxPib--, idxReg -= 2)
    418432    {
    419         uint64_t const uFragment   = pApicPib->aVectorBitmap[idxPib];
     433        uint64_t const uFragment   = pApicPib->au64VectorBitmap[idxPib];
    420434        uint32_t const uFragmentLo = RT_LO_U32(uFragment);
    421435        uint32_t const uFragmentHi = RT_HI_U32(uFragment);
     
    18321846        APIC_REG_COUNTER(&pApicCpu->StatIcrLoWrite,    "Number of times the ICR Lo (send IPI) is written.",
    18331847                         "/Devices/APIC/%u/IcrLoWrite");
     1848        APIC_REG_COUNTER(&pApicCpu->StatIcrHiWrite,    "Number of times the ICR Hi is written.",
     1849                         "/Devices/APIC/%u/IcrHiWrite");
     1850        APIC_REG_COUNTER(&pApicCpu->StatIcrFullWrite,  "Number of times the ICR full (send IPI, x2APIC) is written.",
     1851                         "/Devices/APIC/%u/IcrFullWrite");
    18341852    }
    18351853# undef APIC_PROF_COUNTER
  • trunk/src/VBox/VMM/include/APICInternal.h

    r62019 r63632  
    6363                                                  & (MSR_IA32_APICBASE_EN | MSR_IA32_APICBASE_EXTD)) \
    6464                                              ==    (MSR_IA32_APICBASE_EN | MSR_IA32_APICBASE_EXTD) )
     65
    6566/** Get an xAPIC page offset for an x2APIC MSR value. */
    6667#define X2APIC_GET_XAPIC_OFF(a_uMsr)         ((((a_uMsr) - MSR_IA32_X2APIC_START) << 4) & UINT32_C(0xff0))
     
    10661067/** @} */
    10671068
    1068 /** @name xAPIC Interrupt Command Register bits.
    1069  * See Intel spec. 10.6.1 "Interrupt Command Register (ICR)".
    1070  * See Intel spec. 10.5.1 "Local Vector Table".
    1071  * @{ */
    1072 /**
    1073  * xAPIC trigger mode.
    1074  */
    1075 typedef enum XAPICTRIGGERMODE
    1076 {
    1077     XAPICTRIGGERMODE_EDGE = 0,
    1078     XAPICTRIGGERMODE_LEVEL
    1079 } XAPICTRIGGERMODE;
    1080 
    10811069/**
    10821070 * xAPIC destination shorthand.
     
    11231111/** @} */
    11241112
     1113/** @def APIC_CACHE_LINE_SIZE
     1114 * Padding (in bytes) for aligning data in different cache lines. Present
     1115 * generation x86 CPUs use 64-byte cache lines[1]. However, Intel NetBurst
     1116 * architecture supposedly uses 128-byte cache lines[2]. Since 128 is a
     1117 * multiple of 64, we use the larger one here.
     1118 *
     1119 * [1] - Intel spec "Table 11-1. Characteristics of the Caches, TLBs, Store
     1120 *       Buffer, and Write Combining Buffer in Intel 64 and IA-32 Processors"
     1121 * [2] - Intel spec. 8.10.6.7 "Place Locks and Semaphores in Aligned, 128-Byte
     1122 *       Blocks of Memory".
     1123 */
     1124#define APIC_CACHE_LINE_SIZE              128
     1125
    11251126/**
    11261127 * APIC Pending-Interrupt Bitmap (PIB).
     
    11281129typedef struct APICPIB
    11291130{
    1130     uint64_t volatile aVectorBitmap[4];
     1131    uint64_t volatile au64VectorBitmap[4];
    11311132    uint32_t volatile fOutstandingNotification;
    1132     uint8_t           au8Reserved[28];
     1133    uint8_t           au8Reserved[APIC_CACHE_LINE_SIZE - sizeof(uint32_t) - (sizeof(uint64_t) * 4)];
    11331134} APICPIB;
    11341135AssertCompileMemberOffset(APICPIB, fOutstandingNotification, 256 / 8);
    1135 AssertCompileSize(APICPIB, 64);
     1136AssertCompileSize(APICPIB, APIC_CACHE_LINE_SIZE);
    11361137/** Pointer to a pending-interrupt bitmap. */
    11371138typedef APICPIB *PAPICPIB;
     
    11671168    PCPDMAPICHLPRC              pApicHlpRC;
    11681169    /** The PDM critical section - RC Ptr. */
    1169     RCPTRTYPE(PPDMCRITSECT) pCritSectRC;
     1170    RCPTRTYPE(PPDMCRITSECT)     pCritSectRC;
    11701171    /** Alignment padding. */
    11711172    RCPTRTYPE(void *)           pvAlignment2;
     
    12271228    /** Whether RZ is enabled or not (applies to MSR handling as well). */
    12281229    bool                        fRZEnabled;
     1230    /** Whether Hyper-V x2APIC compatibility mode is enabled. */
     1231    bool                        fHyperVCompatMode;
    12291232    /** Alignment padding. */
    1230     bool                        afAlignment0[7];
     1233    bool                        afAlignment[2];
    12311234    /** The max supported APIC mode from CFGM.  */
    12321235    PDMAPICMODE                 enmMaxMode;
     1236    /** Alignment padding. */
     1237    uint32_t                    u32Alignment1;
    12331238    /** @} */
    12341239} APIC;
     
    12371242/** Pointer to const APIC VM instance data. */
    12381243typedef APIC const *PCAPIC;
     1244AssertCompileMemberAlignment(APIC, cbApicPib, 8);
     1245AssertCompileMemberAlignment(APIC, fVirtApicRegsEnabled, 8);
     1246AssertCompileMemberAlignment(APIC, enmMaxMode, 8);
     1247AssertCompileSizeAlignment(APIC, 8);
    12391248
    12401249/**
     
    12851294    /** The APIC PIB for level-sensitive interrupts. */
    12861295    APICPIB                     ApicPibLevel;
     1296    /** @} */
     1297
     1298    /** @name Other miscellaneous data.
     1299     * @{ */
    12871300    /** Whether the LINT0 interrupt line is active. */
    12881301    bool volatile               fActiveLint0;
     
    13611374    /** Number of times the ICR Lo (send IPI) is written. */
    13621375    STAMCOUNTER                 StatIcrLoWrite;
     1376    /** Number of times the ICR Hi is written. */
     1377    STAMCOUNTER                 StatIcrHiWrite;
     1378    /** Number of times the full ICR (x2APIC send IPI) is written. */
     1379    STAMCOUNTER                 StatIcrFullWrite;
    13631380    /** @} */
    13641381#endif
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