diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-12-16 12:32:35 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-12-16 12:32:35 +0000 |
commit | 142a10c6c8d52689e9770e5f61bcce7b4af9095a (patch) | |
tree | d84b26d6af6904672180889c8bfbba411ac75699 /xen/include/asm-x86/io_apic.h | |
parent | 5a396b13fd70696a6e62eca387d4e4b51dbb6853 (diff) | |
download | xen-142a10c6c8d52689e9770e5f61bcce7b4af9095a.tar.gz xen-142a10c6c8d52689e9770e5f61bcce7b4af9095a.tar.bz2 xen-142a10c6c8d52689e9770e5f61bcce7b4af9095a.zip |
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@hp.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/include/asm-x86/io_apic.h')
-rw-r--r-- | xen/include/asm-x86/io_apic.h | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/xen/include/asm-x86/io_apic.h b/xen/include/asm-x86/io_apic.h index e47ee0c168..d546380435 100644 --- a/xen/include/asm-x86/io_apic.h +++ b/xen/include/asm-x86/io_apic.h @@ -131,20 +131,30 @@ extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; /* 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) +{ + *IO_APIC_BASE(apic) = reg; + return *(IO_APIC_BASE(apic)+4); +} + 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; - return *(IO_APIC_BASE(apic)+4); + *(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_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = value; + __io_apic_write(apic, reg, value); } static inline void io_apic_eoi(unsigned int apic, unsigned int vector) |