diff options
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 23c217692ea9..1eb7a4ae0c9c 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -26,13 +26,13 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/math64.h> | 28 | #include <linux/math64.h> |
29 | #include <linux/slab.h> | ||
29 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
30 | #include <asm/msr.h> | 31 | #include <asm/msr.h> |
31 | #include <asm/page.h> | 32 | #include <asm/page.h> |
32 | #include <asm/current.h> | 33 | #include <asm/current.h> |
33 | #include <asm/apicdef.h> | 34 | #include <asm/apicdef.h> |
34 | #include <asm/atomic.h> | 35 | #include <asm/atomic.h> |
35 | #include <asm/apicdef.h> | ||
36 | #include "kvm_cache_regs.h" | 36 | #include "kvm_cache_regs.h" |
37 | #include "irq.h" | 37 | #include "irq.h" |
38 | #include "trace.h" | 38 | #include "trace.h" |
@@ -374,6 +374,12 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
374 | if (unlikely(!apic_enabled(apic))) | 374 | if (unlikely(!apic_enabled(apic))) |
375 | break; | 375 | break; |
376 | 376 | ||
377 | if (trig_mode) { | ||
378 | apic_debug("level trig mode for vector %d", vector); | ||
379 | apic_set_vector(vector, apic->regs + APIC_TMR); | ||
380 | } else | ||
381 | apic_clear_vector(vector, apic->regs + APIC_TMR); | ||
382 | |||
377 | result = !apic_test_and_set_irr(vector, apic); | 383 | result = !apic_test_and_set_irr(vector, apic); |
378 | trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode, | 384 | trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode, |
379 | trig_mode, vector, !result); | 385 | trig_mode, vector, !result); |
@@ -384,11 +390,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, | |||
384 | break; | 390 | break; |
385 | } | 391 | } |
386 | 392 | ||
387 | if (trig_mode) { | ||
388 | apic_debug("level trig mode for vector %d", vector); | ||
389 | apic_set_vector(vector, apic->regs + APIC_TMR); | ||
390 | } else | ||
391 | apic_clear_vector(vector, apic->regs + APIC_TMR); | ||
392 | kvm_vcpu_kick(vcpu); | 393 | kvm_vcpu_kick(vcpu); |
393 | break; | 394 | break; |
394 | 395 | ||
@@ -471,11 +472,8 @@ static void apic_set_eoi(struct kvm_lapic *apic) | |||
471 | trigger_mode = IOAPIC_LEVEL_TRIG; | 472 | trigger_mode = IOAPIC_LEVEL_TRIG; |
472 | else | 473 | else |
473 | trigger_mode = IOAPIC_EDGE_TRIG; | 474 | trigger_mode = IOAPIC_EDGE_TRIG; |
474 | if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)) { | 475 | if (!(apic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)) |
475 | mutex_lock(&apic->vcpu->kvm->irq_lock); | ||
476 | kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); | 476 | kvm_ioapic_update_eoi(apic->vcpu->kvm, vector, trigger_mode); |
477 | mutex_unlock(&apic->vcpu->kvm->irq_lock); | ||
478 | } | ||
479 | } | 477 | } |
480 | 478 | ||
481 | static void apic_send_ipi(struct kvm_lapic *apic) | 479 | static void apic_send_ipi(struct kvm_lapic *apic) |
@@ -504,9 +502,7 @@ static void apic_send_ipi(struct kvm_lapic *apic) | |||
504 | irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode, | 502 | irq.trig_mode, irq.level, irq.dest_mode, irq.delivery_mode, |
505 | irq.vector); | 503 | irq.vector); |
506 | 504 | ||
507 | mutex_lock(&apic->vcpu->kvm->irq_lock); | ||
508 | kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq); | 505 | kvm_irq_delivery_to_apic(apic->vcpu->kvm, apic, &irq); |
509 | mutex_unlock(&apic->vcpu->kvm->irq_lock); | ||
510 | } | 506 | } |
511 | 507 | ||
512 | static u32 apic_get_tmcct(struct kvm_lapic *apic) | 508 | static u32 apic_get_tmcct(struct kvm_lapic *apic) |
@@ -1156,6 +1152,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu) | |||
1156 | hrtimer_cancel(&apic->lapic_timer.timer); | 1152 | hrtimer_cancel(&apic->lapic_timer.timer); |
1157 | update_divide_count(apic); | 1153 | update_divide_count(apic); |
1158 | start_apic_timer(apic); | 1154 | start_apic_timer(apic); |
1155 | apic->irr_pending = true; | ||
1159 | } | 1156 | } |
1160 | 1157 | ||
1161 | void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) | 1158 | void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) |
@@ -1250,3 +1247,34 @@ int kvm_x2apic_msr_read(struct kvm_vcpu *vcpu, u32 msr, u64 *data) | |||
1250 | 1247 | ||
1251 | return 0; | 1248 | return 0; |
1252 | } | 1249 | } |
1250 | |||
1251 | int kvm_hv_vapic_msr_write(struct kvm_vcpu *vcpu, u32 reg, u64 data) | ||
1252 | { | ||
1253 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
1254 | |||
1255 | if (!irqchip_in_kernel(vcpu->kvm)) | ||
1256 | return 1; | ||
1257 | |||
1258 | /* if this is ICR write vector before command */ | ||
1259 | if (reg == APIC_ICR) | ||
1260 | apic_reg_write(apic, APIC_ICR2, (u32)(data >> 32)); | ||
1261 | return apic_reg_write(apic, reg, (u32)data); | ||
1262 | } | ||
1263 | |||
1264 | int kvm_hv_vapic_msr_read(struct kvm_vcpu *vcpu, u32 reg, u64 *data) | ||
1265 | { | ||
1266 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
1267 | u32 low, high = 0; | ||
1268 | |||
1269 | if (!irqchip_in_kernel(vcpu->kvm)) | ||
1270 | return 1; | ||
1271 | |||
1272 | if (apic_reg_read(apic, reg, 4, &low)) | ||
1273 | return 1; | ||
1274 | if (reg == APIC_ICR) | ||
1275 | apic_reg_read(apic, APIC_ICR2, 4, &high); | ||
1276 | |||
1277 | *data = (((u64)high) << 32) | low; | ||
1278 | |||
1279 | return 0; | ||
1280 | } | ||