@@ -1347,6 +1347,50 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic)
1347
1347
local_irq_restore (flags );
1348
1348
}
1349
1349
1350
+ static void start_sw_period (struct kvm_lapic * apic )
1351
+ {
1352
+ ktime_t now ;
1353
+
1354
+ /* lapic timer in oneshot or periodic mode */
1355
+ now = apic -> lapic_timer .timer .base -> get_time ();
1356
+ apic -> lapic_timer .period = (u64 )kvm_lapic_get_reg (apic , APIC_TMICT )
1357
+ * APIC_BUS_CYCLE_NS * apic -> divide_count ;
1358
+
1359
+ if (!apic -> lapic_timer .period )
1360
+ return ;
1361
+ /*
1362
+ * Do not allow the guest to program periodic timers with small
1363
+ * interval, since the hrtimers are not throttled by the host
1364
+ * scheduler.
1365
+ */
1366
+ if (apic_lvtt_period (apic )) {
1367
+ s64 min_period = min_timer_period_us * 1000LL ;
1368
+
1369
+ if (apic -> lapic_timer .period < min_period ) {
1370
+ pr_info_ratelimited (
1371
+ "kvm: vcpu %i: requested %lld ns "
1372
+ "lapic timer period limited to %lld ns\n" ,
1373
+ apic -> vcpu -> vcpu_id ,
1374
+ apic -> lapic_timer .period , min_period );
1375
+ apic -> lapic_timer .period = min_period ;
1376
+ }
1377
+ }
1378
+
1379
+ hrtimer_start (& apic -> lapic_timer .timer ,
1380
+ ktime_add_ns (now , apic -> lapic_timer .period ),
1381
+ HRTIMER_MODE_ABS_PINNED );
1382
+
1383
+ apic_debug ("%s: bus cycle is %" PRId64 "ns, now 0x%016"
1384
+ PRIx64 ", "
1385
+ "timer initial count 0x%x, period %lldns, "
1386
+ "expire @ 0x%016" PRIx64 ".\n" , __func__ ,
1387
+ APIC_BUS_CYCLE_NS , ktime_to_ns (now ),
1388
+ kvm_lapic_get_reg (apic , APIC_TMICT ),
1389
+ apic -> lapic_timer .period ,
1390
+ ktime_to_ns (ktime_add_ns (now ,
1391
+ apic -> lapic_timer .period )));
1392
+ }
1393
+
1350
1394
bool kvm_lapic_hv_timer_in_use (struct kvm_vcpu * vcpu )
1351
1395
{
1352
1396
if (!lapic_in_kernel (vcpu ))
@@ -1424,50 +1468,11 @@ EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_sw_timer);
1424
1468
1425
1469
static void start_apic_timer (struct kvm_lapic * apic )
1426
1470
{
1427
- ktime_t now ;
1428
-
1429
1471
atomic_set (& apic -> lapic_timer .pending , 0 );
1430
1472
1431
- if (apic_lvtt_period (apic ) || apic_lvtt_oneshot (apic )) {
1432
- /* lapic timer in oneshot or periodic mode */
1433
- now = apic -> lapic_timer .timer .base -> get_time ();
1434
- apic -> lapic_timer .period = (u64 )kvm_lapic_get_reg (apic , APIC_TMICT )
1435
- * APIC_BUS_CYCLE_NS * apic -> divide_count ;
1436
-
1437
- if (!apic -> lapic_timer .period )
1438
- return ;
1439
- /*
1440
- * Do not allow the guest to program periodic timers with small
1441
- * interval, since the hrtimers are not throttled by the host
1442
- * scheduler.
1443
- */
1444
- if (apic_lvtt_period (apic )) {
1445
- s64 min_period = min_timer_period_us * 1000LL ;
1446
-
1447
- if (apic -> lapic_timer .period < min_period ) {
1448
- pr_info_ratelimited (
1449
- "kvm: vcpu %i: requested %lld ns "
1450
- "lapic timer period limited to %lld ns\n" ,
1451
- apic -> vcpu -> vcpu_id ,
1452
- apic -> lapic_timer .period , min_period );
1453
- apic -> lapic_timer .period = min_period ;
1454
- }
1455
- }
1456
-
1457
- hrtimer_start (& apic -> lapic_timer .timer ,
1458
- ktime_add_ns (now , apic -> lapic_timer .period ),
1459
- HRTIMER_MODE_ABS_PINNED );
1460
-
1461
- apic_debug ("%s: bus cycle is %" PRId64 "ns, now 0x%016"
1462
- PRIx64 ", "
1463
- "timer initial count 0x%x, period %lldns, "
1464
- "expire @ 0x%016" PRIx64 ".\n" , __func__ ,
1465
- APIC_BUS_CYCLE_NS , ktime_to_ns (now ),
1466
- kvm_lapic_get_reg (apic , APIC_TMICT ),
1467
- apic -> lapic_timer .period ,
1468
- ktime_to_ns (ktime_add_ns (now ,
1469
- apic -> lapic_timer .period )));
1470
- } else if (apic_lvtt_tscdeadline (apic )) {
1473
+ if (apic_lvtt_period (apic ) || apic_lvtt_oneshot (apic ))
1474
+ start_sw_period (apic );
1475
+ else if (apic_lvtt_tscdeadline (apic )) {
1471
1476
if (!(kvm_x86_ops -> set_hv_timer && start_hv_tscdeadline (apic )))
1472
1477
start_sw_tscdeadline (apic );
1473
1478
}
0 commit comments