VirtualBox

Changeset 88484 in vbox for trunk/src


Ignore:
Timestamp:
Apr 13, 2021 5:50:44 AM (4 years ago)
Author:
vboxsync
Message:

Intel IOMMU: bugref:9967 Main: Use the same I/O APIC PCI address reservation as we do on AMD, as it keeps things simpler than moving PCI devices/slots around again.
Also for now don't opt out of x2APIC (seems Linux VMs are configured with x2APIC by default, so let's try get things working with x2APIC).

Location:
trunk/src/VBox
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevIommuIntel.h

    r88342 r88484  
    3131#define DMAR_PCI_REVISION_ID                        0x01
    3232
    33 /** Feature/capability flags exposed to the guest (x2APIC Opt Out until we get
    34  *  regular APIC setup working). */
    35 #define DMAR_ACPI_DMAR_FLAGS                        (ACPI_DMAR_F_INTR_REMAP | ACPI_DMAR_F_X2APIC_OPT_OUT)
     33/** Feature/capability flags exposed to the guest. */
     34#define DMAR_ACPI_DMAR_FLAGS                        ACPI_DMAR_F_INTR_REMAP
    3635
    3736/** The MMIO base address of the DMAR unit (taken from real hardware). */
  • trunk/src/VBox/Devices/PC/DevACPI.cpp

    r88342 r88484  
    866866    ACPIDMAR            Dmar;
    867867    ACPIDRHD            Drhd;
    868     /* ACPIDMARDEVSCOPE    DevScope; */
     868    ACPIDMARDEVSCOPE    DevScopeIoApic;
    869869} ACPITBLVTD;
    870870#endif  /* VBOX_WITH_IOMMU_INTEL */
     
    33853385
    33863386    /* DRHD. */
    3387     VtdTable.Drhd.cbLength     = sizeof(ACPIDRHD) /* + sizeof(VtdTable.DevScope) */;
     3387    VtdTable.Drhd.cbLength     = sizeof(ACPIDRHD);
    33883388    VtdTable.Drhd.fFlags       = ACPI_DRHD_F_INCLUDE_PCI_ALL;
    33893389    VtdTable.Drhd.uRegBaseAddr = DMAR_MMIO_BASE_PHYSADDR;
     3390
     3391    /* Device Scopes: I/O APIC. */
     3392    if (pThis->u8UseIOApic)
     3393    {
     3394        uint8_t const uIoApicBus = 0;
     3395        uint8_t const uIoApicDev = RT_HI_U16(pThis->u32SbIoApicPciAddress);
     3396        uint8_t const uIoApicFn  = RT_LO_U16(pThis->u32SbIoApicPciAddress);
     3397
     3398        VtdTable.DevScopeIoApic.uType          = ACPIDMARDEVSCOPE_TYPE_IOAPIC;
     3399        VtdTable.DevScopeIoApic.cbLength       = sizeof(ACPIDMARDEVSCOPE);
     3400        VtdTable.DevScopeIoApic.idEnum         = pThis->cCpus;   /* The I/O APIC ID, see u8IOApicId in acpiR3SetupMadt(). */
     3401        VtdTable.DevScopeIoApic.uStartBusNum   = uIoApicBus;
     3402        VtdTable.DevScopeIoApic.Path.uDevice   = uIoApicDev;
     3403        VtdTable.DevScopeIoApic.Path.uFunction = uIoApicFn;
     3404
     3405        VtdTable.Drhd.cbLength += sizeof(VtdTable.DevScopeIoApic);
     3406    }
    33903407
    33913408    /* Finally, compute checksum. */
     
    35383555#ifdef VBOX_WITH_IOMMU_INTEL
    35393556    if (pThis->fUseIommuIntel)
    3540         iIommu = cAddr++;      /* IOMMU (AMD) */
     3557        iIommu = cAddr++;      /* IOMMU (Intel) */
    35413558#endif
    35423559
     
    35553572    Assert(cAddr < RT_ELEMENTS(aGCPhysXsdt));
    35563573
    3557     cbRsdt += cAddr*sizeof(uint32_t);  /* each entry: 32 bits phys. address. */
    3558     cbXsdt += cAddr*sizeof(uint64_t);  /* each entry: 64 bits phys. address. */
     3574    cbRsdt += cAddr * sizeof(uint32_t);  /* each entry: 32 bits phys. address. */
     3575    cbXsdt += cAddr * sizeof(uint64_t);  /* each entry: 64 bits phys. address. */
    35593576
    35603577    /*
     
    42434260    {
    42444261        /* Query IOMMU AMD address (IOMA). */
    4245         rc = pHlp->pfnCFGMQueryU32Def(pCfg, "IommuPciAddress", &pThis->u32IommuPciAddress, 0);
     4262        rc = pHlp->pfnCFGMQueryU32(pCfg, "IommuPciAddress", &pThis->u32IommuPciAddress);
    42464263        if (RT_FAILURE(rc))
    42474264            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"IommuPciAddress\""));
    42484265
    42494266        /* Query southbridge I/O APIC address (required when an AMD IOMMU is configured). */
    4250         rc = pHlp->pfnCFGMQueryU32Def(pCfg, "SbIoApicPciAddress", &pThis->u32SbIoApicPciAddress, 0);
     4267        rc = pHlp->pfnCFGMQueryU32(pCfg, "SbIoApicPciAddress", &pThis->u32SbIoApicPciAddress);
    42514268        if (RT_FAILURE(rc))
    42524269            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"SbIoApicAddress\""));
     
    42584275            LogRel(("ACPI: Warning! AMD IOMMU assigned the PCI host bridge address.\n"));
    42594276
    4260         /* Warn if the SB IOAPIC is not at the required address if an AMD IOMMU is configured. */
     4277        /* Warn if the IOAPIC is not at the expected address. */
    42614278        if (pThis->u32SbIoApicPciAddress != RT_MAKE_U32(VBOX_PCI_FN_SB_IOAPIC, VBOX_PCI_DEV_SB_IOAPIC))
    42624279        {
    4263             /** @todo Maybe make this a VM startup failure later. */
    4264             LogRel(("ACPI: Warning! Southbridge I/O APIC not at %#x:%#x:%#x when an AMD IOMMU is present.\n",
     4280            LogRel(("ACPI: Southbridge I/O APIC not at %#x:%#x:%#x when an AMD IOMMU is present.\n",
    42654281                    VBOX_PCI_BUS_SB_IOAPIC, VBOX_PCI_DEV_SB_IOAPIC, VBOX_PCI_FN_SB_IOAPIC));
     4282            return PDMDEV_SET_ERROR(pDevIns, VERR_MISMATCH, N_("Configuration error: \"SbIoApicAddress\" mismatch"));
    42664283        }
    42674284    }
     
    42774294    {
    42784295        /* Query IOMMU Intel address. */
    4279         rc = pHlp->pfnCFGMQueryU32Def(pCfg, "IommuPciAddress", &pThis->u32IommuPciAddress, 0);
     4296        rc = pHlp->pfnCFGMQueryU32(pCfg, "IommuPciAddress", &pThis->u32IommuPciAddress);
    42804297        if (RT_FAILURE(rc))
    42814298            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"IommuPciAddress\""));
     4299
     4300        /* Get the reserved I/O APIC PCI address (required when an Intel IOMMU is configured). */
     4301        rc = pHlp->pfnCFGMQueryU32(pCfg, "SbIoApicPciAddress", &pThis->u32SbIoApicPciAddress);
     4302        if (RT_FAILURE(rc))
     4303            return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to read \"SbIoApicAddress\""));
     4304
     4305        /* Warn if the IOAPIC is not at the expected address. */
     4306        if (pThis->u32SbIoApicPciAddress != RT_MAKE_U32(VBOX_PCI_FN_SB_IOAPIC, VBOX_PCI_DEV_SB_IOAPIC))
     4307        {
     4308            LogRel(("ACPI: Southbridge I/O APIC not at %#x:%#x:%#x when an Intel IOMMU is present.\n",
     4309                    VBOX_PCI_BUS_SB_IOAPIC, VBOX_PCI_DEV_SB_IOAPIC, VBOX_PCI_FN_SB_IOAPIC));
     4310            return PDMDEV_SET_ERROR(pDevIns, VERR_MISMATCH, N_("Configuration error: \"SbIoApicAddress\" mismatch"));
     4311        }
    42824312    }
    42834313#endif
  • trunk/src/VBox/Main/src-client/BusAssignmentManager.cpp

    r88333 r88484  
    255255 * Intel IOMMU.
    256256 * The VT-d misc, address remapping, system management device is
    257  * located at BDF 00:5:0 on real hardware so we mimick the same.
    258  * LSI logic remains at 0:20:0.
     257 * located at BDF 0:5:0 on real hardware but we use 0:1:0 since that
     258 * slot isn't used for anything else.
     259 *
     260 * While we could place the I/O APIC anywhere, we keep it consistent
     261 * with the AMD IOMMU and we assign the LSI Logic controller to
     262 * device number 23 (and I/O APIC at device 20).
    259263 */
    260264static const DeviceAssignmentRule g_aIch9IommuIntelRules[] =
    261265{
    262266    /* Intel IOMMU. */
    263     {"iommu-intel",   0,  5,  0, 0},
     267    {"iommu-intel",   0,  1,  0, 0},
     268    /* Intel IOMMU: Reserved for I/O APIC. */
     269    {"sb-ioapic",     0, 20,  0, 0},
    264270
    265271    /* Storage controller */
    266     {"lsilogic",      0, 20,  0, 1},
     272    {"lsilogic",      0, 23,  0, 1},
    267273    { NULL,          -1, -1, -1, 0}
    268274};
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r88343 r88484  
    831831    hrc = pMachine->COMGETTER(ParavirtDebug)(strParavirtDebug.asOutParam());                H();
    832832
     833    BOOL fIOAPIC;
     834    hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC);                                 H();
     835
    833836    ChipsetType_T chipsetType;
    834837    hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType);                                   H();
     
    870873#endif
    871874    }
     875
    872876    if (iommuType == IommuType_Intel)
    873877    {
     
    877881#endif
    878882    }
    879     if (   (iommuType == IommuType_AMD || iommuType == IommuType_Intel)
    880         && chipsetType != ChipsetType_ICH9)
     883
     884    if (   iommuType == IommuType_AMD
     885        || iommuType == IommuType_Intel)
     886    {
     887        if (chipsetType != ChipsetType_ICH9)
    881888            return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
    882889                                N_("IOMMU uses MSIs which requires the ICH9 chipset implementation."));
     890        if (!fIOAPIC)
     891            return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     892                            N_("IOMMU requires an I/O APIC for remapping interrupts."));
     893    }
    883894#else
    884895    IommuType_T const iommuType = IommuType_None;
     
    896907    hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam());                             H();
    897908    LogRel(("Guest OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
    898 
    899     BOOL fIOAPIC;
    900     hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC);                                 H();
    901909
    902910    APICMode_T apicMode;
     
    16071615                InsertConfigNode(pInst,    "Config", &pCfg);
    16081616                hrc = pBusMgr->assignPCIDevice("iommu-intel", pInst);                       H();
     1617
     1618                /*
     1619                 * Reserve a specific PCI address for the I/O APIC when using
     1620                 * an Intel IOMMU. For convenience we use the same address as
     1621                 * we do on AMD, see @bugref{9967#c13}.
     1622                 */
     1623                PCIBusAddress PCIAddr = PCIBusAddress(VBOX_PCI_BUS_SB_IOAPIC, VBOX_PCI_DEV_SB_IOAPIC, VBOX_PCI_FN_SB_IOAPIC);
     1624                hrc = pBusMgr->assignPCIDevice("sb-ioapic", NULL /* pCfg */, PCIAddr, true /*fGuestAddressRequired*/);  H();
    16091625            }
    16101626        }
     
    33843400                    if (pBusMgr->findPCIAddress("sb-ioapic", 0, Address))
    33853401                    {
    3386                         uint32_t u32SbIoapicAddress = (Address.miDevice << 16) | Address.miFn;
     3402                        uint32_t const u32SbIoapicAddress = (Address.miDevice << 16) | Address.miFn;
    33873403                        InsertConfigInteger(pCfg, "SbIoApicPciAddress", u32SbIoapicAddress);
    33883404                    }
    33893405                    else
    3390                         LogRel(("IOMMU: AMD IOMMU is enabled, but southbridge I/O APIC is not assigned a PCI address!\n"));
     3406                        return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     3407                                            N_("AMD IOMMU is enabled, but the I/O APIC is not assigned a PCI address!"));
    33913408                }
    33923409            }
     
    33993416                    InsertConfigInteger(pCfg, "IommuIntelEnabled", true);
    34003417                    InsertConfigInteger(pCfg, "IommuPciAddress", u32IommuAddress);
     3418                    if (pBusMgr->findPCIAddress("sb-ioapic", 0, Address))
     3419                    {
     3420                        uint32_t const u32SbIoapicAddress = (Address.miDevice << 16) | Address.miFn;
     3421                        InsertConfigInteger(pCfg, "SbIoApicPciAddress", u32SbIoapicAddress);
     3422                    }
     3423                    else
     3424                        return VMR3SetError(pUVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
     3425                                            N_("Intel IOMMU is enabled, but the I/O APIC is not assigned a PCI address!"));
    34013426                }
    34023427            }
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