diff options
author | Keir Fraser <keir@xen.org> | 2010-11-19 13:43:24 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2010-11-19 13:43:24 +0000 |
commit | 0b469cd6870899a52c41be1cb3c982976531d59d (patch) | |
tree | e80341800e6234bb7c2e81b8ce38dcfbc2e2b949 /xen/arch/x86/hvm/irq.c | |
parent | 26b1575bf3d4abd407724c0cc6a2365fd78e0b6d (diff) | |
download | xen-0b469cd6870899a52c41be1cb3c982976531d59d.tar.gz xen-0b469cd6870899a52c41be1cb3c982976531d59d.tar.bz2 xen-0b469cd6870899a52c41be1cb3c982976531d59d.zip |
Interrupt remapping to PIRQs in HVM guests
This patch allows HVM guests to remap interrupts and MSIs into pirqs;
once the mapping is in place the guest will receive the interrupt (or
the MSI) as an event. The interrupt to be remapped can either be an
interrupt of an emulated device or an interrupt of a passthrough
device and we keep track of that.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/irq.c')
-rw-r--r-- | xen/arch/x86/hvm/irq.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index b0ab1a5343..f1deada076 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -23,9 +23,30 @@ #include <xen/types.h> #include <xen/event.h> #include <xen/sched.h> +#include <xen/irq.h> #include <asm/hvm/domain.h> #include <asm/hvm/support.h> +/* Must be called with hvm_domain->irq_lock hold */ +static void assert_irq(struct domain *d, unsigned ioapic_gsi, unsigned pic_irq) +{ + int pirq = domain_emuirq_to_pirq(d, ioapic_gsi); + if ( pirq != IRQ_UNBOUND ) + { + send_guest_pirq(d, pirq); + return; + } + vioapic_irq_positive_edge(d, ioapic_gsi); + vpic_irq_positive_edge(d, pic_irq); +} + +/* Must be called with hvm_domain->irq_lock hold */ +static void deassert_irq(struct domain *d, unsigned isa_irq) +{ + if ( domain_emuirq_to_pirq(d, isa_irq) != IRQ_UNBOUND ) + vpic_irq_negative_edge(d, isa_irq); +} + static void __hvm_pci_intx_assert( struct domain *d, unsigned int device, unsigned int intx) { @@ -45,10 +66,7 @@ static void __hvm_pci_intx_assert( isa_irq = hvm_irq->pci_link.route[link]; if ( (hvm_irq->pci_link_assert_count[link]++ == 0) && isa_irq && (hvm_irq->gsi_assert_count[isa_irq]++ == 0) ) - { - vioapic_irq_positive_edge(d, isa_irq); - vpic_irq_positive_edge(d, isa_irq); - } + assert_irq(d, isa_irq, isa_irq); } void hvm_pci_intx_assert( @@ -77,7 +95,7 @@ static void __hvm_pci_intx_deassert( isa_irq = hvm_irq->pci_link.route[link]; if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq && (--hvm_irq->gsi_assert_count[isa_irq] == 0) ) - vpic_irq_negative_edge(d, isa_irq); + deassert_irq(d, isa_irq); } void hvm_pci_intx_deassert( @@ -100,10 +118,7 @@ void hvm_isa_irq_assert( if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq.i) && (hvm_irq->gsi_assert_count[gsi]++ == 0) ) - { - vioapic_irq_positive_edge(d, gsi); - vpic_irq_positive_edge(d, isa_irq); - } + assert_irq(d, gsi, isa_irq); spin_unlock(&d->arch.hvm_domain.irq_lock); } @@ -120,7 +135,7 @@ void hvm_isa_irq_deassert( if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq.i) && (--hvm_irq->gsi_assert_count[gsi] == 0) ) - vpic_irq_negative_edge(d, isa_irq); + deassert_irq(d, isa_irq); spin_unlock(&d->arch.hvm_domain.irq_lock); } |