aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-07-28 16:28:21 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-07-28 16:28:21 +0100
commit7ee1d0108a85da052767484255d631352b184fca (patch)
tree18ea83ec4eafb6a09933c5aca970789c27750ed0
parentc88235741e1d230a9dab1be55ee87547b9980f65 (diff)
downloadxen-7ee1d0108a85da052767484255d631352b184fca.tar.gz
xen-7ee1d0108a85da052767484255d631352b184fca.tar.bz2
xen-7ee1d0108a85da052767484255d631352b184fca.zip
passthrough: use tasklet to deliver interrupts
This patch enables delivery of interrupts even if the VCPU#0 is halted. Note: the changes to softirq.{ch} are needed for ia64 build. Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
-rw-r--r--xen/arch/ia64/vmx/vmx_fault.c1
-rw-r--r--xen/arch/x86/hvm/svm/intr.c1
-rw-r--r--xen/arch/x86/hvm/vmx/intr.c1
-rw-r--r--xen/common/softirq.c22
-rw-r--r--xen/drivers/passthrough/io.c26
-rw-r--r--xen/drivers/passthrough/pci.c2
-rw-r--r--xen/include/xen/hvm/irq.h4
-rw-r--r--xen/include/xen/softirq.h26
8 files changed, 37 insertions, 46 deletions
diff --git a/xen/arch/ia64/vmx/vmx_fault.c b/xen/arch/ia64/vmx/vmx_fault.c
index 53d0693876..642d3120c2 100644
--- a/xen/arch/ia64/vmx/vmx_fault.c
+++ b/xen/arch/ia64/vmx/vmx_fault.c
@@ -305,7 +305,6 @@ void leave_hypervisor_tail(void)
viosapic_set_irq(d, callback_irq, 0);
}
}
- hvm_dirq_assist(v);
}
rmb();
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index b6499070c0..369423612b 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -109,7 +109,6 @@ asmlinkage void svm_intr_assist(void)
/* Crank the handle on interrupt state. */
pt_update_irq(v);
- hvm_dirq_assist(v);
do {
intack = hvm_vcpu_has_pending_irq(v);
diff --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c
index ef536ac8f2..299b7d2c2b 100644
--- a/xen/arch/x86/hvm/vmx/intr.c
+++ b/xen/arch/x86/hvm/vmx/intr.c
@@ -127,7 +127,6 @@ asmlinkage void vmx_intr_assist(void)
/* Crank the handle on interrupt state. */
pt_update_irq(v);
- hvm_dirq_assist(v);
do {
intack = hvm_vcpu_has_pending_irq(v);
diff --git a/xen/common/softirq.c b/xen/common/softirq.c
index a4ae6a0c62..ecf3379388 100644
--- a/xen/common/softirq.c
+++ b/xen/common/softirq.c
@@ -53,6 +53,28 @@ void open_softirq(int nr, softirq_handler handler)
softirq_handlers[nr] = handler;
}
+void cpumask_raise_softirq(cpumask_t mask, unsigned int nr)
+{
+ int cpu;
+
+ for_each_cpu_mask(cpu, mask)
+ if ( test_and_set_bit(nr, &softirq_pending(cpu)) )
+ cpu_clear(cpu, mask);
+
+ smp_send_event_check_mask(&mask);
+}
+
+void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+{
+ if ( !test_and_set_bit(nr, &softirq_pending(cpu)) )
+ smp_send_event_check_cpu(cpu);
+}
+
+void raise_softirq(unsigned int nr)
+{
+ set_bit(nr, &softirq_pending(smp_processor_id()));
+}
+
static LIST_HEAD(tasklet_list);
static DEFINE_SPINLOCK(tasklet_lock);
diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index 61060db8e3..97de764536 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -24,6 +24,8 @@
#include <asm/hvm/iommu.h>
#include <xen/hvm/irq.h>
+static void hvm_dirq_assist(unsigned long _d);
+
static int pt_irq_need_timer(uint32_t flags)
{
return !(flags & (HVM_IRQ_DPCI_GUEST_MSI | HVM_IRQ_DPCI_TRANSLATE));
@@ -114,6 +116,8 @@ int pt_irq_create_bind_vtd(
return -ENOMEM;
}
memset(hvm_irq_dpci, 0, sizeof(*hvm_irq_dpci));
+ tasklet_init(&hvm_irq_dpci->dirq_tasklet,
+ hvm_dirq_assist, (unsigned long)d);
hvm_irq_dpci->mirq = xmalloc_array(struct hvm_mirq_dpci_mapping,
d->nr_pirqs);
hvm_irq_dpci->dirq_mask = xmalloc_array(unsigned long,
@@ -368,18 +372,8 @@ int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
!test_bit(mirq, dpci->mapping))
return 0;
- /*
- * Set a timer here to avoid situations where the IRQ line is shared, and
- * the device belonging to the pass-through guest is not yet active. In
- * this case the guest may not pick up the interrupt (e.g., masked at the
- * PIC) and we need to detect that.
- */
set_bit(mirq, dpci->dirq_mask);
- if ( pt_irq_need_timer(dpci->mirq[mirq].flags) )
- set_timer(&dpci->hvm_timer[domain_irq_to_vector(d, mirq)],
- NOW() + PT_IRQ_TIME_OUT);
- vcpu_kick(d->vcpu[0]);
-
+ tasklet_schedule(&dpci->dirq_tasklet);
return 1;
}
@@ -429,16 +423,15 @@ static int hvm_pci_msi_assert(struct domain *d, int pirq)
}
#endif
-void hvm_dirq_assist(struct vcpu *v)
+static void hvm_dirq_assist(unsigned long _d)
{
unsigned int irq;
uint32_t device, intx;
- struct domain *d = v->domain;
+ struct domain *d = (struct domain *)_d;
struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
struct dev_intx_gsi_link *digl;
- if ( !iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
- return;
+ ASSERT(hvm_irq_dpci);
for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, d->nr_pirqs);
irq < d->nr_pirqs;
@@ -456,9 +449,6 @@ void hvm_dirq_assist(struct vcpu *v)
continue;
}
#endif
- if ( pt_irq_need_timer(hvm_irq_dpci->mirq[irq].flags) )
- stop_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)]);
-
list_for_each_entry ( digl, &hvm_irq_dpci->mirq[irq].digl_list, list )
{
device = digl->device;
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 27699e038b..37f1f4ba5c 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -209,6 +209,8 @@ static void pci_clean_dpci_irqs(struct domain *d)
hvm_irq_dpci = domain_get_irq_dpci(d);
if ( hvm_irq_dpci != NULL )
{
+ tasklet_kill(&hvm_irq_dpci->dirq_tasklet);
+
for ( i = find_first_bit(hvm_irq_dpci->mapping, d->nr_pirqs);
i < d->nr_pirqs;
i = find_next_bit(hvm_irq_dpci->mapping, d->nr_pirqs, i + 1) )
diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h
index 4fe118c31b..b50cff6da9 100644
--- a/xen/include/xen/hvm/irq.h
+++ b/xen/include/xen/hvm/irq.h
@@ -24,6 +24,7 @@
#include <xen/types.h>
#include <xen/spinlock.h>
+#include <xen/softirq.h>
#include <asm/irq.h>
#include <public/hvm/save.h>
@@ -88,6 +89,7 @@ struct hvm_irq_dpci {
/* Record of mapped Links */
uint8_t link_cnt[NR_LINK];
struct timer hvm_timer[NR_VECTORS];
+ struct tasklet dirq_tasklet;
};
/* Modify state of a PCI INTx wire. */
@@ -108,6 +110,4 @@ void hvm_maybe_deassert_evtchn_irq(void);
void hvm_assert_evtchn_irq(struct vcpu *v);
void hvm_set_callback_via(struct domain *d, uint64_t via);
-void hvm_dirq_assist(struct vcpu *v);
-
#endif /* __XEN_HVM_IRQ_H__ */
diff --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h
index efd0a54443..5d5661fd43 100644
--- a/xen/include/xen/softirq.h
+++ b/xen/include/xen/softirq.h
@@ -29,29 +29,9 @@ asmlinkage void do_softirq(void);
void open_softirq(int nr, softirq_handler handler);
void softirq_init(void);
-static inline void cpumask_raise_softirq(cpumask_t mask, unsigned int nr)
-{
- int cpu;
-
- for_each_cpu_mask(cpu, mask)
- {
- if ( test_and_set_bit(nr, &softirq_pending(cpu)) )
- cpu_clear(cpu, mask);
- }
-
- smp_send_event_check_mask(&mask);
-}
-
-static inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
-{
- if ( !test_and_set_bit(nr, &softirq_pending(cpu)) )
- smp_send_event_check_cpu(cpu);
-}
-
-static inline void raise_softirq(unsigned int nr)
-{
- set_bit(nr, &softirq_pending(smp_processor_id()));
-}
+void cpumask_raise_softirq(cpumask_t mask, unsigned int nr);
+void cpu_raise_softirq(unsigned int cpu, unsigned int nr);
+void raise_softirq(unsigned int nr);
/*
* TASKLETS -- dynamically-allocatable tasks run in softirq context