diff options
-rw-r--r-- | xen/arch/x86/physdev.c | 18 |
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; } |