diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 3df67c127489..b81944f25fc8 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -88,7 +88,9 @@ static u64 timer_get_offset(struct arch_timer_context *ctxt) switch(arch_timer_ctx_index(ctxt)) { case TIMER_VTIMER: - return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); + if (likely(!kvm_vm_is_protected(vcpu->kvm))) + return __vcpu_sys_reg(vcpu, CNTVOFF_EL2); + fallthrough; default: return 0; } @@ -754,6 +756,9 @@ static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff) struct kvm *kvm = vcpu->kvm; struct kvm_vcpu *tmp; + if (unlikely(kvm_vm_is_protected(vcpu->kvm))) + cntvoff = 0; + mutex_lock(&kvm->lock); kvm_for_each_vcpu(i, tmp, kvm) timer_set_offset(vcpu_vtimer(tmp), cntvoff); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index a5bdee91344e..13870bc5d4d0 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -253,6 +253,28 @@ static void sync_vgic_state(struct kvm_vcpu *host_vcpu, host_cpu_if->vgic_lr[i] = shadow_cpu_if->vgic_lr[i]; } +static void flush_timer_state(struct kvm_vcpu *shadow_vcpu) +{ + /* + * A shadow 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(shadow_vcpu, CNTV_CVAL_EL0), SYS_CNTV_CVAL); + write_sysreg_el0(__vcpu_sys_reg(shadow_vcpu, CNTV_CTL_EL0), SYS_CNTV_CTL); +} + +static void sync_timer_state(struct kvm_vcpu *shadow_vcpu) +{ + /* + * Preserve the vtimer state so that it is always correct, + * even if the host tries to make a mess. + */ + __vcpu_sys_reg(shadow_vcpu, CNTV_CVAL_EL0) = read_sysreg_el0(SYS_CNTV_CVAL); + __vcpu_sys_reg(shadow_vcpu, CNTV_CTL_EL0) = read_sysreg_el0(SYS_CNTV_CTL); +} + static bool handle_shadow_entry(struct kvm_vcpu *shadow_vcpu) { struct kvm_vcpu *host_vcpu = shadow_vcpu->arch.pkvm.host_vcpu; @@ -260,6 +282,7 @@ static bool handle_shadow_entry(struct kvm_vcpu *shadow_vcpu) shadow_entry_exit_handler_fn ec_handler; flush_vgic_state(host_vcpu, shadow_vcpu); + flush_timer_state(shadow_vcpu); switch (ARM_EXCEPTION_CODE(shadow_vcpu->arch.pkvm.exit_code)) { case ARM_EXCEPTION_IRQ: @@ -286,6 +309,7 @@ static void handle_shadow_exit(struct kvm_vcpu *shadow_vcpu) shadow_entry_exit_handler_fn ec_handler; sync_vgic_state(host_vcpu, shadow_vcpu); + sync_timer_state(shadow_vcpu); switch (shadow_vcpu->arch.pkvm.exit_code) { case ARM_EXCEPTION_IRQ: