diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-06-20 11:50:16 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-06-20 11:50:16 +0100 |
commit | 19636447b80747cd9da57cd540f09f475b13cfce (patch) | |
tree | be76ad344ed33741fd7f70b231b4563202791ee0 /xen/arch/x86/hvm/irq.c | |
parent | eed63189dabd90abe422b0e94ab8854783329bed (diff) | |
download | xen-19636447b80747cd9da57cd540f09f475b13cfce.tar.gz xen-19636447b80747cd9da57cd540f09f475b13cfce.tar.bz2 xen-19636447b80747cd9da57cd540f09f475b13cfce.zip |
hvm: Support injection of virtual NMIs and clean up ExtInt handling in general.
Signed-off-by: Keir Fraser <keir@xensource.com>
Diffstat (limited to 'xen/arch/x86/hvm/irq.c')
-rw-r--r-- | xen/arch/x86/hvm/irq.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index c6c3e7c906..6494ea8567 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -285,43 +285,49 @@ void hvm_set_callback_via(struct domain *d, uint64_t via) } } -int cpu_has_pending_irq(struct vcpu *v) +enum hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v) { struct hvm_domain *plat = &v->domain->arch.hvm_domain; - /* APIC */ + if ( unlikely(v->arch.hvm_vcpu.nmi_pending) ) + return hvm_intack_nmi; + if ( vlapic_has_interrupt(v) != -1 ) - return 1; + return hvm_intack_lapic; - /* PIC */ if ( !vlapic_accept_pic_intr(v) ) - return 0; + return hvm_intack_none; - return plat->vpic[0].int_output; + return plat->vpic[0].int_output ? hvm_intack_pic : hvm_intack_none; } -int cpu_get_interrupt(struct vcpu *v, int *type) +int hvm_vcpu_ack_pending_irq(struct vcpu *v, enum hvm_intack type, int *vector) { - int vector; - - if ( (vector = cpu_get_apic_interrupt(v, type)) != -1 ) - return vector; - - if ( (v->vcpu_id == 0) && - ((vector = cpu_get_pic_interrupt(v, type)) != -1) ) - return vector; + switch ( type ) + { + case hvm_intack_nmi: + return test_and_clear_bool(v->arch.hvm_vcpu.nmi_pending); + case hvm_intack_lapic: + return ((*vector = cpu_get_apic_interrupt(v)) != -1); + case hvm_intack_pic: + ASSERT(v->vcpu_id == 0); + return ((*vector = cpu_get_pic_interrupt(v)) != -1); + default: + break; + } - return -1; + return 0; } -int get_isa_irq_vector(struct vcpu *v, int isa_irq, int type) +int get_isa_irq_vector(struct vcpu *v, int isa_irq, enum hvm_intack src) { unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq); - if ( type == APIC_DM_EXTINT ) + if ( src == hvm_intack_pic ) return (v->domain->arch.hvm_domain.vpic[isa_irq >> 3].irq_base + (isa_irq & 7)); + ASSERT(src == hvm_intack_lapic); return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector; } @@ -337,19 +343,20 @@ int is_isa_irq_masked(struct vcpu *v, int isa_irq) domain_vioapic(v->domain)->redirtbl[gsi].fields.mask); } -/* - * TODO: 1. Should not need special treatment of event-channel events. - * 2. Should take notice of interrupt shadows (or clear them). - */ int hvm_local_events_need_delivery(struct vcpu *v) { - int pending; + enum hvm_intack type; + + /* TODO: Get rid of event-channel special case. */ + if ( vcpu_info(v, evtchn_upcall_pending) ) + type = hvm_intack_pic; + else + type = hvm_vcpu_has_pending_irq(v); - pending = (vcpu_info(v, evtchn_upcall_pending) || cpu_has_pending_irq(v)); - if ( unlikely(pending) ) - pending = hvm_interrupts_enabled(v); + if ( likely(type == hvm_intack_none) ) + return 0; - return pending; + return hvm_interrupts_enabled(v, type); } #if 0 /* Keep for debugging */ |