]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/xen.git/commitdiff
[VTD] check BIOS settings before enabling interrupt remapping or x2apic
authorAllen Kay <allen.m.kay@intel.com>
Sat, 2 Apr 2011 14:49:25 +0000 (15:49 +0100)
committerAllen Kay <allen.m.kay@intel.com>
Sat, 2 Apr 2011 14:49:25 +0000 (15:49 +0100)
Check flags field in ACPI DMAR structure before enabling interrupt
remapping or x2apic.  This allows platform vendors to disable
interrupt remapping or x2apic features if on board BIOS does not
support them.

Signed-off-by: Allen Kay <allen.m.kay@intel.com>
xen/arch/x86/apic.c
xen/drivers/passthrough/vtd/dmar.c
xen/drivers/passthrough/vtd/extern.h
xen/drivers/passthrough/vtd/intremap.c
xen/drivers/passthrough/vtd/iommu.c
xen/drivers/passthrough/vtd/iommu.h
xen/include/xen/iommu.h

index 64d0c88c5bb3ef4f0c9caadfdef0c913dbf178c5..cfdb13abf6e3c5aa6617b7335bb97be10cddb0b8 100644 (file)
@@ -516,7 +516,7 @@ static void resume_x2apic(void)
     mask_8259A();
     mask_IO_APIC_setup(ioapic_entries);
 
-    iommu_enable_IR();
+    iommu_enable_x2apic_IR();
     __enable_x2apic();
 
     restore_IO_APIC_setup(ioapic_entries);
@@ -735,7 +735,7 @@ int lapic_suspend(void)
 
     local_irq_save(flags);
     disable_local_APIC();
-    iommu_disable_IR();
+    iommu_disable_x2apic_IR();
     local_irq_restore(flags);
     return 0;
 }
@@ -958,7 +958,7 @@ void __init x2apic_bsp_setup(void)
     mask_8259A();
     mask_IO_APIC_setup(ioapic_entries);
 
-    if ( iommu_enable_IR() )
+    if ( iommu_enable_x2apic_IR() )
     {
         if ( x2apic_enabled )
             panic("Interrupt remapping could not be enabled while "
index dfaf6804fa9d547197409c4b83a8eea2ebb741cd..aadbe1b058611420272521343e12bbb3758c5491 100644 (file)
@@ -47,6 +47,7 @@ static LIST_HEAD_READ_MOSTLY(acpi_atsr_units);
 static LIST_HEAD_READ_MOSTLY(acpi_rhsa_units);
 
 static struct acpi_table_header *__read_mostly dmar_table;
+static int __read_mostly dmar_flags;
 static u64 __read_mostly igd_drhd_address;
 
 static void __init dmar_scope_add_buses(struct dmar_scope *scope, u16 sec_bus,
@@ -761,7 +762,11 @@ out:
 
 int __init acpi_dmar_init(void)
 {
+    struct acpi_table_dmar *dmar;
+
     acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_table);
+    dmar = (struct acpi_table_dmar *) dmar_table;
+    dmar_flags = dmar->flags;
 
     return parse_dmar_table(acpi_parse_dmar);
 }
@@ -781,3 +786,22 @@ void acpi_dmar_zap(void)
     dmar_table->signature[0] = 'X';
     dmar_table->checksum -= 'X'-'D';
 }
+
+int __init platform_supports_intremap(void)
+{
+    unsigned int flags = 0;
+
+    flags = DMAR_INTR_REMAP;
+    return ((dmar_flags & flags) == DMAR_INTR_REMAP);
+}
+
+int __init platform_supports_x2apic(void)
+{
+    unsigned int flags = 0;
+
+    if (!cpu_has_x2apic)
+        return 0;
+
+    flags = DMAR_INTR_REMAP | DMAR_X2APIC_OPT_OUT;
+    return ((dmar_flags & flags) == DMAR_INTR_REMAP);
+}
index ea80fccf2ab5a83fd327bd516ab43527db66796b..a9c3f1c33920dc5b862c4bc97170f00881c5b446 100644 (file)
@@ -119,5 +119,7 @@ void vtd_ops_preamble_quirk(struct iommu* iommu);
 void vtd_ops_postamble_quirk(struct iommu* iommu);
 void me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map);
 void pci_vtd_quirk(struct pci_dev *pdev);
+int __init platform_supports_intremap(void);
+int __init platform_supports_x2apic(void);
 
 #endif // _VTD_EXTERN_H_
index 7e194a49272e6c8bb56492da387af0489d98be5d..09af71f8f3d531d1971f2ae723067590dcf81521 100644 (file)
@@ -735,6 +735,13 @@ int enable_intremap(struct iommu *iommu, int eim)
 
     ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap);
 
+    if ( !platform_supports_intremap() )
+    {
+        dprintk(XENLOG_ERR VTDPREFIX,
+                "Platform firmware does not support interrupt remapping\n");
+        return -EINVAL;
+    }
+
     ir_ctrl = iommu_ir_ctrl(iommu);
     sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
 
@@ -821,10 +828,10 @@ out:
 }
 
 /*
- * This function is used to enable Interrutp remapping when
+ * This function is used to enable Interrupt remapping when
  * enable x2apic
  */
-int iommu_enable_IR(void)
+int iommu_enable_x2apic_IR(void)
 {
     struct acpi_drhd_unit *drhd;
     struct iommu *iommu;
@@ -832,6 +839,9 @@ int iommu_enable_IR(void)
     if ( !iommu_supports_eim() )
         return -1;
 
+    if ( !platform_supports_x2apic() )
+        return -1;
+
     for_each_drhd_unit ( drhd )
     {
         struct qi_ctrl *qi_ctrl = NULL;
@@ -881,7 +891,7 @@ int iommu_enable_IR(void)
  * This function is used to disable Interrutp remapping when
  * suspend local apic
  */
-void iommu_disable_IR(void)
+void iommu_disable_x2apic_IR(void)
 {
     struct acpi_drhd_unit *drhd;
 
index b69d5e3cc0ec33e826bf8a31bf2c2791548aa5e5..52d15859879e26ab0501bb5f419930965d9c0fc3 100644 (file)
@@ -2014,7 +2014,7 @@ static int init_vtd_hw(void)
             if ( enable_intremap(iommu, 0) != 0 )
             {
                 dprintk(XENLOG_WARNING VTDPREFIX,
-                        "Failed to enable Interrupt Remapping!\n");
+                        "Interrupt Remapping not enabled\n");
                 break;
             }
         }
index 6e689a58899e66b8d7cfc0e642010c07bf4beca2..950267569c5711841c247620ffe2936ab7bcc95d 100644 (file)
 
 #include <xen/types.h>
 
+/* DMAR Flags bits */
+#define DMAR_INTR_REMAP 0x1
+#define DMAR_X2APIC_OPT_OUT 0x2
+
 /*
  * Intel IOMMU register specification per version 1.0 public spec.
  */
index 4b93c31e38905b392bfc9215ff368f689063ffa4..b7f20ed61f26beee3489078e8259920e4e25c8fa 100644 (file)
@@ -63,8 +63,8 @@ struct iommu {
 
 int iommu_setup(void);
 int iommu_supports_eim(void);
-int iommu_enable_IR(void);
-void iommu_disable_IR(void);
+int iommu_enable_x2apic_IR(void);
+void iommu_disable_x2apic_IR(void);
 
 int iommu_add_device(struct pci_dev *pdev);
 int iommu_remove_device(struct pci_dev *pdev);