aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-03-18 07:00:14 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-03-21 05:20:16 -0400
commit44847dea79751e95665a439f8c63a65e51da8e1f (patch)
tree1329f713872d1034bfb2c1b80d483ffa0e72777c /virt
parent0bc830b05c667218d703f2026ec866c49df974fc (diff)
KVM: ioapic: extract body of kvm_ioapic_set_irq
We will reuse it to process a nonzero IRR that is passed to KVM_SET_IRQCHIP. Reviewed-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/ioapic.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index 25e16a6898ed..270f7fe73f39 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -163,6 +163,55 @@ static bool rtc_irq_check_coalesced(struct kvm_ioapic *ioapic)
163 return false; 163 return false;
164} 164}
165 165
166static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq,
167 int irq_level, bool line_status)
168{
169 union kvm_ioapic_redirect_entry entry;
170 u32 mask = 1 << irq;
171 u32 old_irr;
172 int edge, ret;
173
174 entry = ioapic->redirtbl[irq];
175 edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
176
177 if (!irq_level) {
178 ioapic->irr &= ~mask;
179 ret = 1;
180 goto out;
181 }
182
183 /*
184 * Return 0 for coalesced interrupts; for edge-triggered interrupts,
185 * this only happens if a previous edge has not been delivered due
186 * do masking. For level interrupts, the remote_irr field tells
187 * us if the interrupt is waiting for an EOI.
188 *
189 * RTC is special: it is edge-triggered, but userspace likes to know
190 * if it has been already ack-ed via EOI because coalesced RTC
191 * interrupts lead to time drift in Windows guests. So we track
192 * EOI manually for the RTC interrupt.
193 */
194 if (irq == RTC_GSI && line_status &&
195 rtc_irq_check_coalesced(ioapic)) {
196 ret = 0;
197 goto out;
198 }
199
200 old_irr = ioapic->irr;
201 ioapic->irr |= mask;
202 if ((edge && old_irr == ioapic->irr) ||
203 (!edge && entry.fields.remote_irr)) {
204 ret = 0;
205 goto out;
206 }
207
208 ret = ioapic_service(ioapic, irq, line_status);
209
210out:
211 trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0);
212 return ret;
213}
214
166static void update_handled_vectors(struct kvm_ioapic *ioapic) 215static void update_handled_vectors(struct kvm_ioapic *ioapic)
167{ 216{
168 DECLARE_BITMAP(handled_vectors, 256); 217 DECLARE_BITMAP(handled_vectors, 256);
@@ -308,38 +357,15 @@ static int ioapic_service(struct kvm_ioapic *ioapic, int irq, bool line_status)
308int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, 357int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id,
309 int level, bool line_status) 358 int level, bool line_status)
310{ 359{
311 u32 old_irr;
312 u32 mask = 1 << irq;
313 union kvm_ioapic_redirect_entry entry;
314 int ret, irq_level; 360 int ret, irq_level;
315 361
316 BUG_ON(irq < 0 || irq >= IOAPIC_NUM_PINS); 362 BUG_ON(irq < 0 || irq >= IOAPIC_NUM_PINS);
317 363
318 spin_lock(&ioapic->lock); 364 spin_lock(&ioapic->lock);
319 old_irr = ioapic->irr;
320 irq_level = __kvm_irq_line_state(&ioapic->irq_states[irq], 365 irq_level = __kvm_irq_line_state(&ioapic->irq_states[irq],
321 irq_source_id, level); 366 irq_source_id, level);
322 entry = ioapic->redirtbl[irq]; 367 ret = ioapic_set_irq(ioapic, irq, irq_level, line_status);
323 if (!irq_level) {
324 ioapic->irr &= ~mask;
325 ret = 1;
326 } else {
327 int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG);
328 368
329 if (irq == RTC_GSI && line_status &&
330 rtc_irq_check_coalesced(ioapic)) {
331 ret = 0; /* coalesced */
332 goto out;
333 }
334 ioapic->irr |= mask;
335 if ((edge && old_irr != ioapic->irr) ||
336 (!edge && !entry.fields.remote_irr))
337 ret = ioapic_service(ioapic, irq, line_status);
338 else
339 ret = 0; /* report coalesced interrupt */
340 }
341out:
342 trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0);
343 spin_unlock(&ioapic->lock); 369 spin_unlock(&ioapic->lock);
344 370
345 return ret; 371 return ret;