diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/kvm/lapic.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 629af0f1c5c4..4c7deb4f78a1 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -1090,6 +1090,17 @@ static void update_divide_count(struct kvm_lapic *apic) | |||
1090 | apic->divide_count); | 1090 | apic->divide_count); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | static void apic_update_lvtt(struct kvm_lapic *apic) | ||
1094 | { | ||
1095 | u32 timer_mode = kvm_apic_get_reg(apic, APIC_LVTT) & | ||
1096 | apic->lapic_timer.timer_mode_mask; | ||
1097 | |||
1098 | if (apic->lapic_timer.timer_mode != timer_mode) { | ||
1099 | apic->lapic_timer.timer_mode = timer_mode; | ||
1100 | hrtimer_cancel(&apic->lapic_timer.timer); | ||
1101 | } | ||
1102 | } | ||
1103 | |||
1093 | static void apic_timer_expired(struct kvm_lapic *apic) | 1104 | static void apic_timer_expired(struct kvm_lapic *apic) |
1094 | { | 1105 | { |
1095 | struct kvm_vcpu *vcpu = apic->vcpu; | 1106 | struct kvm_vcpu *vcpu = apic->vcpu; |
@@ -1298,6 +1309,7 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1298 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, | 1309 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, |
1299 | lvt_val | APIC_LVT_MASKED); | 1310 | lvt_val | APIC_LVT_MASKED); |
1300 | } | 1311 | } |
1312 | apic_update_lvtt(apic); | ||
1301 | atomic_set(&apic->lapic_timer.pending, 0); | 1313 | atomic_set(&apic->lapic_timer.pending, 0); |
1302 | 1314 | ||
1303 | } | 1315 | } |
@@ -1330,20 +1342,13 @@ static int apic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) | |||
1330 | 1342 | ||
1331 | break; | 1343 | break; |
1332 | 1344 | ||
1333 | case APIC_LVTT: { | 1345 | case APIC_LVTT: |
1334 | u32 timer_mode = val & apic->lapic_timer.timer_mode_mask; | ||
1335 | |||
1336 | if (apic->lapic_timer.timer_mode != timer_mode) { | ||
1337 | apic->lapic_timer.timer_mode = timer_mode; | ||
1338 | hrtimer_cancel(&apic->lapic_timer.timer); | ||
1339 | } | ||
1340 | |||
1341 | if (!kvm_apic_sw_enabled(apic)) | 1346 | if (!kvm_apic_sw_enabled(apic)) |
1342 | val |= APIC_LVT_MASKED; | 1347 | val |= APIC_LVT_MASKED; |
1343 | val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); | 1348 | val &= (apic_lvt_mask[0] | apic->lapic_timer.timer_mode_mask); |
1344 | apic_set_reg(apic, APIC_LVTT, val); | 1349 | apic_set_reg(apic, APIC_LVTT, val); |
1350 | apic_update_lvtt(apic); | ||
1345 | break; | 1351 | break; |
1346 | } | ||
1347 | 1352 | ||
1348 | case APIC_TMICT: | 1353 | case APIC_TMICT: |
1349 | if (apic_lvtt_tscdeadline(apic)) | 1354 | if (apic_lvtt_tscdeadline(apic)) |
@@ -1576,7 +1581,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) | |||
1576 | 1581 | ||
1577 | for (i = 0; i < APIC_LVT_NUM; i++) | 1582 | for (i = 0; i < APIC_LVT_NUM; i++) |
1578 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); | 1583 | apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED); |
1579 | apic->lapic_timer.timer_mode = 0; | 1584 | apic_update_lvtt(apic); |
1580 | apic_set_reg(apic, APIC_LVT0, | 1585 | apic_set_reg(apic, APIC_LVT0, |
1581 | SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); | 1586 | SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT)); |
1582 | 1587 | ||
@@ -1802,6 +1807,7 @@ void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu, | |||
1802 | 1807 | ||
1803 | apic_update_ppr(apic); | 1808 | apic_update_ppr(apic); |
1804 | hrtimer_cancel(&apic->lapic_timer.timer); | 1809 | hrtimer_cancel(&apic->lapic_timer.timer); |
1810 | apic_update_lvtt(apic); | ||
1805 | update_divide_count(apic); | 1811 | update_divide_count(apic); |
1806 | start_apic_timer(apic); | 1812 | start_apic_timer(apic); |
1807 | apic->irr_pending = true; | 1813 | apic->irr_pending = true; |