Re: [RFC PATCH 00/29] KVM: VM planes

From: Tom Lendacky
Date: Fri Jun 06 2025 - 12:43:54 EST


On 4/1/25 11:10, Paolo Bonzini wrote:
> I guess April 1st is not the best date to send out such a large series
> after months of radio silence, but here we are.

There were some miscellaneous fixes I had to apply to get the series to
compile and start working properly. I didn't break them out by patch #,
but here they are:

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 21dbc539cbe7..9d078eb001b1 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1316,32 +1316,35 @@ static void kvm_lapic_deliver_interrupt(struct kvm_vcpu *vcpu, struct kvm_lapic
{
struct kvm_vcpu *plane0_vcpu = vcpu->plane0;
struct kvm_plane *running_plane;
+ int irr_pending_planes;
u16 req_exit_planes;

kvm_x86_call(deliver_interrupt)(apic, delivery_mode, trig_mode, vector);

/*
- * test_and_set_bit implies a memory barrier, so IRR is written before
+ * atomic_fetch_or implies a memory barrier, so IRR is written before
* reading irr_pending_planes below...
*/
- if (!test_and_set_bit(vcpu->plane, &plane0_vcpu->arch.irr_pending_planes)) {
- /*
- * ... and also running_plane and req_exit_planes are read after writing
- * irr_pending_planes. Both barriers pair with kvm_arch_vcpu_ioctl_run().
- */
- smp_mb__after_atomic();
+ irr_pending_planes = atomic_fetch_or(BIT(vcpu->plane), &plane0_vcpu->arch.irr_pending_planes);
+ if (irr_pending_planes & BIT(vcpu->plane))
+ return;

- running_plane = READ_ONCE(plane0_vcpu->running_plane);
- if (!running_plane)
- return;
+ /*
+ * ... and also running_plane and req_exit_planes are read after writing
+ * irr_pending_planes. Both barriers pair with kvm_arch_vcpu_ioctl_run().
+ */
+ smp_mb__after_atomic();

- req_exit_planes = READ_ONCE(plane0_vcpu->req_exit_planes);
- if (!(req_exit_planes & BIT(vcpu->plane)))
- return;
+ running_plane = READ_ONCE(plane0_vcpu->running_plane);
+ if (!running_plane)
+ return;

- kvm_make_request(KVM_REQ_PLANE_INTERRUPT,
- kvm_get_plane_vcpu(running_plane, vcpu->vcpu_id));
- }
+ req_exit_planes = READ_ONCE(plane0_vcpu->req_exit_planes);
+ if (!(req_exit_planes & BIT(vcpu->plane)))
+ return;
+
+ kvm_make_request(KVM_REQ_PLANE_INTERRUPT,
+ kvm_get_plane_vcpu(running_plane, vcpu->vcpu_id));
}

/*
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 9d4492862c11..130d895f1d95 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -458,7 +458,7 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
INIT_LIST_HEAD(&sev->mirror_vms);
sev->need_init = false;

- kvm_set_apicv_inhibit(kvm->planes[[0], APICV_INHIBIT_REASON_SEV);
+ kvm_set_apicv_inhibit(kvm->planes[0], APICV_INHIBIT_REASON_SEV);

return 0;

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 917bfe8db101..656b69eabc59 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3252,7 +3252,7 @@ static int interrupt_window_interception(struct kvm_vcpu *vcpu)
* All vCPUs which run still run nested, will remain to have their
* AVIC still inhibited due to per-cpu AVIC inhibition.
*/
- kvm_clear_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_IRQWIN);
+ kvm_clear_apicv_inhibit(vcpu->kvm->planes[vcpu->plane], APICV_INHIBIT_REASON_IRQWIN);

++vcpu->stat->irq_window_exits;
return 1;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 65bc28e82140..704e8f80898f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11742,7 +11742,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
* the other side will certainly see the cleared bit irr_pending_planes
* and set it, and vice versa.
*/
- clear_bit(plane_id, &plane0_vcpu->arch.irr_pending_planes);
+ atomic_and(~BIT(plane_id), &plane0_vcpu->arch.irr_pending_planes);
smp_mb__after_atomic();
if (kvm_lapic_find_highest_irr(vcpu))
atomic_or(BIT(plane_id), &plane0_vcpu->arch.irr_pending_planes);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 3a04fdf0865d..efd45e05fddf 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4224,7 +4224,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm_plane *plane, struct kvm_vcpu *pl
* release semantics, which ensures the write is visible to kvm_get_vcpu().
*/
vcpu->plane = -1;
- if (plane->plane)
+ if (!plane->plane)
vcpu->vcpu_idx = atomic_read(&kvm->online_vcpus);
else
vcpu->vcpu_idx = plane0_vcpu->vcpu_idx;
@@ -4249,7 +4249,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm_plane *plane, struct kvm_vcpu *pl
if (r < 0)
goto kvm_put_xa_erase;

- if (!plane0_vcpu)
+ if (!plane->plane)
atomic_inc(&kvm->online_vcpus);

/*

Thanks,
Tom

>