162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2019 Western Digital Corporation or its affiliates.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Authors:
662306a36Sopenharmony_ci *     Atish Patra <atish.patra@wdc.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/errno.h>
1062306a36Sopenharmony_ci#include <linux/err.h>
1162306a36Sopenharmony_ci#include <linux/kvm_host.h>
1262306a36Sopenharmony_ci#include <linux/uaccess.h>
1362306a36Sopenharmony_ci#include <clocksource/timer-riscv.h>
1462306a36Sopenharmony_ci#include <asm/csr.h>
1562306a36Sopenharmony_ci#include <asm/delay.h>
1662306a36Sopenharmony_ci#include <asm/kvm_vcpu_timer.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistatic u64 kvm_riscv_current_cycles(struct kvm_guest_timer *gt)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	return get_cycles64() + gt->time_delta;
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic u64 kvm_riscv_delta_cycles2ns(u64 cycles,
2462306a36Sopenharmony_ci				     struct kvm_guest_timer *gt,
2562306a36Sopenharmony_ci				     struct kvm_vcpu_timer *t)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	unsigned long flags;
2862306a36Sopenharmony_ci	u64 cycles_now, cycles_delta, delta_ns;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	local_irq_save(flags);
3162306a36Sopenharmony_ci	cycles_now = kvm_riscv_current_cycles(gt);
3262306a36Sopenharmony_ci	if (cycles_now < cycles)
3362306a36Sopenharmony_ci		cycles_delta = cycles - cycles_now;
3462306a36Sopenharmony_ci	else
3562306a36Sopenharmony_ci		cycles_delta = 0;
3662306a36Sopenharmony_ci	delta_ns = (cycles_delta * gt->nsec_mult) >> gt->nsec_shift;
3762306a36Sopenharmony_ci	local_irq_restore(flags);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	return delta_ns;
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic enum hrtimer_restart kvm_riscv_vcpu_hrtimer_expired(struct hrtimer *h)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	u64 delta_ns;
4562306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = container_of(h, struct kvm_vcpu_timer, hrt);
4662306a36Sopenharmony_ci	struct kvm_vcpu *vcpu = container_of(t, struct kvm_vcpu, arch.timer);
4762306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	if (kvm_riscv_current_cycles(gt) < t->next_cycles) {
5062306a36Sopenharmony_ci		delta_ns = kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t);
5162306a36Sopenharmony_ci		hrtimer_forward_now(&t->hrt, ktime_set(0, delta_ns));
5262306a36Sopenharmony_ci		return HRTIMER_RESTART;
5362306a36Sopenharmony_ci	}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	t->next_set = false;
5662306a36Sopenharmony_ci	kvm_riscv_vcpu_set_interrupt(vcpu, IRQ_VS_TIMER);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	return HRTIMER_NORESTART;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic int kvm_riscv_vcpu_timer_cancel(struct kvm_vcpu_timer *t)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	if (!t->init_done || !t->next_set)
6462306a36Sopenharmony_ci		return -EINVAL;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	hrtimer_cancel(&t->hrt);
6762306a36Sopenharmony_ci	t->next_set = false;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return 0;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic int kvm_riscv_vcpu_update_vstimecmp(struct kvm_vcpu *vcpu, u64 ncycles)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci#if defined(CONFIG_32BIT)
7562306a36Sopenharmony_ci		csr_write(CSR_VSTIMECMP, ncycles & 0xFFFFFFFF);
7662306a36Sopenharmony_ci		csr_write(CSR_VSTIMECMPH, ncycles >> 32);
7762306a36Sopenharmony_ci#else
7862306a36Sopenharmony_ci		csr_write(CSR_VSTIMECMP, ncycles);
7962306a36Sopenharmony_ci#endif
8062306a36Sopenharmony_ci		return 0;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic int kvm_riscv_vcpu_update_hrtimer(struct kvm_vcpu *vcpu, u64 ncycles)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
8662306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
8762306a36Sopenharmony_ci	u64 delta_ns;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	if (!t->init_done)
9062306a36Sopenharmony_ci		return -EINVAL;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	kvm_riscv_vcpu_unset_interrupt(vcpu, IRQ_VS_TIMER);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	delta_ns = kvm_riscv_delta_cycles2ns(ncycles, gt, t);
9562306a36Sopenharmony_ci	t->next_cycles = ncycles;
9662306a36Sopenharmony_ci	hrtimer_start(&t->hrt, ktime_set(0, delta_ns), HRTIMER_MODE_REL);
9762306a36Sopenharmony_ci	t->next_set = true;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	return 0;
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciint kvm_riscv_vcpu_timer_next_event(struct kvm_vcpu *vcpu, u64 ncycles)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return t->timer_next_event(vcpu, ncycles);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic enum hrtimer_restart kvm_riscv_vcpu_vstimer_expired(struct hrtimer *h)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	u64 delta_ns;
11262306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = container_of(h, struct kvm_vcpu_timer, hrt);
11362306a36Sopenharmony_ci	struct kvm_vcpu *vcpu = container_of(t, struct kvm_vcpu, arch.timer);
11462306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	if (kvm_riscv_current_cycles(gt) < t->next_cycles) {
11762306a36Sopenharmony_ci		delta_ns = kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t);
11862306a36Sopenharmony_ci		hrtimer_forward_now(&t->hrt, ktime_set(0, delta_ns));
11962306a36Sopenharmony_ci		return HRTIMER_RESTART;
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	t->next_set = false;
12362306a36Sopenharmony_ci	kvm_vcpu_kick(vcpu);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return HRTIMER_NORESTART;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cibool kvm_riscv_vcpu_timer_pending(struct kvm_vcpu *vcpu)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
13162306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if (!kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t) ||
13462306a36Sopenharmony_ci	    kvm_riscv_vcpu_has_interrupts(vcpu, 1UL << IRQ_VS_TIMER))
13562306a36Sopenharmony_ci		return true;
13662306a36Sopenharmony_ci	else
13762306a36Sopenharmony_ci		return false;
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic void kvm_riscv_vcpu_timer_blocking(struct kvm_vcpu *vcpu)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
14362306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
14462306a36Sopenharmony_ci	u64 delta_ns;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (!t->init_done)
14762306a36Sopenharmony_ci		return;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	delta_ns = kvm_riscv_delta_cycles2ns(t->next_cycles, gt, t);
15062306a36Sopenharmony_ci	hrtimer_start(&t->hrt, ktime_set(0, delta_ns), HRTIMER_MODE_REL);
15162306a36Sopenharmony_ci	t->next_set = true;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic void kvm_riscv_vcpu_timer_unblocking(struct kvm_vcpu *vcpu)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	kvm_riscv_vcpu_timer_cancel(&vcpu->arch.timer);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ciint kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
16062306a36Sopenharmony_ci				 const struct kvm_one_reg *reg)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
16362306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
16462306a36Sopenharmony_ci	u64 __user *uaddr = (u64 __user *)(unsigned long)reg->addr;
16562306a36Sopenharmony_ci	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
16662306a36Sopenharmony_ci					    KVM_REG_SIZE_MASK |
16762306a36Sopenharmony_ci					    KVM_REG_RISCV_TIMER);
16862306a36Sopenharmony_ci	u64 reg_val;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	if (KVM_REG_SIZE(reg->id) != sizeof(u64))
17162306a36Sopenharmony_ci		return -EINVAL;
17262306a36Sopenharmony_ci	if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
17362306a36Sopenharmony_ci		return -ENOENT;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	switch (reg_num) {
17662306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(frequency):
17762306a36Sopenharmony_ci		reg_val = riscv_timebase;
17862306a36Sopenharmony_ci		break;
17962306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(time):
18062306a36Sopenharmony_ci		reg_val = kvm_riscv_current_cycles(gt);
18162306a36Sopenharmony_ci		break;
18262306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(compare):
18362306a36Sopenharmony_ci		reg_val = t->next_cycles;
18462306a36Sopenharmony_ci		break;
18562306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(state):
18662306a36Sopenharmony_ci		reg_val = (t->next_set) ? KVM_RISCV_TIMER_STATE_ON :
18762306a36Sopenharmony_ci					  KVM_RISCV_TIMER_STATE_OFF;
18862306a36Sopenharmony_ci		break;
18962306a36Sopenharmony_ci	default:
19062306a36Sopenharmony_ci		return -ENOENT;
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
19462306a36Sopenharmony_ci		return -EFAULT;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	return 0;
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ciint kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
20062306a36Sopenharmony_ci				 const struct kvm_one_reg *reg)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
20362306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
20462306a36Sopenharmony_ci	u64 __user *uaddr = (u64 __user *)(unsigned long)reg->addr;
20562306a36Sopenharmony_ci	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
20662306a36Sopenharmony_ci					    KVM_REG_SIZE_MASK |
20762306a36Sopenharmony_ci					    KVM_REG_RISCV_TIMER);
20862306a36Sopenharmony_ci	u64 reg_val;
20962306a36Sopenharmony_ci	int ret = 0;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	if (KVM_REG_SIZE(reg->id) != sizeof(u64))
21262306a36Sopenharmony_ci		return -EINVAL;
21362306a36Sopenharmony_ci	if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
21462306a36Sopenharmony_ci		return -ENOENT;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
21762306a36Sopenharmony_ci		return -EFAULT;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	switch (reg_num) {
22062306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(frequency):
22162306a36Sopenharmony_ci		if (reg_val != riscv_timebase)
22262306a36Sopenharmony_ci			return -EINVAL;
22362306a36Sopenharmony_ci		break;
22462306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(time):
22562306a36Sopenharmony_ci		gt->time_delta = reg_val - get_cycles64();
22662306a36Sopenharmony_ci		break;
22762306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(compare):
22862306a36Sopenharmony_ci		t->next_cycles = reg_val;
22962306a36Sopenharmony_ci		break;
23062306a36Sopenharmony_ci	case KVM_REG_RISCV_TIMER_REG(state):
23162306a36Sopenharmony_ci		if (reg_val == KVM_RISCV_TIMER_STATE_ON)
23262306a36Sopenharmony_ci			ret = kvm_riscv_vcpu_timer_next_event(vcpu, reg_val);
23362306a36Sopenharmony_ci		else
23462306a36Sopenharmony_ci			ret = kvm_riscv_vcpu_timer_cancel(t);
23562306a36Sopenharmony_ci		break;
23662306a36Sopenharmony_ci	default:
23762306a36Sopenharmony_ci		ret = -ENOENT;
23862306a36Sopenharmony_ci		break;
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	return ret;
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ciint kvm_riscv_vcpu_timer_init(struct kvm_vcpu *vcpu)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	if (t->init_done)
24962306a36Sopenharmony_ci		return -EINVAL;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	hrtimer_init(&t->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
25262306a36Sopenharmony_ci	t->init_done = true;
25362306a36Sopenharmony_ci	t->next_set = false;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* Enable sstc for every vcpu if available in hardware */
25662306a36Sopenharmony_ci	if (riscv_isa_extension_available(NULL, SSTC)) {
25762306a36Sopenharmony_ci		t->sstc_enabled = true;
25862306a36Sopenharmony_ci		t->hrt.function = kvm_riscv_vcpu_vstimer_expired;
25962306a36Sopenharmony_ci		t->timer_next_event = kvm_riscv_vcpu_update_vstimecmp;
26062306a36Sopenharmony_ci	} else {
26162306a36Sopenharmony_ci		t->sstc_enabled = false;
26262306a36Sopenharmony_ci		t->hrt.function = kvm_riscv_vcpu_hrtimer_expired;
26362306a36Sopenharmony_ci		t->timer_next_event = kvm_riscv_vcpu_update_hrtimer;
26462306a36Sopenharmony_ci	}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	return 0;
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ciint kvm_riscv_vcpu_timer_deinit(struct kvm_vcpu *vcpu)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	int ret;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	ret = kvm_riscv_vcpu_timer_cancel(&vcpu->arch.timer);
27462306a36Sopenharmony_ci	vcpu->arch.timer.init_done = false;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	return ret;
27762306a36Sopenharmony_ci}
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ciint kvm_riscv_vcpu_timer_reset(struct kvm_vcpu *vcpu)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	t->next_cycles = -1ULL;
28462306a36Sopenharmony_ci	return kvm_riscv_vcpu_timer_cancel(&vcpu->arch.timer);
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistatic void kvm_riscv_vcpu_update_timedelta(struct kvm_vcpu *vcpu)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &vcpu->kvm->arch.timer;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci#if defined(CONFIG_32BIT)
29262306a36Sopenharmony_ci	csr_write(CSR_HTIMEDELTA, (u32)(gt->time_delta));
29362306a36Sopenharmony_ci	csr_write(CSR_HTIMEDELTAH, (u32)(gt->time_delta >> 32));
29462306a36Sopenharmony_ci#else
29562306a36Sopenharmony_ci	csr_write(CSR_HTIMEDELTA, gt->time_delta);
29662306a36Sopenharmony_ci#endif
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_civoid kvm_riscv_vcpu_timer_restore(struct kvm_vcpu *vcpu)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	kvm_riscv_vcpu_update_timedelta(vcpu);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (!t->sstc_enabled)
30662306a36Sopenharmony_ci		return;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci#if defined(CONFIG_32BIT)
30962306a36Sopenharmony_ci	csr_write(CSR_VSTIMECMP, (u32)t->next_cycles);
31062306a36Sopenharmony_ci	csr_write(CSR_VSTIMECMPH, (u32)(t->next_cycles >> 32));
31162306a36Sopenharmony_ci#else
31262306a36Sopenharmony_ci	csr_write(CSR_VSTIMECMP, t->next_cycles);
31362306a36Sopenharmony_ci#endif
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	/* timer should be enabled for the remaining operations */
31662306a36Sopenharmony_ci	if (unlikely(!t->init_done))
31762306a36Sopenharmony_ci		return;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	kvm_riscv_vcpu_timer_unblocking(vcpu);
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_civoid kvm_riscv_vcpu_timer_sync(struct kvm_vcpu *vcpu)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	if (!t->sstc_enabled)
32762306a36Sopenharmony_ci		return;
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci#if defined(CONFIG_32BIT)
33062306a36Sopenharmony_ci	t->next_cycles = csr_read(CSR_VSTIMECMP);
33162306a36Sopenharmony_ci	t->next_cycles |= (u64)csr_read(CSR_VSTIMECMPH) << 32;
33262306a36Sopenharmony_ci#else
33362306a36Sopenharmony_ci	t->next_cycles = csr_read(CSR_VSTIMECMP);
33462306a36Sopenharmony_ci#endif
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_civoid kvm_riscv_vcpu_timer_save(struct kvm_vcpu *vcpu)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	struct kvm_vcpu_timer *t = &vcpu->arch.timer;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	if (!t->sstc_enabled)
34262306a36Sopenharmony_ci		return;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	/*
34562306a36Sopenharmony_ci	 * The vstimecmp CSRs are saved by kvm_riscv_vcpu_timer_sync()
34662306a36Sopenharmony_ci	 * upon every VM exit so no need to save here.
34762306a36Sopenharmony_ci	 */
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	/* timer should be enabled for the remaining operations */
35062306a36Sopenharmony_ci	if (unlikely(!t->init_done))
35162306a36Sopenharmony_ci		return;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if (kvm_vcpu_is_blocking(vcpu))
35462306a36Sopenharmony_ci		kvm_riscv_vcpu_timer_blocking(vcpu);
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_civoid kvm_riscv_guest_timer_init(struct kvm *kvm)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	struct kvm_guest_timer *gt = &kvm->arch.timer;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	riscv_cs_get_mult_shift(&gt->nsec_mult, &gt->nsec_shift);
36262306a36Sopenharmony_ci	gt->time_delta = -get_cycles64();
36362306a36Sopenharmony_ci}
364