WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] IO-APIC update hypercall fixes. These are known to fix i

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] IO-APIC update hypercall fixes. These are known to fix issues with
From: Xen patchbot -3.0-testing <patchbot-3.0-testing@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 08 Apr 2006 14:16:15 +0000
Delivery-date: Sat, 08 Apr 2006 07:17:25 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 1bce05ff1e5206f8d5b152130ded2f75296118c4
# Parent  8b40a2c75f8e2b562ee64807ba3d9575aa30e85c
IO-APIC update hypercall fixes. These are known to fix issues with
'pnpacpi' in domain 0.  Incorporates the following three changesets
from xen-unstable.hg:
 9589:e36892ad41444b5d2deb2fbea6b4ee2e52b7edac
 "Clean up IO-APIC update tracing and demote to DPRINTK()."
 9588:70837ac15cadf83e1fda27ae8468317afeb88ab0
 "Fix remove_pin_at_irq()."
 9586:f84a333d8aa6e1a25e2b73b07610e95007267f6a
 "Robustify and add tracing to the IO-APIC update hypercall."

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 8b40a2c75f8e -r 1bce05ff1e52 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Sat Apr  8 08:07:54 2006
+++ b/xen/arch/x86/io_apic.c    Sat Apr  8 11:14:27 2006
@@ -75,6 +75,7 @@
 static struct irq_pin_list {
     int apic, pin, next;
 } irq_2_pin[PIN_MAP_SIZE];
+static int irq_2_pin_free_entry = NR_IRQS;
 
 int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
 
@@ -85,20 +86,57 @@
  */
 static void add_pin_to_irq(unsigned int irq, int apic, int pin)
 {
-    static int first_free_entry = NR_IRQS;
     struct irq_pin_list *entry = irq_2_pin + irq;
 
-    while (entry->next)
+    while (entry->next) {
+        BUG_ON((entry->apic == apic) && (entry->pin == pin));
         entry = irq_2_pin + entry->next;
+    }
+
+    BUG_ON((entry->apic == apic) && (entry->pin == pin));
 
     if (entry->pin != -1) {
-        entry->next = first_free_entry;
+        if (irq_2_pin_free_entry >= PIN_MAP_SIZE)
+            panic("io_apic.c: whoops");
+        entry->next = irq_2_pin_free_entry;
         entry = irq_2_pin + entry->next;
-        if (++first_free_entry >= PIN_MAP_SIZE)
-            panic("io_apic.c: whoops");
+        irq_2_pin_free_entry = entry->next;
+        entry->next = 0;
     }
     entry->apic = apic;
     entry->pin = pin;
+}
+
+static void remove_pin_at_irq(unsigned int irq, int apic, int pin)
+{
+    struct irq_pin_list *entry, *prev;
+
+    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
+        if ((entry->apic == apic) && (entry->pin == pin))
+            break;
+        if (!entry->next)
+            BUG();
+    }
+
+    entry->pin = entry->apic = -1;
+    
+    if (entry != &irq_2_pin[irq]) {
+        /* Removed entry is not at head of list. */
+        prev = &irq_2_pin[irq];
+        while (&irq_2_pin[prev->next] != entry)
+            prev = &irq_2_pin[prev->next];
+        prev->next = entry->next;
+        entry->next = irq_2_pin_free_entry;
+        irq_2_pin_free_entry = entry - irq_2_pin;
+    } else if (entry->next != 0) {
+        /* Removed entry is at head of multi-item list. */
+        prev  = entry;
+        entry = &irq_2_pin[entry->next];
+        *prev = *entry;
+        entry->pin = entry->apic = -1;
+        entry->next = irq_2_pin_free_entry;
+        irq_2_pin_free_entry = entry - irq_2_pin;
+    }
 }
 
 /*
@@ -958,6 +996,10 @@
         irq_2_pin[i].pin = -1;
         irq_2_pin[i].next = 0;
     }
+
+    /* Initialise dynamic irq_2_pin free list. */
+    for (i = NR_IRQS; i < PIN_MAP_SIZE; i++)
+        irq_2_pin[i].next = i + 1;
 
     /*
      * The number of IO-APIC IRQ registers (== #pins):
@@ -1852,11 +1894,17 @@
     return 0;
 }
 
+#define WARN_BOGUS_WRITE(f, a...)                                       \
+    DPRINTK("\n%s: apic=%d, pin=%d, old_irq=%d, new_irq=%d\n"           \
+            "%s: old_entry=%08x, new_entry=%08x\n"                      \
+            "%s: " f, __FUNCTION__, apic, pin, old_irq, new_irq,        \
+            __FUNCTION__, *(u32 *)&old_rte, *(u32 *)&new_rte,           \
+            __FUNCTION__ , ##a )
+
 int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
 {
-    int apic, pin, irq;
-    struct IO_APIC_route_entry rte = { 0 };
-    struct irq_pin_list *entry;
+    int apic, pin, old_irq = -1, new_irq = -1;
+    struct IO_APIC_route_entry old_rte = { 0 }, new_rte = { 0 };
     unsigned long flags;
 
     if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
@@ -1868,8 +1916,9 @@
     
     pin = (reg - 0x10) >> 1;
 
-    *(u32 *)&rte = val;
-    rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+    /* Write first half from guest; second half is target info. */
+    *(u32 *)&new_rte = val;
+    new_rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
 
     /*
      * What about weird destination types?
@@ -1879,7 +1928,7 @@
      *  ExtINT: Ignore? Linux only asserts this at start of day.
      * For now, print a message and return an error. We can fix up on demand.
      */
-    if ( rte.delivery_mode > dest_LowestPrio )
+    if ( new_rte.delivery_mode > dest_LowestPrio )
     {
         printk("ERROR: Attempt to write weird IOAPIC destination mode!\n");
         printk("       APIC=%d/%d, lo-reg=%x\n", apic, pin, val);
@@ -1890,36 +1939,69 @@
      * The guest does not know physical APIC arrangement (flat vs. cluster).
      * Apply genapic conventions for this platform.
      */
-    rte.delivery_mode = INT_DELIVERY_MODE;
-    rte.dest_mode     = INT_DEST_MODE;
-
-    if ( rte.vector >= FIRST_DEVICE_VECTOR )
-    {
-        /* Is there a valid irq mapped to this vector? */
-        irq = vector_irq[rte.vector];
-        if ( !IO_APIC_IRQ(irq) )
+    new_rte.delivery_mode = INT_DELIVERY_MODE;
+    new_rte.dest_mode     = INT_DEST_MODE;
+
+    spin_lock_irqsave(&ioapic_lock, flags);
+
+    /* Read first (interesting) half of current routing entry. */
+    *(u32 *)&old_rte = io_apic_read(apic, 0x10 + 2 * pin);
+
+    /* No change to the first half of the routing entry? Bail quietly. */
+    if ( *(u32 *)&old_rte == *(u32 *)&new_rte )
+    {
+        spin_unlock_irqrestore(&ioapic_lock, flags);
+        return 0;
+    }
+
+    if ( old_rte.vector >= FIRST_DEVICE_VECTOR )
+        old_irq = vector_irq[old_rte.vector];
+    if ( new_rte.vector >= FIRST_DEVICE_VECTOR )
+        new_irq = vector_irq[new_rte.vector];
+
+    if ( (old_irq != new_irq) && (old_irq != -1) && IO_APIC_IRQ(old_irq) )
+    {
+        if ( irq_desc[IO_APIC_VECTOR(old_irq)].action )
+        {
+            WARN_BOGUS_WRITE("Attempt to remove IO-APIC pin of in-use IRQ!\n");
+            spin_unlock_irqrestore(&ioapic_lock, flags);
             return 0;
-
+        }
+
+        remove_pin_at_irq(old_irq, apic, pin);
+    }
+
+    if ( (new_irq != -1) && IO_APIC_IRQ(new_irq) )
+    {
+        if ( irq_desc[IO_APIC_VECTOR(new_irq)].action )
+        {
+            WARN_BOGUS_WRITE("Attempt to %s IO-APIC pin for in-use IRQ!\n",
+                             (old_irq != new_irq) ? "add" : "modify");
+            spin_unlock_irqrestore(&ioapic_lock, flags);
+            return 0;
+        }
+        
         /* Set the correct irq-handling type. */
-        irq_desc[IO_APIC_VECTOR(irq)].handler = rte.trigger ? 
+        irq_desc[IO_APIC_VECTOR(new_irq)].handler = new_rte.trigger ? 
             &ioapic_level_type: &ioapic_edge_type;
-
-        /* Record the pin<->irq mapping. */
-        for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] )
-        {
-            if ( (entry->apic == apic) && (entry->pin == pin) )
-                break;
-            if ( !entry->next )
-            {
-                add_pin_to_irq(irq, apic, pin);
-                break;
-            }
-        }
-    }
-
-    spin_lock_irqsave(&ioapic_lock, flags);
-    io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0));
-    io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1));
+        
+        if ( old_irq != new_irq )
+            add_pin_to_irq(new_irq, apic, pin);
+
+        /* Mask iff level triggered. */
+        new_rte.mask = new_rte.trigger;
+    }
+    else if ( !new_rte.mask )
+    {
+        /* This pin leads nowhere but the guest has not masked it. */
+        WARN_BOGUS_WRITE("Installing bogus unmasked IO-APIC entry!\n");
+        new_rte.mask = 1;
+    }
+
+
+    io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&new_rte) + 0));
+    io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&new_rte) + 1));
+
     spin_unlock_irqrestore(&ioapic_lock, flags);
 
     return 0;

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] IO-APIC update hypercall fixes. These are known to fix issues with, Xen patchbot -3 . 0-testing <=