diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-09-18 08:46:32 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-09-18 08:46:32 +0100 |
commit | d75c52c50c4b8ac03aca431f366ebe0b2f493dbe (patch) | |
tree | 0cae8642f37c1c54d9191bb9381cc6ae2d0fa005 | |
parent | 41c06ea3f57221d4c99fd7226dfba01f0156a866 (diff) | |
download | xen-d75c52c50c4b8ac03aca431f366ebe0b2f493dbe.tar.gz xen-d75c52c50c4b8ac03aca431f366ebe0b2f493dbe.tar.bz2 xen-d75c52c50c4b8ac03aca431f366ebe0b2f493dbe.zip |
iommu: Fix pirq conflict issue when guest adopts per-cpu vector.
Latest Linux and Windows may adopt per-cpu vector instead of global
vector, so same vector in different vcpu may correspond to different
interrupt sources. That is to say, vector and pirq should be 1:n
mapping, and the array msi_gvec_pirq can't meet the mapping
requirement, so need to improve the related logic, otherwise it may
introduce strange issues.
Signed-off-by: Xiantao Zhang <xiantao.zhang@intel.com>
-rw-r--r-- | xen/arch/x86/hvm/vmsi.c | 9 | ||||
-rw-r--r-- | xen/drivers/passthrough/io.c | 23 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vlapic.h | 10 | ||||
-rw-r--r-- | xen/include/xen/hvm/irq.h | 1 |
4 files changed, 25 insertions, 18 deletions
diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c index 24e38ebf6d..3662a4c757 100644 --- a/xen/arch/x86/hvm/vmsi.c +++ b/xen/arch/x86/hvm/vmsi.c @@ -64,15 +64,6 @@ static void vmsi_inj_irq( } } -#define VMSI_RH_MASK 0x100 -#define VMSI_DM_MASK 0x200 -#define VMSI_DELIV_MASK 0x7000 -#define VMSI_TRIG_MODE 0x8000 - -#define GFLAGS_SHIFT_RH 8 -#define GLFAGS_SHIFT_DELIV_MODE 12 -#define GLFAGS_SHIFT_TRG_MODE 15 - int vmsi_deliver(struct domain *d, int pirq) { struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index 79a0c9e53a..198c08962d 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -161,7 +161,6 @@ int pt_irq_create_bind_vtd( HVM_IRQ_DPCI_GUEST_MSI; hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; - hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq; /* bind after hvm_irq_dpci is setup to avoid race with irq handler*/ rc = pirq_guest_bind(d->vcpu[0], pirq, 0); if ( rc == 0 && pt_irq_bind->u.msi.gtable ) @@ -172,7 +171,6 @@ int pt_irq_create_bind_vtd( } if ( unlikely(rc) ) { - hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = 0; hvm_irq_dpci->mirq[pirq].gmsi.gflags = 0; hvm_irq_dpci->mirq[pirq].gmsi.gvec = 0; hvm_irq_dpci->mirq[pirq].flags = 0; @@ -194,10 +192,8 @@ int pt_irq_create_bind_vtd( /* if pirq is already mapped as vmsi, update the guest data/addr */ old_gvec = hvm_irq_dpci->mirq[pirq].gmsi.gvec; - hvm_irq_dpci->msi_gvec_pirq[old_gvec] = 0; hvm_irq_dpci->mirq[pirq].gmsi.gvec = pt_irq_bind->u.msi.gvec; hvm_irq_dpci->mirq[pirq].gmsi.gflags = pt_irq_bind->u.msi.gflags; - hvm_irq_dpci->msi_gvec_pirq[pt_irq_bind->u.msi.gvec] = pirq; } } else @@ -405,17 +401,28 @@ static void __msi_pirq_eoi(struct domain *d, int pirq) void hvm_dpci_msi_eoi(struct domain *d, int vector) { + int pirq, dest, dest_mode; struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; - int pirq; if ( !iommu_enabled || (hvm_irq_dpci == NULL) ) return; spin_lock(&d->event_lock); + for ( pirq = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs); + pirq < d->nr_pirqs; + pirq = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, pirq + 1) ) + { + if ( (!(hvm_irq_dpci->mirq[pirq].flags & HVM_IRQ_DPCI_MACH_MSI)) || + (hvm_irq_dpci->mirq[pirq].gmsi.gvec != vector) ) + continue; - pirq = hvm_irq_dpci->msi_gvec_pirq[vector]; - __msi_pirq_eoi(d, pirq); - + dest = hvm_irq_dpci->mirq[pirq].gmsi.gflags & VMSI_DEST_ID_MASK; + dest_mode = !!(hvm_irq_dpci->mirq[pirq].gmsi.gflags & VMSI_DM_MASK); + if ( vlapic_match_dest(vcpu_vlapic(current), NULL, 0, dest, dest_mode) ) + break; + } + if ( pirq < d->nr_pirqs ) + __msi_pirq_eoi(d, pirq); spin_unlock(&d->event_lock); } diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h index 880754d2ab..d882af2d54 100644 --- a/xen/include/asm-x86/hvm/vlapic.h +++ b/xen/include/asm-x86/hvm/vlapic.h @@ -52,6 +52,16 @@ #define vlapic_base_address(vlapic) \ ((vlapic)->hw.apic_base_msr & MSR_IA32_APICBASE_BASE) +#define VMSI_DEST_ID_MASK 0xff +#define VMSI_RH_MASK 0x100 +#define VMSI_DM_MASK 0x200 +#define VMSI_DELIV_MASK 0x7000 +#define VMSI_TRIG_MODE 0x8000 + +#define GFLAGS_SHIFT_RH 8 +#define GLFAGS_SHIFT_DELIV_MODE 12 +#define GLFAGS_SHIFT_TRG_MODE 15 + struct vlapic { struct hvm_hw_lapic hw; struct hvm_hw_lapic_regs *regs; diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h index 739507af95..af298e5fe3 100644 --- a/xen/include/xen/hvm/irq.h +++ b/xen/include/xen/hvm/irq.h @@ -83,7 +83,6 @@ struct hvm_irq_dpci { unsigned long *dirq_mask; /* Guest IRQ to guest device/intx mapping. */ struct list_head girq[NR_HVM_IRQS]; - uint8_t msi_gvec_pirq[0x100]; /* Record of mapped ISA IRQs */ DECLARE_BITMAP(isairq_map, NR_ISAIRQS); /* Record of mapped Links */ |