# Commit 992fdf6f46252a459c6b1b8d971b2c71f01460f8 # Date 2013-02-22 11:56:54 +0100 # Author Jan Beulich # Committer Jan Beulich honor ACPI v4 FADT flags - force use of physical APIC mode if indicated so (as we don't support xAPIC cluster mode, the respective flag is taken to force physical mode too) - don't use MSI if indicated so (implies no IOMMU) Both can be overridden on the command line, for the MSI case this at once adds a new command line option allowing to turn off PCI MSI (IOMMU and HPET are unaffected by this). Signed-off-by: Jan Beulich Acked-by: Keir Fraser --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -602,6 +602,13 @@ limit is ignored by Xen. Specify if the MMConfig space should be enabled. +### msi +> `= ` + +> Default: `true` + +Force Xen to (not) use PCI-MSI, even if ACPI FADT says otherwise. + ### nmi > `= ignore | dom0 | fatal` --- a/xen/arch/x86/genapic/bigsmp.c +++ b/xen/arch/x86/genapic/bigsmp.c @@ -40,7 +40,14 @@ static struct dmi_system_id __initdata b static __init int probe_bigsmp(void) { - if (!def_to_bigsmp) + /* + * We don't implement cluster mode, so force use of + * physical mode in both cases. + */ + if (acpi_gbl_FADT.flags & + (ACPI_FADT_APIC_CLUSTER | ACPI_FADT_APIC_PHYSICAL)) + def_to_bigsmp = 1; + else if (!def_to_bigsmp) dmi_check_system(bigsmp_dmi_table); return def_to_bigsmp; } --- a/xen/arch/x86/genapic/x2apic.c +++ b/xen/arch/x86/genapic/x2apic.c @@ -29,9 +29,6 @@ #include #include -static bool_t __initdata x2apic_phys; /* By default we use logical cluster mode. */ -boolean_param("x2apic_phys", x2apic_phys); - static void init_apic_ldr_x2apic_phys(void) { } @@ -121,8 +118,14 @@ static const struct genapic apic_x2apic_ .send_IPI_self = send_IPI_self_x2apic }; +static s8 __initdata x2apic_phys = -1; /* By default we use logical cluster mode. */ +boolean_param("x2apic_phys", x2apic_phys); + const struct genapic *__init apic_x2apic_probe(void) { + if ( x2apic_phys < 0 ) + x2apic_phys = !!(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL); + return x2apic_phys ? &apic_x2apic_phys : &apic_x2apic_cluster; } --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -31,6 +31,9 @@ #include #include +static s8 __read_mostly use_msi = -1; +boolean_param("msi", use_msi); + /* bitmap indicate which fixed map is free */ DEFINE_SPINLOCK(msix_fixmap_lock); DECLARE_BITMAP(msix_fixmap_pages, FIX_MSIX_MAX_PAGES); @@ -958,6 +961,9 @@ int pci_enable_msi(struct msi_info *msi, { ASSERT(spin_is_locked(&pcidevs_lock)); + if ( !use_msi ) + return -EPERM; + return msi->table_base ? __pci_enable_msix(msi, desc) : __pci_enable_msi(msi, desc); } @@ -1003,7 +1009,10 @@ int pci_restore_msi_state(struct pci_dev ASSERT(spin_is_locked(&pcidevs_lock)); - if (!pdev) + if ( !use_msi ) + return -EOPNOTSUPP; + + if ( !pdev ) return -EINVAL; ret = xsm_resource_setup_pci((pdev->seg << 16) | (pdev->bus << 8) | pdev->devfn); @@ -1062,7 +1071,7 @@ unsigned int pci_msix_get_table_len(stru func = PCI_FUNC(pdev->devfn); pos = pci_find_cap_offset(seg, bus, slot, func, PCI_CAP_ID_MSIX); - if ( !pos ) + if ( !pos || !use_msi ) return 0; control = pci_conf_read16(seg, bus, slot, func, msix_control_reg(pos)); @@ -1135,6 +1144,9 @@ static struct keyhandler dump_msi_keyhan static int __init msi_setup_keyhandler(void) { + if ( use_msi < 0 ) + use_msi = !(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI); + register_keyhandler('M', &dump_msi_keyhandler); return 0; } --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -1066,5 +1066,8 @@ int __init amd_iommu_get_ivrs_dev_entrie int __init amd_iommu_update_ivrs_mapping_acpi(void) { + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) + return -EPERM; + return acpi_table_parse(ACPI_SIG_IVRS, parse_ivrs_table); } --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -2119,6 +2119,12 @@ int __init intel_vtd_setup(void) if ( list_empty(&acpi_drhd_units) ) return -ENODEV; + if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) ) + { + ret = -EPERM; + goto error; + } + platform_quirks_init(); /* We enable the following features only if they are supported by all VT-d