lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0ff98f7888b5ff26d5a2c546587dcb52234aafe9.1770116050.git.isaku.yamahata@intel.com>
Date: Tue,  3 Feb 2026 10:16:46 -0800
From: isaku.yamahata@...el.com
To: kvm@...r.kernel.org
Cc: isaku.yamahata@...el.com,
	isaku.yamahata@...il.com,
	Paolo Bonzini <pbonzini@...hat.com>,
	Sean Christopherson <seanjc@...gle.com>,
	linux-kernel@...r.kernel.org,
	Yang Zhong <yang.zhong@...ux.intel.com>
Subject: [PATCH 03/32] KVM: x86/lapic: Start/stop sw/hv timer on vCPU un/block

From: Yang Zhong <yang.zhong@...ux.intel.com>

Switch to use software timer when a vCPU is blocked by instructions such as
HLT similar to the hv timer case.

The guest deadline shadow field is read to obtain the guest_tsc value,
which is then used to program an hrtimer for the duration of the vCPU
block. Upon completion of the block, if the LAPIC timer has pending
interrupts, the LAPIC timer is transitioned to APIC virt timer mode to
continue providing timer services to the guest.
Set the guest TSC deadline to 0 when injecting a timer interrupt, as the
TSC deadline is cleared to zero when a timer interrupt is injected.  Do so
when injecting a timer interrupt to the vCPU.

Co-developed-by: Yang Zhong <yang.zhong@...ux.intel.com>
Signed-off-by: Yang Zhong <yang.zhong@...ux.intel.com>
Co-developed-by: Isaku Yamahata <isaku.yamahata@...el.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@...el.com>
---
 arch/x86/kvm/lapic.c | 20 +++++++++++++++++---
 arch/x86/kvm/lapic.h |  6 ++++++
 arch/x86/kvm/x86.c   |  7 +++++--
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index b942210c6a25..ee15d3bf5ef9 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2041,6 +2041,8 @@ static void kvm_apic_inject_pending_timer_irqs(struct kvm_lapic *apic)
 	kvm_apic_local_deliver(apic, APIC_LVTT);
 	if (apic_lvtt_tscdeadline(apic)) {
 		ktimer->tscdeadline = 0;
+		if (apic->lapic_timer.apic_virt_timer_in_use)
+			kvm_x86_call(set_guest_tsc_deadline_virt)(apic->vcpu, 0);
 	} else if (apic_lvtt_oneshot(apic)) {
 		ktimer->tscdeadline = 0;
 		ktimer->target_expiration = 0;
@@ -2320,8 +2322,10 @@ static void start_sw_timer(struct kvm_lapic *apic)
 	struct kvm_timer *ktimer = &apic->lapic_timer;
 
 	WARN_ON(preemptible());
-	if (apic->lapic_timer.hv_timer_in_use)
+	if (apic->lapic_timer.hv_timer_in_use) {
 		cancel_hv_timer(apic);
+		trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, false);
+	}
 	if (!apic_lvtt_period(apic) && atomic_read(&ktimer->pending))
 		return;
 
@@ -2329,7 +2333,6 @@ static void start_sw_timer(struct kvm_lapic *apic)
 		start_sw_period(apic);
 	else if (apic_lvtt_tscdeadline(apic))
 		start_sw_tscdeadline(apic);
-	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id, false);
 }
 
 static void restart_apic_timer(struct kvm_lapic *apic)
@@ -2374,13 +2377,24 @@ void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu)
 	restart_apic_timer(vcpu->arch.apic);
 }
 
+void kvm_lapic_switch_to_apic_virt_timer(struct kvm_vcpu *vcpu)
+{
+	hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
+}
+
 void kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
 	preempt_disable();
+
+	if (apic->lapic_timer.apic_virt_timer_in_use)
+		apic->lapic_timer.tscdeadline =
+			kvm_x86_call(get_guest_tsc_deadline_virt)(vcpu);
+
 	/* Possibly the TSC deadline timer is not enabled yet */
-	if (apic->lapic_timer.hv_timer_in_use)
+	if (apic->lapic_timer.hv_timer_in_use ||
+	    apic->lapic_timer.apic_virt_timer_in_use)
 		start_sw_timer(apic);
 	preempt_enable();
 }
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 42fbb66f1e4e..67172fef1b5b 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -241,10 +241,16 @@ bool kvm_intr_is_single_vcpu(struct kvm *kvm, struct kvm_lapic_irq *irq,
 			     struct kvm_vcpu **dest_vcpu);
 void kvm_lapic_switch_to_sw_timer(struct kvm_vcpu *vcpu);
 void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu);
+void kvm_lapic_switch_to_apic_virt_timer(struct kvm_vcpu *vcpu);
 void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu);
 bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu);
 void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu);
 
+static inline bool kvm_lapic_apic_virt_timer_in_use(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.apic->lapic_timer.apic_virt_timer_in_use;
+}
+
 static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
 {
 	return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 63afdb6bb078..2a72709aeb03 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11563,7 +11563,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 /* Called within kvm->srcu read side.  */
 static inline int vcpu_block(struct kvm_vcpu *vcpu)
 {
-	bool hv_timer;
+	bool hv_timer, virt_timer;
 
 	if (!kvm_arch_vcpu_runnable(vcpu)) {
 		/*
@@ -11574,7 +11574,8 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu)
 		 * timer before blocking.
 		 */
 		hv_timer = kvm_lapic_hv_timer_in_use(vcpu);
-		if (hv_timer)
+		virt_timer = kvm_lapic_apic_virt_timer_in_use(vcpu);
+		if (hv_timer || virt_timer)
 			kvm_lapic_switch_to_sw_timer(vcpu);
 
 		kvm_vcpu_srcu_read_unlock(vcpu);
@@ -11586,6 +11587,8 @@ static inline int vcpu_block(struct kvm_vcpu *vcpu)
 
 		if (hv_timer)
 			kvm_lapic_switch_to_hv_timer(vcpu);
+		else if (virt_timer)
+			kvm_lapic_switch_to_apic_virt_timer(vcpu);
 
 		/*
 		 * If the vCPU is not runnable, a signal or another host event
-- 
2.45.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ