All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH] KVM: arm64: Restrict CNTP_CVAL/CNTHP_CVAL save/reload when ptimer is used
@ 2026-09-21 11:18 Zhou Wang
  2026-09-21 11:41 ` sashiko-bot
  2026-09-21 13:22 ` Marc Zyngier
  0 siblings, 2 replies; 6+ messages in thread
From: Zhou Wang @ 2026-09-21 11:18 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton, Fuad Tabba, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Will Deacon,
	Mark Rutland
  Cc: kvmarm, Zhou Wang, Nianyao Tang

A guest's physical timer may be used in nested guest or directly used in
VHE mode. We can check above cases to avoid useless CNTP_CVAL/CNTHP_CVAL save
and reload.

Use lazy detection to determine whether a non-nested VHE guest actually uses
the physical timer.

timer_set_traps() initially traps CNTP_CTL_EL0 writes for non-nested guests.
On the first write that sets CNTP_CTL.ENABLE=1, the trap handler records
ptimer_used and clears the trap in CNTHCTL_EL2, allowing the guest direct
access thereafter.

A test result from KUT in HiSilicon HIP12 is:

                    nopatch        patch
 hvc                758            624
 mmio_read_user     3647           3479
 mmio_read_vgic     949            817
 eoi                29             29
 ipi                2534           2302
 lpi                2684           2442
 timer_10ms         2393           2168

Reported-by: Nianyao Tang <tangnianyao@huawei.com>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
 arch/arm64/kvm/arch_timer.c     | 15 +++++++++++++++
 arch/arm64/kvm/hyp/vhe/switch.c |  6 ++++--
 include/kvm/arm_arch_timer.h    |  1 +
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c
index 6ac3321f4c57..fcbd1e133ad0 100644
--- a/arch/arm64/kvm/arch_timer.c
+++ b/arch/arm64/kvm/arch_timer.c
@@ -832,6 +832,10 @@ static void timer_set_traps(struct kvm_vcpu *vcpu, struct timer_map *map)
 	if (!has_cntpoff() && timer_get_offset(map->direct_ptimer))
 		tpt = tpc = true;
 
+	/* Lazy ptimer detection: trap CTL until guest first enables it */
+	if (has_cntpoff() && !vcpu_has_nv(vcpu) && !vcpu_timer(vcpu)->ptimer_used)
+		tpt = true;
+
 	/*
 	 * For the poor sods that could not correctly subtract one value
 	 * from another, trap the full virtual timer and counter.
@@ -1054,6 +1058,7 @@ void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
 		offs->vm_offset = &vcpu->kvm->arch.timer_data.poffset;
 	}
 
+	timer->ptimer_used = false;
 	if (timer->enabled) {
 		for (int i = 0; i < nr_timers(vcpu); i++)
 			kvm_timer_update_irq(vcpu, false,
@@ -1270,6 +1275,16 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
 		preempt_disable();
 		timer_save_state(timer);
 		kvm_arm_timer_write(vcpu, timer, treg, val);
+
+		/* Lazy ptimer detection: catch first CNTP_CTL enable */
+		if (has_cntpoff() && !vcpu_has_nv(vcpu) &&
+		    tmr == TIMER_PTIMER && treg == TIMER_REG_CTL &&
+		    (val & ARCH_TIMER_CTRL_ENABLE) &&
+		    !vcpu_timer(vcpu)->ptimer_used) {
+			vcpu_timer(vcpu)->ptimer_used = true;
+			sysreg_clear_set(cnthctl_el2, 0,
+					 CNTHCTL_EL1PCEN << 10);
+		}
 		timer_restore_state(timer);
 		preempt_enable();
 	}
diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
index 7875911c0506..0cd73093878a 100644
--- a/arch/arm64/kvm/hyp/vhe/switch.c
+++ b/arch/arm64/kvm/hyp/vhe/switch.c
@@ -122,7 +122,8 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
 
 	___activate_traps(vcpu, __compute_hcr(vcpu));
 
-	if (has_cntpoff()) {
+	if (has_cntpoff() &&
+	    (vcpu_has_nv(vcpu) || vcpu_timer(vcpu)->ptimer_used)) {
 		struct timer_map map;
 
 		get_timer_map(vcpu, &map);
@@ -156,7 +157,8 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
 
 	write_sysreg_hcr(HCR_HOST_VHE_FLAGS);
 
-	if (has_cntpoff()) {
+	if (has_cntpoff() &&
+	    (vcpu_has_nv(vcpu) || vcpu_timer(vcpu)->ptimer_used)) {
 		struct timer_map map;
 		u64 val, offset;
 
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index bc6f2fdd7ad3..f427246a7726 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -90,6 +90,7 @@ struct arch_timer_cpu {
 
 	/* Is the timer enabled */
 	bool			enabled;
+	bool			ptimer_used;
 };
 
 int __init kvm_timer_hyp_init(bool has_gic);
-- 
2.33.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-28  8:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-21 11:18 [RFC PATCH] KVM: arm64: Restrict CNTP_CVAL/CNTHP_CVAL save/reload when ptimer is used Zhou Wang
2026-09-21 11:41 ` sashiko-bot
2026-09-21 13:22 ` Marc Zyngier
2026-09-22 10:16   ` Zhou Wang
2026-09-24 17:58     ` Marc Zyngier
2026-09-28  8:30       ` Zhou Wang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.