mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 18:21:39 +01:00
vt-d: Do dpci eoi outside of irq_lock.
Deadlock may occur if do hvm_dpci_eoi() inside of irq_lock on MP platform. For example, there are two physical cpus. If interrupt is injected on cpu0, but vcpu is migrated to cpu1 and it does eoi inside of irq_lock, then IPI will be issued to cpu0. At the same time, cpu0 may have disabled irq and is acquiring the same irq_lock. In addition, current code cannot guarantee do hvm_dpci_eoi() inside of irq_lock when timeout. This patch does hvm_dpci_eoi() outside of irq_lock, and solves above problems. Signed-off-by: Xiaohui Xin <xiaohui.xin@intel.com> Signed-off-by: Weidong Han <weidong.han@intel.com> Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
dbda63b318
commit
06e3f8f276
5 files changed
+14
-16
No files matched your search
@@ -26,7 +26,7 @@
|
||||
#include <asm/hvm/domain.h>
|
||||
#include <asm/hvm/support.h>
|
||||
|
||||
void __hvm_pci_intx_assert(
|
||||
static void __hvm_pci_intx_assert(
|
||||
struct domain *d, unsigned int device, unsigned int intx)
|
||||
{
|
||||
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
|
||||
@@ -59,7 +59,7 @@ void hvm_pci_intx_assert(
|
||||
spin_unlock(&d->arch.hvm_domain.irq_lock);
|
||||
}
|
||||
|
||||
void __hvm_pci_intx_deassert(
|
||||
static void __hvm_pci_intx_deassert(
|
||||
struct domain *d, unsigned int device, unsigned int intx)
|
||||
{
|
||||
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
|
||||
|
||||
@@ -459,7 +459,11 @@ void vioapic_update_EOI(struct domain *d, int vector)
|
||||
ent->fields.remote_irr = 0;
|
||||
|
||||
if ( vtd_enabled )
|
||||
{
|
||||
spin_unlock(&d->arch.hvm_domain.irq_lock);
|
||||
hvm_dpci_eoi(current->domain, gsi, ent);
|
||||
spin_lock(&d->arch.hvm_domain.irq_lock);
|
||||
}
|
||||
|
||||
if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
|
||||
!ent->fields.mask &&
|
||||
|
||||
@@ -145,8 +145,6 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
|
||||
struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
|
||||
uint32_t device, intx, machine_gsi;
|
||||
|
||||
ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
|
||||
|
||||
if ( !vtd_enabled || (hvm_irq_dpci == NULL) ||
|
||||
!hvm_irq_dpci->girq[guest_gsi].valid )
|
||||
return;
|
||||
@@ -157,7 +155,7 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
|
||||
intx = hvm_irq_dpci->girq[guest_gsi].intx;
|
||||
gdprintk(XENLOG_INFO, "hvm_dpci_eoi:: device %x intx %x\n",
|
||||
device, intx);
|
||||
__hvm_pci_intx_deassert(d, device, intx);
|
||||
hvm_pci_intx_deassert(d, device, intx);
|
||||
if ( (ent == NULL) || !ent->fields.mask )
|
||||
pirq_guest_eoi(d, machine_gsi);
|
||||
}
|
||||
|
||||
@@ -249,13 +249,13 @@ static void vpic_ioport_write(
|
||||
vpic->isr &= ~(1 << irq);
|
||||
if ( cmd == 7 )
|
||||
vpic->priority_add = (irq + 1) & 7;
|
||||
if ( vtd_enabled )
|
||||
{
|
||||
irq |= ((addr & 0xa0) == 0xa0) ? 8 : 0;
|
||||
hvm_dpci_eoi(current->domain,
|
||||
hvm_isa_irq_to_gsi(irq), NULL);
|
||||
}
|
||||
break;
|
||||
/* Release lock and EOI the physical interrupt (if any). */
|
||||
vpic_update_int_output(vpic);
|
||||
vpic_unlock(vpic);
|
||||
hvm_dpci_eoi(current->domain,
|
||||
hvm_isa_irq_to_gsi((addr >> 7) ? (irq|8) : irq),
|
||||
NULL);
|
||||
return; /* bail immediately */
|
||||
case 6: /* Set Priority */
|
||||
vpic->priority_add = (val + 1) & 7;
|
||||
break;
|
||||
|
||||
@@ -121,12 +121,8 @@ struct hvm_irq {
|
||||
#define hvm_isa_irq_to_gsi(isa_irq) ((isa_irq) ? : 2)
|
||||
|
||||
/* Modify state of a PCI INTx wire. */
|
||||
void __hvm_pci_intx_assert(
|
||||
struct domain *d, unsigned int device, unsigned int intx);
|
||||
void hvm_pci_intx_assert(
|
||||
struct domain *d, unsigned int device, unsigned int intx);
|
||||
void __hvm_pci_intx_deassert(
|
||||
struct domain *d, unsigned int device, unsigned int intx);
|
||||
void hvm_pci_intx_deassert(
|
||||
struct domain *d, unsigned int device, unsigned int intx);
|
||||
|
||||
|
||||