aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/i8259.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2009-02-04 10:28:14 -0500
committerAvi Kivity <avi@redhat.com>2009-03-24 05:03:11 -0400
commit4925663a079c77d95d8685228ad6675fc5639c8e (patch)
tree52e93df78b23a44ed21d015f835688f673dd351a /arch/x86/kvm/i8259.c
parent452425dbaa1974e9fc489e64a8de46a47b4c2754 (diff)
KVM: Report IRQ injection status to userspace.
IRQ injection status is either -1 (if there was no CPU found that should except the interrupt because IRQ was masked or ioapic was misconfigured or ...) or >= 0 in that case the number indicates to how many CPUs interrupt was injected. If the value is 0 it means that the interrupt was coalesced and probably should be reinjected. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/i8259.c')
-rw-r--r--arch/x86/kvm/i8259.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 93160375c841..b4e662e94ddc 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -77,12 +77,13 @@ void kvm_pic_clear_isr_ack(struct kvm *kvm)
77/* 77/*
78 * set irq level. If an edge is detected, then the IRR is set to 1 78 * set irq level. If an edge is detected, then the IRR is set to 1
79 */ 79 */
80static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) 80static inline int pic_set_irq1(struct kvm_kpic_state *s, int irq, int level)
81{ 81{
82 int mask; 82 int mask, ret = 1;
83 mask = 1 << irq; 83 mask = 1 << irq;
84 if (s->elcr & mask) /* level triggered */ 84 if (s->elcr & mask) /* level triggered */
85 if (level) { 85 if (level) {
86 ret = !(s->irr & mask);
86 s->irr |= mask; 87 s->irr |= mask;
87 s->last_irr |= mask; 88 s->last_irr |= mask;
88 } else { 89 } else {
@@ -91,11 +92,15 @@ static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level)
91 } 92 }
92 else /* edge triggered */ 93 else /* edge triggered */
93 if (level) { 94 if (level) {
94 if ((s->last_irr & mask) == 0) 95 if ((s->last_irr & mask) == 0) {
96 ret = !(s->irr & mask);
95 s->irr |= mask; 97 s->irr |= mask;
98 }
96 s->last_irr |= mask; 99 s->last_irr |= mask;
97 } else 100 } else
98 s->last_irr &= ~mask; 101 s->last_irr &= ~mask;
102
103 return (s->imr & mask) ? -1 : ret;
99} 104}
100 105
101/* 106/*
@@ -172,16 +177,19 @@ void kvm_pic_update_irq(struct kvm_pic *s)
172 pic_unlock(s); 177 pic_unlock(s);
173} 178}
174 179
175void kvm_pic_set_irq(void *opaque, int irq, int level) 180int kvm_pic_set_irq(void *opaque, int irq, int level)
176{ 181{
177 struct kvm_pic *s = opaque; 182 struct kvm_pic *s = opaque;
183 int ret = -1;
178 184
179 pic_lock(s); 185 pic_lock(s);
180 if (irq >= 0 && irq < PIC_NUM_PINS) { 186 if (irq >= 0 && irq < PIC_NUM_PINS) {
181 pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); 187 ret = pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
182 pic_update_irq(s); 188 pic_update_irq(s);
183 } 189 }
184 pic_unlock(s); 190 pic_unlock(s);
191
192 return ret;
185} 193}
186 194
187/* 195/*