From ddfe333aef87e6c5f52b84c8beb3277be4663313 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 19 May 2015 12:00:09 +0200 Subject: [PATCH] x86: don't change affinity with interrupt unmasked With ->startup unmasking the IRQ, setting the affinity afterwards without masking the IRQ again is invalid namely for MSI (address and data can't be updated atomically and may - at least for MSI-X - be cached while unmasked). Signed-off-by: Jan Beulich Reviewed-by: Konrad Rzeszutek Wilk Reviewed-by: Andrew Cooper AMD IOMMU: only translate remapped IO-APIC RTEs 1aeb1156fa ("x86 don't change affinity with interrupt unmasked") introducing RTE reads prior to the respective interrupt having got enabled for the first time uncovered a bug in 2ca9fbd739 ("AMD IOMMU: allocate IRTE entries instead of using a static mapping"): We obviously shouldn't be translating RTEs for which remapping didn't get set up yet. Reported-by: Sander Eikelenboom Signed-off-by: Jan Beulich Acked-by: Suravee Suthikulpanit master commit: 1aeb1156fa43fe2cd2b5003995b20466cd19a622 master date: 2015-03-26 11:18:28 +0100 master commit: c33c51b81c82a51515bf4fa2a9717098c03e5013 master date: 2015-04-24 12:06:26 +0200 --- xen/arch/x86/irq.c | 5 +++-- xen/drivers/passthrough/amd/iommu_intr.c | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 84738e53d3..3cf6777f54 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -1608,12 +1608,13 @@ int pirq_guest_bind(struct vcpu *v, struct pirq *pirq, int will_share) init_timer(&action->eoi_timer, irq_guest_eoi_timer_fn, desc, 0); desc->status |= IRQ_GUEST; - desc->status &= ~IRQ_DISABLED; - desc->handler->startup(desc); /* Attempt to bind the interrupt target to the correct CPU. */ if ( !opt_noirqbalance && (desc->handler->set_affinity != NULL) ) desc->handler->set_affinity(desc, cpumask_of(v->processor)); + + desc->status &= ~IRQ_DISABLED; + desc->handler->startup(desc); } else if ( !will_share || !action->shareable ) { diff --git a/xen/drivers/passthrough/amd/iommu_intr.c b/xen/drivers/passthrough/amd/iommu_intr.c index c1b76fb9d0..18d8b5ffc1 100644 --- a/xen/drivers/passthrough/amd/iommu_intr.c +++ b/xen/drivers/passthrough/amd/iommu_intr.c @@ -365,15 +365,17 @@ unsigned int amd_iommu_read_ioapic_from_ire( unsigned int apic, unsigned int reg) { unsigned int val = __io_apic_read(apic, reg); + unsigned int pin = (reg - 0x10) / 2; + unsigned int offset = ioapic_sbdf[IO_APIC_ID(apic)].pin_2_idx[pin]; - if ( !(reg & 1) ) + if ( !(reg & 1) && offset < INTREMAP_ENTRIES ) { - unsigned int offset = val & (INTREMAP_ENTRIES - 1); u16 bdf = ioapic_sbdf[IO_APIC_ID(apic)].bdf; u16 seg = ioapic_sbdf[IO_APIC_ID(apic)].seg; u16 req_id = get_intremap_requestor_id(seg, bdf); const u32 *entry = get_intremap_entry(seg, req_id, offset); + ASSERT(offset == (val & (INTREMAP_ENTRIES - 1))); val &= ~(INTREMAP_ENTRIES - 1); val |= get_field_from_reg_u32(*entry, INT_REMAP_ENTRY_INTTYPE_MASK,