aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/booke.c
diff options
context:
space:
mode:
authorBharat Bhushan <r65777@freescale.com>2012-08-08 16:38:19 -0400
committerAlexander Graf <agraf@suse.de>2012-10-05 17:38:47 -0400
commitf61c94bb99ca4253ac5dd57750e1af209a4beb7a (patch)
tree348d15c584a683cd805ed71ed5c8a81848d24e70 /arch/powerpc/kvm/booke.c
parent7c973a2ebb8fb9c8ee2ae9647f9ad7b0ad58a3e6 (diff)
KVM: PPC: booke: Add watchdog emulation
This patch adds the watchdog emulation in KVM. The watchdog emulation is enabled by KVM_ENABLE_CAP(KVM_CAP_PPC_BOOKE_WATCHDOG) ioctl. The kernel timer are used for watchdog emulation and emulates h/w watchdog state machine. On watchdog timer expiry, it exit to QEMU if TCR.WRC is non ZERO. QEMU can reset/shutdown etc depending upon how it is configured. Signed-off-by: Liu Yu <yu.liu@freescale.com> Signed-off-by: Scott Wood <scottwood@freescale.com> [bharat.bhushan@freescale.com: reworked patch] Signed-off-by: Bharat Bhushan <bharat.bhushan@freescale.com> [agraf: adjust to new request framework] Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r--arch/powerpc/kvm/booke.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index c36493087dbf..09e8bf33a8c9 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -209,6 +209,16 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu,
209 clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions); 209 clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions);
210} 210}
211 211
212static void kvmppc_core_queue_watchdog(struct kvm_vcpu *vcpu)
213{
214 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_WATCHDOG);
215}
216
217static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu)
218{
219 clear_bit(BOOKE_IRQPRIO_WATCHDOG, &vcpu->arch.pending_exceptions);
220}
221
212static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) 222static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1)
213{ 223{
214#ifdef CONFIG_KVM_BOOKE_HV 224#ifdef CONFIG_KVM_BOOKE_HV
@@ -328,6 +338,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
328 msr_mask = MSR_CE | MSR_ME | MSR_DE; 338 msr_mask = MSR_CE | MSR_ME | MSR_DE;
329 int_class = INT_CLASS_NONCRIT; 339 int_class = INT_CLASS_NONCRIT;
330 break; 340 break;
341 case BOOKE_IRQPRIO_WATCHDOG:
331 case BOOKE_IRQPRIO_CRITICAL: 342 case BOOKE_IRQPRIO_CRITICAL:
332 case BOOKE_IRQPRIO_DBELL_CRIT: 343 case BOOKE_IRQPRIO_DBELL_CRIT:
333 allowed = vcpu->arch.shared->msr & MSR_CE; 344 allowed = vcpu->arch.shared->msr & MSR_CE;
@@ -407,12 +418,121 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
407 return allowed; 418 return allowed;
408} 419}
409 420
421/*
422 * Return the number of jiffies until the next timeout. If the timeout is
423 * longer than the NEXT_TIMER_MAX_DELTA, then return NEXT_TIMER_MAX_DELTA
424 * because the larger value can break the timer APIs.
425 */
426static unsigned long watchdog_next_timeout(struct kvm_vcpu *vcpu)
427{
428 u64 tb, wdt_tb, wdt_ticks = 0;
429 u64 nr_jiffies = 0;
430 u32 period = TCR_GET_WP(vcpu->arch.tcr);
431
432 wdt_tb = 1ULL << (63 - period);
433 tb = get_tb();
434 /*
435 * The watchdog timeout will hapeen when TB bit corresponding
436 * to watchdog will toggle from 0 to 1.
437 */
438 if (tb & wdt_tb)
439 wdt_ticks = wdt_tb;
440
441 wdt_ticks += wdt_tb - (tb & (wdt_tb - 1));
442
443 /* Convert timebase ticks to jiffies */
444 nr_jiffies = wdt_ticks;
445
446 if (do_div(nr_jiffies, tb_ticks_per_jiffy))
447 nr_jiffies++;
448
449 return min_t(unsigned long long, nr_jiffies, NEXT_TIMER_MAX_DELTA);
450}
451
452static void arm_next_watchdog(struct kvm_vcpu *vcpu)
453{
454 unsigned long nr_jiffies;
455 unsigned long flags;
456
457 /*
458 * If TSR_ENW and TSR_WIS are not set then no need to exit to
459 * userspace, so clear the KVM_REQ_WATCHDOG request.
460 */
461 if ((vcpu->arch.tsr & (TSR_ENW | TSR_WIS)) != (TSR_ENW | TSR_WIS))
462 clear_bit(KVM_REQ_WATCHDOG, &vcpu->requests);
463
464 spin_lock_irqsave(&vcpu->arch.wdt_lock, flags);
465 nr_jiffies = watchdog_next_timeout(vcpu);
466 /*
467 * If the number of jiffies of watchdog timer >= NEXT_TIMER_MAX_DELTA
468 * then do not run the watchdog timer as this can break timer APIs.
469 */
470 if (nr_jiffies < NEXT_TIMER_MAX_DELTA)
471 mod_timer(&vcpu->arch.wdt_timer, jiffies + nr_jiffies);
472 else
473 del_timer(&vcpu->arch.wdt_timer);
474 spin_unlock_irqrestore(&vcpu->arch.wdt_lock, flags);
475}
476
477void kvmppc_watchdog_func(unsigned long data)
478{
479 struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data;
480 u32 tsr, new_tsr;
481 int final;
482
483 do {
484 new_tsr = tsr = vcpu->arch.tsr;
485 final = 0;
486
487 /* Time out event */
488 if (tsr & TSR_ENW) {
489 if (tsr & TSR_WIS)
490 final = 1;
491 else
492 new_tsr = tsr | TSR_WIS;
493 } else {
494 new_tsr = tsr | TSR_ENW;
495 }
496 } while (cmpxchg(&vcpu->arch.tsr, tsr, new_tsr) != tsr);
497
498 if (new_tsr & TSR_WIS) {
499 smp_wmb();
500 kvm_make_request(KVM_REQ_PENDING_TIMER, vcpu);
501 kvm_vcpu_kick(vcpu);
502 }
503
504 /*
505 * If this is final watchdog expiry and some action is required
506 * then exit to userspace.
507 */
508 if (final && (vcpu->arch.tcr & TCR_WRC_MASK) &&
509 vcpu->arch.watchdog_enabled) {
510 smp_wmb();
511 kvm_make_request(KVM_REQ_WATCHDOG, vcpu);
512 kvm_vcpu_kick(vcpu);
513 }
514
515 /*
516 * Stop running the watchdog timer after final expiration to
517 * prevent the host from being flooded with timers if the
518 * guest sets a short period.
519 * Timers will resume when TSR/TCR is updated next time.
520 */
521 if (!final)
522 arm_next_watchdog(vcpu);
523}
524
410static void update_timer_ints(struct kvm_vcpu *vcpu) 525static void update_timer_ints(struct kvm_vcpu *vcpu)
411{ 526{
412 if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS)) 527 if ((vcpu->arch.tcr & TCR_DIE) && (vcpu->arch.tsr & TSR_DIS))
413 kvmppc_core_queue_dec(vcpu); 528 kvmppc_core_queue_dec(vcpu);
414 else 529 else
415 kvmppc_core_dequeue_dec(vcpu); 530 kvmppc_core_dequeue_dec(vcpu);
531
532 if ((vcpu->arch.tcr & TCR_WIE) && (vcpu->arch.tsr & TSR_WIS))
533 kvmppc_core_queue_watchdog(vcpu);
534 else
535 kvmppc_core_dequeue_watchdog(vcpu);
416} 536}
417 537
418static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu) 538static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu)
@@ -466,6 +586,11 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu)
466 kvmppc_core_flush_tlb(vcpu); 586 kvmppc_core_flush_tlb(vcpu);
467#endif 587#endif
468 588
589 if (kvm_check_request(KVM_REQ_WATCHDOG, vcpu)) {
590 vcpu->run->exit_reason = KVM_EXIT_WATCHDOG;
591 r = 0;
592 }
593
469 return r; 594 return r;
470} 595}
471 596
@@ -995,6 +1120,21 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
995 return r; 1120 return r;
996} 1121}
997 1122
1123int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu)
1124{
1125 /* setup watchdog timer once */
1126 spin_lock_init(&vcpu->arch.wdt_lock);
1127 setup_timer(&vcpu->arch.wdt_timer, kvmppc_watchdog_func,
1128 (unsigned long)vcpu);
1129
1130 return 0;
1131}
1132
1133void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu)
1134{
1135 del_timer_sync(&vcpu->arch.wdt_timer);
1136}
1137
998int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 1138int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
999{ 1139{
1000 int i; 1140 int i;
@@ -1090,7 +1230,13 @@ static int set_sregs_base(struct kvm_vcpu *vcpu,
1090 } 1230 }
1091 1231
1092 if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) { 1232 if (sregs->u.e.update_special & KVM_SREGS_E_UPDATE_TSR) {
1233 u32 old_tsr = vcpu->arch.tsr;
1234
1093 vcpu->arch.tsr = sregs->u.e.tsr; 1235 vcpu->arch.tsr = sregs->u.e.tsr;
1236
1237 if ((old_tsr ^ vcpu->arch.tsr) & (TSR_ENW | TSR_WIS))
1238 arm_next_watchdog(vcpu);
1239
1094 update_timer_ints(vcpu); 1240 update_timer_ints(vcpu);
1095 } 1241 }
1096 1242
@@ -1251,6 +1397,7 @@ void kvmppc_core_commit_memory_region(struct kvm *kvm,
1251void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr) 1397void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr)
1252{ 1398{
1253 vcpu->arch.tcr = new_tcr; 1399 vcpu->arch.tcr = new_tcr;
1400 arm_next_watchdog(vcpu);
1254 update_timer_ints(vcpu); 1401 update_timer_ints(vcpu);
1255} 1402}
1256 1403
@@ -1265,6 +1412,14 @@ void kvmppc_set_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
1265void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits) 1412void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits)
1266{ 1413{
1267 clear_bits(tsr_bits, &vcpu->arch.tsr); 1414 clear_bits(tsr_bits, &vcpu->arch.tsr);
1415
1416 /*
1417 * We may have stopped the watchdog due to
1418 * being stuck on final expiration.
1419 */
1420 if (tsr_bits & (TSR_ENW | TSR_WIS))
1421 arm_next_watchdog(vcpu);
1422
1268 update_timer_ints(vcpu); 1423 update_timer_ints(vcpu);
1269} 1424}
1270 1425