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.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 08e8a899e005..b8345dd41b25 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -112,17 +112,6 @@ static inline int __apic_test_and_clear_vector(int vec, void *bitmap)
112struct static_key_deferred apic_hw_disabled __read_mostly; 112struct static_key_deferred apic_hw_disabled __read_mostly;
113struct static_key_deferred apic_sw_disabled __read_mostly; 113struct static_key_deferred apic_sw_disabled __read_mostly;
114 114
115static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
116{
117 if ((kvm_apic_get_reg(apic, APIC_SPIV) ^ val) & APIC_SPIV_APIC_ENABLED) {
118 if (val & APIC_SPIV_APIC_ENABLED)
119 static_key_slow_dec_deferred(&apic_sw_disabled);
120 else
121 static_key_slow_inc(&apic_sw_disabled.key);
122 }
123 apic_set_reg(apic, APIC_SPIV, val);
124}
125
126static inline int apic_enabled(struct kvm_lapic *apic) 115static inline int apic_enabled(struct kvm_lapic *apic)
127{ 116{
128 return kvm_apic_sw_enabled(apic) && kvm_apic_hw_enabled(apic); 117 return kvm_apic_sw_enabled(apic) && kvm_apic_hw_enabled(apic);
@@ -210,6 +199,20 @@ out:
210 kvm_vcpu_request_scan_ioapic(kvm); 199 kvm_vcpu_request_scan_ioapic(kvm);
211} 200}
212 201
202static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
203{
204 u32 prev = kvm_apic_get_reg(apic, APIC_SPIV);
205
206 apic_set_reg(apic, APIC_SPIV, val);
207 if ((prev ^ val) & APIC_SPIV_APIC_ENABLED) {
208 if (val & APIC_SPIV_APIC_ENABLED) {
209 static_key_slow_dec_deferred(&apic_sw_disabled);
210 recalculate_apic_map(apic->vcpu->kvm);
211 } else
212 static_key_slow_inc(&apic_sw_disabled.key);
213 }
214}
215
213static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id) 216static inline void kvm_apic_set_id(struct kvm_lapic *apic, u8 id)
214{ 217{
215 apic_set_reg(apic, APIC_ID, id << 24); 218 apic_set_reg(apic, APIC_ID, id << 24);
@@ -706,6 +709,8 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
706 int result = 0; 709 int result = 0;
707 struct kvm_vcpu *vcpu = apic->vcpu; 710 struct kvm_vcpu *vcpu = apic->vcpu;
708 711
712 trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
713 trig_mode, vector);
709 switch (delivery_mode) { 714 switch (delivery_mode) {
710 case APIC_DM_LOWEST: 715 case APIC_DM_LOWEST:
711 vcpu->arch.apic_arb_prio++; 716 vcpu->arch.apic_arb_prio++;
@@ -727,8 +732,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
727 kvm_make_request(KVM_REQ_EVENT, vcpu); 732 kvm_make_request(KVM_REQ_EVENT, vcpu);
728 kvm_vcpu_kick(vcpu); 733 kvm_vcpu_kick(vcpu);
729 } 734 }
730 trace_kvm_apic_accept_irq(vcpu->vcpu_id, delivery_mode,
731 trig_mode, vector, false);
732 break; 735 break;
733 736
734 case APIC_DM_REMRD: 737 case APIC_DM_REMRD:
@@ -1352,6 +1355,9 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data)
1352 return; 1355 return;
1353 1356
1354 hrtimer_cancel(&apic->lapic_timer.timer); 1357 hrtimer_cancel(&apic->lapic_timer.timer);
1358 /* Inject here so clearing tscdeadline won't override new value */
1359 if (apic_has_pending_timer(vcpu))
1360 kvm_inject_apic_timer_irqs(vcpu);
1355 apic->lapic_timer.tscdeadline = data; 1361 apic->lapic_timer.tscdeadline = data;
1356 start_apic_timer(apic); 1362 start_apic_timer(apic);
1357} 1363}
@@ -1639,6 +1645,8 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
1639 1645
1640 if (atomic_read(&apic->lapic_timer.pending) > 0) { 1646 if (atomic_read(&apic->lapic_timer.pending) > 0) {
1641 kvm_apic_local_deliver(apic, APIC_LVTT); 1647 kvm_apic_local_deliver(apic, APIC_LVTT);
1648 if (apic_lvtt_tscdeadline(apic))
1649 apic->lapic_timer.tscdeadline = 0;
1642 atomic_set(&apic->lapic_timer.pending, 0); 1650 atomic_set(&apic->lapic_timer.pending, 0);
1643 } 1651 }
1644} 1652}