Re: [PATCH 55/59] arm64: KVM: nv: Add handling of EL2-specific timer registers

Alexandru Elisei
2019-07-11T12:35:23Z

On 6/21/19 10:38 AM, Marc Zyngier wrote:

> Add the required handling for EL2 and EL02 registers, as
> well as EL1 registers used in the E2H context.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm64/kvm/sys_regs.c | 72 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 72 insertions(+)
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index ba3bcd29c02d..0bd6a66b621e 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1361,20 +1361,92 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
>
> switch (reg) {
> case SYS_CNTP_TVAL_EL0:
> + if (vcpu_mode_el2(vcpu) && vcpu_el2_e2h_is_set(vcpu))
> + tmr = TIMER_HPTIMER;
> + else
> + tmr = TIMER_PTIMER;
> + treg = TIMER_REG_TVAL;
> + break;
> +
> case SYS_AARCH32_CNTP_TVAL:
> + case SYS_CNTP_TVAL_EL02:
> tmr = TIMER_PTIMER;
> treg = TIMER_REG_TVAL;
> break;
> +
> + case SYS_CNTV_TVAL_EL02:
> + tmr = TIMER_VTIMER;
> + treg = TIMER_REG_TVAL;
> + break;
> +
> + case SYS_CNTHP_TVAL_EL2:
> + tmr = TIMER_HPTIMER;
> + treg = TIMER_REG_TVAL;
> + break;
> +
> + case SYS_CNTHV_TVAL_EL2:
> + tmr = TIMER_HVTIMER;
> + treg = TIMER_REG_TVAL;
> + break;
> +
> case SYS_CNTP_CTL_EL0:
> + if (vcpu_mode_el2(vcpu) && vcpu_el2_e2h_is_set(vcpu))
> + tmr = TIMER_HPTIMER;
> + else
> + tmr = TIMER_PTIMER;
> + treg = TIMER_REG_CTL;
> + break;
> +
> case SYS_AARCH32_CNTP_CTL:
> + case SYS_CNTP_CTL_EL02:
> tmr = TIMER_PTIMER;
> treg = TIMER_REG_CTL;
> break;
> +
> + case SYS_CNTV_CTL_EL02:
> + tmr = TIMER_VTIMER;
> + treg = TIMER_REG_CTL;
> + break;
> +
> + case SYS_CNTHP_CTL_EL2:
> + tmr = TIMER_HPTIMER;
> + treg = TIMER_REG_CTL;
> + break;
> +
> + case SYS_CNTHV_CTL_EL2:
> + tmr = TIMER_HVTIMER;
> + treg = TIMER_REG_CTL;
> + break;
> +
> case SYS_CNTP_CVAL_EL0:
> + if (vcpu_mode_el2(vcpu) && vcpu_el2_e2h_is_set(vcpu))
> + tmr = TIMER_HPTIMER;
> + else
> + tmr = TIMER_PTIMER;
> + treg = TIMER_REG_CVAL;
> + break;
> +
> case SYS_AARCH32_CNTP_CVAL:
> + case SYS_CNTP_CVAL_EL02:
> tmr = TIMER_PTIMER;
> treg = TIMER_REG_CVAL;
> break;
> +
> + case SYS_CNTV_CVAL_EL02:
> + tmr = TIMER_VTIMER;
> + treg = TIMER_REG_CVAL;
> + break;
> +
> + case SYS_CNTHP_CVAL_EL2:
> + tmr = TIMER_HPTIMER;
> + treg = TIMER_REG_CVAL;
> + break;
> +
> + case SYS_CNTHV_CVAL_EL2:
> + tmr = TIMER_HVTIMER;
> + treg = TIMER_REG_CVAL;
> + break;
> +
> case SYS_CNTVOFF_EL2:
> tmr = TIMER_VTIMER;
> treg = TIMER_REG_VOFF;

Shouldn't we forward physical timer traps to the L1 guest hypervisor if
__vcpu_sys_reg(vcpu, CNTHCTL_EL2.EL1PTEN) == 0 (trap access) and
!vcpu_mode_el2(vcpu)? A regular (non-nested) non-vhe hypervisor can set that bit
to emulate the physical timer. If I remember correctly, KVM with VHE used to do
it too until some time ago.