[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] vt-d: enhance the support of Interrupt Remapping EIM and x2APIC



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1252309490 -3600
# Node ID be45bf6fe25135cf704d9621faa1742cc7f74e7e
# Parent  fb36c9e103dcc0f1148dfee82f46be607fef5174
vt-d: enhance the support of Interrupt Remapping EIM and x2APIC

1) Clear Interrupt Remapping(IR) unit's CFI (Compatibility Format
Interrupt) to enhance security;
2) Move the iommu_setup() ahead and put it before we begin to use
IOAPIC so we can make sure after we enable Interrupt Remapping, the
later IOAPIC (and MSI) initialization would setup IOAPIC RTEs (and
MSI) with remappable format;
3) Enable x2APIC only when all VT-d engines support IR with EIM
(Extended Interrupt Mode). EIM enables external devices to deliver
interrupts to logical processor with >8-bit APIC ID.

Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 xen/arch/ia64/xen/xensetup.c           |    2 ++
 xen/arch/x86/apic.c                    |   13 ++++++++++++-
 xen/arch/x86/genapic/probe.c           |    2 --
 xen/arch/x86/setup.c                   |    6 ++++--
 xen/drivers/passthrough/iommu.c        |    3 +--
 xen/drivers/passthrough/vtd/dmar.c     |    4 ++++
 xen/drivers/passthrough/vtd/dmar.h     |    3 +++
 xen/drivers/passthrough/vtd/intremap.c |   27 ++++++++++++++++++---------
 xen/drivers/passthrough/vtd/iommu.h    |    2 +-
 xen/drivers/passthrough/vtd/vtd.h      |    1 -
 xen/include/asm-x86/genapic.h          |    1 +
 xen/include/asm-x86/smp.h              |    1 +
 xen/include/xen/iommu.h                |    3 +++
 13 files changed, 50 insertions(+), 18 deletions(-)

diff -r fb36c9e103dc -r be45bf6fe251 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/arch/ia64/xen/xensetup.c      Mon Sep 07 08:44:50 2009 +0100
@@ -630,6 +630,8 @@ printk("num_online_cpus=%d, max_cpus=%d\
 
     initialise_gdb(); /* could be moved earlier */
 
+    iommu_setup();    /* setup iommu if available */
+
     do_initcalls();
     sort_main_extable();
 
diff -r fb36c9e103dc -r be45bf6fe251 xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/arch/x86/apic.c       Mon Sep 07 08:44:50 2009 +0100
@@ -848,6 +848,9 @@ void enable_x2apic(void)
 {
     u32 lo, hi;
 
+    if ( !iommu_supports_eim() )
+        return;
+
     rdmsr(MSR_IA32_APICBASE, lo, hi);
     if ( !(lo & MSR_IA32_APICBASE_EXTD) )
     {
@@ -858,7 +861,13 @@ void enable_x2apic(void)
     else
         printk("x2APIC mode enabled by BIOS.\n");
 
-    x2apic_enabled = 1;
+    if ( !x2apic_enabled )
+    {
+        x2apic_enabled = 1;
+        genapic = &apic_x2apic;
+        printk(KERN_INFO "Switched to APIC driver %s.\n",
+                       genapic->name);
+    }
 }
 
 void __init init_apic_mappings(void)
@@ -889,6 +898,8 @@ __next:
      */
     if (boot_cpu_physical_apicid == -1U)
         boot_cpu_physical_apicid = get_apic_id();
+    x86_cpu_to_apicid[0] = get_apic_id();
+    cpu_2_logical_apicid[0] = get_logical_apic_id();
 
     init_ioapic_mappings();
 }
diff -r fb36c9e103dc -r be45bf6fe251 xen/arch/x86/genapic/probe.c
--- a/xen/arch/x86/genapic/probe.c      Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/arch/x86/genapic/probe.c      Mon Sep 07 08:44:50 2009 +0100
@@ -14,7 +14,6 @@
 #include <asm/apicdef.h>
 #include <asm/genapic.h>
 
-extern struct genapic apic_x2apic;
 extern struct genapic apic_summit;
 extern struct genapic apic_bigsmp;
 extern struct genapic apic_default;
@@ -22,7 +21,6 @@ struct genapic *genapic;
 struct genapic *genapic;
 
 struct genapic *apic_probe[] __initdata = { 
-       &apic_x2apic, 
        &apic_summit,
        &apic_bigsmp, 
        &apic_default,  /* must be last */
diff -r fb36c9e103dc -r be45bf6fe251 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/arch/x86/setup.c      Mon Sep 07 08:44:50 2009 +0100
@@ -904,10 +904,10 @@ void __init __start_xen(unsigned long mb
 
     generic_apic_probe();
 
+    acpi_boot_init();
+
     if ( x2apic_is_available() )
         enable_x2apic();
-
-    acpi_boot_init();
 
     init_cpu_to_node();
 
@@ -953,6 +953,8 @@ void __init __start_xen(unsigned long mb
 
     if ( opt_nosmp )
         max_cpus = 0;
+
+    iommu_setup();    /* setup iommu if available */
 
     smp_prepare_cpus(max_cpus);
 
diff -r fb36c9e103dc -r be45bf6fe251 xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c   Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/drivers/passthrough/iommu.c   Mon Sep 07 08:44:50 2009 +0100
@@ -260,7 +260,7 @@ int deassign_device(struct domain *d, u8
     return 0;
 }
 
-static int iommu_setup(void)
+int iommu_setup(void)
 {
     int rc = -ENODEV;
 
@@ -279,7 +279,6 @@ static int iommu_setup(void)
                iommu_pv_enabled ? "en" : "dis");
     return rc;
 }
-__initcall(iommu_setup);
 
 int iommu_get_device_group(struct domain *d, u8 bus, u8 devfn, 
     XEN_GUEST_HANDLE_64(uint32) buf, int max_sdevs)
diff -r fb36c9e103dc -r be45bf6fe251 xen/drivers/passthrough/vtd/dmar.c
--- a/xen/drivers/passthrough/vtd/dmar.c        Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.c        Mon Sep 07 08:44:50 2009 +0100
@@ -357,6 +357,7 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
     struct acpi_table_drhd * drhd = (struct acpi_table_drhd *)header;
     void *dev_scope_start, *dev_scope_end;
     struct acpi_drhd_unit *dmaru;
+    void *addr;
     int ret = 0;
     static int include_all = 0;
 
@@ -370,6 +371,9 @@ acpi_parse_one_drhd(struct acpi_dmar_ent
     INIT_LIST_HEAD(&dmaru->ioapic_list);
     dprintk(XENLOG_INFO VTDPREFIX, "dmaru->address = %"PRIx64"\n",
             dmaru->address);
+
+    addr = map_to_nocache_virt(0, drhd->address);
+    dmaru->ecap = dmar_readq(addr, DMAR_ECAP_REG);
 
     dev_scope_start = (void *)(drhd + 1);
     dev_scope_end = ((void *)drhd) + header->length;
diff -r fb36c9e103dc -r be45bf6fe251 xen/drivers/passthrough/vtd/dmar.h
--- a/xen/drivers/passthrough/vtd/dmar.h        Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/drivers/passthrough/vtd/dmar.h        Mon Sep 07 08:44:50 2009 +0100
@@ -50,6 +50,7 @@ struct acpi_drhd_unit {
     struct dmar_scope scope;            /* must be first member of struct */
     struct list_head list;
     u64    address;                     /* register base address of the unit */
+    u64    ecap;
     u8     include_all:1;
     struct iommu *iommu;
     struct list_head ioapic_list;
@@ -109,6 +110,8 @@ do {                                    
     }                                                           \
 } while (0)
 
+void *map_to_nocache_virt(int nr_iommus, u64 maddr);
+
 int vtd_hw_check(void);
 void disable_pmr(struct iommu *iommu);
 int is_usb_device(u8 bus, u8 devfn);
diff -r fb36c9e103dc -r be45bf6fe251 xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c    Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c    Mon Sep 07 08:44:50 2009 +0100
@@ -121,6 +121,22 @@ static void set_ioapic_source_id(int api
                 apicid_to_bdf(apic_id));
 }
 
+int iommu_supports_eim(void)
+{
+    struct acpi_drhd_unit *drhd;
+
+    if ( !iommu_enabled || !iommu_qinval || !iommu_intremap )
+        return 0;
+
+    for_each_drhd_unit ( drhd )
+        if ( !ecap_queued_inval(drhd->ecap) ||
+             !ecap_intr_remap(drhd->ecap) ||
+             !ecap_eim(drhd->ecap) )
+            return 0;
+
+    return 1;
+}
+
 static int remap_entry_to_ioapic_rte(
     struct iommu *iommu, struct IO_xAPIC_route_entry *old_rte)
 {
@@ -635,10 +651,10 @@ int enable_intremap(struct iommu *iommu)
         ir_ctrl->iremap_index = -1;
     }
 
-#if defined(ENABLED_EXTENDED_INTERRUPT_SUPPORT)
+#ifdef CONFIG_X86
     /* set extended interrupt mode bit */
     ir_ctrl->iremap_maddr |=
-            ecap_ext_intr(iommu->ecap) ? (1 << IRTA_REG_EIME_SHIFT) : 0;
+            x2apic_enabled ? (1 << IRTA_REG_EIME_SHIFT) : 0;
 #endif
     spin_lock_irqsave(&iommu->register_lock, flags);
 
@@ -659,13 +675,6 @@ int enable_intremap(struct iommu *iommu)
     iommu_flush_iec_global(iommu);
 
     spin_lock_irqsave(&iommu->register_lock, flags);
-    /* enable comaptiblity format interrupt pass through */
-    gcmd |= DMA_GCMD_CFI;
-    dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
-
-    IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
-                  (sts & DMA_GSTS_CFIS), sts);
-
     /* enable interrupt remapping hardware */
     gcmd |= DMA_GCMD_IRE;
     dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
diff -r fb36c9e103dc -r be45bf6fe251 xen/drivers/passthrough/vtd/iommu.h
--- a/xen/drivers/passthrough/vtd/iommu.h       Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.h       Mon Sep 07 08:44:50 2009 +0100
@@ -101,7 +101,7 @@
 #define ecap_queued_inval(e)     ((e >> 1) & 0x1)
 #define ecap_dev_iotlb(e)        ((e >> 2) & 0x1)
 #define ecap_intr_remap(e)       ((e >> 3) & 0x1)
-#define ecap_ext_intr(e)         ((e >> 4) & 0x1)
+#define ecap_eim(e)              ((e >> 4) & 0x1)
 #define ecap_cache_hints(e)      ((e >> 5) & 0x1)
 #define ecap_pass_thru(e)        ((e >> 6) & 0x1)
 #define ecap_snp_ctl(e)          ((e >> 7) & 0x1)
diff -r fb36c9e103dc -r be45bf6fe251 xen/drivers/passthrough/vtd/vtd.h
--- a/xen/drivers/passthrough/vtd/vtd.h Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/drivers/passthrough/vtd/vtd.h Mon Sep 07 08:44:50 2009 +0100
@@ -100,7 +100,6 @@ unsigned int get_cache_line_size(void);
 unsigned int get_cache_line_size(void);
 void cacheline_flush(char *);
 void flush_all_cache(void);
-void *map_to_nocache_virt(int nr_iommus, u64 maddr);
 u64 alloc_pgtable_maddr(struct acpi_drhd_unit *drhd, unsigned long npages);
 void free_pgtable_maddr(u64 maddr);
 void *map_vtd_domain_page(u64 maddr);
diff -r fb36c9e103dc -r be45bf6fe251 xen/include/asm-x86/genapic.h
--- a/xen/include/asm-x86/genapic.h     Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/include/asm-x86/genapic.h     Mon Sep 07 08:44:50 2009 +0100
@@ -49,6 +49,7 @@ struct genapic {
        APICFUNC(acpi_madt_oem_check)
 
 extern struct genapic *genapic;
+extern struct genapic apic_x2apic;
 
 void init_apic_ldr_flat(void);
 void clustered_apic_check_flat(void);
diff -r fb36c9e103dc -r be45bf6fe251 xen/include/asm-x86/smp.h
--- a/xen/include/asm-x86/smp.h Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/include/asm-x86/smp.h Mon Sep 07 08:44:50 2009 +0100
@@ -49,6 +49,7 @@ extern void zap_low_mappings(l2_pgentry_
 
 #define MAX_APICID 256
 extern u32 x86_cpu_to_apicid[];
+extern u32 cpu_2_logical_apicid[];
 
 #define cpu_physical_id(cpu)   x86_cpu_to_apicid[cpu]
 
diff -r fb36c9e103dc -r be45bf6fe251 xen/include/xen/iommu.h
--- a/xen/include/xen/iommu.h   Mon Sep 07 08:44:00 2009 +0100
+++ b/xen/include/xen/iommu.h   Mon Sep 07 08:44:50 2009 +0100
@@ -56,6 +56,9 @@ struct iommu {
     int irq;
     struct intel_iommu *intel;
 };
+
+int iommu_setup(void);
+int iommu_supports_eim(void);
 
 int iommu_add_device(struct pci_dev *pdev);
 int iommu_remove_device(struct pci_dev *pdev);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.