aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c52
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
481static void apic_send_ipi(struct kvm_lapic *apic) 479static 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
512static u32 apic_get_tmcct(struct kvm_lapic *apic) 508static 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
1161void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) 1158void __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
1251int 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
1264int 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}