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 <maz@kernel.org>
Signed-off-by: Will Deacon <willdeacon@google.com>
Bug: 233587962
Change-Id: I51fd848f12c71e2c6cb14d3db834a12f1a3226d8
This commit is contained in:
Marc Zyngier
2022-04-20 12:02:15 +01:00
committed by Will Deacon
parent e36af628ae
commit bd91ee22a4

View File

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