* [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests
@ 2026-08-04 18:29 Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes Amit Machhiwal
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Amit Machhiwal @ 2026-08-04 18:29 UTC (permalink / raw)
To: qemu-ppc, Harsh Prateek Bora
Cc: Amit Machhiwal, Vaibhav Jain, Nicholas Piggin, Chinmay Rath,
Glenn Miles, Paolo Bonzini, Gautam Menghani, kvm, qemu-devel
On POWER systems, newer processor generations can operate in compatibility
modes corresponding to earlier generations (e.g., a Power11 system running
in Power10 compatibility mode). In such cases, the effective CPU level
exposed to guests differs from the physical processor generation.
This creates issues for nested virtualization. When booting a nested KVM
guest, QEMU may derive the CPU model from the raw hardware PVR and attempt
to configure the guest accordingly. However, the host is constrained by the
compatibility level negotiated with the hypervisor, and requests exceeding
that level are rejected by KVM, leading to guest boot failures such as:
KVM-NESTEDv2: couldn't set guest wide elements
This series addresses the issue by preventing fallback to raw mode when the
host itself is booted in a compatibility mode, and by querying the effective
CPU compatibility modes supported by the host via KVM. The kernel interface
uses copy_struct_from/to_user() for forward and backward ABI compatibility.
With these changes, QEMU ensures that nested guests are configured with CPU
models consistent with the host compatibility mode, allowing them to boot
correctly.
Patch summary:
[1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes
[2/3] target/ppc/kvm: Add support for querying host compatibility mode
[3/3] target/ppc/kvm: Use host compatibility mode for nested guests
Changes in v5:
- Patch 1: Updated KVM_PPC_GET_COMPAT_CAPS ioctl number from 0xe4 to
0xb8 to match the corresponding Linux kernel v6 series change; the
0xe0-0xe3 range is reserved for KVM_CREATE_DEVICE fd ioctls
Testing (with kernel v6 patches):
KVM APIv1 Testing
=================
On P10 PowerNV machine (L0)
---------------------------
- P10 L1 KVM guest -> works
- P10 nested L2 KVM guest -> works
- P9 compat nested L2 KVM guest -> works
- P9 compat L1 KVM guest -> works
- P9 nested L2 KVM guest -> works
On Powernv11 TCG Guest (L0)
---------------------------
- P11 PowerNV TCG L0 guest -> works
- P11 L1 KVM guest -> works
- P11 L2 KVM guest -> works
- P10 compat L1 KVM guest -> works
- P10 L2 KVM guest -> works
- P9 compat L1 KVM guest -> works
- P9 L2 KVM guest -> works
KVM APIv2 Testing
=================
On P11 PowerVM LPAR (L1)
------------------------
- P11 L2 KVM guest -> works
- P10 compat L2 KVM guest -> works
- P9 compat L2 KVM guest fails to boot as expected
- Without QEMU patches but Linux patches
- P11 L2 KVM guest -> works
- P10 compat L2 KVM guest -> works
- P9 compat L2 KVM guest fails to boot as expected
- Without Linux patches but QEMU patches
- P11 L2 KVM guest -> works
- P10 compat L2 KVM guest -> works
On P11 LPAR in P10 compat (L1)
------------------------------
- P10 (host compat) L2 KVM guest -> works
- Without QEMU patch but Linux patches
- P10 guest fails to boot as expected (error: kvm run failed Invalid argument)
- Without Linux patch but QEMU patches
- P10 guest fails to boot as expected (KVM: unknown exit, hardware reason ffffffffffffffea)
On P10 PowerVM LPAR (L1)
------------------------
- P10 L2 KVM guest -> works
- P9 compat L2 KVM guest fails to boot as expected
TCG pSeries Guest
=================
- P11 (default) pSeries guest boots fine
ABI Extensibility Testing (struct size 32, extra member)
=========================================================
- Newer struct on QEMU, older kernel -> works (kernel returns -E2BIG,
QEMU retries with correct size)
- New struct on Linux kernel, older QEMU -> works (kernel zero-pads
trailing fields, QEMU gets correct data)
Note: Patch 1 is marked DO_NOT_MERGE as it contains linux-headers updates
that will be synced separately once the corresponding kernel patches are
merged.
The corresponding Linux kernel patches (v6) are being posted concurrently.
v4: https://lore.kernel.org/all/20260701052341.62289-1-amachhiw@linux.ibm.com/
v3: https://lore.kernel.org/all/20260616113915.25589-1-amachhiw@linux.ibm.com/
v2: https://lore.kernel.org/all/20260502140021.69712-1-amachhiw@linux.ibm.com/
v1: https://lore.kernel.org/all/20260430061333.37905-1-amachhiw@linux.ibm.com/
Previous kernel patch versions:
v6: https://lore.kernel.org/all/20260804180705.59160-1-amachhiw@linux.ibm.com/
v5: https://lore.kernel.org/all/20260701051409.51820-1-amachhiw@linux.ibm.com/
v4: https://lore.kernel.org/all/20260616123314.82721-1-amachhiw@linux.ibm.com/
v3: https://lore.kernel.org/all/20260522152744.55251-1-amachhiw@linux.ibm.com/
v2: https://lore.kernel.org/all/20260513100755.83195-1-amachhiw@linux.ibm.com/
v1: https://lore.kernel.org/all/20260430054906.94401-1-amachhiw@linux.ibm.com/
Amit Machhiwal (3):
[DO_NOT_MERGE] linux-headers: Add uapi header changes
target/ppc/kvm: Add support for querying host compatibility mode
target/ppc/kvm: Use host compatibility mode for nested guests
hw/ppc/spapr_hcall.c | 14 ++++++
linux-headers/asm-powerpc/kvm.h | 19 +++++++
linux-headers/linux/kvm.h | 3 ++
target/ppc/kvm.c | 87 +++++++++++++++++++++++++++++++++
target/ppc/kvm_ppc.h | 7 +++
5 files changed, 130 insertions(+)
base-commit: b428fe036233cbd15d37e3c027ab6ca4d3661a80
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v5 1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes
2026-08-04 18:29 [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests Amit Machhiwal
@ 2026-08-04 18:29 ` Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 2/3] target/ppc/kvm: Add support for querying host compatibility mode Amit Machhiwal
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Amit Machhiwal @ 2026-08-04 18:29 UTC (permalink / raw)
To: qemu-ppc, Harsh Prateek Bora
Cc: Amit Machhiwal, Vaibhav Jain, Nicholas Piggin, Chinmay Rath,
Glenn Miles, Paolo Bonzini, kvm, qemu-devel, Gautam Menghani
This is a temporary patch intended for review and testing purposes only.
It syncs the QEMU linux-headers with the kernel v6 changes that introduce
the KVM_PPC_GET_COMPAT_CAPS ioctl for querying host CPU compatibility
capabilities. The struct kvm_ppc_compat_caps places 'size' as the first
field as required by copy_struct_from/to_user() versioning, with
KVM_PPC_COMPAT_CAPS_SIZE_VER0 (24) defined as the frozen version-floor
constant. The capability number is KVM_CAP_PPC_COMPAT_CAPS (250) and
the ioctl is defined as _IO so the ioctl number remains stable if the
struct grows in future versions. Capability bit definitions for POWER9,
POWER10, and POWER11 compatibility modes are also included.
The actual header sync will be done via scripts/update-linux-headers.sh
once the kernel changes [1] are merged upstream.
[1] https://lore.kernel.org/all/20260804180705.59160-1-amachhiw@linux.ibm.com/
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Reviewed-by: Gautam Menghani <gautam@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
Changes in this version:
- Updated KVM_PPC_GET_COMPAT_CAPS ioctl number from 0xe4 to 0xb8 to
match the corresponding Linux kernel v6 series change; the
0xe0-0xe3 range is reserved for KVM_CREATE_DEVICE fd ioctls
| 19 +++++++++++++++++++
| 3 +++
2 files changed, 22 insertions(+)
--git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 077c5437f521..2c229fe0562c 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -437,6 +437,25 @@ struct kvm_ppc_cpu_char {
__u64 behaviour_mask; /* valid bits in behaviour */
};
+/* For KVM_PPC_GET_COMPAT_CAPS */
+struct kvm_ppc_compat_caps {
+ __u64 size; /* Size of this structure */
+ __u64 flags; /* Reserved for future use */
+ __u64 compat_capabilities; /* Capabilities supported by the host */
+};
+#define KVM_PPC_COMPAT_CAPS_SIZE_VER0 24 /* sizeof first published struct */
+
+/*
+ * Capability bits for compat_capabilities field in kvm_ppc_compat_caps.
+ * These bits indicate which processor compatibility modes are supported.
+ */
+#define KVM_PPC_COMPAT_CAP_POWER9 (1ULL << 62)
+#define KVM_PPC_COMPAT_CAP_POWER10 (1ULL << 61)
+#define KVM_PPC_COMPAT_CAP_POWER11 (1ULL << 60)
+#define KVM_PPC_COMPAT_BITMASK (KVM_PPC_COMPAT_CAP_POWER9 | \
+ KVM_PPC_COMPAT_CAP_POWER10 | \
+ KVM_PPC_COMPAT_CAP_POWER11)
+
/*
* Values for character and character_mask.
* These are identical to the values used by H_GET_CPU_CHARACTERISTICS.
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index dd52e2a65bfd..aea4ab5c6953 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -986,6 +986,7 @@ struct kvm_enable_cap {
#define KVM_CAP_S390_KEYOP 247
#define KVM_CAP_S390_VSIE_ESAMODE 248
#define KVM_CAP_S390_HPAGE_2G 249
+#define KVM_CAP_PPC_COMPAT_CAPS 250
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -1330,6 +1331,8 @@ struct kvm_s390_keyop {
/* Available with KVM_CAP_COUNTER_OFFSET */
#define KVM_ARM_SET_COUNTER_OFFSET _IOW(KVMIO, 0xb5, struct kvm_arm_counter_offset)
#define KVM_ARM_GET_REG_WRITABLE_MASKS _IOR(KVMIO, 0xb6, struct reg_mask_range)
+/* Available with KVM_CAP_PPC_COMPAT_CAPS */
+#define KVM_PPC_GET_COMPAT_CAPS _IO(KVMIO, 0xb8)
/* ioctl for vm fd */
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v5 2/3] target/ppc/kvm: Add support for querying host compatibility mode
2026-08-04 18:29 [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes Amit Machhiwal
@ 2026-08-04 18:29 ` Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests Amit Machhiwal
2026-08-05 8:25 ` [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly " Anushree Mathur
3 siblings, 0 replies; 7+ messages in thread
From: Amit Machhiwal @ 2026-08-04 18:29 UTC (permalink / raw)
To: qemu-ppc, Harsh Prateek Bora
Cc: Amit Machhiwal, Vaibhav Jain, Nicholas Piggin, Chinmay Rath,
Glenn Miles, Paolo Bonzini, kvm, qemu-devel, Gautam Menghani
Add infrastructure to query the host CPU compatibility mode via the
KVM_PPC_GET_COMPAT_CAPS ioctl. This allows QEMU to determine if the
host is running in a compatibility mode (e.g., a Power11 processor
operating in Power10 compatibility mode).
The kvmppc_get_compat_caps() function issues the ioctl and returns the
compat_capabilities bitmap. The kvm_ppc_host_compat_pvr() function derives
the effective PVR from the bitmap using ctz64() to find the lowest set
bit (highest supported compat level in IBM MSB-0 numbering).
The struct kvm_ppc_compat_caps places 'size' first and userspace sets it
to sizeof(struct kvm_ppc_compat_caps) before calling the ioctl. The kernel
uses copy_struct_from/to_user() to handle forward and backward ABI
compatibility: an older userspace with a smaller struct gets trailing fields
zero-padded. When newer userspace passes a larger struct to an older kernel
(usize > ksize), the kernel unconditionally returns -E2BIG and writes its
own ksize back into host_compat.size. QEMU detects this, validates the
returned size against KVM_PPC_COMPAT_CAPS_SIZE_VER0, and retries with that
size.
Additionally, cas_check_pvr() in hw/ppc/spapr_hcall.c is updated to
prevent fallback to raw mode when the host is running in compatibility
mode. This ensures that nested guests cannot exceed the host's
compatibility level. The call is guarded with kvm_enabled() since
kvm_ppc_host_compat_pvr() invokes kvm_vm_ioctl() which dereferences
kvm_state; without the guard, a TCG guest on a CONFIG_KVM=y binary
would segfault.
If the capability is not supported or the query fails, the functions
return 0, allowing fallback to existing behavior.
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Reviewed-by: Gautam Menghani <gautam@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
No changes in this version.
hw/ppc/spapr_hcall.c | 14 +++++++++
target/ppc/kvm.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
target/ppc/kvm_ppc.h | 7 +++++
3 files changed, 96 insertions(+)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 23bcd788daf6..708902934cff 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1136,6 +1136,7 @@ static uint32_t cas_check_pvr(PowerPCCPU *cpu, uint32_t max_compat,
{
bool explicit_match = false; /* Matched the CPU's real PVR */
uint32_t best_compat = 0;
+ uint32_t compat_host_pvr = 0;
int i;
/*
@@ -1163,6 +1164,19 @@ static uint32_t cas_check_pvr(PowerPCCPU *cpu, uint32_t max_compat,
}
}
+ if (explicit_match && kvm_enabled()) {
+ compat_host_pvr = kvm_ppc_host_compat_pvr();
+ /*
+ * If the host is booted in a compatibility mode, do not try booting in
+ * the raw mode as it may allow KVM guests to boot with a higher CPU
+ * version compared to what host was booted with; which should not be
+ * allowed.
+ */
+ if (compat_host_pvr) {
+ explicit_match = false;
+ }
+ }
+
*raw_mode_supported = explicit_match;
/* Parsing finished */
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 116b39a00f4e..d4c5601a00c4 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2602,6 +2602,81 @@ bool kvmppc_supports_ail_3(void)
return cap_ail_mode_3;
}
+#if defined(TARGET_PPC64)
+static target_ulong kvmppc_get_compat_caps(void)
+{
+ struct kvm_ppc_compat_caps host_compat;
+ int ret;
+
+ if (!kvm_check_extension(kvm_state, KVM_CAP_PPC_COMPAT_CAPS)) {
+ return 0;
+ }
+
+ /*
+ * Set size to sizeof(struct kvm_ppc_compat_caps) so the kernel applies
+ * copy_struct_from/to_user() versioning. size must be >= VER0.
+ */
+ memset(&host_compat, 0, sizeof(host_compat));
+ host_compat.size = sizeof(host_compat);
+
+ ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_COMPAT_CAPS, &host_compat);
+ if (ret == -E2BIG && host_compat.size >= KVM_PPC_COMPAT_CAPS_SIZE_VER0) {
+ /*
+ * Kernel is older and knows only a smaller struct version. It
+ * wrote back its ksize into host_compat.size. Retry with that
+ * size so the kernel accepts the call.
+ *
+ * When a VER1 struct is introduced, add a check here:
+ * if (host_compat.size >= KVM_PPC_COMPAT_CAPS_SIZE_VER1) { ... }
+ */
+ uint64_t ksize = host_compat.size;
+ memset(&host_compat, 0, sizeof(host_compat));
+ host_compat.size = ksize;
+ ret = kvm_vm_ioctl(kvm_state, KVM_PPC_GET_COMPAT_CAPS, &host_compat);
+ }
+
+ if (ret < 0) {
+ error_report("KVM: failed to get host CPU compat capabilities: %s",
+ strerror(-ret));
+ return 0;
+ }
+
+ return host_compat.compat_capabilities & KVM_PPC_COMPAT_BITMASK;
+}
+
+/*
+ * Return the effective host PVR based on the CPU compatibility mode
+ * reported by KVM. Returns 0 if no compat mode is active or the
+ * capability is not supported, in which case the caller falls back
+ * to the raw hardware PVR.
+ */
+uint32_t kvm_ppc_host_compat_pvr(void)
+{
+ uint32_t compat_host_pvr = 0;
+ uint64_t cap_idx = 0;
+ target_ulong host_caps = kvmppc_get_compat_caps();
+
+ if (host_caps) {
+ cap_idx = 1ULL << ctz64(host_caps);
+ switch (cap_idx) {
+ case KVM_PPC_COMPAT_CAP_POWER9:
+ compat_host_pvr = CPU_POWERPC_POWER9_DD22;
+ break;
+ case KVM_PPC_COMPAT_CAP_POWER10:
+ compat_host_pvr = CPU_POWERPC_POWER10_DD20;
+ break;
+ case KVM_PPC_COMPAT_CAP_POWER11:
+ compat_host_pvr = CPU_POWERPC_POWER11_DD20;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return compat_host_pvr;
+}
+#endif /* TARGET_PPC64 */
+
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
{
uint32_t host_pvr = mfpvr();
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
index 742881231e16..195dbaac5e17 100644
--- a/target/ppc/kvm_ppc.h
+++ b/target/ppc/kvm_ppc.h
@@ -81,6 +81,8 @@ bool kvmppc_supports_ail_3(void);
int kvmppc_enable_hwrng(void);
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
+
+uint32_t kvm_ppc_host_compat_pvr(void);
void kvmppc_check_papr_resize_hpt(Error **errp);
int kvmppc_resize_hpt_prepare(PowerPCCPU *cpu, target_ulong flags, int shift);
int kvmppc_resize_hpt_commit(PowerPCCPU *cpu, target_ulong flags, int shift);
@@ -440,6 +442,11 @@ static inline PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
return NULL;
}
+static inline uint32_t kvm_ppc_host_compat_pvr(void)
+{
+ return 0;
+}
+
static inline void kvmppc_check_papr_resize_hpt(Error **errp)
{
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests
2026-08-04 18:29 [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 2/3] target/ppc/kvm: Add support for querying host compatibility mode Amit Machhiwal
@ 2026-08-04 18:29 ` Amit Machhiwal
2026-08-04 19:55 ` BALATON Zoltan
2026-08-05 8:25 ` [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly " Anushree Mathur
3 siblings, 1 reply; 7+ messages in thread
From: Amit Machhiwal @ 2026-08-04 18:29 UTC (permalink / raw)
To: qemu-ppc, Harsh Prateek Bora
Cc: Amit Machhiwal, Vaibhav Jain, Nicholas Piggin, Chinmay Rath,
Glenn Miles, Paolo Bonzini, kvm, qemu-devel, Gautam Menghani
On POWER systems, the host CPU may run in a compatibility mode (e.g.,
a Power11 processor operating in Power10 compatibility mode). When
running nested KVM guests, QEMU currently derives the host CPU type
using mfpvr(), which reflects the physical processor version. This can
result in a mismatch between the CPU model used by QEMU and the
compatibility mode enforced by the host, leading to guest boot failures
such as "KVM-NESTEDv2: couldn't set guest wide elements".
Update kvm_ppc_get_host_cpu_class() to check if the host is running in
a compatibility mode using kvm_ppc_host_compat_pvr(). When available,
use the compatibility PVR instead of the raw hardware PVR when selecting
the CPU model. This ensures that QEMU selects a CPU model consistent
with the host compatibility mode, allowing nested guests to boot
correctly.
The guard uses #if defined(TARGET_PPC64) to prevent build breakage on
ppc32 targets where the POWER9/10/11 PVR constants are not defined.
Tested-by: Gautam Menghani <gautam@linux.ibm.com>
Reviewed-by: Gautam Menghani <gautam@linux.ibm.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
No changes in this version.
target/ppc/kvm.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index d4c5601a00c4..aa8269186a1a 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -2682,6 +2682,18 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
uint32_t host_pvr = mfpvr();
PowerPCCPUClass *pvr_pcc;
+#if defined(TARGET_PPC64)
+#ifndef CONFIG_KVM
+#error "CONFIG_KVM is not enabled"
+#endif
+ uint32_t compat_host_pvr;
+
+ compat_host_pvr = kvm_ppc_host_compat_pvr();
+ if (compat_host_pvr) {
+ host_pvr = compat_host_pvr;
+ }
+#endif /* TARGET_PPC64 */
+
pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
if (pvr_pcc == NULL) {
pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr);
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests
2026-08-04 18:29 ` [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests Amit Machhiwal
@ 2026-08-04 19:55 ` BALATON Zoltan
2026-08-05 14:33 ` Amit Machhiwal
0 siblings, 1 reply; 7+ messages in thread
From: BALATON Zoltan @ 2026-08-04 19:55 UTC (permalink / raw)
To: Amit Machhiwal
Cc: qemu-ppc, Harsh Prateek Bora, Vaibhav Jain, Nicholas Piggin,
Chinmay Rath, Glenn Miles, Paolo Bonzini, kvm, qemu-devel,
Gautam Menghani
On Tue, 4 Aug 2026, Amit Machhiwal wrote:
> On POWER systems, the host CPU may run in a compatibility mode (e.g.,
> a Power11 processor operating in Power10 compatibility mode). When
> running nested KVM guests, QEMU currently derives the host CPU type
> using mfpvr(), which reflects the physical processor version. This can
> result in a mismatch between the CPU model used by QEMU and the
> compatibility mode enforced by the host, leading to guest boot failures
> such as "KVM-NESTEDv2: couldn't set guest wide elements".
>
> Update kvm_ppc_get_host_cpu_class() to check if the host is running in
> a compatibility mode using kvm_ppc_host_compat_pvr(). When available,
> use the compatibility PVR instead of the raw hardware PVR when selecting
> the CPU model. This ensures that QEMU selects a CPU model consistent
> with the host compatibility mode, allowing nested guests to boot
> correctly.
>
> The guard uses #if defined(TARGET_PPC64) to prevent build breakage on
> ppc32 targets where the POWER9/10/11 PVR constants are not defined.
>
> Tested-by: Gautam Menghani <gautam@linux.ibm.com>
> Reviewed-by: Gautam Menghani <gautam@linux.ibm.com>
> Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
> ---
> No changes in this version.
>
> target/ppc/kvm.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> index d4c5601a00c4..aa8269186a1a 100644
> --- a/target/ppc/kvm.c
> +++ b/target/ppc/kvm.c
> @@ -2682,6 +2682,18 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
> uint32_t host_pvr = mfpvr();
> PowerPCCPUClass *pvr_pcc;
>
> +#if defined(TARGET_PPC64)
> +#ifndef CONFIG_KVM
> +#error "CONFIG_KVM is not enabled"
> +#endif
In meson.build:
ppc_system_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
so I think this check and #error does not make sense.
Regards,
BALATON Zoltan
> + uint32_t compat_host_pvr;
> +
> + compat_host_pvr = kvm_ppc_host_compat_pvr();
> + if (compat_host_pvr) {
> + host_pvr = compat_host_pvr;
> + }
> +#endif /* TARGET_PPC64 */
> +
> pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
> if (pvr_pcc == NULL) {
> pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr);
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests
2026-08-04 18:29 [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests Amit Machhiwal
` (2 preceding siblings ...)
2026-08-04 18:29 ` [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests Amit Machhiwal
@ 2026-08-05 8:25 ` Anushree Mathur
3 siblings, 0 replies; 7+ messages in thread
From: Anushree Mathur @ 2026-08-05 8:25 UTC (permalink / raw)
To: Amit Machhiwal, qemu-ppc, Harsh Prateek Bora
Cc: Vaibhav Jain, Nicholas Piggin, Chinmay Rath, Glenn Miles,
Paolo Bonzini, Gautam Menghani, kvm, qemu-devel, Anushree Mathur
On 04/08/26 11:59 PM, Amit Machhiwal wrote:
> On POWER systems, newer processor generations can operate in compatibility
> modes corresponding to earlier generations (e.g., a Power11 system running
> in Power10 compatibility mode). In such cases, the effective CPU level
> exposed to guests differs from the physical processor generation.
>
> This creates issues for nested virtualization. When booting a nested KVM
> guest, QEMU may derive the CPU model from the raw hardware PVR and attempt
> to configure the guest accordingly. However, the host is constrained by the
> compatibility level negotiated with the hypervisor, and requests exceeding
> that level are rejected by KVM, leading to guest boot failures such as:
>
> KVM-NESTEDv2: couldn't set guest wide elements
>
> This series addresses the issue by preventing fallback to raw mode when the
> host itself is booted in a compatibility mode, and by querying the effective
> CPU compatibility modes supported by the host via KVM. The kernel interface
> uses copy_struct_from/to_user() for forward and backward ABI compatibility.
> With these changes, QEMU ensures that nested guests are configured with CPU
> models consistent with the host compatibility mode, allowing them to boot
> correctly.
>
> Patch summary:
> [1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes
> [2/3] target/ppc/kvm: Add support for querying host compatibility mode
> [3/3] target/ppc/kvm: Use host compatibility mode for nested guests
>
> Changes in v5:
> - Patch 1: Updated KVM_PPC_GET_COMPAT_CAPS ioctl number from 0xe4 to
> 0xb8 to match the corresponding Linux kernel v6 series change; the
> 0xe0-0xe3 range is reserved for KVM_CREATE_DEVICE fd ioctls
>
> Testing (with kernel v6 patches):
>
> KVM APIv1 Testing
> =================
> On P10 PowerNV machine (L0)
> ---------------------------
> - P10 L1 KVM guest -> works
> - P10 nested L2 KVM guest -> works
> - P9 compat nested L2 KVM guest -> works
> - P9 compat L1 KVM guest -> works
> - P9 nested L2 KVM guest -> works
>
> On Powernv11 TCG Guest (L0)
> ---------------------------
> - P11 PowerNV TCG L0 guest -> works
> - P11 L1 KVM guest -> works
> - P11 L2 KVM guest -> works
> - P10 compat L1 KVM guest -> works
> - P10 L2 KVM guest -> works
> - P9 compat L1 KVM guest -> works
> - P9 L2 KVM guest -> works
>
> KVM APIv2 Testing
> =================
> On P11 PowerVM LPAR (L1)
> ------------------------
> - P11 L2 KVM guest -> works
> - P10 compat L2 KVM guest -> works
> - P9 compat L2 KVM guest fails to boot as expected
> - Without QEMU patches but Linux patches
> - P11 L2 KVM guest -> works
> - P10 compat L2 KVM guest -> works
> - P9 compat L2 KVM guest fails to boot as expected
> - Without Linux patches but QEMU patches
> - P11 L2 KVM guest -> works
> - P10 compat L2 KVM guest -> works
>
> On P11 LPAR in P10 compat (L1)
> ------------------------------
> - P10 (host compat) L2 KVM guest -> works
> - Without QEMU patch but Linux patches
> - P10 guest fails to boot as expected (error: kvm run failed Invalid argument)
> - Without Linux patch but QEMU patches
> - P10 guest fails to boot as expected (KVM: unknown exit, hardware reason ffffffffffffffea)
>
> On P10 PowerVM LPAR (L1)
> ------------------------
> - P10 L2 KVM guest -> works
> - P9 compat L2 KVM guest fails to boot as expected
>
> TCG pSeries Guest
> =================
> - P11 (default) pSeries guest boots fine
>
> ABI Extensibility Testing (struct size 32, extra member)
> =========================================================
> - Newer struct on QEMU, older kernel -> works (kernel returns -E2BIG,
> QEMU retries with correct size)
> - New struct on Linux kernel, older QEMU -> works (kernel zero-pads
> trailing fields, QEMU gets correct data)
>
> Note: Patch 1 is marked DO_NOT_MERGE as it contains linux-headers updates
> that will be synced separately once the corresponding kernel patches are
> merged.
>
> The corresponding Linux kernel patches (v6) are being posted concurrently.
>
> v4: https://lore.kernel.org/all/20260701052341.62289-1-amachhiw@linux.ibm.com/
> v3: https://lore.kernel.org/all/20260616113915.25589-1-amachhiw@linux.ibm.com/
> v2: https://lore.kernel.org/all/20260502140021.69712-1-amachhiw@linux.ibm.com/
> v1: https://lore.kernel.org/all/20260430061333.37905-1-amachhiw@linux.ibm.com/
>
> Previous kernel patch versions:
> v6: https://lore.kernel.org/all/20260804180705.59160-1-amachhiw@linux.ibm.com/
> v5: https://lore.kernel.org/all/20260701051409.51820-1-amachhiw@linux.ibm.com/
> v4: https://lore.kernel.org/all/20260616123314.82721-1-amachhiw@linux.ibm.com/
> v3: https://lore.kernel.org/all/20260522152744.55251-1-amachhiw@linux.ibm.com/
> v2: https://lore.kernel.org/all/20260513100755.83195-1-amachhiw@linux.ibm.com/
> v1: https://lore.kernel.org/all/20260430054906.94401-1-amachhiw@linux.ibm.com/
>
> Amit Machhiwal (3):
> [DO_NOT_MERGE] linux-headers: Add uapi header changes
> target/ppc/kvm: Add support for querying host compatibility mode
> target/ppc/kvm: Use host compatibility mode for nested guests
>
> hw/ppc/spapr_hcall.c | 14 ++++++
> linux-headers/asm-powerpc/kvm.h | 19 +++++++
> linux-headers/linux/kvm.h | 3 ++
> target/ppc/kvm.c | 87 +++++++++++++++++++++++++++++++++
> target/ppc/kvm_ppc.h | 7 +++
> 5 files changed, 130 insertions(+)
>
>
> base-commit: b428fe036233cbd15d37e3c027ab6ca4d3661a80
Hi Amit,
I have tested this patch and it works as expected. Here is my analysis :
I booted a host with Power10 compat mode and tried following scenarios -
lscpu on host :
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Model name: POWER10 (architected), altivec supported
Before applying the patch :
When I am trying to bringup the guest on a compat mode host it was
bringing up a Power11 guest and was failing as
[ 1411.578944] [ T2928] KVM-NESTEDv2: couldn't set guest wide elements
[ 1411.578963] [ T2928] vcpu 000000000b9c4155 (0):
[ 1411.578968] [ T2928] pc = 000000007daf9790 msr =
8000000000103000 trap = ffffffea
[ 1411.578973] [ T2928] r 0 = 8000000000003000 r16 = 0000000000000000
[ 1411.578978] [ T2928] r 1 = 000000007e581e20 r17 = 0000000000000000
[ 1411.578982] [ T2928] r 2 = 000000007db26c00 r18 = 0000000000000000
[ 1411.578985] [ T2928] r 3 = 0000000000000000 r19 = 0000000000000000
[ 1411.578989] [ T2928] r 4 = 0000000002e30c80 r20 = 0000000000000000
[ 1411.578993] [ T2928] r 5 = 000000007df80000 r21 = 0000000000000000
[ 1411.578996] [ T2928] r 6 = 0000000000200000 r22 = 00000000018c5fd6
[ 1411.579000] [ T2928] r 7 = 000000007df80000 r23 = 000000007db21cc0
[ 1411.579003] [ T2928] r 8 = 000000007db6e5d8 r24 = 000000007db66000
[ 1411.579006] [ T2928] r 9 = 000000007e6655d8 r25 = 000000007e665508
[ 1411.579010] [ T2928] r10 = 000000007db6e5d0 r26 = 00000000018c5fd6
[ 1411.579013] [ T2928] r11 = 0000000000003000 r27 = 0000000000000003
[ 1411.579017] [ T2928] r12 = 8000000000000001 r28 = 000000007db6e5e0
[ 1411.579020] [ T2928] r13 = 0000000000000000 r29 = 000000007db224b0
[ 1411.579024] [ T2928] r14 = 0000000000000000 r30 = 000000007daf274c
[ 1411.579028] [ T2928] r15 = 0000000000000000 r31 = 000000007db76000
[ 1411.579033] [ T2928] ctr = 000000007daf1b44 lr = 000000007daf1b7c
[ 1411.579037] [ T2928] srr0 = 000000007daf9790 srr1 = 8000000000102000
[ 1411.579041] [ T2928] sprg0 = 0000000000000000 sprg1 = 000000000000ff10
[ 1411.579045] [ T2928] sprg2 = 0000000000000000 sprg3 = 0000000000000000
[ 1411.579049] [ T2928] cr = 20000402 xer = 0000000020040000 dsisr =
00000000
[ 1411.579054] [ T2928] dar = 0000000000000000
[ 1411.579057] [ T2928] fault dar = 0000000000000000 dsisr = 00000000
[ 1411.579061] [ T2928] SLB (0 entries):
[ 1411.579064] [ T2928] lpcr = 0040000000020400 sdr1 =
0000000000000000 last_inst = ffffffffffffffff
[ 1411.579069] [ T2928] trap=0xffffffea | pc=0x7daf9790 |
msr=0x8000000000103000
After applying this patch along with the kernel built with it's
dependent patch
(https://lore.kernel.org/all/20260804180705.59160-1-amachhiw@linux.ibm.com/):
I am able to bringup a guest and it got boot up with Power10 by default:
lscpu on guest -
ltcbonn53-vm2:~ # lscpu
Architecture: ppc64le
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Model name: POWER10 (architected), altivec supported
Model: 2.0 (pvr 0082 0200)
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
Please feel free to add my tested-by:
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Thank you,
Anushree Mathur
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests
2026-08-04 19:55 ` BALATON Zoltan
@ 2026-08-05 14:33 ` Amit Machhiwal
0 siblings, 0 replies; 7+ messages in thread
From: Amit Machhiwal @ 2026-08-05 14:33 UTC (permalink / raw)
To: BALATON Zoltan
Cc: Amit Machhiwal, qemu-ppc, Harsh Prateek Bora, Vaibhav Jain,
Nicholas Piggin, Chinmay Rath, Glenn Miles, Paolo Bonzini, kvm,
qemu-devel, Gautam Menghani
Hi BALATON,
Thanks for reviewing this patch. Please find my response inline below.
On 2026/08/04 09:55 PM, BALATON Zoltan wrote:
> On Tue, 4 Aug 2026, Amit Machhiwal wrote:
> > On POWER systems, the host CPU may run in a compatibility mode (e.g.,
> > a Power11 processor operating in Power10 compatibility mode). When
> > running nested KVM guests, QEMU currently derives the host CPU type
> > using mfpvr(), which reflects the physical processor version. This can
> > result in a mismatch between the CPU model used by QEMU and the
> > compatibility mode enforced by the host, leading to guest boot failures
> > such as "KVM-NESTEDv2: couldn't set guest wide elements".
> >
> > Update kvm_ppc_get_host_cpu_class() to check if the host is running in
> > a compatibility mode using kvm_ppc_host_compat_pvr(). When available,
> > use the compatibility PVR instead of the raw hardware PVR when selecting
> > the CPU model. This ensures that QEMU selects a CPU model consistent
> > with the host compatibility mode, allowing nested guests to boot
> > correctly.
> >
> > The guard uses #if defined(TARGET_PPC64) to prevent build breakage on
> > ppc32 targets where the POWER9/10/11 PVR constants are not defined.
> >
> > Tested-by: Gautam Menghani <gautam@linux.ibm.com>
> > Reviewed-by: Gautam Menghani <gautam@linux.ibm.com>
> > Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
> > ---
> > No changes in this version.
> >
> > target/ppc/kvm.c | 12 ++++++++++++
> > 1 file changed, 12 insertions(+)
> >
> > diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
> > index d4c5601a00c4..aa8269186a1a 100644
> > --- a/target/ppc/kvm.c
> > +++ b/target/ppc/kvm.c
> > @@ -2682,6 +2682,18 @@ PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
> > uint32_t host_pvr = mfpvr();
> > PowerPCCPUClass *pvr_pcc;
> >
> > +#if defined(TARGET_PPC64)
> > +#ifndef CONFIG_KVM
> > +#error "CONFIG_KVM is not enabled"
> > +#endif
>
> In meson.build:
>
> ppc_system_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
>
> so I think this check and #error does not make sense.
You're right that kvm.c is always compiled with CONFIG_KVM enabled due
to the meson.build constraint, so the #ifndef CONFIG_KVM / #error check
can never fire. I added it as an explicit compile-time assertion to
document the assumption, but it is redundant given the build system
already enforces it. I'll drop it in the next version.
Thanks,
Amit
>
> Regards,
> BALATON Zoltan
>
> > + uint32_t compat_host_pvr;
> > +
> > + compat_host_pvr = kvm_ppc_host_compat_pvr();
> > + if (compat_host_pvr) {
> > + host_pvr = compat_host_pvr;
> > + }
> > +#endif /* TARGET_PPC64 */
> > +
> > pvr_pcc = ppc_cpu_class_by_pvr(host_pvr);
> > if (pvr_pcc == NULL) {
> > pvr_pcc = ppc_cpu_class_by_pvr_mask(host_pvr);
> >
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-05 14:33 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-04 18:29 [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly for nested guests Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 1/3] [DO_NOT_MERGE] linux-headers: Add uapi header changes Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 2/3] target/ppc/kvm: Add support for querying host compatibility mode Amit Machhiwal
2026-08-04 18:29 ` [PATCH v5 3/3] target/ppc/kvm: Use host compatibility mode for nested guests Amit Machhiwal
2026-08-04 19:55 ` BALATON Zoltan
2026-08-05 14:33 ` Amit Machhiwal
2026-08-05 8:25 ` [PATCH v5 0/3] ppc/kvm: Handle CPU compatibility mode correctly " Anushree Mathur
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox