diff options
author | Bharat Bhushan <r65777@freescale.com> | 2012-08-08 16:38:19 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-10-05 17:38:47 -0400 |
commit | f61c94bb99ca4253ac5dd57750e1af209a4beb7a (patch) | |
tree | 348d15c584a683cd805ed71ed5c8a81848d24e70 | |
parent | 7c973a2ebb8fb9c8ee2ae9647f9ad7b0ad58a3e6 (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>
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 3 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/reg_booke.h | 7 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 155 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke_emulate.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 14 | ||||
-rw-r--r-- | include/linux/kvm.h | 2 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 |
9 files changed, 199 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 4a5ec8f573c7..51b0ccd56769 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -471,6 +471,8 @@ struct kvm_vcpu_arch { | |||
471 | ulong fault_esr; | 471 | ulong fault_esr; |
472 | ulong queued_dear; | 472 | ulong queued_dear; |
473 | ulong queued_esr; | 473 | ulong queued_esr; |
474 | spinlock_t wdt_lock; | ||
475 | struct timer_list wdt_timer; | ||
474 | u32 tlbcfg[4]; | 476 | u32 tlbcfg[4]; |
475 | u32 mmucfg; | 477 | u32 mmucfg; |
476 | u32 epr; | 478 | u32 epr; |
@@ -486,6 +488,7 @@ struct kvm_vcpu_arch { | |||
486 | u8 osi_needed; | 488 | u8 osi_needed; |
487 | u8 osi_enabled; | 489 | u8 osi_enabled; |
488 | u8 papr_enabled; | 490 | u8 papr_enabled; |
491 | u8 watchdog_enabled; | ||
489 | u8 sane; | 492 | u8 sane; |
490 | u8 cpu_type; | 493 | u8 cpu_type; |
491 | u8 hcall_needed; | 494 | u8 hcall_needed; |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 3dfc437fb9d9..c06a64b53362 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -68,6 +68,8 @@ extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu); | |||
68 | extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb); | 68 | extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb); |
69 | extern void kvmppc_decrementer_func(unsigned long data); | 69 | extern void kvmppc_decrementer_func(unsigned long data); |
70 | extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu); | 70 | extern int kvmppc_sanity_check(struct kvm_vcpu *vcpu); |
71 | extern int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu); | ||
72 | extern void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu); | ||
71 | 73 | ||
72 | /* Core-specific hooks */ | 74 | /* Core-specific hooks */ |
73 | 75 | ||
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 2d916c4982c5..e07e6af5e1ff 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h | |||
@@ -539,6 +539,13 @@ | |||
539 | #define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ | 539 | #define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ |
540 | #define TCR_ARE 0x00400000 /* Auto Reload Enable */ | 540 | #define TCR_ARE 0x00400000 /* Auto Reload Enable */ |
541 | 541 | ||
542 | #ifdef CONFIG_E500 | ||
543 | #define TCR_GET_WP(tcr) ((((tcr) & 0xC0000000) >> 30) | \ | ||
544 | (((tcr) & 0x1E0000) >> 15)) | ||
545 | #else | ||
546 | #define TCR_GET_WP(tcr) (((tcr) & 0xC0000000) >> 30) | ||
547 | #endif | ||
548 | |||
542 | /* Bit definitions for the TSR. */ | 549 | /* Bit definitions for the TSR. */ |
543 | #define TSR_ENW 0x80000000 /* Enable Next Watchdog */ | 550 | #define TSR_ENW 0x80000000 /* Enable Next Watchdog */ |
544 | #define TSR_WIS 0x40000000 /* WDT Interrupt Status */ | 551 | #define TSR_WIS 0x40000000 /* WDT Interrupt Status */ |
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 3f2a8360c857..e94666566fa9 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
413 | 413 | ||
414 | int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu) | ||
415 | { | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu) | ||
420 | { | ||
421 | } | ||
422 | |||
414 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | 423 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) |
415 | { | 424 | { |
416 | int i; | 425 | int i; |
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 | ||
212 | static void kvmppc_core_queue_watchdog(struct kvm_vcpu *vcpu) | ||
213 | { | ||
214 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_WATCHDOG); | ||
215 | } | ||
216 | |||
217 | static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu) | ||
218 | { | ||
219 | clear_bit(BOOKE_IRQPRIO_WATCHDOG, &vcpu->arch.pending_exceptions); | ||
220 | } | ||
221 | |||
212 | static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) | 222 | static 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 | */ | ||
426 | static 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 | |||
452 | static 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 | |||
477 | void 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 | |||
410 | static void update_timer_ints(struct kvm_vcpu *vcpu) | 525 | static 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 | ||
418 | static void kvmppc_core_check_exceptions(struct kvm_vcpu *vcpu) | 538 | static 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 | ||
1123 | int 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 | |||
1133 | void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu) | ||
1134 | { | ||
1135 | del_timer_sync(&vcpu->arch.wdt_timer); | ||
1136 | } | ||
1137 | |||
998 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | 1138 | int 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, | |||
1251 | void kvmppc_set_tcr(struct kvm_vcpu *vcpu, u32 new_tcr) | 1397 | void 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) | |||
1265 | void kvmppc_clr_tsr_bits(struct kvm_vcpu *vcpu, u32 tsr_bits) | 1412 | void 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 | ||
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index 12834bb608ab..5a66ade7fd17 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c | |||
@@ -145,6 +145,14 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
145 | kvmppc_clr_tsr_bits(vcpu, spr_val); | 145 | kvmppc_clr_tsr_bits(vcpu, spr_val); |
146 | break; | 146 | break; |
147 | case SPRN_TCR: | 147 | case SPRN_TCR: |
148 | /* | ||
149 | * WRC is a 2-bit field that is supposed to preserve its | ||
150 | * value once written to non-zero. | ||
151 | */ | ||
152 | if (vcpu->arch.tcr & TCR_WRC_MASK) { | ||
153 | spr_val &= ~TCR_WRC_MASK; | ||
154 | spr_val |= vcpu->arch.tcr & TCR_WRC_MASK; | ||
155 | } | ||
148 | kvmppc_set_tcr(vcpu, spr_val); | 156 | kvmppc_set_tcr(vcpu, spr_val); |
149 | break; | 157 | break; |
150 | 158 | ||
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 54b12af577d0..0ffd7d17adc7 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -300,6 +300,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
300 | switch (ext) { | 300 | switch (ext) { |
301 | #ifdef CONFIG_BOOKE | 301 | #ifdef CONFIG_BOOKE |
302 | case KVM_CAP_PPC_BOOKE_SREGS: | 302 | case KVM_CAP_PPC_BOOKE_SREGS: |
303 | case KVM_CAP_PPC_BOOKE_WATCHDOG: | ||
303 | #else | 304 | #else |
304 | case KVM_CAP_PPC_SEGSTATE: | 305 | case KVM_CAP_PPC_SEGSTATE: |
305 | case KVM_CAP_PPC_HIOR: | 306 | case KVM_CAP_PPC_HIOR: |
@@ -476,6 +477,8 @@ enum hrtimer_restart kvmppc_decrementer_wakeup(struct hrtimer *timer) | |||
476 | 477 | ||
477 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | 478 | int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) |
478 | { | 479 | { |
480 | int ret; | ||
481 | |||
479 | hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); | 482 | hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
480 | tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu); | 483 | tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu); |
481 | vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; | 484 | vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; |
@@ -484,13 +487,14 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | |||
484 | #ifdef CONFIG_KVM_EXIT_TIMING | 487 | #ifdef CONFIG_KVM_EXIT_TIMING |
485 | mutex_init(&vcpu->arch.exit_timing_lock); | 488 | mutex_init(&vcpu->arch.exit_timing_lock); |
486 | #endif | 489 | #endif |
487 | 490 | ret = kvmppc_subarch_vcpu_init(vcpu); | |
488 | return 0; | 491 | return ret; |
489 | } | 492 | } |
490 | 493 | ||
491 | void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) | 494 | void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) |
492 | { | 495 | { |
493 | kvmppc_mmu_destroy(vcpu); | 496 | kvmppc_mmu_destroy(vcpu); |
497 | kvmppc_subarch_vcpu_uninit(vcpu); | ||
494 | } | 498 | } |
495 | 499 | ||
496 | void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 500 | void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) |
@@ -735,6 +739,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, | |||
735 | r = 0; | 739 | r = 0; |
736 | vcpu->arch.papr_enabled = true; | 740 | vcpu->arch.papr_enabled = true; |
737 | break; | 741 | break; |
742 | #ifdef CONFIG_BOOKE | ||
743 | case KVM_CAP_PPC_BOOKE_WATCHDOG: | ||
744 | r = 0; | ||
745 | vcpu->arch.watchdog_enabled = true; | ||
746 | break; | ||
747 | #endif | ||
738 | #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) | 748 | #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) |
739 | case KVM_CAP_SW_TLB: { | 749 | case KVM_CAP_SW_TLB: { |
740 | struct kvm_config_tlb cfg; | 750 | struct kvm_config_tlb cfg; |
diff --git a/include/linux/kvm.h b/include/linux/kvm.h index 4cb3761bebae..1649d4b57e1f 100644 --- a/include/linux/kvm.h +++ b/include/linux/kvm.h | |||
@@ -167,6 +167,7 @@ struct kvm_pit_config { | |||
167 | #define KVM_EXIT_OSI 18 | 167 | #define KVM_EXIT_OSI 18 |
168 | #define KVM_EXIT_PAPR_HCALL 19 | 168 | #define KVM_EXIT_PAPR_HCALL 19 |
169 | #define KVM_EXIT_S390_UCONTROL 20 | 169 | #define KVM_EXIT_S390_UCONTROL 20 |
170 | #define KVM_EXIT_WATCHDOG 21 | ||
170 | 171 | ||
171 | /* For KVM_EXIT_INTERNAL_ERROR */ | 172 | /* For KVM_EXIT_INTERNAL_ERROR */ |
172 | #define KVM_INTERNAL_ERROR_EMULATION 1 | 173 | #define KVM_INTERNAL_ERROR_EMULATION 1 |
@@ -628,6 +629,7 @@ struct kvm_ppc_smmu_info { | |||
628 | #define KVM_CAP_READONLY_MEM 81 | 629 | #define KVM_CAP_READONLY_MEM 81 |
629 | #endif | 630 | #endif |
630 | #define KVM_CAP_IRQFD_RESAMPLE 82 | 631 | #define KVM_CAP_IRQFD_RESAMPLE 82 |
632 | #define KVM_CAP_PPC_BOOKE_WATCHDOG 83 | ||
631 | 633 | ||
632 | #ifdef KVM_CAP_IRQ_ROUTING | 634 | #ifdef KVM_CAP_IRQ_ROUTING |
633 | 635 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 2850656e2e96..0ca3663206f8 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -118,6 +118,7 @@ static inline bool is_error_page(struct page *page) | |||
118 | #define KVM_REQ_IMMEDIATE_EXIT 15 | 118 | #define KVM_REQ_IMMEDIATE_EXIT 15 |
119 | #define KVM_REQ_PMU 16 | 119 | #define KVM_REQ_PMU 16 |
120 | #define KVM_REQ_PMI 17 | 120 | #define KVM_REQ_PMI 17 |
121 | #define KVM_REQ_WATCHDOG 18 | ||
121 | 122 | ||
122 | #define KVM_USERSPACE_IRQ_SOURCE_ID 0 | 123 | #define KVM_USERSPACE_IRQ_SOURCE_ID 0 |
123 | #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 | 124 | #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 |