VirtualBox

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.

File:
1 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}
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