]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Move CNT*CT_EL0 userspace accessors to generic infrastructure
authorMarc Zyngier <maz@kernel.org>
Mon, 29 Sep 2025 16:04:52 +0000 (17:04 +0100)
committerMarc Zyngier <maz@kernel.org>
Mon, 13 Oct 2025 13:42:41 +0000 (14:42 +0100)
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>
arch/arm64/kvm/guest.c
arch/arm64/kvm/sys_regs.c

index c23ec9be4ce27741a5eb2389c2de467df452d213..138e5e2dc10c82829e33d8b4fecf9c3a07300fbe 100644 (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;
 }
 
index 68e88d5c0dfb504370016a6dbd2f483388e19d41..e67eb39ddc11844f0bc4c862c1784f95f8a34676 100644 (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 },