--- /dev/null
- arch/arm64/kvm/guest.c | 4 +-
- arch/loongarch/kvm/vcpu.c | 2 +-
- arch/loongarch/kvm/vm.c | 2 +-
- arch/mips/kvm/mips.c | 4 +-
- arch/powerpc/kvm/book3s.c | 4 +-
- arch/powerpc/kvm/booke.c | 4 +-
- arch/riscv/kvm/vcpu.c | 2 +-
- arch/riscv/kvm/vm.c | 2 +-
- arch/s390/kvm/kvm-s390.c | 4 +-
- arch/x86/kvm/x86.c | 4 +-
- include/linux/kvm_host.h | 83 +++++++++++++++++----------------------
- include/uapi/linux/kvm.h | 8 ++++
- virt/kvm/binary_stats.c | 2 +-
- virt/kvm/kvm_main.c | 20 +++++-----
+ From 71ad3de8d96c11cc06c2fee360b691627d613e16 Mon Sep 17 00:00:00 2001
+ From: Sasha Levin <sashal@kernel.org>
+ Date: Fri, 5 Dec 2025 15:26:55 -0800
+ Subject: KVM: Remove subtle "struct kvm_stats_desc" pseudo-overlay
+
+ From: Sean Christopherson <seanjc@google.com>
+
+ [ Upstream commit da142f3d373a6ddaca0119615a8db2175ddc4121 ]
+
+ Remove KVM's internal pseudo-overlay of kvm_stats_desc, which subtly
+ aliases the flexible name[] in the uAPI definition with a fixed-size array
+ of the same name. The unusual embedded structure results in compiler
+ warnings due to -Wflex-array-member-not-at-end, and also necessitates an
+ extra level of dereferencing in KVM. To avoid the "overlay", define the
+ uAPI structure to have a fixed-size name when building for the kernel.
+
+ Opportunistically clean up the indentation for the stats macros, and
+ replace spaces with tabs.
+
+ No functional change intended.
+
+ Reported-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+ Closes: https://lore.kernel.org/all/aPfNKRpLfhmhYqfP@kspp
+ Acked-by: Marc Zyngier <maz@kernel.org>
+ Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+ [..]
+ Acked-by: Anup Patel <anup@brainfault.org>
+ Reviewed-by: Bibo Mao <maobibo@loongson.cn>
+ Acked-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+ Link: https://patch.msgid.link/20251205232655.445294-1-seanjc@google.com
+ Signed-off-by: Sean Christopherson <seanjc@google.com>
+ Signed-off-by: Sasha Levin <sashal@kernel.org>
+ ---
-diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
-index 962f985977c2d..e67109b54ae90 100644
++ arch/arm64/kvm/guest.c | 4 +-
++ arch/loongarch/kvm/vcpu.c | 2 -
++ arch/loongarch/kvm/vm.c | 2 -
++ arch/mips/kvm/mips.c | 4 +-
++ arch/powerpc/kvm/book3s.c | 4 +-
++ arch/powerpc/kvm/booke.c | 4 +-
++ arch/riscv/kvm/vcpu.c | 2 -
++ arch/riscv/kvm/vm.c | 2 -
++ arch/s390/kvm/kvm-s390.c | 4 +-
++ arch/x86/kvm/x86.c | 4 +-
++ include/linux/kvm_host.h | 83 +++++++++++++++++++---------------------------
++ include/uapi/linux/kvm.h | 8 ++++
++ virt/kvm/binary_stats.c | 2 -
++ virt/kvm/kvm_main.c | 20 +++++------
+ 14 files changed, 70 insertions(+), 75 deletions(-)
+
-@@ -42,7 +42,7 @@ const struct kvm_stats_header kvm_vm_stats_header = {
+ --- a/arch/arm64/kvm/guest.c
+ +++ b/arch/arm64/kvm/guest.c
+ @@ -29,7 +29,7 @@
+
+ #include "trace.h"
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS()
+ };
+
-diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
-index 8579bddb544a7..38d3435d4fe0e 100644
++@@ -42,7 +42,7 @@ const struct kvm_stats_header kvm_vm_sta
+ sizeof(kvm_vm_stats_desc),
+ };
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, hvc_exit_stat),
+ STATS_DESC_COUNTER(VCPU, wfe_exit_stat),
-diff --git a/arch/loongarch/kvm/vm.c b/arch/loongarch/kvm/vm.c
-index fe9e973912d44..06c3fbab8c6fb 100644
+ --- a/arch/loongarch/kvm/vcpu.c
+ +++ b/arch/loongarch/kvm/vcpu.c
+ @@ -14,7 +14,7 @@
+ #define CREATE_TRACE_POINTS
+ #include "trace.h"
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, int_exits),
+ STATS_DESC_COUNTER(VCPU, idle_exits),
-diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
-index 60b43ea85c125..3f8d5310bbd27 100644
+ --- a/arch/loongarch/kvm/vm.c
+ +++ b/arch/loongarch/kvm/vm.c
+ @@ -7,7 +7,7 @@
+ #include <asm/kvm_mmu.h>
+ #include <asm/kvm_vcpu.h>
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS(),
+ STATS_DESC_ICOUNTER(VM, pages),
+ STATS_DESC_ICOUNTER(VM, hugepages),
-@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_stats_header = {
+ --- a/arch/mips/kvm/mips.c
+ +++ b/arch/mips/kvm/mips.c
+ @@ -38,7 +38,7 @@
+ #define VECTORSPACING 0x100 /* for EI/VI mode */
+ #endif
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS()
+ };
+
-diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
-index ff6c383739575..b6c4c1490a9f8 100644
++@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_sta
+ sizeof(kvm_vm_stats_desc),
+ };
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, wait_exits),
+ STATS_DESC_COUNTER(VCPU, cache_exits),
-@@ -53,7 +53,7 @@ const struct kvm_stats_header kvm_vm_stats_header = {
+ --- a/arch/powerpc/kvm/book3s.c
+ +++ b/arch/powerpc/kvm/book3s.c
+ @@ -38,7 +38,7 @@
+
+ /* #define EXIT_DEBUG */
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS(),
+ STATS_DESC_ICOUNTER(VM, num_2M_pages),
+ STATS_DESC_ICOUNTER(VM, num_1G_pages)
-diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
-index 6a5be025a8afb..368b4381fe6b0 100644
++@@ -53,7 +53,7 @@ const struct kvm_stats_header kvm_vm_sta
+ sizeof(kvm_vm_stats_desc),
+ };
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, sum_exits),
+ STATS_DESC_COUNTER(VCPU, mmio_exits),
-@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_stats_header = {
+ --- a/arch/powerpc/kvm/booke.c
+ +++ b/arch/powerpc/kvm/booke.c
+ @@ -36,7 +36,7 @@
+
+ unsigned long kvmppc_booke_handlers;
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS(),
+ STATS_DESC_ICOUNTER(VM, num_2M_pages),
+ STATS_DESC_ICOUNTER(VM, num_1G_pages)
-diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
-index 8d7d381737ee5..da01c81bf4167 100644
++@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_sta
+ sizeof(kvm_vm_stats_desc),
+ };
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, sum_exits),
+ STATS_DESC_COUNTER(VCPU, mmio_exits),
-diff --git a/arch/riscv/kvm/vm.c b/arch/riscv/kvm/vm.c
-index 7396b8654f454..b7713ffe4c548 100644
+ --- a/arch/riscv/kvm/vcpu.c
+ +++ b/arch/riscv/kvm/vcpu.c
+ @@ -24,7 +24,7 @@
+ #define CREATE_TRACE_POINTS
+ #include "trace.h"
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, ecall_exit_stat),
+ STATS_DESC_COUNTER(VCPU, wfi_exit_stat),
-diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
-index 286a224c81ee4..70d7bbd62120d 100644
+ --- a/arch/riscv/kvm/vm.c
+ +++ b/arch/riscv/kvm/vm.c
+ @@ -12,7 +12,7 @@
+ #include <linux/uaccess.h>
+ #include <linux/kvm_host.h>
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS()
+ };
+ static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
-@@ -85,7 +85,7 @@ const struct kvm_stats_header kvm_vm_stats_header = {
+ --- a/arch/s390/kvm/kvm-s390.c
+ +++ b/arch/s390/kvm/kvm-s390.c
+ @@ -59,7 +59,7 @@
+ #define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \
+ (KVM_MAX_VCPUS + LOCAL_IRQS))
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS(),
+ STATS_DESC_COUNTER(VM, inject_io),
+ STATS_DESC_COUNTER(VM, inject_float_mchk),
-diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
-index 8a52b7bb821a7..693a9961fbec1 100644
++@@ -85,7 +85,7 @@ const struct kvm_stats_header kvm_vm_sta
+ sizeof(kvm_vm_stats_desc),
+ };
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, exit_userspace),
+ STATS_DESC_COUNTER(VCPU, exit_null),
-@@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(allow_smaller_maxphyaddr);
+ --- a/arch/x86/kvm/x86.c
+ +++ b/arch/x86/kvm/x86.c
-@@ -255,7 +255,7 @@ const struct kvm_stats_header kvm_vm_stats_header = {
++@@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(allow_smaller_maxphyad
+ bool __read_mostly enable_apicv = true;
+ EXPORT_SYMBOL_GPL(enable_apicv);
+
+ -const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS(),
+ STATS_DESC_COUNTER(VM, mmu_shadow_zapped),
+ STATS_DESC_COUNTER(VM, mmu_pte_write),
-diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
-index a2ebc37a29ff4..966511b1e70fa 100644
++@@ -255,7 +255,7 @@ const struct kvm_stats_header kvm_vm_sta
+ sizeof(kvm_vm_stats_desc),
+ };
+
+ -const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ +const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ STATS_DESC_COUNTER(VCPU, pf_taken),
+ STATS_DESC_COUNTER(VCPU, pf_fixed),
-@@ -1877,56 +1877,43 @@ enum kvm_stat_kind {
+ --- a/include/linux/kvm_host.h
+ +++ b/include/linux/kvm_host.h
-@@ -2003,7 +1990,7 @@ struct _kvm_stats_desc {
++@@ -1884,56 +1884,43 @@ enum kvm_stat_kind {
+
+ struct kvm_stat_data {
+ struct kvm *kvm;
+ - const struct _kvm_stats_desc *desc;
+ + const struct kvm_stats_desc *desc;
+ enum kvm_stat_kind kind;
+ };
+
+ -struct _kvm_stats_desc {
+ - struct kvm_stats_desc desc;
+ - char name[KVM_STATS_NAME_SIZE];
+ -};
+ -
+ -#define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \
+ - .flags = type | unit | base | \
+ - BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \
+ - BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \
+ - BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \
+ - .exponent = exp, \
+ - .size = sz, \
+ +#define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \
+ + .flags = type | unit | base | \
+ + BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \
+ + BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \
+ + BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \
+ + .exponent = exp, \
+ + .size = sz, \
+ .bucket_size = bsz
+
+ -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ - { \
+ - { \
+ - STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ - .offset = offsetof(struct kvm_vm_stat, generic.stat) \
+ - }, \
+ - .name = #stat, \
+ - }
+ -#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ - { \
+ - { \
+ - STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ - .offset = offsetof(struct kvm_vcpu_stat, generic.stat) \
+ - }, \
+ - .name = #stat, \
+ - }
+ -#define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ - { \
+ - { \
+ - STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ - .offset = offsetof(struct kvm_vm_stat, stat) \
+ - }, \
+ - .name = #stat, \
+ - }
+ -#define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ - { \
+ - { \
+ - STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ - .offset = offsetof(struct kvm_vcpu_stat, stat) \
+ - }, \
+ - .name = #stat, \
+ - }
+ +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ +{ \
+ + STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ + .offset = offsetof(struct kvm_vm_stat, generic.stat), \
+ + .name = #stat, \
+ +}
+ +#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ +{ \
+ + STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ + .offset = offsetof(struct kvm_vcpu_stat, generic.stat), \
+ + .name = #stat, \
+ +}
+ +#define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ +{ \
+ + STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ + .offset = offsetof(struct kvm_vm_stat, stat), \
+ + .name = #stat, \
+ +}
+ +#define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
+ +{ \
+ + STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
+ + .offset = offsetof(struct kvm_vcpu_stat, stat), \
+ + .name = #stat, \
+ +}
+ /* SCOPE: VM, VM_GENERIC, VCPU, VCPU_GENERIC */
+ #define STATS_DESC(SCOPE, stat, type, unit, base, exp, sz, bsz) \
+ SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, bsz)
-@@ -2048,9 +2035,9 @@ static inline void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
++@@ -2010,7 +1997,7 @@ struct _kvm_stats_desc {
+ STATS_DESC_IBOOLEAN(VCPU_GENERIC, blocking)
+
+ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
+ - const struct _kvm_stats_desc *desc,
+ + const struct kvm_stats_desc *desc,
+ void *stats, size_t size_stats,
+ char __user *user_buffer, size_t size, loff_t *offset);
+
-diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
-index 637efc0551453..03bbe12620e98 100644
++@@ -2055,9 +2042,9 @@ static inline void kvm_stats_log_hist_up
+
+
+ extern const struct kvm_stats_header kvm_vm_stats_header;
+ -extern const struct _kvm_stats_desc kvm_vm_stats_desc[];
+ +extern const struct kvm_stats_desc kvm_vm_stats_desc[];
+ extern const struct kvm_stats_header kvm_vcpu_stats_header;
+ -extern const struct _kvm_stats_desc kvm_vcpu_stats_desc[];
+ +extern const struct kvm_stats_desc kvm_vcpu_stats_desc[];
+
+ #ifdef CONFIG_KVM_GENERIC_MMU_NOTIFIER
+ static inline int mmu_invalidate_retry(struct kvm *kvm, unsigned long mmu_seq)
-diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
-index eefca6c69f519..76ce697c773bf 100644
+ --- a/include/uapi/linux/kvm.h
+ +++ b/include/uapi/linux/kvm.h
+ @@ -14,6 +14,10 @@
+ #include <linux/ioctl.h>
+ #include <asm/kvm.h>
+
+ +#ifdef __KERNEL__
+ +#include <linux/kvm_types.h>
+ +#endif
+ +
+ #define KVM_API_VERSION 12
+
+ /*
+ @@ -1526,7 +1530,11 @@ struct kvm_stats_desc {
+ __u16 size;
+ __u32 offset;
+ __u32 bucket_size;
+ +#ifdef __KERNEL__
+ + char name[KVM_STATS_NAME_SIZE];
+ +#else
+ char name[];
+ +#endif
+ };
+
+ #define KVM_GET_STATS_FD _IO(KVMIO, 0xce)
-diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
-index 16cb973741f42..833553e0f2cc5 100644
+ --- a/virt/kvm/binary_stats.c
+ +++ b/virt/kvm/binary_stats.c
+ @@ -50,7 +50,7 @@
+ * Return: the number of bytes that has been successfully read
+ */
+ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
+ - const struct _kvm_stats_desc *desc,
+ + const struct kvm_stats_desc *desc,
+ void *stats, size_t size_stats,
+ char __user *user_buffer, size_t size, loff_t *offset)
+ {
-@@ -1013,9 +1013,9 @@ static void kvm_free_memslots(struct kvm *kvm, struct kvm_memslots *slots)
+ --- a/virt/kvm/kvm_main.c
+ +++ b/virt/kvm/kvm_main.c
-@@ -1050,7 +1050,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, const char *fdname)
++@@ -1013,9 +1013,9 @@ static void kvm_free_memslots(struct kvm
+ kvm_free_memslot(kvm, memslot);
+ }
+
+ -static umode_t kvm_stats_debugfs_mode(const struct _kvm_stats_desc *pdesc)
+ +static umode_t kvm_stats_debugfs_mode(const struct kvm_stats_desc *desc)
+ {
+ - switch (pdesc->desc.flags & KVM_STATS_TYPE_MASK) {
+ + switch (desc->flags & KVM_STATS_TYPE_MASK) {
+ case KVM_STATS_TYPE_INSTANT:
+ return 0444;
+ case KVM_STATS_TYPE_CUMULATIVE:
-@@ -6164,11 +6164,11 @@ static int kvm_stat_data_get(void *data, u64 *val)
++@@ -1050,7 +1050,7 @@ static int kvm_create_vm_debugfs(struct
+ struct dentry *dent;
+ char dir_name[ITOA_MAX_LEN * 2];
+ struct kvm_stat_data *stat_data;
+ - const struct _kvm_stats_desc *pdesc;
+ + const struct kvm_stats_desc *pdesc;
+ int i, ret = -ENOMEM;
+ int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc +
+ kvm_vcpu_stats_header.num_desc;
-@@ -6186,11 +6186,11 @@ static int kvm_stat_data_clear(void *data, u64 val)
++@@ -6164,11 +6164,11 @@ static int kvm_stat_data_get(void *data,
+ switch (stat_data->kind) {
+ case KVM_STAT_VM:
+ r = kvm_get_stat_per_vm(stat_data->kvm,
+ - stat_data->desc->desc.offset, val);
+ + stat_data->desc->offset, val);
+ break;
+ case KVM_STAT_VCPU:
+ r = kvm_get_stat_per_vcpu(stat_data->kvm,
+ - stat_data->desc->desc.offset, val);
+ + stat_data->desc->offset, val);
+ break;
+ }
+
-@@ -6338,7 +6338,7 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm)
++@@ -6186,11 +6186,11 @@ static int kvm_stat_data_clear(void *dat
+ switch (stat_data->kind) {
+ case KVM_STAT_VM:
+ r = kvm_clear_stat_per_vm(stat_data->kvm,
+ - stat_data->desc->desc.offset);
+ + stat_data->desc->offset);
+ break;
+ case KVM_STAT_VCPU:
+ r = kvm_clear_stat_per_vcpu(stat_data->kvm,
+ - stat_data->desc->desc.offset);
+ + stat_data->desc->offset);
+ break;
+ }
+
---
-2.53.0
-
++@@ -6338,7 +6338,7 @@ static void kvm_uevent_notify_change(uns
+ static void kvm_init_debug(void)
+ {
+ const struct file_operations *fops;
+ - const struct _kvm_stats_desc *pdesc;
+ + const struct kvm_stats_desc *pdesc;
+ int i;
+
+ kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);
+ @@ -6351,7 +6351,7 @@ static void kvm_init_debug(void)
+ fops = &vm_stat_readonly_fops;
+ debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc),
+ kvm_debugfs_dir,
+ - (void *)(long)pdesc->desc.offset, fops);
+ + (void *)(long)pdesc->offset, fops);
+ }
+
+ for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) {
+ @@ -6362,7 +6362,7 @@ static void kvm_init_debug(void)
+ fops = &vcpu_stat_readonly_fops;
+ debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc),
+ kvm_debugfs_dir,
+ - (void *)(long)pdesc->desc.offset, fops);
+ + (void *)(long)pdesc->offset, fops);
+ }
+ }
+
--- /dev/null
- arch/x86/include/uapi/asm/kvm.h | 12 ++++++------
- include/uapi/linux/kvm.h | 11 ++++++-----
+ From 5bcd1314f8d8ba91a01e1ca3e6a8c8e42827305c Mon Sep 17 00:00:00 2001
+ From: Sasha Levin <sashal@kernel.org>
+ Date: Thu, 5 Mar 2026 20:49:55 +0100
+ Subject: KVM: x86: Use __DECLARE_FLEX_ARRAY() for UAPI structures with VLAs
+
+ From: David Woodhouse <dwmw@amazon.co.uk>
+
+ [ Upstream commit 2619da73bb2f10d88f7e1087125c40144fdf0987 ]
+
+ Commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with
+ flexible-array members") broke the userspace API for C++.
+
+ These structures ending in VLAs are typically a *header*, which can be
+ followed by an arbitrary number of entries. Userspace typically creates
+ a larger structure with some non-zero number of entries, for example in
+ QEMU's kvm_arch_get_supported_msr_feature():
+
+ struct {
+ struct kvm_msrs info;
+ struct kvm_msr_entry entries[1];
+ } msr_data = {};
+
+ While that works in C, it fails in C++ with an error like:
+ flexible array member 'kvm_msrs::entries' not at end of 'struct msr_data'
+
+ Fix this by using __DECLARE_FLEX_ARRAY() for the VLA, which uses [0]
+ for C++ compilation.
+
+ Fixes: 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members")
+ Cc: stable@vger.kernel.org
+ Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+ Link: https://patch.msgid.link/3abaf6aefd6e5efeff3b860ac38421d9dec908db.camel@infradead.org
+ [sean: tag for stable@]
+ Signed-off-by: Sean Christopherson <seanjc@google.com>
+ Signed-off-by: Sasha Levin <sashal@kernel.org>
+ ---
-diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
-index 64cdf9763c0e0..f1b0a28b3a36b 100644
++ arch/x86/include/uapi/asm/kvm.h | 12 ++++++------
++ include/uapi/linux/kvm.h | 11 ++++++-----
+ 2 files changed, 12 insertions(+), 11 deletions(-)
+
-diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
-index 03bbe12620e98..9222f5e3c59b9 100644
+ --- a/arch/x86/include/uapi/asm/kvm.h
+ +++ b/arch/x86/include/uapi/asm/kvm.h
+ @@ -192,13 +192,13 @@ struct kvm_msrs {
+ __u32 nmsrs; /* number of msrs in entries */
+ __u32 pad;
+
+ - struct kvm_msr_entry entries[];
+ + __DECLARE_FLEX_ARRAY(struct kvm_msr_entry, entries);
+ };
+
+ /* for KVM_GET_MSR_INDEX_LIST */
+ struct kvm_msr_list {
+ __u32 nmsrs; /* number of msrs in entries */
+ - __u32 indices[];
+ + __DECLARE_FLEX_ARRAY(__u32, indices);
+ };
+
+ /* Maximum size of any access bitmap in bytes */
+ @@ -240,7 +240,7 @@ struct kvm_cpuid_entry {
+ struct kvm_cpuid {
+ __u32 nent;
+ __u32 padding;
+ - struct kvm_cpuid_entry entries[];
+ + __DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry, entries);
+ };
+
+ struct kvm_cpuid_entry2 {
+ @@ -262,7 +262,7 @@ struct kvm_cpuid_entry2 {
+ struct kvm_cpuid2 {
+ __u32 nent;
+ __u32 padding;
+ - struct kvm_cpuid_entry2 entries[];
+ + __DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry2, entries);
+ };
+
+ /* for KVM_GET_PIT and KVM_SET_PIT */
+ @@ -393,7 +393,7 @@ struct kvm_xsave {
+ * the contents of CPUID leaf 0xD on the host.
+ */
+ __u32 region[1024];
+ - __u32 extra[];
+ + __DECLARE_FLEX_ARRAY(__u32, extra);
+ };
+
+ #define KVM_MAX_XCRS 16
+ @@ -530,7 +530,7 @@ struct kvm_pmu_event_filter {
+ __u32 fixed_counter_bitmap;
+ __u32 flags;
+ __u32 pad[4];
+ - __u64 events[];
+ + __DECLARE_FLEX_ARRAY(__u64, events);
+ };
+
+ #define KVM_PMU_EVENT_ALLOW 0
---
-2.53.0
-
+ --- a/include/uapi/linux/kvm.h
+ +++ b/include/uapi/linux/kvm.h
+ @@ -11,6 +11,7 @@
+ #include <linux/const.h>
+ #include <linux/types.h>
+ #include <linux/compiler.h>
+ +#include <linux/stddef.h>
+ #include <linux/ioctl.h>
+ #include <asm/kvm.h>
+
+ @@ -496,7 +497,7 @@ struct kvm_coalesced_mmio {
+
+ struct kvm_coalesced_mmio_ring {
+ __u32 first, last;
+ - struct kvm_coalesced_mmio coalesced_mmio[];
+ + __DECLARE_FLEX_ARRAY(struct kvm_coalesced_mmio, coalesced_mmio);
+ };
+
+ #define KVM_COALESCED_MMIO_MAX \
+ @@ -546,7 +547,7 @@ struct kvm_clear_dirty_log {
+ /* for KVM_SET_SIGNAL_MASK */
+ struct kvm_signal_mask {
+ __u32 len;
+ - __u8 sigset[];
+ + __DECLARE_FLEX_ARRAY(__u8, sigset);
+ };
+
+ /* for KVM_TPR_ACCESS_REPORTING */
+ @@ -999,7 +1000,7 @@ struct kvm_irq_routing_entry {
+ struct kvm_irq_routing {
+ __u32 nr;
+ __u32 flags;
+ - struct kvm_irq_routing_entry entries[];
+ + __DECLARE_FLEX_ARRAY(struct kvm_irq_routing_entry, entries);
+ };
+
+ #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
+ @@ -1086,7 +1087,7 @@ struct kvm_dirty_tlb {
+
+ struct kvm_reg_list {
+ __u64 n; /* number of regs */
+ - __u64 reg[];
+ + __DECLARE_FLEX_ARRAY(__u64, reg);
+ };
+
+ struct kvm_one_reg {
+ @@ -1533,7 +1534,7 @@ struct kvm_stats_desc {
+ #ifdef __KERNEL__
+ char name[KVM_STATS_NAME_SIZE];
+ #else
+ - char name[];
+ + __DECLARE_FLEX_ARRAY(char, name);
+ #endif
+ };
+