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] [xen-unstable] iommu: Actually clear IO-APIC pins on boo

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] iommu: Actually clear IO-APIC pins on boot and shutdown when used with an IOMMU
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 16 Dec 2009 06:00:28 -0800
Delivery-date: Wed, 16 Dec 2009 06:01:01 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1260966755 0
# Node ID b543acc1aaad743f20e8ee44ab048ca239350685
# Parent  976d679b04fbcf8c64aff958fc0dd9f1ade09250
iommu: Actually clear IO-APIC pins on boot and shutdown when used with an IOMMU

When booted with iommu=on, io_apic_read/write functions call into the
interrupt remapping code to update the IRTEs.  Unfortunately, on boot
and shutdown, we really want clear_IO_APIC() to sanitize the actual
IOAPIC RTE, and not just the bits that are active when interrupt
remapping is enabled.  This is particularly a problem on older
versions of Xen which used the IOAPIC RTE as the canonical source for
the IRTE index.  In that case, clear_IO_APIC() actually causes
whatever happens to be stored in the RTEs to be used as an IRTE index,
which can come back and bite us in ioapic_guest_write() if we attempt
to remove an interrupt that didn't actually exist.  Current upstream
appears less susceptible to errors since the IRTE index is stored in
an array, but it's still a good idea to sanitize the IOAPIC state.

Signed-off-by: Alex Williamson <alex.williamson@xxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/io_apic.c        |   25 +++++++++++++++++--------
 xen/include/asm-x86/io_apic.h |   26 ++++++++++++++++++--------
 2 files changed, 35 insertions(+), 16 deletions(-)

diff -r 976d679b04fb -r b543acc1aaad xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c    Wed Dec 16 12:23:21 2009 +0000
+++ b/xen/arch/x86/io_apic.c    Wed Dec 16 12:32:35 2009 +0000
@@ -221,15 +221,21 @@ static void eoi_IO_APIC_irq(unsigned int
     spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
-static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
-{
+#define clear_IO_APIC_pin(a,p)     __clear_IO_APIC_pin(a,p,0)
+#define clear_IO_APIC_pin_raw(a,p) __clear_IO_APIC_pin(a,p,1)
+static void __clear_IO_APIC_pin(unsigned int apic, unsigned int pin, int raw)
+{
+    unsigned int (*read)(unsigned int, unsigned int)
+        = raw ? __io_apic_read : io_apic_read;
+    void (*write)(unsigned int, unsigned int, unsigned int)
+        = raw ? __io_apic_write : io_apic_write;
     struct IO_APIC_route_entry entry;
     unsigned long flags;
     
     /* Check delivery_mode to be sure we're not clearing an SMI pin */
     spin_lock_irqsave(&ioapic_lock, flags);
-    *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
-    *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
+    *(((int*)&entry) + 0) = (*read)(apic, 0x10 + 2 * pin);
+    *(((int*)&entry) + 1) = (*read)(apic, 0x11 + 2 * pin);
     spin_unlock_irqrestore(&ioapic_lock, flags);
     if (entry.delivery_mode == dest_SMI)
         return;
@@ -240,8 +246,8 @@ static void clear_IO_APIC_pin(unsigned i
     memset(&entry, 0, sizeof(entry));
     entry.mask = 1;
     spin_lock_irqsave(&ioapic_lock, flags);
-    io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
-    io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
+    (*write)(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
+    (*write)(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
     spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
@@ -249,9 +255,12 @@ static void clear_IO_APIC (void)
 {
     int apic, pin;
 
-    for (apic = 0; apic < nr_ioapics; apic++)
-        for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
+    for (apic = 0; apic < nr_ioapics; apic++) {
+        for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
             clear_IO_APIC_pin(apic, pin);
+            clear_IO_APIC_pin_raw(apic, pin);
+        }
+    }
 }
 
 #ifdef CONFIG_SMP
diff -r 976d679b04fb -r b543acc1aaad xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h     Wed Dec 16 12:23:21 2009 +0000
+++ b/xen/include/asm-x86/io_apic.h     Wed Dec 16 12:32:35 2009 +0000
@@ -131,20 +131,30 @@ extern struct mpc_config_ioapic mp_ioapi
 /* Only need to remap ioapic RTE (reg: 10~3Fh) */
 #define ioapic_reg_remapped(reg) (iommu_enabled && ((reg) >= 0x10))
 
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
-       if (ioapic_reg_remapped(reg))
-               return iommu_read_apic_from_ire(apic, reg);
+static inline unsigned int __io_apic_read(unsigned int apic, unsigned int reg)
+{
        *IO_APIC_BASE(apic) = reg;
        return *(IO_APIC_BASE(apic)+4);
 }
 
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned 
int value)
-{
-       if (ioapic_reg_remapped(reg))
-               return iommu_update_ire_from_apic(apic, reg, value);
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+       if (ioapic_reg_remapped(reg))
+               return iommu_read_apic_from_ire(apic, reg);
+       return __io_apic_read(apic, reg);
+}
+
+static inline void __io_apic_write(unsigned int apic, unsigned int reg, 
unsigned int value)
+{
        *IO_APIC_BASE(apic) = reg;
        *(IO_APIC_BASE(apic)+4) = value;
+}
+
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned 
int value)
+{
+       if (ioapic_reg_remapped(reg))
+               return iommu_update_ire_from_apic(apic, reg, value);
+       __io_apic_write(apic, reg, value);
 }
 
 static inline void io_apic_eoi(unsigned int apic, unsigned int vector)

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] iommu: Actually clear IO-APIC pins on boot and shutdown when used with an IOMMU, Xen patchbot-unstable <=