From bd91ee22a492a01a93f97155abd2e1eee474e5cd Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 20 Apr 2022 12:02:15 +0100 Subject: [PATCH] ANDROID: KVM: arm64: Add the {flush,sync}_hyp_timer_state() primitives In preparation for save/restore of the timer state at EL2 for protected VMs, introduce a couple of sync/flush primitives for the architected timer, in much the same way as we have for the GIC. Signed-off-by: Marc Zyngier Signed-off-by: Will Deacon Bug: 233587962 Change-Id: I51fd848f12c71e2c6cb14d3db834a12f1a3226d8 --- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 39f1446c0954..359d64f6885b 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -63,6 +63,38 @@ static void sync_hyp_vgic_state(struct pkvm_hyp_vcpu *hyp_vcpu) WRITE_ONCE(host_cpu_if->vgic_lr[i], hyp_cpu_if->vgic_lr[i]); } +static void flush_hyp_timer_state(struct pkvm_hyp_vcpu *hyp_vcpu) +{ + if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu)) + return; + + /* + * A hyp vcpu has no offset, and sees vtime == ptime. The + * ptimer is fully emulated by EL1 and cannot be trusted. + */ + write_sysreg(0, cntvoff_el2); + isb(); + write_sysreg_el0(__vcpu_sys_reg(&hyp_vcpu->vcpu, CNTV_CVAL_EL0), + SYS_CNTV_CVAL); + write_sysreg_el0(__vcpu_sys_reg(&hyp_vcpu->vcpu, CNTV_CTL_EL0), + SYS_CNTV_CTL); +} + +static void sync_hyp_timer_state(struct pkvm_hyp_vcpu *hyp_vcpu) +{ + if (!pkvm_hyp_vcpu_is_protected(hyp_vcpu)) + return; + + /* + * Preserve the vtimer state so that it is always correct, + * even if the host tries to make a mess. + */ + __vcpu_sys_reg(&hyp_vcpu->vcpu, CNTV_CVAL_EL0) = + read_sysreg_el0(SYS_CNTV_CVAL); + __vcpu_sys_reg(&hyp_vcpu->vcpu, CNTV_CTL_EL0) = + read_sysreg_el0(SYS_CNTV_CTL); +} + static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) { struct kvm_vcpu *host_vcpu = hyp_vcpu->host_vcpu; @@ -85,6 +117,7 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) hyp_vcpu->vcpu.arch.vsesr_el2 = host_vcpu->arch.vsesr_el2; flush_hyp_vgic_state(hyp_vcpu); + flush_hyp_timer_state(hyp_vcpu); } static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) @@ -102,6 +135,7 @@ static void sync_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu) host_vcpu->arch.fp_state = hyp_vcpu->vcpu.arch.fp_state; sync_hyp_vgic_state(hyp_vcpu); + sync_hyp_timer_state(hyp_vcpu); } static void handle___kvm_vcpu_run(struct kvm_cpu_context *host_ctxt)