VirtualBox

Changeset 88826 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 3, 2021 11:12:01 AM (4 years ago)
Author:
vboxsync
Message:

DevIoApic: Code-style nit and a todo. We should be able to release the PDM lock here so IOMMU can re-acquire it if needed for a short amount of time.
Afaict, APICBusDeliver doesn't care about PDM lock being held.

File:
1 edited

Legend:

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

    r88822 r88826  
    502502    uint64_t const u64Rte = pThis->au64RedirTable[idxRte];
    503503    if (!IOAPIC_RTE_IS_MASKED(u64Rte))
    504     {
    505         /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */
    506         uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte);
    507         if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL)
     504    { /* likely */ }
     505    else
     506        return;
     507
     508    /* We cannot accept another level-triggered interrupt until remote IRR has been cleared. */
     509    uint8_t const u8TriggerMode = IOAPIC_RTE_GET_TRIGGER_MODE(u64Rte);
     510    if (u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL)
     511    {
     512        uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
     513        if (u8RemoteIrr)
    508514        {
    509             uint8_t const u8RemoteIrr = IOAPIC_RTE_GET_REMOTE_IRR(u64Rte);
    510             if (u8RemoteIrr)
    511             {
    512                 STAM_COUNTER_INC(&pThis->StatSuppressedLevelIntr);
    513                 return;
    514             }
    515         }
    516 
    517         XAPICINTR ApicIntr;
    518         RT_ZERO(ApicIntr);
    519         ApicIntr.u8Vector       = IOAPIC_RTE_GET_VECTOR(u64Rte);
    520         ApicIntr.u8Dest         = IOAPIC_RTE_GET_DEST(u64Rte);
    521         ApicIntr.u8DestMode     = IOAPIC_RTE_GET_DEST_MODE(u64Rte);
    522         ApicIntr.u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
    523         ApicIntr.u8Polarity     = IOAPIC_RTE_GET_POLARITY(u64Rte);
    524         ApicIntr.u8TriggerMode  = u8TriggerMode;
    525         ApicIntr.u8RedirHint    = 0;
    526 
    527 #if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
    528         /*
    529          * The interrupt may need to be remapped (or discarded) if an IOMMU is present.
    530          * For line-based interrupts we must use the southbridge I/O APIC's BDF as
    531          * the origin of the interrupt, see @bugref{9654#c74}.
    532          */
    533         MSIMSG MsiOut;
    534         MSIMSG MsiIn;
    535         RT_ZERO(MsiOut);
    536         RT_ZERO(MsiIn);
    537         ioapicGetMsiFromApicIntr(&ApicIntr, &MsiIn);
    538         int const rcRemap = pThisCC->pIoApicHlp->pfnIommuMsiRemap(pDevIns, VBOX_PCI_BDF_SB_IOAPIC, &MsiIn, &MsiOut);
    539         if (   rcRemap == VERR_IOMMU_NOT_PRESENT
    540             || rcRemap == VERR_IOMMU_CANNOT_CALL_SELF)
    541             MsiOut = MsiIn;
    542         else if (RT_SUCCESS(rcRemap))
    543             STAM_COUNTER_INC(&pThis->StatIommuRemappedIntr);
    544         else
    545         {
    546             STAM_COUNTER_INC(&pThis->StatIommuDiscardedIntr);
     515            STAM_COUNTER_INC(&pThis->StatSuppressedLevelIntr);
    547516            return;
    548517        }
    549 
    550         ioapicGetApicIntrFromMsi(&MsiOut, &ApicIntr);
     518    }
     519
     520    /** @todo We might be able to release the IOAPIC(PDM) lock here and re-acquire it
     521     *        before setting the remote IRR bit below. The APIC and IOMMU should not
     522     *        require the caller to hold the PDM lock. */
     523
     524    XAPICINTR ApicIntr;
     525    RT_ZERO(ApicIntr);
     526    ApicIntr.u8Vector       = IOAPIC_RTE_GET_VECTOR(u64Rte);
     527    ApicIntr.u8Dest         = IOAPIC_RTE_GET_DEST(u64Rte);
     528    ApicIntr.u8DestMode     = IOAPIC_RTE_GET_DEST_MODE(u64Rte);
     529    ApicIntr.u8DeliveryMode = IOAPIC_RTE_GET_DELIVERY_MODE(u64Rte);
     530    ApicIntr.u8Polarity     = IOAPIC_RTE_GET_POLARITY(u64Rte);
     531    ApicIntr.u8TriggerMode  = u8TriggerMode;
     532    //ApicIntr.u8RedirHint    = 0;
     533
     534#if defined(VBOX_WITH_IOMMU_AMD) || defined(VBOX_WITH_IOMMU_INTEL)
     535    /*
     536     * The interrupt may need to be remapped (or discarded) if an IOMMU is present.
     537     * For line-based interrupts we must use the southbridge I/O APIC's BDF as
     538     * the origin of the interrupt, see @bugref{9654#c74}.
     539     */
     540    MSIMSG MsiOut;
     541    MSIMSG MsiIn;
     542    RT_ZERO(MsiOut);
     543    RT_ZERO(MsiIn);
     544    ioapicGetMsiFromApicIntr(&ApicIntr, &MsiIn);
     545    int const rcRemap = pThisCC->pIoApicHlp->pfnIommuMsiRemap(pDevIns, VBOX_PCI_BDF_SB_IOAPIC, &MsiIn, &MsiOut);
     546    if (   rcRemap == VERR_IOMMU_NOT_PRESENT
     547        || rcRemap == VERR_IOMMU_CANNOT_CALL_SELF)
     548        MsiOut = MsiIn;
     549    else if (RT_SUCCESS(rcRemap))
     550        STAM_COUNTER_INC(&pThis->StatIommuRemappedIntr);
     551    else
     552    {
     553        STAM_COUNTER_INC(&pThis->StatIommuDiscardedIntr);
     554        return;
     555    }
     556
     557    ioapicGetApicIntrFromMsi(&MsiOut, &ApicIntr);
    551558
    552559# ifdef RT_STRICT
    553         if (RT_SUCCESS(rcRemap))
    554         {
    555             Assert(ApicIntr.u8Polarity == IOAPIC_RTE_GET_POLARITY(u64Rte)); /* Ensure polarity hasn't changed. */
    556             Assert(ApicIntr.u8TriggerMode == u8TriggerMode);                /* Ensure trigger mode hasn't changed. */
    557         }
     560    if (RT_SUCCESS(rcRemap))
     561    {
     562        Assert(ApicIntr.u8Polarity == IOAPIC_RTE_GET_POLARITY(u64Rte)); /* Ensure polarity hasn't changed. */
     563        Assert(ApicIntr.u8TriggerMode == u8TriggerMode);                /* Ensure trigger mode hasn't changed. */
     564    }
    558565# endif
    559566#endif
    560567
    561         uint32_t const u32TagSrc = pThis->au32TagSrc[idxRte];
    562         Log2(("IOAPIC: Signaling %s-triggered interrupt. Dest=%#x DestMode=%s Vector=%#x (%u)\n",
    563               ApicIntr.u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE ? "edge" : "level", ApicIntr.u8Dest,
    564               ApicIntr.u8DestMode == IOAPIC_RTE_DEST_MODE_PHYSICAL ? "physical" : "logical",
    565               ApicIntr.u8Vector, ApicIntr.u8Vector));
    566 
    567         /*
    568          * Deliver to the local APIC via the system/3-wire-APIC bus.
    569          */
    570         int rc = pThisCC->pIoApicHlp->pfnApicBusDeliver(pDevIns,
    571                                                         ApicIntr.u8Dest,
    572                                                         ApicIntr.u8DestMode,
    573                                                         ApicIntr.u8DeliveryMode,
    574                                                         ApicIntr.u8Vector,
    575                                                         ApicIntr.u8Polarity,
    576                                                         ApicIntr.u8TriggerMode,
    577                                                         u32TagSrc);
    578         /* Can't reschedule to R3. */
    579         Assert(rc == VINF_SUCCESS || rc == VERR_APIC_INTR_DISCARDED);
     568    uint32_t const u32TagSrc = pThis->au32TagSrc[idxRte];
     569    Log2(("IOAPIC: Signaling %s-triggered interrupt. Dest=%#x DestMode=%s Vector=%#x (%u)\n",
     570          ApicIntr.u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_EDGE ? "edge" : "level", ApicIntr.u8Dest,
     571          ApicIntr.u8DestMode == IOAPIC_RTE_DEST_MODE_PHYSICAL ? "physical" : "logical",
     572          ApicIntr.u8Vector, ApicIntr.u8Vector));
     573
     574    /*
     575     * Deliver to the local APIC via the system/3-wire-APIC bus.
     576     */
     577    int rc = pThisCC->pIoApicHlp->pfnApicBusDeliver(pDevIns,
     578                                                    ApicIntr.u8Dest,
     579                                                    ApicIntr.u8DestMode,
     580                                                    ApicIntr.u8DeliveryMode,
     581                                                    ApicIntr.u8Vector,
     582                                                    ApicIntr.u8Polarity,
     583                                                    ApicIntr.u8TriggerMode,
     584                                                    u32TagSrc);
     585    /* Can't reschedule to R3. */
     586    Assert(rc == VINF_SUCCESS || rc == VERR_APIC_INTR_DISCARDED);
    580587#ifdef DEBUG_ramshankar
    581         if (rc == VERR_APIC_INTR_DISCARDED)
    582             AssertMsgFailed(("APIC: Interrupt discarded u8Vector=%#x (%u) u64Rte=%#RX64\n", u8Vector, u8Vector, u64Rte));
     588    if (rc == VERR_APIC_INTR_DISCARDED)
     589        AssertMsgFailed(("APIC: Interrupt discarded u8Vector=%#x (%u) u64Rte=%#RX64\n", u8Vector, u8Vector, u64Rte));
    583590#endif
    584591
    585         /*
    586          * For level-triggered interrupts, we set the remote IRR bit to indicate
    587          * the local APIC has accepted the interrupt.
    588          *
    589          * For edge-triggered interrupts, we should not clear the IRR bit as it
    590          * should remain intact to reflect the state of the interrupt line.
    591          * The device will explicitly transition to inactive state via the
    592          * ioapicSetIrq() callback.
    593          */
    594         if (   u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL
    595             && rc == VINF_SUCCESS)
    596         {
    597             Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
    598             pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR;
    599             STAM_COUNTER_INC(&pThis->StatLevelIrqSent);
    600         }
     592    /*
     593     * For level-triggered interrupts, we set the remote IRR bit to indicate
     594     * the local APIC has accepted the interrupt.
     595     *
     596     * For edge-triggered interrupts, we should not clear the IRR bit as it
     597     * should remain intact to reflect the state of the interrupt line.
     598     * The device will explicitly transition to inactive state via the
     599     * ioapicSetIrq() callback.
     600     */
     601    if (   u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL
     602        && rc == VINF_SUCCESS)
     603    {
     604        Assert(u8TriggerMode == IOAPIC_RTE_TRIGGER_MODE_LEVEL);
     605        pThis->au64RedirTable[idxRte] |= IOAPIC_RTE_REMOTE_IRR;
     606        STAM_COUNTER_INC(&pThis->StatLevelIrqSent);
    601607    }
    602608}
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