aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/i8259.c46
-rw-r--r--xen/arch/x86/hvm/svm/intr.c9
-rw-r--r--xen/arch/x86/hvm/vioapic.c22
-rw-r--r--xen/arch/x86/hvm/vmx/io.c9
-rw-r--r--xen/include/asm-x86/hvm/vioapic.h2
-rw-r--r--xen/include/asm-x86/hvm/vpic.h8
6 files changed, 59 insertions, 37 deletions
diff --git a/xen/arch/x86/hvm/i8259.c b/xen/arch/x86/hvm/i8259.c
index 4e29cbfa85..e90f365044 100644
--- a/xen/arch/x86/hvm/i8259.c
+++ b/xen/arch/x86/hvm/i8259.c
@@ -86,7 +86,7 @@ static int pic_get_irq(PicState *s)
ASSERT(spin_is_locked(&s->pics_state->lock));
- mask = s->irr & ~s->imr;
+ mask = (s->irr|s->irr_xen) & ~s->imr;
priority = get_priority(s, mask);
if (priority == 8)
return -1;
@@ -128,6 +128,32 @@ void pic_update_irq(struct hvm_virpic *s)
}
}
+void pic_set_xen_irq(void *opaque, int irq, int level)
+{
+ struct hvm_virpic *s = opaque;
+ unsigned long flags;
+ PicState *ps;
+
+ spin_lock_irqsave(&s->lock, flags);
+
+ hvm_vioapic_set_xen_irq(current->domain, irq, level);
+
+ /* Set it on the 8259s */
+ ps = &s->pics[irq >> 3];
+ if (!(ps->elcr & (1 << (irq & 7)))) {
+ DPRINTK("edge-triggered override IRQ?\n");
+ domain_crash(current->domain);
+ }
+ if (level) {
+ ps->irr_xen |= 1 << (irq & 7);
+ } else {
+ ps->irr_xen &= ~(1 << (irq & 7));
+ }
+
+ pic_update_irq(s);
+ spin_unlock_irqrestore(&s->lock, flags);
+}
+
void pic_set_irq_new(void *opaque, int irq, int level)
{
struct hvm_virpic *s = opaque;
@@ -136,9 +162,6 @@ void pic_set_irq_new(void *opaque, int irq, int level)
spin_lock_irqsave(&s->lock, flags);
hvm_vioapic_set_irq(current->domain, irq, level);
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
- /* used for IOAPIC irqs */
- if (s->alt_irq_func)
- s->alt_irq_func(s->alt_irq_opaque, irq, level);
pic_update_irq(s);
spin_unlock_irqrestore(&s->lock, flags);
}
@@ -371,6 +394,7 @@ static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
s->pics_state->pics[0].irr &= ~(1 << 2);
}
s->irr &= ~(1 << ret);
+ s->irr_xen &= ~(1 << ret);
s->isr &= ~(1 << ret);
if (addr1 >> 7 || ret != 2)
pic_update_irq(s->pics_state);
@@ -400,7 +424,7 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
if (s->read_reg_select)
ret = s->isr;
else
- ret = s->irr;
+ ret = s->irr | s->irr_xen;
} else {
ret = s->imr;
}
@@ -472,18 +496,6 @@ void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int),
s->irq_request_opaque = irq_request_opaque;
}
-void pic_set_alt_irq_func(struct hvm_virpic *s,
- void (*alt_irq_func)(void *, int, int),
- void *alt_irq_opaque)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->alt_irq_func = alt_irq_func;
- s->alt_irq_opaque = alt_irq_opaque;
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
static int intercept_pic_io(ioreq_t *p)
{
struct hvm_virpic *pic;
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index d053c6d122..1e283d8bbe 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -122,13 +122,8 @@ asmlinkage void svm_intr_assist(void)
}
callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
- if ( callback_irq != 0 &&
- local_events_need_delivery() ) {
- /*inject para-device call back irq*/
- v->vcpu_info->evtchn_upcall_mask = 1;
- pic_set_irq(pic, callback_irq, 0);
- pic_set_irq(pic, callback_irq, 1);
- }
+ if ( callback_irq != 0)
+ pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
if ( cpu_has_pending_irq(v) )
intr_vector = cpu_get_interrupt(v, &intr_type);
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 2999bfe4f1..daa812a6f3 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -479,7 +479,7 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
static int ioapic_get_highest_irq(hvm_vioapic_t *s)
{
- uint32_t irqs = s->irr & ~s->isr & ~s->imr;
+ uint32_t irqs = (s->irr | s->irr_xen) & ~s->isr & ~s->imr;
return fls(irqs) - 1;
}
@@ -501,6 +501,7 @@ static void service_ioapic(hvm_vioapic_t *s)
}
s->irr &= ~(1 << irqno);
+ s->irr_xen &= ~(1 << irqno);
}
}
@@ -526,6 +527,25 @@ void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs)
service_ioapic(s);
}
+void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level)
+{
+ hvm_vioapic_t *s = &d->arch.hvm_domain.vioapic;
+
+ if (!hvm_apic_support(d) || !IOAPICEnabled(s) ||
+ s->redirtbl[irq].RedirForm.mask)
+ return;
+
+ if (s->redirtbl[irq].RedirForm.trigmod != IOAPIC_LEVEL_TRIGGER) {
+ DPRINTK("Forcing edge triggered APIC irq %d?\n", irq);
+ domain_crash(d);
+ }
+
+ if (level)
+ s->irr_xen |= 1 << irq;
+ else
+ s->irr_xen &= ~(1 << irq);
+}
+
void hvm_vioapic_set_irq(struct domain *d, int irq, int level)
{
hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c
index 75632a41d6..ae8d89a31d 100644
--- a/xen/arch/x86/hvm/vmx/io.c
+++ b/xen/arch/x86/hvm/vmx/io.c
@@ -92,13 +92,8 @@ asmlinkage void vmx_intr_assist(void)
}
callback_irq = v->domain->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ];
- if ( callback_irq != 0 &&
- local_events_need_delivery() ) {
- /*inject para-device call back irq*/
- v->vcpu_info->evtchn_upcall_mask = 1;
- pic_set_irq(pic, callback_irq, 0);
- pic_set_irq(pic, callback_irq, 1);
- }
+ if ( callback_irq != 0 )
+ pic_set_xen_irq(pic, callback_irq, local_events_need_delivery());
has_ext_irq = cpu_has_pending_irq(v);
diff --git a/xen/include/asm-x86/hvm/vioapic.h b/xen/include/asm-x86/hvm/vioapic.h
index 72c758c133..b5ec7e4597 100644
--- a/xen/include/asm-x86/hvm/vioapic.h
+++ b/xen/include/asm-x86/hvm/vioapic.h
@@ -88,6 +88,7 @@ typedef union RedirStatus
typedef struct hvm_vioapic {
uint32_t irr;
+ uint32_t irr_xen; /* interrupts forced on by the hypervisor. */
uint32_t isr; /* This is used for level trigger */
uint32_t imr;
uint32_t ioregsel;
@@ -105,6 +106,7 @@ hvm_vioapic_t *hvm_vioapic_init(struct domain *d);
void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs);
+void hvm_vioapic_set_xen_irq(struct domain *d, int irq, int level);
void hvm_vioapic_set_irq(struct domain *d, int irq, int level);
int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v);
diff --git a/xen/include/asm-x86/hvm/vpic.h b/xen/include/asm-x86/hvm/vpic.h
index 8fa5daa5ad..f6a488e339 100644
--- a/xen/include/asm-x86/hvm/vpic.h
+++ b/xen/include/asm-x86/hvm/vpic.h
@@ -34,6 +34,8 @@ typedef struct IOAPICState IOAPICState;
typedef struct PicState {
uint8_t last_irr; /* edge detection */
uint8_t irr; /* interrupt request register */
+ uint8_t irr_xen; /* interrupts forced on by the hypervisor e.g.
+ the callback irq. */
uint8_t imr; /* interrupt mask register */
uint8_t isr; /* interrupt service register */
uint8_t priority_add; /* highest irq priority */
@@ -58,20 +60,16 @@ struct hvm_virpic {
void (*irq_request)(void *opaque, int level);
void *irq_request_opaque;
/* IOAPIC callback support */
- void (*alt_irq_func)(void *opaque, int irq_num, int level);
- void *alt_irq_opaque;
spinlock_t lock;
};
+void pic_set_xen_irq(void *opaque, int irq, int level);
void pic_set_irq(struct hvm_virpic *s, int irq, int level);
void pic_set_irq_new(void *opaque, int irq, int level);
void pic_init(struct hvm_virpic *s,
void (*irq_request)(void *, int),
void *irq_request_opaque);
-void pic_set_alt_irq_func(struct hvm_virpic *s,
- void (*alt_irq_func)(void *, int, int),
- void *alt_irq_opaque);
int pic_read_irq(struct hvm_virpic *s);
void pic_update_irq(struct hvm_virpic *s); /* Caller must hold s->lock */
uint32_t pic_intack_read(struct hvm_virpic *s);