diff options
author | Gleb Natapov <gleb@redhat.com> | 2009-02-04 10:28:14 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:03:11 -0400 |
commit | 4925663a079c77d95d8685228ad6675fc5639c8e (patch) | |
tree | 52e93df78b23a44ed21d015f835688f673dd351a /arch/x86/kvm/i8259.c | |
parent | 452425dbaa1974e9fc489e64a8de46a47b4c2754 (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.c | 18 |
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 | */ |
80 | static inline void pic_set_irq1(struct kvm_kpic_state *s, int irq, int level) | 80 | static 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 | ||
175 | void kvm_pic_set_irq(void *opaque, int irq, int level) | 180 | int 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 | /* |