diff options
author | Yang Zhang <yang.z.zhang@Intel.com> | 2013-04-11 07:21:40 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-04-15 22:20:34 -0400 |
commit | aa2fbe6d44892070d78995f0df875ce930904e29 (patch) | |
tree | bc2350a65c4e656df5597ebe4111bcfd98116bfe /virt/kvm/ioapic.c | |
parent | f3bff6318fa0f54956b02ed451d9b120441006ea (diff) |
KVM: Let ioapic know the irq line status
Userspace may deliver RTC interrupt without query the status. So we
want to track RTC EOI for this case.
Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com>
Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r-- | virt/kvm/ioapic.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 76528fff252d..a49fcd55b378 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -50,7 +50,8 @@ | |||
50 | #else | 50 | #else |
51 | #define ioapic_debug(fmt, arg...) | 51 | #define ioapic_debug(fmt, arg...) |
52 | #endif | 52 | #endif |
53 | static int ioapic_deliver(struct kvm_ioapic *vioapic, int irq); | 53 | static int ioapic_deliver(struct kvm_ioapic *vioapic, int irq, |
54 | bool line_status); | ||
54 | 55 | ||
55 | static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, | 56 | static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, |
56 | unsigned long addr, | 57 | unsigned long addr, |
@@ -146,7 +147,8 @@ static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic) | |||
146 | __rtc_irq_eoi_tracking_restore_one(vcpu); | 147 | __rtc_irq_eoi_tracking_restore_one(vcpu); |
147 | } | 148 | } |
148 | 149 | ||
149 | static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) | 150 | static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx, |
151 | bool line_status) | ||
150 | { | 152 | { |
151 | union kvm_ioapic_redirect_entry *pent; | 153 | union kvm_ioapic_redirect_entry *pent; |
152 | int injected = -1; | 154 | int injected = -1; |
@@ -154,7 +156,7 @@ static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) | |||
154 | pent = &ioapic->redirtbl[idx]; | 156 | pent = &ioapic->redirtbl[idx]; |
155 | 157 | ||
156 | if (!pent->fields.mask) { | 158 | if (!pent->fields.mask) { |
157 | injected = ioapic_deliver(ioapic, idx); | 159 | injected = ioapic_deliver(ioapic, idx, line_status); |
158 | if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) | 160 | if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) |
159 | pent->fields.remote_irr = 1; | 161 | pent->fields.remote_irr = 1; |
160 | } | 162 | } |
@@ -248,13 +250,13 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | |||
248 | kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after); | 250 | kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after); |
249 | if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG | 251 | if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG |
250 | && ioapic->irr & (1 << index)) | 252 | && ioapic->irr & (1 << index)) |
251 | ioapic_service(ioapic, index); | 253 | ioapic_service(ioapic, index, false); |
252 | kvm_ioapic_make_eoibitmap_request(ioapic->kvm); | 254 | kvm_ioapic_make_eoibitmap_request(ioapic->kvm); |
253 | break; | 255 | break; |
254 | } | 256 | } |
255 | } | 257 | } |
256 | 258 | ||
257 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | 259 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq, bool line_status) |
258 | { | 260 | { |
259 | union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; | 261 | union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; |
260 | struct kvm_lapic_irq irqe; | 262 | struct kvm_lapic_irq irqe; |
@@ -277,7 +279,7 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | |||
277 | } | 279 | } |
278 | 280 | ||
279 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, | 281 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, |
280 | int level) | 282 | int level, bool line_status) |
281 | { | 283 | { |
282 | u32 old_irr; | 284 | u32 old_irr; |
283 | u32 mask = 1 << irq; | 285 | u32 mask = 1 << irq; |
@@ -300,7 +302,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int irq_source_id, | |||
300 | ioapic->irr |= mask; | 302 | ioapic->irr |= mask; |
301 | if ((edge && old_irr != ioapic->irr) || | 303 | if ((edge && old_irr != ioapic->irr) || |
302 | (!edge && !entry.fields.remote_irr)) | 304 | (!edge && !entry.fields.remote_irr)) |
303 | ret = ioapic_service(ioapic, irq); | 305 | ret = ioapic_service(ioapic, irq, line_status); |
304 | else | 306 | else |
305 | ret = 0; /* report coalesced interrupt */ | 307 | ret = 0; /* report coalesced interrupt */ |
306 | } | 308 | } |
@@ -349,7 +351,7 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, | |||
349 | ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); | 351 | ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); |
350 | ent->fields.remote_irr = 0; | 352 | ent->fields.remote_irr = 0; |
351 | if (!ent->fields.mask && (ioapic->irr & (1 << i))) | 353 | if (!ent->fields.mask && (ioapic->irr & (1 << i))) |
352 | ioapic_service(ioapic, i); | 354 | ioapic_service(ioapic, i, false); |
353 | } | 355 | } |
354 | } | 356 | } |
355 | 357 | ||