KVM: arm64: Move CNT*CT_EL0 userspace accessors to generic infrastructure

Moving the counter registers is a bit more involved than for the control
and comparator (there is no shadow data for the counter), but still
pretty manageable.

Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
Marc Zyngier 2025-09-29 17:04:52 +01:00
parent 8af198980e
commit c3be3a48fb
2 changed files with 31 additions and 10 deletions

View File

@ -592,19 +592,12 @@ static unsigned long num_core_regs(const struct kvm_vcpu *vcpu)
}
static const u64 timer_reg_list[] = {
KVM_REG_ARM_TIMER_CNT,
KVM_REG_ARM_PTIMER_CNT,
};
#define NUM_TIMER_REGS ARRAY_SIZE(timer_reg_list)
static bool is_timer_reg(u64 index)
{
switch (index) {
case KVM_REG_ARM_TIMER_CNT:
case KVM_REG_ARM_PTIMER_CNT:
return true;
}
return false;
}

View File

@ -1605,12 +1605,38 @@ static int arch_timer_set_user(struct kvm_vcpu *vcpu,
case SYS_CNTHP_CTL_EL2:
val &= ~ARCH_TIMER_CTRL_IT_STAT;
break;
case SYS_CNTVCT_EL0:
if (!test_bit(KVM_ARCH_FLAG_VM_COUNTER_OFFSET, &vcpu->kvm->arch.flags))
timer_set_offset(vcpu_vtimer(vcpu), kvm_phys_timer_read() - val);
return 0;
case SYS_CNTPCT_EL0:
if (!test_bit(KVM_ARCH_FLAG_VM_COUNTER_OFFSET, &vcpu->kvm->arch.flags))
timer_set_offset(vcpu_ptimer(vcpu), kvm_phys_timer_read() - val);
return 0;
}
__vcpu_assign_sys_reg(vcpu, rd->reg, val);
return 0;
}
static int arch_timer_get_user(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd,
u64 *val)
{
switch (reg_to_encoding(rd)) {
case SYS_CNTVCT_EL0:
*val = kvm_phys_timer_read() - timer_get_offset(vcpu_vtimer(vcpu));
break;
case SYS_CNTPCT_EL0:
*val = kvm_phys_timer_read() - timer_get_offset(vcpu_ptimer(vcpu));
break;
default:
*val = __vcpu_sys_reg(vcpu, rd->reg);
}
return 0;
}
static s64 kvm_arm64_ftr_safe_value(u32 id, const struct arm64_ftr_bits *ftrp,
s64 new, s64 cur)
{
@ -2539,7 +2565,7 @@ static bool bad_redir_trap(struct kvm_vcpu *vcpu,
#define TIMER_REG(name, vis) \
SYS_REG_USER_FILTER(name, access_arch_timer, reset_val, 0, \
NULL, arch_timer_set_user, vis)
arch_timer_get_user, arch_timer_set_user, vis)
/*
* Since reset() callback and field val are not used for idregs, they will be
@ -3506,8 +3532,10 @@ static const struct sys_reg_desc sys_reg_descs[] = {
AMU_AMEVTYPER1_EL0(14),
AMU_AMEVTYPER1_EL0(15),
{ SYS_DESC(SYS_CNTPCT_EL0), access_arch_timer },
{ SYS_DESC(SYS_CNTVCT_EL0), access_arch_timer },
{ SYS_DESC(SYS_CNTPCT_EL0), .access = access_arch_timer,
.get_user = arch_timer_get_user, .set_user = arch_timer_set_user },
{ SYS_DESC(SYS_CNTVCT_EL0), .access = access_arch_timer,
.get_user = arch_timer_get_user, .set_user = arch_timer_set_user },
{ SYS_DESC(SYS_CNTPCTSS_EL0), access_arch_timer },
{ SYS_DESC(SYS_CNTVCTSS_EL0), access_arch_timer },
{ SYS_DESC(SYS_CNTP_TVAL_EL0), access_arch_timer },