[RFC 3/3] KVM: PPC: Book3S HV nestedv2: cap max vcpus to PAPR limit

From: Ritesh Harjani (IBM)

Date: Fri Sep 11 2026 - 01:01:04 EST


PAPR spec for H_GUEST_CREATE_VCPU says:

"Only 2048 VCPUs can be created, and the specified ID must be in the range of 0
to 2047"

However, KVM reports KVM_CAP_MAX_VCPUS as NR_CPUS and KVM_CAP_MAX_VCPU_ID as
8 * NR_CPUS. It also passes the userspace vCPU id through to the hcall unchanged.
On a nestedv2 host (KVM on PowerVM / pseries nested PAPR) built with
NR_CPUS > 2048, kvm selftest e.g. kvm_create_max_vcpus will create vCPU
2048 and fail with EINVAL when the hypervisor returns H_P3.

Following error gets reported (with a debug print added to selftest to
print failed vcpu_id number):
./kvm_create_max_vcpus
Random seed: 0x6ec3f539
KVM_CAP_MAX_VCPU_ID: 65536
KVM_CAP_MAX_VCPUS: 8192
Testing creating 8192 vCPUs, with IDs 0...8191.
[ 62.655458][ T302] KVM: Create Guest vcpu hcall failed, rc=-56
[ 62.655458][ T302] KVM: Create Guest vcpu hcall failed, rc=-56
Failed KVM_CREATE_VCPU for vcpu_id 2048 with errno 22

==== Test Assertion Failure ====
lib/kvm_util.c:1395: vcpu->fd >= 0
pid=302 tid=302 errno=22 - Invalid argument
1 0x00000000100061d3: __vm_vcpu_add at kvm_util.c:1395 (discriminator 6)
2 0x0000000010001a6b: test_vcpu_creation at kvm_create_max_vcpus.c:32 (discriminator 3)
3 0x000000001000160b: main at kvm_create_max_vcpus.c:59
4 0x000000001001b713: __libc_start_call_main at libc-start.o:?
5 0x000000001001bb47: __libc_start_main_impl at ??:?
KVM_CREATE_VCPU failed, rc: -1 errno: 22 (Invalid argument)
[ 65.316986][ T302] KVM: TLB LPID invalidation hcall failed, rc=-2
[ 65.316986][ T302] KVM: TLB LPID invalidation hcall failed, rc=-2

Cap both extensions at 2048 when kvmhv_is_nestedv2() is set, so
userspace never requests an id the L0 cannot create. PowerNV and
nestedv1 are unchanged. The issue is only seen with nestedv2.
While at it, this also fixes the limit for KVM_CAP_NR_VCPUS.

Fixes: 19d31c5f1157 ("KVM: PPC: Add support for nestedv2 guests")
Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx>
---
arch/powerpc/include/asm/kvm_host.h | 1 +
arch/powerpc/kvm/powerpc.c | 6 ++++++
2 files changed, 7 insertions(+)

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 2d139c807577..d48232557259 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -37,6 +37,7 @@
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
#include <asm/kvm_book3s_asm.h> /* for MAX_SMT_THREADS */
#define KVM_MAX_VCPU_IDS (MAX_SMT_THREADS * KVM_MAX_VCORES)
+#define KVM_MAX_VCPU_IDS_NESTEDv2 2048 /* PAPR H_GUEST_CREATE_VCPU vcpuId */

/*
* Limit the nested partition table to 4096 entries (because that's what
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 9194cf492d1c..cf620b6534de 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -663,12 +663,18 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = min(num_present_cpus(), KVM_MAX_VCPUS);
else
r = min(num_online_cpus(), KVM_MAX_VCPUS);
+ if (kvmhv_is_nestedv2())
+ r = min(r, KVM_MAX_VCPU_IDS_NESTEDv2);
break;
case KVM_CAP_MAX_VCPUS:
r = KVM_MAX_VCPUS;
+ if (kvmhv_is_nestedv2())
+ r = min(r, KVM_MAX_VCPU_IDS_NESTEDv2);
break;
case KVM_CAP_MAX_VCPU_ID:
r = KVM_MAX_VCPU_IDS;
+ if (kvmhv_is_nestedv2())
+ r = min(r, KVM_MAX_VCPU_IDS_NESTEDv2);
break;
#ifdef CONFIG_PPC_BOOK3S_64
case KVM_CAP_PPC_GET_SMMU_INFO:
--
2.39.5