VirtualBox

Changeset 61581 in vbox


Ignore:
Timestamp:
Jun 8, 2016 2:35:00 PM (9 years ago)
Author:
vboxsync
Message:

VMM/APIC: Fix remote IRR bit for level-triggered LINT0 interrupts and make LINT0/LINT1 only edge-triggered interrupts
on an edge-transition to the active state. For this we need to track the interrupt line state for LINT0/LINT1 pins.
Saved-state change will follow.

Location:
trunk/src/VBox/VMM
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/APICAll.cpp

    r61557 r61581  
    12131213            apicClearVectorInReg(&pXApicPage->tmr, uVector);
    12141214            apicBusBroadcastEoi(pVCpu, uVector);
     1215
     1216            /*
     1217             * Clear the remote IRR bit for level-triggered, fixed mode LINT0 interrupt.
     1218             * The LINT1 pin does not support level-triggered interrupts.
     1219             * See Intel spec. 10.5.1 "Local Vector Table".
     1220             */
     1221            uint32_t const uLvtLint0 = pXApicPage->lvt_lint0.all.u32LvtLint0;
     1222            if (   XAPIC_LVT_GET_REMOTE_IRR(uLvtLint0)
     1223                && XAPIC_LVT_GET_VECTOR(uLvtLint0) == uVector
     1224                && XAPIC_LVT_GET_DELIVERY_MODE(uLvtLint0) == XAPICDELIVERYMODE_FIXED)
     1225            {
     1226                ASMAtomicAndU32((volatile uint32_t *)&pXApicPage->lvt_lint0.all.u32LvtLint0, ~XAPIC_LVT_REMOTE_IRR);
     1227                Log2(("APIC%u: apicSetEoi: Cleared remote-IRR for LINT0. uVector=%#x\n", pVCpu->idCpu, uVector));
     1228            }
     1229
    12151230            Log2(("APIC%u: apicSetEoi: Cleared level triggered interrupt from TMR. uVector=%#x\n", pVCpu->idCpu, uVector));
    12161231        }
     
    22922307                case XAPICDELIVERYMODE_FIXED:
    22932308                {
     2309                    PAPICCPU       pApicCpu = VMCPU_TO_APICCPU(pVCpu);
     2310                    uint8_t const  uVector  = XAPIC_LVT_GET_VECTOR(uLvt);
     2311                    bool           fActive  = RT_BOOL(u8Level & 1);
     2312                    bool volatile *pfActiveLine = u8Pin == 0 ? &pApicCpu->fActiveLint0 : &pApicCpu->fActiveLint1;
     2313                    /** @todo Polarity is busted elsewhere, we need to fix that
     2314                     *        first. See @bugref{8386#c7}. */
     2315#if 0
     2316                    uint8_t const u8Polarity = XAPIC_LVT_GET_POLARITY(uLvt);
     2317                    fActive ^= u8Polarity; */
     2318#endif
     2319                    if (!fActive)
     2320                    {
     2321                        ASMAtomicWriteBool(pfActiveLine, false);
     2322                        break;
     2323                    }
     2324
    22942325                    /* Level-sensitive interrupts are not supported for LINT1. See Intel spec. 10.5.1 "Local Vector Table". */
    22952326                    if (offLvt == XAPIC_OFF_LVT_LINT1)
     
    22992330                              use level-sensitive triggering, regardless if edge-sensitive triggering is selected."
    23002331                              means. */
    2301                     /* fallthru */
     2332
     2333                    bool fSendIntr;
     2334                    if (enmTriggerMode == XAPICTRIGGERMODE_EDGE)
     2335                    {
     2336                        /* Recognize and send the interrupt only on an edge transition. */
     2337                        fSendIntr = ASMAtomicCmpXchgBool(pfActiveLine, true, false);
     2338                    }
     2339                    else
     2340                    {
     2341                        /* For level-triggered interrupts, redundant interrupts are not a problem. */
     2342                        Assert(enmTriggerMode == XAPICTRIGGERMODE_LEVEL);
     2343                        ASMAtomicCmpXchgBool(pfActiveLine, true, false);
     2344
     2345                        /* Only when the remote IRR isn't set, set it and send the interrupt. */
     2346                        if (!(pXApicPage->lvt_lint0.all.u32LvtLint0 & XAPIC_LVT_REMOTE_IRR))
     2347                        {
     2348                            Assert(offLvt == XAPIC_OFF_LVT_LINT0);
     2349                            ASMAtomicOrU32((volatile uint32_t *)&pXApicPage->lvt_lint0.all.u32LvtLint0, XAPIC_LVT_REMOTE_IRR);
     2350                            fSendIntr = true;
     2351                        }
     2352                        else
     2353                            fSendIntr = false;
     2354                    }
     2355
     2356                    if (fSendIntr)
     2357                    {
     2358                        VMCPUSET DestCpuSet;
     2359                        VMCPUSET_EMPTY(&DestCpuSet);
     2360                        VMCPUSET_ADD(&DestCpuSet, pVCpu->idCpu);
     2361                        rcStrict = apicSendIntr(pVCpu->CTX_SUFF(pVM), pVCpu, uVector, enmTriggerMode, enmDeliveryMode,
     2362                                                &DestCpuSet, rcRZ);
     2363                    }
     2364                    break;
    23022365                }
     2366
    23032367                case XAPICDELIVERYMODE_SMI:
    23042368                case XAPICDELIVERYMODE_NMI:
  • trunk/src/VBox/VMM/VMMR3/APIC.cpp

    r61579 r61581  
    217217    RT_BZERO(&pApicCpu->ApicPibLevel, sizeof(APICPIB));
    218218    RT_BZERO(pApicCpu->pvApicPibR3,   sizeof(APICPIB));
     219
     220    /* Clear the interrupt line states for LINT0 and LINT1 pins. */
     221    pApicCpu->fActiveLint0 = false;
     222    pApicCpu->fActiveLint1 = false;
    219223}
    220224
  • trunk/src/VBox/VMM/include/APICInternal.h

    r61573 r61581  
    12861286    /** The APIC PIB for level-sensitive interrupts. */
    12871287    APICPIB                     ApicPibLevel;
     1288    /** Whether the LINT0 interrupt line is active. */
     1289    bool volatile               fActiveLint0;
     1290    /** Whether the LINT1 interrupt line is active. */
     1291    bool volatile               fActiveLint1;
     1292    /** Alignment padding. */
     1293    uint8_t                     auAlignment0[6];
    12881294    /** @} */
    12891295
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