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

[Xen-changelog] [xen-4.1-testing] x86/IRQ: prevent vector sharing within IO-APICs



# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1331201062 0
# Node ID 7c0d02aa4742e45507bef41fbc2fc03129a33a7b
# Parent  0bbaff574126e8fb417abe6d94b42f7bf460ad26
x86/IRQ: prevent vector sharing within IO-APICs

Following the prevention of vector sharing for MSIs, this change
enforces the same within IO-APICs: Pin based interrupts use the
IO-APIC as their identifying device under the AMD IOMMU (and just like
for MSIs, only the identifying device is used to remap interrupts
here, with no regard to an interrupt's destination).

Additionally, LAPIC initiated EOIs (for level triggered interrupts)
too use only the vector for identifying which interrupts to end. While
this generally causes no significant problem (at worst an interrupt
would be re-raised without a new interrupt event actually having
occurred), it still seems better to avoid the situation.

For this second aspect, a distinction is being made between the
traditional and the directed-EOI cases: In the former, vectors should
not be shared throughout all IO-APICs in the system, while in the
latter case only individual IO-APICs need to be contrained (or, if the
firmware indicates so, sub- groups of them having the same GSI appear
at multiple pins).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
xen-unstable changeset:   24156:f29b5bd6e25f
xen-unstable date:        Fri Nov 18 09:21:24 2011 +0100
---


diff -r 0bbaff574126 -r 7c0d02aa4742 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Thu Mar 08 10:03:35 2012 +0000
+++ b/xen/arch/x86/io_apic.c    Thu Mar 08 10:04:22 2012 +0000
@@ -70,6 +70,34 @@
 
 #define ioapic_has_eoi_reg(apic) (mp_ioapics[(apic)].mpc_apicver >= 0x20)
 
+static int apic_pin_2_gsi_irq(int apic, int pin);
+
+static vmask_t *__read_mostly vector_map[MAX_IO_APICS];
+
+static void share_vector_maps(unsigned int src, unsigned int dst)
+{
+    unsigned int pin;
+
+    if (vector_map[src] == vector_map[dst])
+        return;
+
+    bitmap_or(vector_map[src]->_bits, vector_map[src]->_bits,
+              vector_map[dst]->_bits, NR_VECTORS);
+
+    for (pin = 0; pin < nr_ioapic_registers[dst]; ++pin) {
+        int irq = apic_pin_2_gsi_irq(dst, pin);
+        struct irq_cfg *cfg;
+
+        if (irq < 0)
+            continue;
+        cfg = irq_cfg(irq);
+        if (cfg->used_vectors == vector_map[dst])
+            cfg->used_vectors = vector_map[src];
+    }
+
+    vector_map[dst] = vector_map[src];
+}
+
 /*
  * This is performance-critical, we want to do it O(1)
  *
@@ -110,6 +138,7 @@
     }
     entry->apic = apic;
     entry->pin = pin;
+    share_vector_maps(irq_2_pin[irq].apic, apic);
 }
 
 /*
@@ -125,6 +154,7 @@
         if (entry->apic == oldapic && entry->pin == oldpin) {
             entry->apic = newapic;
             entry->pin = newpin;
+            share_vector_maps(oldapic, newapic);
         }
         if (!entry->next)
             break;
@@ -132,6 +162,16 @@
     }
 }
 
+vmask_t *io_apic_get_used_vector_map(unsigned int irq)
+{
+    struct irq_pin_list *entry = irq_2_pin + irq;
+
+    if (entry->pin == -1)
+        return NULL;
+
+    return vector_map[entry->apic];
+}
+
 struct IO_APIC_route_entry **alloc_ioapic_entries(void)
 {
     int apic;
@@ -1294,6 +1334,18 @@
     for (i = irq_2_pin_free_entry = nr_irqs_gsi; i < PIN_MAP_SIZE; i++)
         irq_2_pin[i].next = i + 1;
 
+    if (directed_eoi_enabled) {
+        for (apic = 0; apic < nr_ioapics; apic++) {
+            vector_map[apic] = xzalloc(vmask_t);
+            BUG_ON(!vector_map[apic]);
+        }
+    } else {
+        vector_map[0] = xzalloc(vmask_t);
+        BUG_ON(!vector_map[0]);
+        for (apic = 1; apic < nr_ioapics; apic++)
+            vector_map[apic] = vector_map[0];
+    }
+
     for(apic = 0; apic < nr_ioapics; apic++) {
         int pin;
         /* See if any of the pins is in ExtINT mode */
@@ -2465,13 +2517,12 @@
     }
 
     if ( cfg->vector <= 0 || cfg->vector > LAST_DYNAMIC_VECTOR ) {
+        add_pin_to_irq(irq, apic, pin);
         vector = assign_irq_vector(irq);
         if ( vector < 0 )
             return vector;
 
         printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
-
-        add_pin_to_irq(irq, apic, pin);
     }
     spin_lock(&pcidevs_lock);
     spin_lock(&dom0->event_lock);
diff -r 0bbaff574126 -r 7c0d02aa4742 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Thu Mar 08 10:03:35 2012 +0000
+++ b/xen/arch/x86/irq.c        Thu Mar 08 10:04:22 2012 +0000
@@ -403,6 +403,11 @@
             }
         }
     }
+    else if ( IO_APIC_IRQ(irq) &&
+              opt_irq_vector_map != OPT_IRQ_VECTOR_MAP_NONE )
+    {
+        ret = io_apic_get_used_vector_map(irq);
+    }
 
     return ret;
 }
diff -r 0bbaff574126 -r 7c0d02aa4742 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Thu Mar 08 10:03:35 2012 +0000
+++ b/xen/include/asm-x86/irq.h Thu Mar 08 10:04:22 2012 +0000
@@ -113,6 +113,7 @@
 void disable_IO_APIC(void);
 void print_IO_APIC(void);
 void setup_ioapic_dest(void);
+vmask_t *io_apic_get_used_vector_map(unsigned int irq);
 
 extern unsigned long io_apic_irqs;
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
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®.