ANDROID: KVM: arm64: Save/restore virtual timer state from the shadow vcpu

Similar to the vgic state, make sure to sync and flush the virtual timer
state between the host and the hyp shadow vCPU structs when running in
nVHE protected mode.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Bug: 209580772
Change-Id: Ib90273bb670d9d815dd9f542369dde00753655cf
Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
Marc Zyngier
2021-10-12 17:46:25 +01:00
committed by Will Deacon
parent 3784299dce
commit be1849348b
2 changed files with 30 additions and 1 deletions

View File

@@ -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);

View File

@@ -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: