]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
KVM: arm64: Convert timer offset VA when accessed in HYP code
authorMarc Zyngier <maz@kernel.org>
Wed, 12 Feb 2025 17:34:54 +0000 (17:34 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 13 Feb 2025 17:55:13 +0000 (17:55 +0000)
Now that EL2 has gained some early timer emulation, it accesses
the offsets pointed to by the timer structure, both of which
live in the KVM structure.

Of course, these are *kernel* pointers, so the dereferencing
of these pointers in non-kernel code must be itself be offset.

Given switch.h its own version of timer_get_offset() and use that
instead.

Fixes: b86fc215dc26d ("KVM: arm64: Handle counter access early in non-HYP context")
Reported-by: Linux Kernel Functional Testing <lkft@linaro.org>
Reviewed-by: Oliver Upton <oliver.upton@linux.dev>
Tested-by: Anders Roxell <anders.roxell@linaro.org>
Link: https://lore.kernel.org/r/20250212173454.2864462-1-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/hyp/include/hyp/switch.h

index f5e882a358e2d6e6805d112ed646a112455012e8..23bbe28eaaf95d2a61b6c189d603c23a85f71203 100644 (file)
@@ -581,9 +581,22 @@ static inline bool handle_tx2_tvm(struct kvm_vcpu *vcpu)
        return true;
 }
 
+/* Open-coded version of timer_get_offset() to allow for kern_hyp_va() */
+static inline u64 hyp_timer_get_offset(struct arch_timer_context *ctxt)
+{
+       u64 offset = 0;
+
+       if (ctxt->offset.vm_offset)
+               offset += *kern_hyp_va(ctxt->offset.vm_offset);
+       if (ctxt->offset.vcpu_offset)
+               offset += *kern_hyp_va(ctxt->offset.vcpu_offset);
+
+       return offset;
+}
+
 static inline u64 compute_counter_value(struct arch_timer_context *ctxt)
 {
-       return arch_timer_read_cntpct_el0() - timer_get_offset(ctxt);
+       return arch_timer_read_cntpct_el0() - hyp_timer_get_offset(ctxt);
 }
 
 static bool kvm_handle_cntxct(struct kvm_vcpu *vcpu)