aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/physdev.c
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2011-10-27 16:07:18 +0100
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2011-10-27 16:07:18 +0100
commitb96a29f78513b970c530e0e91dff16bfb559fad3 (patch)
tree44c58a1cd4267e16564a0920625e9d9fb38c869a /xen/arch/x86/physdev.c
parent6f4e4735b30d5709c76e6da64f9bf2b616808cb1 (diff)
downloadxen-b96a29f78513b970c530e0e91dff16bfb559fad3.tar.gz
xen-b96a29f78513b970c530e0e91dff16bfb559fad3.tar.bz2
xen-b96a29f78513b970c530e0e91dff16bfb559fad3.zip
x86: re-inject emulated level pirqs in PV on HVM guests if still
asserted PV on HVM guests can loose level interrupts coming from emulated devices if they have been remapped onto event channels. The reason is that we are missing the code to inject a pirq again in the guest when the guest EOIs it, if it corresponds to an emulated level interrupt and the interrupt is still asserted. Fix this issue and also return error when the guest tries to get the irq_status of a non-existing pirq. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Committed-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/physdev.c')
-rw-r--r--xen/arch/x86/physdev.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index eccf8849ee..569ad81a87 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -11,6 +11,7 @@
#include <asm/current.h>
#include <asm/io_apic.h>
#include <asm/msi.h>
+#include <asm/hvm/irq.h>
#include <asm/hypercall.h>
#include <public/xen.h>
#include <public/physdev.h>
@@ -270,6 +271,18 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
if ( !is_hvm_domain(v->domain) ||
domain_pirq_to_irq(v->domain, eoi.irq) > 0 )
pirq_guest_eoi(pirq);
+ if ( is_hvm_domain(v->domain) &&
+ domain_pirq_to_emuirq(v->domain, eoi.irq) > 0 )
+ {
+ struct hvm_irq *hvm_irq = &v->domain->arch.hvm_domain.irq;
+ int gsi = domain_pirq_to_emuirq(v->domain, eoi.irq);
+
+ /* if this is a level irq and count > 0, send another
+ * notification */
+ if ( gsi >= NR_ISAIRQS /* ISA irqs are edge triggered */
+ && hvm_irq->gsi_assert_count[gsi] )
+ send_guest_pirq(v->domain, pirq);
+ }
spin_unlock(&v->domain->event_lock);
ret = 0;
break;
@@ -328,9 +341,10 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
break;
irq_status_query.flags = 0;
if ( is_hvm_domain(v->domain) &&
- domain_pirq_to_irq(v->domain, irq) <= 0 )
+ domain_pirq_to_irq(v->domain, irq) <= 0 &&
+ domain_pirq_to_emuirq(v->domain, irq) == IRQ_UNBOUND )
{
- ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0;
+ ret = -EINVAL;
break;
}