aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kvm/kvm_mips_emul.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kvm/kvm_mips_emul.c')
-rw-r--r--arch/mips/kvm/kvm_mips_emul.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/arch/mips/kvm/kvm_mips_emul.c b/arch/mips/kvm/kvm_mips_emul.c
index 65c8dea6d1f5..6d257384c9b4 100644
--- a/arch/mips/kvm/kvm_mips_emul.c
+++ b/arch/mips/kvm/kvm_mips_emul.c
@@ -498,6 +498,54 @@ void kvm_mips_init_count(struct kvm_vcpu *vcpu)
498} 498}
499 499
500/** 500/**
501 * kvm_mips_set_count_hz() - Update the frequency of the timer.
502 * @vcpu: Virtual CPU.
503 * @count_hz: Frequency of CP0_Count timer in Hz.
504 *
505 * Change the frequency of the CP0_Count timer. This is done atomically so that
506 * CP0_Count is continuous and no timer interrupt is lost.
507 *
508 * Returns: -EINVAL if @count_hz is out of range.
509 * 0 on success.
510 */
511int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz)
512{
513 struct mips_coproc *cop0 = vcpu->arch.cop0;
514 int dc;
515 ktime_t now;
516 u32 count;
517
518 /* ensure the frequency is in a sensible range... */
519 if (count_hz <= 0 || count_hz > NSEC_PER_SEC)
520 return -EINVAL;
521 /* ... and has actually changed */
522 if (vcpu->arch.count_hz == count_hz)
523 return 0;
524
525 /* Safely freeze timer so we can keep it continuous */
526 dc = kvm_mips_count_disabled(vcpu);
527 if (dc) {
528 now = kvm_mips_count_time(vcpu);
529 count = kvm_read_c0_guest_count(cop0);
530 } else {
531 now = kvm_mips_freeze_hrtimer(vcpu, &count);
532 }
533
534 /* Update the frequency */
535 vcpu->arch.count_hz = count_hz;
536 vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32, count_hz);
537 vcpu->arch.count_dyn_bias = 0;
538
539 /* Calculate adjusted bias so dynamic count is unchanged */
540 vcpu->arch.count_bias = count - kvm_mips_ktime_to_count(vcpu, now);
541
542 /* Update and resume hrtimer */
543 if (!dc)
544 kvm_mips_resume_hrtimer(vcpu, now, count);
545 return 0;
546}
547
548/**
501 * kvm_mips_write_compare() - Modify compare and update timer. 549 * kvm_mips_write_compare() - Modify compare and update timer.
502 * @vcpu: Virtual CPU. 550 * @vcpu: Virtual CPU.
503 * @compare: New CP0_Compare value. 551 * @compare: New CP0_Compare value.