Re: [PATCH v4 03/28] KVM: arm64: pkvm: Add pkvm_time_get()

Will Deacon
2025-09-09T17:21:02Z

On Tue, Aug 19, 2025 at 09:51:31PM +0000, Mostafa Saleh wrote:
> Add a function to return time in us.
>
> This can be used from IOMMU drivers while waiting for conditions as
> for SMMUv3 TLB invalidation waiting for sync.
>
> Signed-off-by: Mostafa Saleh <smostafa@google.com>
> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
> ---
> arch/arm64/kvm/hyp/include/nvhe/pkvm.h | 2 ++
> arch/arm64/kvm/hyp/nvhe/setup.c | 4 ++++
> arch/arm64/kvm/hyp/nvhe/timer-sr.c | 33 ++++++++++++++++++++++++++
> 3 files changed, 39 insertions(+)
>
> diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> index ce31d3b73603..6c19691720cd 100644
> --- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> +++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
> @@ -87,4 +87,6 @@ bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
> void kvm_init_pvm_id_regs(struct kvm_vcpu *vcpu);
> int kvm_check_pvm_sysreg_table(void);
>
> +int pkvm_timer_init(void);
> +u64 pkvm_time_get(void);
> #endif /* __ARM64_KVM_NVHE_PKVM_H__ */
> diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c
> index a48d3f5a5afb..ee6435473204 100644
> --- a/arch/arm64/kvm/hyp/nvhe/setup.c
> +++ b/arch/arm64/kvm/hyp/nvhe/setup.c
> @@ -304,6 +304,10 @@ void __noreturn __pkvm_init_finalise(void)
> };
> pkvm_pgtable.mm_ops = &pkvm_pgtable_mm_ops;
>
> + ret = pkvm_timer_init();
> + if (ret)
> + goto out;
> +
> ret = fix_host_ownership();
> if (ret)
> goto out;
> diff --git a/arch/arm64/kvm/hyp/nvhe/timer-sr.c b/arch/arm64/kvm/hyp/nvhe/timer-sr.c
> index ff176f4ce7de..e166cd5a56b8 100644
> --- a/arch/arm64/kvm/hyp/nvhe/timer-sr.c
> +++ b/arch/arm64/kvm/hyp/nvhe/timer-sr.c
> @@ -11,6 +11,10 @@
> #include <asm/kvm_hyp.h>
> #include <asm/kvm_mmu.h>
>
> +#include <nvhe/pkvm.h>
> +
> +static u32 timer_freq;
> +
> void __kvm_timer_set_cntvoff(u64 cntvoff)
> {
> write_sysreg(cntvoff, cntvoff_el2);
> @@ -68,3 +72,32 @@ void __timer_enable_traps(struct kvm_vcpu *vcpu)
>
> sysreg_clear_set(cnthctl_el2, clr, set);
> }
> +
> +static u64 pkvm_ticks_get(void)
> +{
> + return __arch_counter_get_cntvct();
> +}
> +
> +#define SEC_TO_US 1000000
> +
> +int pkvm_timer_init(void)
> +{
> + timer_freq = read_sysreg(cntfrq_el0);
> + /*
> + * TODO: The highest privileged level is supposed to initialize this
> + * register. But on some systems (which?), this information is only
> + * contained in the device-tree, so we'll need to find it out some other
> + * way.
> + */
> + if (!timer_freq || timer_freq < SEC_TO_US)
> + return -ENODEV;
> + return 0;
> +}

Right, I think the frequency should be provided by the host once the arch
timer driver has probed successfully. Relying on CNTFRQ isn't viable imo.

Will