| From d21ac42171b150d6870e91a395f72845982311ff Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 14 Aug 2025 17:11:57 -0700 |
| Subject: KVM: VMX: Handle KVM-induced preemption timer exits in fastpath for |
| L2 |
| |
| From: Sean Christopherson <seanjc@google.com> |
| |
| [ Upstream commit 7b3d1bbf8d68d76fb21210932a5e8ed8ea80dbcc ] |
| |
| Eat VMX treemption timer exits in the fastpath regardless of whether L1 or |
| L2 is active. The VM-Exit is 100% KVM-induced, i.e. there is nothing |
| directly related to the exit that KVM needs to do on behalf of the guest, |
| thus there is no reason to wait until the slow path to do nothing. |
| |
| Opportunistically add comments explaining why preemption timer exits for |
| emulating the guest's APIC timer need to go down the slow path. |
| |
| Link: https://lore.kernel.org/r/20240110012705.506918-6-seanjc@google.com |
| Signed-off-by: Sean Christopherson <seanjc@google.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/kvm/vmx/vmx.c | 22 ++++++++++++++++++++-- |
| 1 file changed, 20 insertions(+), 2 deletions(-) |
| |
| diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c |
| index 18ceed9046a9..4db9d41d988c 100644 |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -5948,13 +5948,26 @@ static fastpath_t handle_fastpath_preemption_timer(struct kvm_vcpu *vcpu) |
| if (vmx->req_immediate_exit) |
| return EXIT_FASTPATH_EXIT_HANDLED; |
| |
| + /* |
| + * If L2 is active, go down the slow path as emulating the guest timer |
| + * expiration likely requires synthesizing a nested VM-Exit. |
| + */ |
| + if (is_guest_mode(vcpu)) |
| + return EXIT_FASTPATH_NONE; |
| + |
| kvm_lapic_expired_hv_timer(vcpu); |
| return EXIT_FASTPATH_REENTER_GUEST; |
| } |
| |
| static int handle_preemption_timer(struct kvm_vcpu *vcpu) |
| { |
| - handle_fastpath_preemption_timer(vcpu); |
| + /* |
| + * This non-fastpath handler is reached if and only if the preemption |
| + * timer was being used to emulate a guest timer while L2 is active. |
| + * All other scenarios are supposed to be handled in the fastpath. |
| + */ |
| + WARN_ON_ONCE(!is_guest_mode(vcpu)); |
| + kvm_lapic_expired_hv_timer(vcpu); |
| return 1; |
| } |
| |
| @@ -7138,7 +7151,12 @@ void noinstr vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx, |
| |
| static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu) |
| { |
| - if (is_guest_mode(vcpu)) |
| + /* |
| + * If L2 is active, some VMX preemption timer exits can be handled in |
| + * the fastpath even, all other exits must use the slow path. |
| + */ |
| + if (is_guest_mode(vcpu) && |
| + to_vmx(vcpu)->exit_reason.basic != EXIT_REASON_PREEMPTION_TIMER) |
| return EXIT_FASTPATH_NONE; |
| |
| switch (to_vmx(vcpu)->exit_reason.basic) { |
| -- |
| 2.50.1 |
| |