From: Sean Christopherson <seanjc@google.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
roy.hopkins@suse.com, thomas.lendacky@amd.com,
ashish.kalra@amd.com, michael.roth@amd.com, jroedel@suse.de,
nsaenz@amazon.com, anelkz@amazon.de,
James.Bottomley@hansenpartnership.com
Subject: Re: [PATCH 07/29] KVM: do not use online_vcpus to test vCPU validity
Date: Thu, 5 Jun 2025 15:45:25 -0700 [thread overview]
Message-ID: <aEIeBU72WBWnlZdZ@google.com> (raw)
In-Reply-To: <20250401161106.790710-8-pbonzini@redhat.com>
On Tue, Apr 01, 2025, Paolo Bonzini wrote:
> Different planes can initialize their vCPUs separately, therefore there is
> no single online_vcpus value that can be used to test that a vCPU has
> indeed been fully initialized.
>
> Use the shiny new plane field instead, initializing it to an invalid value
> (-1) while the vCPU is visible in the xarray but may still disappear if
> the creation fails.
Checking vcpu->plane _in addition_ to online_cpus seems way safer than checking
vcpu->plane _instead_ of online_cpus. Even if we end up checking only vcpu->plane,
I think that should be a separate patch.
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> arch/x86/kvm/i8254.c | 3 ++-
> include/linux/kvm_host.h | 23 ++++++-----------------
> virt/kvm/kvm_main.c | 20 +++++++++++++-------
> 3 files changed, 21 insertions(+), 25 deletions(-)
>
> diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
> index d7ab8780ab9e..e3a3e7b90c26 100644
> --- a/arch/x86/kvm/i8254.c
> +++ b/arch/x86/kvm/i8254.c
> @@ -260,9 +260,10 @@ static void pit_do_work(struct kthread_work *work)
> * VCPUs and only when LVT0 is in NMI mode. The interrupt can
> * also be simultaneously delivered through PIC and IOAPIC.
> */
> - if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0)
> + if (atomic_read(&kvm->arch.vapics_in_nmi_mode) > 0) {
Spurious change (a good change, but noisy for this patch).
> kvm_for_each_vcpu(i, vcpu, kvm)
> kvm_apic_nmi_wd_deliver(vcpu);
> + }
> }
>
> static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 4d408d1d5ccc..0db27814294f 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -992,27 +992,16 @@ static inline struct kvm_io_bus *kvm_get_bus(struct kvm *kvm, enum kvm_bus idx)
>
> static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
> {
> - int num_vcpus = atomic_read(&kvm->online_vcpus);
> -
> - /*
> - * Explicitly verify the target vCPU is online, as the anti-speculation
> - * logic only limits the CPU's ability to speculate, e.g. given a "bad"
> - * index, clamping the index to 0 would return vCPU0, not NULL.
> - */
> - if (i >= num_vcpus)
> + struct kvm_vcpu *vcpu = xa_load(&kvm->vcpu_array, i);
newline
> + if (vcpu && unlikely(vcpu->plane == -1))
> return NULL;
>
> - i = array_index_nospec(i, num_vcpus);
Don't we still need to prevent speculating into the xarray ?
> -
> - /* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu. */
> - smp_rmb();
> - return xa_load(&kvm->vcpu_array, i);
> + return vcpu;
> }
>
> -#define kvm_for_each_vcpu(idx, vcpup, kvm) \
> - if (atomic_read(&kvm->online_vcpus)) \
> - xa_for_each_range(&kvm->vcpu_array, idx, vcpup, 0, \
> - (atomic_read(&kvm->online_vcpus) - 1))
> +#define kvm_for_each_vcpu(idx, vcpup, kvm) \
> + xa_for_each(&kvm->vcpu_array, idx, vcpup) \
> + if ((vcpup)->plane == -1) ; else \
>
> static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id)
> {
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index e343905e46d8..eba02cb7cc57 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -4186,6 +4186,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, unsigned long id)
> goto unlock_vcpu_destroy;
> }
>
> + /*
> + * Store an invalid plane number until fully initialized. xa_insert() has
> + * release semantics, which ensures the write is visible to kvm_get_vcpu().
> + */
> + vcpu->plane = -1;
> vcpu->vcpu_idx = atomic_read(&kvm->online_vcpus);
> r = xa_insert(&kvm->vcpu_array, vcpu->vcpu_idx, vcpu, GFP_KERNEL_ACCOUNT);
> WARN_ON_ONCE(r == -EBUSY);
> @@ -4195,7 +4200,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, unsigned long id)
> /*
> * Now it's all set up, let userspace reach it. Grab the vCPU's mutex
> * so that userspace can't invoke vCPU ioctl()s until the vCPU is fully
> - * visible (per online_vcpus), e.g. so that KVM doesn't get tricked
> + * visible (valid vcpu->plane), e.g. so that KVM doesn't get tricked
> * into a NULL-pointer dereference because KVM thinks the _current_
> * vCPU doesn't exist. As a bonus, taking vcpu->mutex ensures lockdep
> * knows it's taken *inside* kvm->lock.
> @@ -4206,12 +4211,13 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, unsigned long id)
> if (r < 0)
> goto kvm_put_xa_erase;
>
> - /*
> - * Pairs with smp_rmb() in kvm_get_vcpu. Store the vcpu
> - * pointer before kvm->online_vcpu's incremented value.
Bad me for not updating this comment, but kvm_vcpu_on_spin() also pairs with this
barrier, and needs to be updated to be planes-aware, e.g. this looks like a NULL
pointer deref waiting to happen:
vcpu = xa_load(&plane->vcpu_array, idx);
if (!READ_ONCE(vcpu->ready))
continue;
next prev parent reply other threads:[~2025-06-05 22:45 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-01 16:10 [RFC PATCH 00/29] KVM: VM planes Paolo Bonzini
2025-04-01 16:10 ` [PATCH 01/29] Documentation: kvm: introduce "VM plane" concept Paolo Bonzini
2025-04-21 18:43 ` Tom Lendacky
2025-04-01 16:10 ` [PATCH 02/29] KVM: API definitions for plane userspace exit Paolo Bonzini
2025-06-04 0:10 ` Sean Christopherson
2025-04-01 16:10 ` [PATCH 03/29] KVM: add plane info to structs Paolo Bonzini
2025-04-21 18:57 ` Tom Lendacky
2025-04-21 19:04 ` Tom Lendacky
2025-04-01 16:10 ` [PATCH 04/29] KVM: introduce struct kvm_arch_plane Paolo Bonzini
2025-04-01 16:10 ` [PATCH 05/29] KVM: add plane support to KVM_SIGNAL_MSI Paolo Bonzini
2025-04-01 16:10 ` [PATCH 06/29] KVM: move mem_attr_array to kvm_plane Paolo Bonzini
2025-06-06 22:50 ` Sean Christopherson
2025-04-01 16:10 ` [PATCH 07/29] KVM: do not use online_vcpus to test vCPU validity Paolo Bonzini
2025-06-05 22:45 ` Sean Christopherson [this message]
2025-06-06 13:49 ` Sean Christopherson
2025-04-01 16:10 ` [PATCH 08/29] KVM: move vcpu_array to struct kvm_plane Paolo Bonzini
2025-04-01 16:10 ` [PATCH 09/29] KVM: implement plane file descriptors ioctl and creation Paolo Bonzini
2025-04-21 20:32 ` Tom Lendacky
2025-04-01 16:10 ` [PATCH 10/29] KVM: share statistics for same vCPU id on different planes Paolo Bonzini
2025-06-06 16:23 ` Sean Christopherson
2025-06-06 16:32 ` Paolo Bonzini
2025-04-01 16:10 ` [PATCH 11/29] KVM: anticipate allocation of dirty ring Paolo Bonzini
2025-04-01 16:10 ` [PATCH 12/29] KVM: share dirty ring for same vCPU id on different planes Paolo Bonzini
2025-04-21 21:51 ` Tom Lendacky
2025-04-01 16:10 ` [PATCH 13/29] KVM: implement vCPU creation for extra planes Paolo Bonzini
2025-04-21 22:08 ` Tom Lendacky
2025-06-05 22:47 ` Sean Christopherson
2025-04-01 16:10 ` [PATCH 14/29] KVM: pass plane to kvm_arch_vcpu_create Paolo Bonzini
2025-04-01 16:10 ` [PATCH 15/29] KVM: x86: pass vcpu to kvm_pv_send_ipi() Paolo Bonzini
2025-04-01 16:10 ` [PATCH 16/29] KVM: x86: split "if" in __kvm_set_or_clear_apicv_inhibit Paolo Bonzini
2025-04-01 16:10 ` [PATCH 17/29] KVM: x86: block creating irqchip if planes are active Paolo Bonzini
2025-04-01 16:10 ` [PATCH 18/29] KVM: x86: track APICv inhibits per plane Paolo Bonzini
2025-04-01 16:10 ` [PATCH 19/29] KVM: x86: move APIC map to kvm_arch_plane Paolo Bonzini
2025-04-01 16:10 ` [PATCH 20/29] KVM: x86: add planes support for interrupt delivery Paolo Bonzini
2025-06-06 16:30 ` Sean Christopherson
2025-06-06 16:38 ` Paolo Bonzini
2025-04-01 16:10 ` [PATCH 21/29] KVM: x86: add infrastructure to share FPU across planes Paolo Bonzini
2025-04-01 16:10 ` [PATCH 22/29] KVM: x86: implement initial plane support Paolo Bonzini
2025-04-01 16:11 ` [PATCH 23/29] KVM: x86: extract kvm_post_set_cpuid Paolo Bonzini
2025-04-01 16:11 ` [PATCH 24/29] KVM: x86: initialize CPUID for non-default planes Paolo Bonzini
2025-04-01 16:11 ` [PATCH 25/29] KVM: x86: handle interrupt priorities for planes Paolo Bonzini
2025-04-01 16:11 ` [PATCH 26/29] KVM: x86: enable up to 16 planes Paolo Bonzini
2025-06-06 22:41 ` Sean Christopherson
2025-04-01 16:11 ` [PATCH 27/29] selftests: kvm: introduce basic test for VM planes Paolo Bonzini
2025-04-01 16:11 ` [PATCH 28/29] selftests: kvm: add plane infrastructure Paolo Bonzini
2025-04-01 16:11 ` [PATCH 29/29] selftests: kvm: add x86-specific plane test Paolo Bonzini
2025-04-01 16:16 ` [RFC PATCH 00/29] KVM: VM planes Sean Christopherson
2025-06-06 16:42 ` Tom Lendacky
2025-08-07 12:34 ` Vaishali Thakkar
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=aEIeBU72WBWnlZdZ@google.com \
--to=seanjc@google.com \
--cc=James.Bottomley@hansenpartnership.com \
--cc=anelkz@amazon.de \
--cc=ashish.kalra@amd.com \
--cc=jroedel@suse.de \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=nsaenz@amazon.com \
--cc=pbonzini@redhat.com \
--cc=roy.hopkins@suse.com \
--cc=thomas.lendacky@amd.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 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.