aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/irq.c19
-rw-r--r--xen/include/asm-x86/event.h7
2 files changed, 23 insertions, 3 deletions
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index aa531b33fb..a85151eb26 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -337,6 +337,25 @@ 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;
+
+ pending = (vcpu_info(v, evtchn_upcall_pending) || cpu_has_pending_irq(v));
+ if ( unlikely(pending) )
+ {
+ struct cpu_user_regs regs;
+ hvm_store_cpu_guest_regs(v, &regs, NULL);
+ pending = !irq_masked(regs.eflags);
+ }
+
+ return pending;
+}
+
#if 0 /* Keep for debugging */
static void irq_dump(struct domain *d)
{
diff --git a/xen/include/asm-x86/event.h b/xen/include/asm-x86/event.h
index 09440bcc4a..32b157b8db 100644
--- a/xen/include/asm-x86/event.h
+++ b/xen/include/asm-x86/event.h
@@ -35,12 +35,13 @@ static inline void vcpu_mark_events_pending(struct vcpu *v)
vcpu_kick(v);
}
+int hvm_local_events_need_delivery(struct vcpu *v);
static inline int local_events_need_delivery(void)
{
struct vcpu *v = current;
- return ((vcpu_info(v, evtchn_upcall_pending) &&
- !vcpu_info(v, evtchn_upcall_mask)) ||
- (is_hvm_vcpu(v) && cpu_has_pending_irq(v)));
+ return (is_hvm_vcpu(v) ? hvm_local_events_need_delivery(v) :
+ (vcpu_info(v, evtchn_upcall_pending) &&
+ !vcpu_info(v, evtchn_upcall_mask)));
}
static inline int local_event_delivery_is_enabled(void)