Skip to content

Commit fe769e6

Browse files
Marc Zyngieroupton
Marc Zyngier
authored andcommitted
KVM: arm64: timers: Use CNTHCTL_EL2 when setting non-CNTKCTL_EL1 bits
It recently appeared that, when running VHE, there is a notable difference between using CNTKCTL_EL1 and CNTHCTL_EL2, despite what the architecture documents: - When accessed from EL2, bits [19:18] and [16:10] of CNTKCTL_EL1 have the same assignment as CNTHCTL_EL2 - When accessed from EL1, bits [19:18] and [16:10] are RES0 It is all OK, until you factor in NV, where the EL2 guest runs at EL1. In this configuration, CNTKCTL_EL11 doesn't trap, nor ends up in the VNCR page. This means that any write from the guest affecting CNTHCTL_EL2 using CNTKCTL_EL1 ends up losing some state. Not good. The fix it obvious: don't use CNTKCTL_EL1 if you want to change bits that are not part of the EL1 definition of CNTKCTL_EL1, and use CNTHCTL_EL2 instead. This doesn't change anything for a bare-metal OS, and fixes it when running under NV. The NV hypervisor will itself have to work harder to merge the two accessors. Note that there is a pending update to the architecture to address this issue by making the affected bits UNKNOWN when CNTKCTL_EL1 is used from EL2 with VHE enabled. Fixes: c605ee2 ("KVM: arm64: timers: Allow physical offset without CNTPOFF_EL2") Signed-off-by: Marc Zyngier <[email protected]> Cc: [email protected] # v6.4 Reviewed-by: Eric Auger <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent 06c2afb commit fe769e6

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

arch/arm64/kvm/arch_timer.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,8 +827,8 @@ static void timer_set_traps(struct kvm_vcpu *vcpu, struct timer_map *map)
827827
assign_clear_set_bit(tpt, CNTHCTL_EL1PCEN << 10, set, clr);
828828
assign_clear_set_bit(tpc, CNTHCTL_EL1PCTEN << 10, set, clr);
829829

830-
/* This only happens on VHE, so use the CNTKCTL_EL1 accessor */
831-
sysreg_clear_set(cntkctl_el1, clr, set);
830+
/* This only happens on VHE, so use the CNTHCTL_EL2 accessor. */
831+
sysreg_clear_set(cnthctl_el2, clr, set);
832832
}
833833

834834
void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
@@ -1563,7 +1563,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
15631563
void kvm_timer_init_vhe(void)
15641564
{
15651565
if (cpus_have_final_cap(ARM64_HAS_ECV_CNTPOFF))
1566-
sysreg_clear_set(cntkctl_el1, 0, CNTHCTL_ECV);
1566+
sysreg_clear_set(cnthctl_el2, 0, CNTHCTL_ECV);
15671567
}
15681568

15691569
int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)

0 commit comments

Comments
 (0)