From: Sean Christopherson <seanjc@google.com>
To: "Naveen N Rao (AMD)" <naveen@kernel.org>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Paolo Bonzini <pbonzini@redhat.com>,
Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>,
Vasant Hegde <vasant.hegde@amd.com>,
Maxim Levitsky <mlevitsk@redhat.com>,
Vitaly Kuznetsov <vkuznets@redhat.com>
Subject: Re: [PATCH 3/3] KVM: x86: Decouple APICv activation state from apicv_inhibit_reasons
Date: Mon, 3 Feb 2025 10:45:27 -0800 [thread overview]
Message-ID: <Z6EOxxZA9XLdXvrA@google.com> (raw)
In-Reply-To: <405a98c2f21b9fe73eddbc35c80b60d6523db70c.1738595289.git.naveen@kernel.org>
On Mon, Feb 03, 2025, Naveen N Rao (AMD) wrote:
> apicv_inhibit_reasons is used to determine if APICv is active, and if
> not, the reason(s) why it may be inhibited. In some scenarios, inhibit
> reasons can be set and cleared often, resulting in increased contention
> on apicv_update_lock used to guard updates to apicv_inhibit_reasons.
>
> In particular, if a guest is using PIT in reinject mode (the default)
> and if AVIC is enabled in kvm_amd kernel module, we inhibit AVIC during
> kernel PIT creation (APICV_INHIBIT_REASON_PIT_REINJ), resulting in KVM
> emulating x2APIC for the guest. In that case, since AVIC is enabled in
> the kvm_amd kernel module, KVM additionally inhibits AVIC for requesting
> a IRQ window every time it has to inject external interrupts resulting
> in a barrage of inhibits being set and cleared. This shows significant
> performance degradation compared to AVIC being disabled, due to high
> contention on apicv_update_lock.
>
> Though apicv_update_lock is being used to guard updates to
> apicv_inhibit_reasons, it is only necessary if the APICv activation
> state changes. Introduce a separate boolean, apicv_activated, to track
> if APICv is active or not, and limit use of apicv_update_lock for when
> APICv is being (de)activated. Convert apicv_inhibit_reasons to an atomic
> and use atomic operations to fetch/update it.
It's a moot point, but there is too much going on in this patch. For a change
like this, it should be split into at ~4 patches:
1. Add an kvm_x86_ops.required_apicv_inhibits check outside outside of the lock,
which we can and should do anyways. I would probably vote to turn the one
inside the lock into a WARN, as that "optimized" path is only an optimization
if the inhibit applies to both SVM and VMX.
2. Use a bool to track the activated state.
3. Use an atomic.
4. Implement the optimized updates.
#3 is optional, #1 and #2 are not.
It's a moot point though, because toggling APICv inhibits on IRQ windows is
laughably broken. I'm guessing it "works" because the only time it triggers in
practice is in conjunction with PIT re-injection.
1. vCPU0 waits for an IRQ window, APICV_INHIBIT_REASON_IRQWIN = 1
2. vCPU1 waits for an IRQ window, APICV_INHIBIT_REASON_IRQWIN = 1
3. vCPU1 gets its IRQ window, APICV_INHIBIT_REASON_IRQWIN = 0
4. vCPU0 is sad
APICV_INHIBIT_REASON_BLOCKIRQ is also tied to per-vCPU state, but is a-ok because
KVM walks all vCPUs to generate inhibit. That approach won't work for IRQ windows
though, because it's obviously not a slow path.
What is generating so many external interrupts? E.g. is the guest using the PIT
for TSC or APIC calibration? I suppose it doesn't matter terribly in this case
since APICV_INHIBIT_REASON_PIT_REINJ is already set.
Unless there's a very, very good reason to support a use case that generates
ExtInts during boot, but _only_ during boot, and otherwise doesn't have any APICv
ihibits, I'm leaning towards making SVM's IRQ window inhibit sticky, i.e. never
clear it. And then we can more simply optimize kvm_set_or_clear_apicv_inhibit()
to do nothing if the inhibit is sticky and already set.
E.g. something like this:
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6d4a6734b2d6..6f926fd6fc1c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10629,6 +10629,14 @@ void kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
if (!enable_apicv)
return;
+ if (kvm_is_apicv_inhibit_sticky(reason)) {
+ if (WARN_ON_ONCE(!set))
+ return;
+
+ if (kvm_test_apicv_inhibit(reason))
+ return;
+ }
+
down_write(&kvm->arch.apicv_update_lock);
__kvm_set_or_clear_apicv_inhibit(kvm, reason, set);
up_write(&kvm->arch.apicv_update_lock);
next prev parent reply other threads:[~2025-02-03 18:45 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-03 17:03 [PATCH 0/3] KVM: x86: Address performance degradation due to APICv inhibits Naveen N Rao (AMD)
2025-02-03 17:03 ` [PATCH 1/3] KVM: x86: hyper-v: Convert synic_auto_eoi_used to an atomic Naveen N Rao (AMD)
2025-02-04 1:30 ` Maxim Levitsky
2025-02-04 13:09 ` Naveen N Rao
2025-02-04 19:33 ` Sean Christopherson
2025-02-05 11:00 ` Naveen N Rao
2025-02-03 17:03 ` [PATCH 2/3] KVM: x86: Remove use of apicv_update_lock when toggling guest debug state Naveen N Rao (AMD)
2025-02-04 2:00 ` Maxim Levitsky
2025-02-04 13:10 ` Naveen N Rao
2025-02-04 14:25 ` Naveen N Rao
2025-02-04 17:51 ` Sean Christopherson
2025-02-04 17:58 ` Paolo Bonzini
2025-02-04 19:42 ` Maxim Levitsky
2025-02-05 11:13 ` Naveen N Rao
2025-02-03 17:03 ` [PATCH 3/3] KVM: x86: Decouple APICv activation state from apicv_inhibit_reasons Naveen N Rao (AMD)
2025-02-03 18:45 ` Sean Christopherson [this message]
2025-02-03 22:22 ` Paolo Bonzini
2025-02-03 23:46 ` Sean Christopherson
2025-02-04 1:23 ` Maxim Levitsky
2025-02-04 19:18 ` Sean Christopherson
2025-02-04 20:08 ` Maxim Levitsky
2025-02-05 1:41 ` Sean Christopherson
2025-02-05 10:54 ` Naveen N Rao
2025-02-05 11:36 ` Paolo Bonzini
2025-02-11 15:57 ` Naveen N Rao
2025-02-11 16:37 ` Sean Christopherson
2025-02-11 18:13 ` Naveen N Rao
2025-02-04 11:06 ` Naveen N Rao
2025-02-04 14:08 ` Paolo Bonzini
2025-02-11 14:37 ` Naveen N Rao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z6EOxxZA9XLdXvrA@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mlevitsk@redhat.com \
--cc=naveen@kernel.org \
--cc=pbonzini@redhat.com \
--cc=suravee.suthikulpanit@amd.com \
--cc=vasant.hegde@amd.com \
--cc=vkuznets@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).