[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] iommu: Actually clear IO-APIC pins on boot and shutdown when used with an IOMMU
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |