VirtualBox

Changeset 84677 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 4, 2020 1:12:06 PM (5 years ago)
Author:
vboxsync
Message:

AMD IOMMU: bugref:9654 Add I/O APIC PDM helper for talking to the IOMMU for remapping MSIs and related bits.

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuAmd.cpp

    r84651 r84677  
    45484548 * @param   uDevId      The device ID.
    45494549 * @param   pDte        The device table entry.
    4550  * @param   GCPhysIn    The source MSI address.
    4551  * @param   uDataIn     The source MSI data.
    45524550 * @param   enmOp       The IOMMU operation being performed.
    4553  * @param   pGCPhysOut  Where to store the remapped MSI address.
    4554  * @param   puDataOut   Where to store the remapped MSI data.
     4551 * @param   pMsiIn      The source MSI.
     4552 * @param   pMsiOut     Where to store the remapped MSI.
    45554553 *
    45564554 * @thread  Any.
    45574555 */
    4558 static int iommuAmdRemapIntr(PPDMDEVINS pDevIns, uint16_t uDevId, PCDTE_T pDte, RTGCPHYS GCPhysIn, uint32_t uDataIn,
    4559                              IOMMUOP enmOp, PRTGCPHYS pGCPhysOut, uint32_t *puDataOut)
    4560 {
    4561     /** @todo Replace GCPhys[Out|In], uData[Out|In] with MSIMSG. */
     4556static int iommuAmdRemapIntr(PPDMDEVINS pDevIns, uint16_t uDevId, PCDTE_T pDte, IOMMUOP enmOp, PCMSIMSG pMsiIn,
     4557                             PMSIMSG pMsiOut)
     4558{
    45624559    Assert(pDte->n.u2IntrCtrl == IOMMU_INTR_CTRL_REMAP);
    45634560
    45644561    IRTE_T Irte;
    4565     int rc = iommuAmdReadIrte(pDevIns, uDevId, pDte, GCPhysIn, uDataIn, enmOp, &Irte);
     4562    int rc = iommuAmdReadIrte(pDevIns, uDevId, pDte, pMsiIn->Addr.u64, pMsiIn->Data.u32, enmOp, &Irte);
    45664563    if (RT_SUCCESS(rc))
    45674564    {
     
    45724569                if (Irte.n.u3IntrType < VBOX_MSI_DELIVERY_MODE_LOWEST_PRIO)
    45734570                {
    4574                     MSIADDR MsiAddrIn;
    4575                     MsiAddrIn.u64 = GCPhysIn;
    4576 
    4577                     MSIDATA MsiDataIn;
    4578                     MsiDataIn.u32 = uDataIn;
    4579 
    4580                     PMSIADDR pMsiAddrOut = (PMSIADDR)pGCPhysOut;
    4581                     PMSIDATA pMsiDataOut = (PMSIDATA)puDataOut;
    4582 
    45834571                    /* Preserve all bits from the source MSI address that don't map 1:1 from the IRTE. */
    4584                     pMsiAddrOut->u64 = GCPhysIn;
    4585                     pMsiAddrOut->n.u1DestMode = Irte.n.u1DestMode;
    4586                     pMsiAddrOut->n.u8DestId   = Irte.n.u8Dest;
     4572                    pMsiOut->Addr.u64 = pMsiIn->Addr.u64;
     4573                    pMsiOut->Addr.n.u1DestMode = Irte.n.u1DestMode;
     4574                    pMsiOut->Addr.n.u8DestId   = Irte.n.u8Dest;
    45874575
    45884576                    /* Preserve all bits from the source MSI data that don't map 1:1 from the IRTE. */
    4589                     pMsiDataOut->u32 = uDataIn;
    4590                     pMsiDataOut->n.u8Vector       = Irte.n.u8Vector;
    4591                     pMsiDataOut->n.u3DeliveryMode = Irte.n.u3IntrType;
     4577                    pMsiOut->Data.u32 = pMsiIn->Data.u32;
     4578                    pMsiOut->Data.n.u8Vector       = Irte.n.u8Vector;
     4579                    pMsiOut->Data.n.u3DeliveryMode = Irte.n.u3IntrType;
    45924580
    45934581                    return VINF_SUCCESS;
     
    45964584                Log((IOMMU_LOG_PFX ": Interrupt type (%#x) invalid -> IOPF", Irte.n.u3IntrType));
    45974585                EVT_IO_PAGE_FAULT_T EvtIoPageFault;
    4598                 iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, GCPhysIn, Irte.n.u1RemapEnable, true /* fRsvdNotZero */,
    4599                                              false /* fPermDenied */, enmOp, &EvtIoPageFault);
     4586                iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, pMsiIn->Addr.u64, Irte.n.u1RemapEnable,
     4587                                             true /* fRsvdNotZero */, false /* fPermDenied */, enmOp, &EvtIoPageFault);
    46004588                iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, &Irte, enmOp, &EvtIoPageFault, kIoPageFaultType_IrteRsvdIntType);
    46014589                return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     
    46044592            Log((IOMMU_LOG_PFX ": Guest mode not supported -> IOPF"));
    46054593            EVT_IO_PAGE_FAULT_T EvtIoPageFault;
    4606             iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, GCPhysIn, Irte.n.u1RemapEnable, true /* fRsvdNotZero */,
    4607                                          false /* fPermDenied */, enmOp, &EvtIoPageFault);
     4594            iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, pMsiIn->Addr.u64, Irte.n.u1RemapEnable,
     4595                                         true /* fRsvdNotZero */, false /* fPermDenied */, enmOp, &EvtIoPageFault);
    46084596            iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, &Irte, enmOp, &EvtIoPageFault, kIoPageFaultType_IrteRsvdNotZero);
    46094597            return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     
    46124600        Log((IOMMU_LOG_PFX ": Remapping disabled -> IOPF"));
    46134601        EVT_IO_PAGE_FAULT_T EvtIoPageFault;
    4614         iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, GCPhysIn, Irte.n.u1RemapEnable, false /* fRsvdNotZero */,
    4615                                      false /* fPermDenied */, enmOp, &EvtIoPageFault);
     4602        iommuAmdInitIoPageFaultEvent(uDevId, pDte->n.u16DomainId, pMsiIn->Addr.u64, Irte.n.u1RemapEnable,
     4603                                     false /* fRsvdNotZero */, false /* fPermDenied */, enmOp, &EvtIoPageFault);
    46164604        iommuAmdRaiseIoPageFaultEvent(pDevIns, pDte, &Irte, enmOp, &EvtIoPageFault, kIoPageFaultType_IrteRemapEn);
    46174605        return VERR_IOMMU_ADDR_TRANSLATION_FAILED;
     
    46284616 * @param   pDevIns     The IOMMU instance data.
    46294617 * @param   uDevId      The device ID.
    4630  * @param   GCPhysIn    The source MSI address.
    4631  * @param   uDataIn     The source MSI data.
    46324618 * @param   enmOp       The IOMMU operation being performed.
    4633  * @param   pGCPhysOut  Where to store the remapped MSI address.
    4634  * @param   puDataOut   Where to store the remapped MSI data.
     4619 * @param   pMsiIn      The source MSI.
     4620 * @param   pMsiOut     Where to store the remapped MSI.
    46354621 *
    46364622 * @thread  Any.
    46374623 */
    4638 static int iommuAmdLookupIntrTable(PPDMDEVINS pDevIns, uint16_t uDevId, RTGCPHYS GCPhysIn, uint32_t uDataIn, IOMMUOP enmOp,
    4639                                    PRTGCPHYS pGCPhysOut, uint32_t *puDataOut)
     4624static int iommuAmdLookupIntrTable(PPDMDEVINS pDevIns, uint16_t uDevId, IOMMUOP enmOp, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
    46404625{
    46414626    /* Read the device table entry from memory. */
     
    46584643                     fRsvd1));
    46594644                EVT_ILLEGAL_DTE_T Event;
    4660                 iommuAmdInitIllegalDteEvent(uDevId, GCPhysIn, true /* fRsvdNotZero */, enmOp, &Event);
     4645                iommuAmdInitIllegalDteEvent(uDevId, pMsiIn->Addr.u64, true /* fRsvdNotZero */, enmOp, &Event);
    46614646                iommuAmdRaiseIllegalDteEvent(pDevIns, enmOp, &Event, kIllegalDteType_RsvdNotZero);
    46624647                return VERR_IOMMU_INTR_REMAP_FAILED;
     
    46804665             * See Intel spec. 10.11.1 "Message Address Register Format".
    46814666             */
    4682             MSIADDR MsiAddrIn;
    4683             MsiAddrIn.u64 = GCPhysIn;
    4684             if ((MsiAddrIn.u64 & VBOX_MSI_ADDR_ADDR_MASK) == VBOX_MSI_ADDR_BASE)
     4667            if ((pMsiIn->Addr.u64 & VBOX_MSI_ADDR_ADDR_MASK) == VBOX_MSI_ADDR_BASE)
    46854668            {
    4686                 MSIDATA MsiDataIn;
    4687                 MsiDataIn.u32 = uDataIn;
    4688 
    46894669                /*
    46904670                 * The IOMMU remaps fixed and arbitrated interrupts using the IRTE.
    46914671                 * See AMD IOMMU spec. "2.2.5.1 Interrupt Remapping Tables, Guest Virtual APIC Not Enabled".
    46924672                 */
    4693                 uint8_t const u8DeliveryMode = MsiDataIn.n.u3DeliveryMode;
     4673                uint8_t const u8DeliveryMode = pMsiIn->Data.n.u3DeliveryMode;
    46944674                bool fPassThru = false;
    46954675                switch (u8DeliveryMode)
     
    47294709                                NOREF(pThis);
    47304710
    4731                                 return iommuAmdRemapIntr(pDevIns, uDevId, &Dte, GCPhysIn, uDataIn, enmOp, pGCPhysOut, puDataOut);
     4711                                return iommuAmdRemapIntr(pDevIns, uDevId, &Dte, enmOp, pMsiIn, pMsiOut);
    47324712                            }
    47334713
    47344714                            Log((IOMMU_LOG_PFX ": Invalid interrupt table length %#x -> Illegal DTE\n", uIntTabLen));
    47354715                            EVT_ILLEGAL_DTE_T Event;
    4736                             iommuAmdInitIllegalDteEvent(uDevId, GCPhysIn, false /* fRsvdNotZero */, enmOp, &Event);
     4716                            iommuAmdInitIllegalDteEvent(uDevId, pMsiIn->Addr.u64, false /* fRsvdNotZero */, enmOp, &Event);
    47374717                            iommuAmdRaiseIllegalDteEvent(pDevIns, enmOp, &Event, kIllegalDteType_RsvdIntTabLen);
    47384718                            return VERR_IOMMU_INTR_REMAP_FAILED;
     
    47444724                        Log((IOMMU_LOG_PFX ":IntCtl mode invalid %#x -> Illegal DTE", uIntrCtrl));
    47454725                        EVT_ILLEGAL_DTE_T Event;
    4746                         iommuAmdInitIllegalDteEvent(uDevId, GCPhysIn, true /* fRsvdNotZero */, enmOp, &Event);
     4726                        iommuAmdInitIllegalDteEvent(uDevId, pMsiIn->Addr.u64, true /* fRsvdNotZero */, enmOp, &Event);
    47474727                        iommuAmdRaiseIllegalDteEvent(pDevIns, enmOp, &Event, kIllegalDteType_RsvdIntCtl);
    47484728                        return VERR_IOMMU_INTR_REMAP_FAILED;
     
    47644744                if (fPassThru)
    47654745                {
    4766                     *pGCPhysOut = GCPhysIn;
    4767                     *puDataOut  = uDataIn;
     4746                    *pMsiOut = *pMsiIn;
    47684747                    return VINF_SUCCESS;
    47694748                }
     
    47744753            else
    47754754            {
    4776                 Log((IOMMU_LOG_PFX ":MSI address region invalid %#RX64.", MsiAddrIn.u64));
     4755                Log((IOMMU_LOG_PFX ":MSI address region invalid %#RX64.", pMsiIn->Addr.u64));
    47774756                return VERR_IOMMU_INTR_REMAP_FAILED;
    47784757            }
     
    47814760        {
    47824761            /** @todo IOMMU: Add to interrupt remapping cache. */
    4783             *pGCPhysOut = GCPhysIn;
    4784             *puDataOut  = uDataIn;
     4762            *pMsiOut = *pMsiIn;
    47854763            return VINF_SUCCESS;
    47864764        }
     
    47984776 * @param   pDevIns     The IOMMU device instance.
    47994777 * @param   uDevId      The device ID (bus, device, function).
    4800  * @param   GCPhysIn    The source MSI address.
    4801  * @param   uDataIn     The source MSI data.
    4802  * @param   pGCPhysOut  Where to store the remapped MSI address.
    4803  * @param   puDataOut   Where to store the remapped MSI data.
    4804  */
    4805 static int iommuAmdDeviceMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, RTGCPHYS GCPhysIn, uint32_t uDataIn,
    4806                                   PRTGCPHYS pGCPhysOut, uint32_t *puDataOut)
     4778 * @param   pMsiIn      The source MSI.
     4779 * @param   pMsiOut     Where to store the remapped MSI.
     4780 */
     4781static int iommuAmdDeviceMsiRemap(PPDMDEVINS pDevIns, uint16_t uDevId, PCMSIMSG pMsiIn, PMSIMSG pMsiOut)
    48074782{
    48084783    /* Validate. */
    48094784    Assert(pDevIns);
    4810     Assert(pGCPhysOut);
    4811     Assert(puDataOut);
    4812 
    4813     /* Remove later. */
    4814     RT_NOREF(uDevId, GCPhysIn, uDataIn, pGCPhysOut, puDataOut);
     4785    Assert(pMsiIn);
     4786    Assert(pMsiOut);
    48154787
    48164788    PIOMMU pThis = PDMDEVINS_2_DATA(pDevIns, PIOMMU);
     
    48224794        /** @todo Cache? */
    48234795
    4824         return iommuAmdLookupIntrTable(pDevIns, uDevId, GCPhysIn, uDataIn, IOMMUOP_INTR_REQ, pGCPhysOut, puDataOut);
    4825     }
    4826 
    4827     *pGCPhysOut = GCPhysIn;
    4828     *puDataOut  = uDataIn;
     4796        return iommuAmdLookupIntrTable(pDevIns, uDevId, IOMMUOP_INTR_REQ, pMsiIn, pMsiOut);
     4797    }
     4798
     4799    *pMsiOut = *pMsiIn;
    48294800    return VINF_SUCCESS;
    48304801}
  • trunk/src/VBox/Devices/PC/DevIoApic.cpp

    r84666 r84677  
    432432     * See Intel spec. 10.11.2 "Message Data Register Format".
    433433     */
    434     pIntr->u8Dest         = pMsi->MsiAddr.n.u8DestId;
    435     pIntr->u8DestMode     = pMsi->MsiAddr.n.u1DestMode;
    436     pIntr->u8RedirHint    = pMsi->MsiAddr.n.u1RedirHint;
    437 
    438     pIntr->u8Vector       = pMsi->MsiData.n.u8Vector;
    439     pIntr->u8TriggerMode  = pMsi->MsiData.n.u1TriggerMode;
    440     pIntr->u8DeliveryMode = pMsi->MsiData.n.u3DeliveryMode;
     434    pIntr->u8Dest         = pMsi->Addr.n.u8DestId;
     435    pIntr->u8DestMode     = pMsi->Addr.n.u1DestMode;
     436    pIntr->u8RedirHint    = pMsi->Addr.n.u1RedirHint;
     437
     438    pIntr->u8Vector       = pMsi->Data.n.u8Vector;
     439    pIntr->u8TriggerMode  = pMsi->Data.n.u1TriggerMode;
     440    pIntr->u8DeliveryMode = pMsi->Data.n.u3DeliveryMode;
    441441}
    442442
     
    450450DECLINLINE(void) ioapicGetMsiFromApicIntr(PCXAPICINTR pIntr, PMSIMSG pMsi)
    451451{
    452     pMsi->MsiAddr.n.u12Addr        = VBOX_MSI_ADDR_BASE >> VBOX_MSI_ADDR_SHIFT;
    453     pMsi->MsiAddr.n.u8DestId       = pIntr->u8Dest;
    454     pMsi->MsiAddr.n.u1RedirHint    = pIntr->u8RedirHint;
    455     pMsi->MsiAddr.n.u1DestMode     = pIntr->u8DestMode;
    456 
    457     pMsi->MsiData.n.u8Vector       = pIntr->u8Vector;
    458     pMsi->MsiData.n.u3DeliveryMode = pIntr->u8DeliveryMode;
    459     pMsi->MsiData.n.u1TriggerMode  = pIntr->u8TriggerMode;
    460 
    461     /* pMsi->MsiData.n.u1Level     = ??? */
     452    pMsi->Addr.n.u12Addr        = VBOX_MSI_ADDR_BASE >> VBOX_MSI_ADDR_SHIFT;
     453    pMsi->Addr.n.u8DestId       = pIntr->u8Dest;
     454    pMsi->Addr.n.u1RedirHint    = pIntr->u8RedirHint;
     455    pMsi->Addr.n.u1DestMode     = pIntr->u8DestMode;
     456
     457    pMsi->Data.n.u8Vector       = pIntr->u8Vector;
     458    pMsi->Data.n.u3DeliveryMode = pIntr->u8DeliveryMode;
     459    pMsi->Data.n.u1TriggerMode  = pIntr->u8TriggerMode;
     460
     461    /* pMsi->Data.n.u1Level     = ??? */
    462462    /** @todo r=ramshankar: Level triggered MSIs don't make much sense though
    463463     *        possible in theory? Maybe document this more explicitly... */
     
    855855    LogFlow(("IOAPIC: ioapicSendMsi: GCPhys=%#RGp uValue=%#RX32\n", GCPhys, uValue));
    856856
    857     MSIMSG MsiMsg;
    858     MsiMsg.MsiAddr.u64 = GCPhys;
    859     MsiMsg.MsiData.u32 = uValue;
     857    MSIMSG Msi;
     858    Msi.Addr.u64 = GCPhys;
     859    Msi.Data.u32 = uValue;
    860860
    861861    XAPICINTR ApicIntr;
    862862    RT_ZERO(ApicIntr);
    863     ioapicGetApicIntrFromMsi(&MsiMsg, &ApicIntr);
     863    ioapicGetApicIntrFromMsi(&Msi, &ApicIntr);
    864864
    865865    /*
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