diff options
-rw-r--r-- | arch/x86/kvm/lapic.c | 19 | ||||
-rw-r--r-- | virt/kvm/ioapic.c | 10 | ||||
-rw-r--r-- | virt/kvm/ioapic.h | 1 |
3 files changed, 21 insertions, 9 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 858432287ab6..992b4eaae684 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -92,6 +92,11 @@ static inline int apic_test_and_clear_vector(int vec, void *bitmap) | |||
92 | return test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 92 | return test_and_clear_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
93 | } | 93 | } |
94 | 94 | ||
95 | static inline int apic_test_vector(int vec, void *bitmap) | ||
96 | { | ||
97 | return test_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | ||
98 | } | ||
99 | |||
95 | static inline void apic_set_vector(int vec, void *bitmap) | 100 | static inline void apic_set_vector(int vec, void *bitmap) |
96 | { | 101 | { |
97 | set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); | 102 | set_bit(VEC_POS(vec), (bitmap) + REG_POS(vec)); |
@@ -480,7 +485,6 @@ int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2) | |||
480 | static void apic_set_eoi(struct kvm_lapic *apic) | 485 | static void apic_set_eoi(struct kvm_lapic *apic) |
481 | { | 486 | { |
482 | int vector = apic_find_highest_isr(apic); | 487 | int vector = apic_find_highest_isr(apic); |
483 | int trigger_mode; | ||
484 | /* | 488 | /* |
485 | * Not every write EOI will has corresponding ISR, | 489 | * Not every write EOI will has corresponding ISR, |
486 | * one example is when Kernel check timer on setup_IO_APIC | 490 | * one example is when Kernel check timer on setup_IO_APIC |
@@ -491,12 +495,15 @@ static void apic_set_eoi(struct kvm_lapic *apic) | |||
491 | apic_clear_vector(vector, apic->regs + APIC_ISR); | 495 | apic_clear_vector(vector, apic->regs + APIC_ISR); |
492 | apic_update_ppr(apic); | 496 | apic_update_ppr(apic); |
493 | 497 | ||
494 | if (apic_test_and_clear_vector(vector, apic->regs + APIC_TMR)) | 498 | if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) && |
495 | trigger_mode = IOAPIC_LEVEL_TRIG; | 499 | kvm_ioapic_handles_vector(apic->vcpu->kvm, vector)) { |
496 | else | 500 | int trigger_mode; |
497 | trigger_mode = IOAPIC_EDGE_TRIG; | 501 | if (apic_test_vector(vector, apic->regs + APIC_TMR)) |
498 | if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)) | 502 | trigger_mode = IOAPIC_LEVEL_TRIG; |
503 | else | ||
504 | trigger_mode = IOAPIC_EDGE_TRIG; | ||
499 | kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); | 505 | kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); |
506 | } | ||
500 | kvm_make_request(KVM_REQ_EVENT, apic->vcpu); | 507 | kvm_make_request(KVM_REQ_EVENT, apic->vcpu); |
501 | } | 508 | } |
502 | 509 | ||
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index dcaf272c26c0..26fd54dc459e 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -254,13 +254,17 @@ static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, | |||
254 | } | 254 | } |
255 | } | 255 | } |
256 | 256 | ||
257 | bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector) | ||
258 | { | ||
259 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; | ||
260 | smp_rmb(); | ||
261 | return test_bit(vector, ioapic->handled_vectors); | ||
262 | } | ||
263 | |||
257 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode) | 264 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode) |
258 | { | 265 | { |
259 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; | 266 | struct kvm_ioapic *ioapic = kvm->arch.vioapic; |
260 | 267 | ||
261 | smp_rmb(); | ||
262 | if (!test_bit(vector, ioapic->handled_vectors)) | ||
263 | return; | ||
264 | spin_lock(&ioapic->lock); | 268 | spin_lock(&ioapic->lock); |
265 | __kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); | 269 | __kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); |
266 | spin_unlock(&ioapic->lock); | 270 | spin_unlock(&ioapic->lock); |
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 0b190c34ccc3..32872a09b63f 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h | |||
@@ -71,6 +71,7 @@ int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | |||
71 | int short_hand, int dest, int dest_mode); | 71 | int short_hand, int dest, int dest_mode); |
72 | int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2); | 72 | int kvm_apic_compare_prio(struct kvm_vcpu *vcpu1, struct kvm_vcpu *vcpu2); |
73 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); | 73 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); |
74 | bool kvm_ioapic_handles_vector(struct kvm *kvm, int vector); | ||
74 | int kvm_ioapic_init(struct kvm *kvm); | 75 | int kvm_ioapic_init(struct kvm *kvm); |
75 | void kvm_ioapic_destroy(struct kvm *kvm); | 76 | void kvm_ioapic_destroy(struct kvm *kvm); |
76 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); | 77 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); |