aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-16 16:00:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-16 16:00:24 -0500
commit974aa5630b318938273d7efe7a2cf031c7b927db (patch)
treeb79803c07b9c16d87058ce69f80ebe173cdfd838 /arch/x86/kvm/lapic.c
parent441692aafc1731087bbaf657a8b6059d95c2a6df (diff)
parenta6014f1ab7088dc02b58991cfb6b32a34afdbf12 (diff)
Merge tag 'kvm-4.15-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM updates from Radim Krčmář: "First batch of KVM changes for 4.15 Common: - Python 3 support in kvm_stat - Accounting of slabs to kmemcg ARM: - Optimized arch timer handling for KVM/ARM - Improvements to the VGIC ITS code and introduction of an ITS reset ioctl - Unification of the 32-bit fault injection logic - More exact external abort matching logic PPC: - Support for running hashed page table (HPT) MMU mode on a host that is using the radix MMU mode; single threaded mode on POWER 9 is added as a pre-requisite - Resolution of merge conflicts with the last second 4.14 HPT fixes - Fixes and cleanups s390: - Some initial preparation patches for exitless interrupts and crypto - New capability for AIS migration - Fixes x86: - Improved emulation of LAPIC timer mode changes, MCi_STATUS MSRs, and after-reset state - Refined dependencies for VMX features - Fixes for nested SMI injection - A lot of cleanups" * tag 'kvm-4.15-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (89 commits) KVM: s390: provide a capability for AIS state migration KVM: s390: clear_io_irq() requests are not expected for adapter interrupts KVM: s390: abstract conversion between isc and enum irq_types KVM: s390: vsie: use common code functions for pinning KVM: s390: SIE considerations for AP Queue virtualization KVM: s390: document memory ordering for kvm_s390_vcpu_wakeup KVM: PPC: Book3S HV: Cosmetic post-merge cleanups KVM: arm/arm64: fix the incompatible matching for external abort KVM: arm/arm64: Unify 32bit fault injection KVM: arm/arm64: vgic-its: Implement KVM_DEV_ARM_ITS_CTRL_RESET KVM: arm/arm64: Document KVM_DEV_ARM_ITS_CTRL_RESET KVM: arm/arm64: vgic-its: Free caches when GITS_BASER Valid bit is cleared KVM: arm/arm64: vgic-its: New helper functions to free the caches KVM: arm/arm64: vgic-its: Remove kvm_its_unmap_device arm/arm64: KVM: Load the timer state when enabling the timer KVM: arm/arm64: Rework kvm_timer_should_fire KVM: arm/arm64: Get rid of kvm_timer_flush_hwstate KVM: arm/arm64: Avoid phys timer emulation in vcpu entry/exit KVM: arm/arm64: Move phys_timer_emulate function KVM: arm/arm64: Use kvm_arm_timer_set/get_reg for guest register traps ...
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c91
1 files changed, 70 insertions, 21 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 36c90d631096..943acbf00c69 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1301,14 +1301,42 @@ static void update_divide_count(struct kvm_lapic *apic)
1301 apic->divide_count); 1301 apic->divide_count);
1302} 1302}
1303 1303
1304static void limit_periodic_timer_frequency(struct kvm_lapic *apic)
1305{
1306 /*
1307 * Do not allow the guest to program periodic timers with small
1308 * interval, since the hrtimers are not throttled by the host
1309 * scheduler.
1310 */
1311 if (apic_lvtt_period(apic) && apic->lapic_timer.period) {
1312 s64 min_period = min_timer_period_us * 1000LL;
1313
1314 if (apic->lapic_timer.period < min_period) {
1315 pr_info_ratelimited(
1316 "kvm: vcpu %i: requested %lld ns "
1317 "lapic timer period limited to %lld ns\n",
1318 apic->vcpu->vcpu_id,
1319 apic->lapic_timer.period, min_period);
1320 apic->lapic_timer.period = min_period;
1321 }
1322 }
1323}
1324
1304static void apic_update_lvtt(struct kvm_lapic *apic) 1325static void apic_update_lvtt(struct kvm_lapic *apic)
1305{ 1326{
1306 u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) & 1327 u32 timer_mode = kvm_lapic_get_reg(apic, APIC_LVTT) &
1307 apic->lapic_timer.timer_mode_mask; 1328 apic->lapic_timer.timer_mode_mask;
1308 1329
1309 if (apic->lapic_timer.timer_mode != timer_mode) { 1330 if (apic->lapic_timer.timer_mode != timer_mode) {
1331 if (apic_lvtt_tscdeadline(apic) != (timer_mode ==
1332 APIC_LVT_TIMER_TSCDEADLINE)) {
1333 hrtimer_cancel(&apic->lapic_timer.timer);
1334 kvm_lapic_set_reg(apic, APIC_TMICT, 0);
1335 apic->lapic_timer.period = 0;
1336 apic->lapic_timer.tscdeadline = 0;
1337 }
1310 apic->lapic_timer.timer_mode = timer_mode; 1338 apic->lapic_timer.timer_mode = timer_mode;
1311 hrtimer_cancel(&apic->lapic_timer.timer); 1339 limit_periodic_timer_frequency(apic);
1312 } 1340 }
1313} 1341}
1314 1342
@@ -1430,6 +1458,30 @@ static void start_sw_period(struct kvm_lapic *apic)
1430 HRTIMER_MODE_ABS_PINNED); 1458 HRTIMER_MODE_ABS_PINNED);
1431} 1459}
1432 1460
1461static void update_target_expiration(struct kvm_lapic *apic, uint32_t old_divisor)
1462{
1463 ktime_t now, remaining;
1464 u64 ns_remaining_old, ns_remaining_new;
1465
1466 apic->lapic_timer.period = (u64)kvm_lapic_get_reg(apic, APIC_TMICT)
1467 * APIC_BUS_CYCLE_NS * apic->divide_count;
1468 limit_periodic_timer_frequency(apic);
1469
1470 now = ktime_get();
1471 remaining = ktime_sub(apic->lapic_timer.target_expiration, now);
1472 if (ktime_to_ns(remaining) < 0)
1473 remaining = 0;
1474
1475 ns_remaining_old = ktime_to_ns(remaining);
1476 ns_remaining_new = mul_u64_u32_div(ns_remaining_old,
1477 apic->divide_count, old_divisor);
1478
1479 apic->lapic_timer.tscdeadline +=
1480 nsec_to_cycles(apic->vcpu, ns_remaining_new) -
1481 nsec_to_cycles(apic->vcpu, ns_remaining_old);
1482 apic->lapic_timer.target_expiration = ktime_add_ns(now, ns_remaining_new);
1483}
1484
1433static bool set_target_expiration(struct kvm_lapic *apic) 1485static bool set_target_expiration(struct kvm_lapic *apic)
1434{ 1486{
1435 ktime_t now; 1487 ktime_t now;
@@ -1439,27 +1491,13 @@ static bool set_target_expiration(struct kvm_lapic *apic)
1439 apic->lapic_timer.period = (u64)kvm_lapic_get_reg(apic, APIC_TMICT) 1491 apic->lapic_timer.period = (u64)kvm_lapic_get_reg(apic, APIC_TMICT)
1440 * APIC_BUS_CYCLE_NS * apic->divide_count; 1492 * APIC_BUS_CYCLE_NS * apic->divide_count;
1441 1493
1442 if (!apic->lapic_timer.period) 1494 if (!apic->lapic_timer.period) {
1495 apic->lapic_timer.tscdeadline = 0;
1443 return false; 1496 return false;
1444
1445 /*
1446 * Do not allow the guest to program periodic timers with small
1447 * interval, since the hrtimers are not throttled by the host
1448 * scheduler.
1449 */
1450 if (apic_lvtt_period(apic)) {
1451 s64 min_period = min_timer_period_us * 1000LL;
1452
1453 if (apic->lapic_timer.period < min_period) {
1454 pr_info_ratelimited(
1455 "kvm: vcpu %i: requested %lld ns "
1456 "lapic timer period limited to %lld ns\n",
1457 apic->vcpu->vcpu_id,
1458 apic->lapic_timer.period, min_period);
1459 apic->lapic_timer.period = min_period;
1460 }
1461 } 1497 }
1462 1498
1499 limit_periodic_timer_frequency(apic);
1500
1463 apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016" 1501 apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
1464 PRIx64 ", " 1502 PRIx64 ", "
1465 "timer initial count 0x%x, period %lldns, " 1503 "timer initial count 0x%x, period %lldns, "
@@ -1515,6 +1553,9 @@ static bool start_hv_timer(struct kvm_lapic *apic)
1515 if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending)) 1553 if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
1516 return false; 1554 return false;
1517 1555
1556 if (!ktimer->tscdeadline)
1557 return false;
1558
1518 r = kvm_x86_ops->set_hv_timer(apic->vcpu, ktimer->tscdeadline); 1559 r = kvm_x86_ops->set_hv_timer(apic->vcpu, ktimer->tscdeadline);
1519 if (r < 0) 1560 if (r < 0)
1520 return false; 1561 return false;
@@ -1738,13 +1779,21 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
1738 start_apic_timer(apic); 1779 start_apic_timer(apic);
1739 break; 1780 break;
1740 1781
1741 case APIC_TDCR: 1782 case APIC_TDCR: {
1783 uint32_t old_divisor = apic->divide_count;
1784
1742 if (val & 4) 1785 if (val & 4)
1743 apic_debug("KVM_WRITE:TDCR %x\n", val); 1786 apic_debug("KVM_WRITE:TDCR %x\n", val);
1744 kvm_lapic_set_reg(apic, APIC_TDCR, val); 1787 kvm_lapic_set_reg(apic, APIC_TDCR, val);
1745 update_divide_count(apic); 1788 update_divide_count(apic);
1789 if (apic->divide_count != old_divisor &&
1790 apic->lapic_timer.period) {
1791 hrtimer_cancel(&apic->lapic_timer.timer);
1792 update_target_expiration(apic, old_divisor);
1793 restart_apic_timer(apic);
1794 }
1746 break; 1795 break;
1747 1796 }
1748 case APIC_ESR: 1797 case APIC_ESR:
1749 if (apic_x2apic_mode(apic) && val != 0) { 1798 if (apic_x2apic_mode(apic) && val != 0) {
1750 apic_debug("KVM_WRITE:ESR not zero %x\n", val); 1799 apic_debug("KVM_WRITE:ESR not zero %x\n", val);