diff options
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 858432287ab..93c15743f1e 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 | ||
@@ -1081,6 +1088,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) | |||
1081 | apic_update_ppr(apic); | 1088 | apic_update_ppr(apic); |
1082 | 1089 | ||
1083 | vcpu->arch.apic_arb_prio = 0; | 1090 | vcpu->arch.apic_arb_prio = 0; |
1091 | vcpu->arch.apic_attention = 0; | ||
1084 | 1092 | ||
1085 | apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr=" | 1093 | apic_debug(KERN_INFO "%s: vcpu=%p, id=%d, base_msr=" |
1086 | "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__, | 1094 | "0x%016" PRIx64 ", base_address=0x%0lx.\n", __func__, |
@@ -1280,7 +1288,7 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) | |||
1280 | u32 data; | 1288 | u32 data; |
1281 | void *vapic; | 1289 | void *vapic; |
1282 | 1290 | ||
1283 | if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr) | 1291 | if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention)) |
1284 | return; | 1292 | return; |
1285 | 1293 | ||
1286 | vapic = kmap_atomic(vcpu->arch.apic->vapic_page); | 1294 | vapic = kmap_atomic(vcpu->arch.apic->vapic_page); |
@@ -1297,7 +1305,7 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) | |||
1297 | struct kvm_lapic *apic; | 1305 | struct kvm_lapic *apic; |
1298 | void *vapic; | 1306 | void *vapic; |
1299 | 1307 | ||
1300 | if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr) | 1308 | if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention)) |
1301 | return; | 1309 | return; |
1302 | 1310 | ||
1303 | apic = vcpu->arch.apic; | 1311 | apic = vcpu->arch.apic; |
@@ -1317,10 +1325,11 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) | |||
1317 | 1325 | ||
1318 | void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) | 1326 | void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) |
1319 | { | 1327 | { |
1320 | if (!irqchip_in_kernel(vcpu->kvm)) | ||
1321 | return; | ||
1322 | |||
1323 | vcpu->arch.apic->vapic_addr = vapic_addr; | 1328 | vcpu->arch.apic->vapic_addr = vapic_addr; |
1329 | if (vapic_addr) | ||
1330 | __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention); | ||
1331 | else | ||
1332 | __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention); | ||
1324 | } | 1333 | } |
1325 | 1334 | ||
1326 | int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) | 1335 | int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) |