summaryrefslogtreecommitdiff
path: root/include/kvm
diff options
context:
space:
mode:
authorSascha Bischoff <Sascha.Bischoff@arm.com>2026-09-04 11:40:22 +0000
committerMarc Zyngier <maz@kernel.org>2026-09-14 10:49:07 +0100
commit21fd40005fb36c24ce0c28758b48da1238ffc909 (patch)
tree8f67ebec18cf9bd35560dbb45ddc4454a73a7d78 /include/kvm
parent884d518cef62c5f4beb940709bf1920021b773b8 (diff)
KVM: arm64: vgic: Enforce model-specific vCPU limits
A GICv5 host with FEAT_GCIE_LEGACY can expose either a native vGICv5 or a vGICv3 device. These models do not necessarily have the same vCPU limit: the native GICv5 limit is probed from the IRS VPE capacity, while the GICv3 limit remains the fixed KVM vGICv3 limit. Keep the IRS-derived limit separately for vGICv5 creation. The pre-VGIC KVM_CAP_MAX_VCPUS value continues to expose the largest limit among the still-selectable models, and kvm_vgic_create() clamps the VM to the limit of the VGIC model userspace actually selected. Userspace can create vCPUs before creating a VGIC. Hence, checking only the number of existing vCPUs after reducing the limit is not sufficient. For example, a single vCPU with ID 500 passes the GICv2 count limit even though GICv2 can represent only eight target CPUs. The GICv2 code subsequently uses the vCPU ID in target and SGI source masks, leading to shifts beyond the width of the operand. GICv5 has a similar requirement because the userspace-provided vcpu_id is used as the index into the VPET. This means that the vcpu_id also represents the IAFFID for a VPE, and therefore is visible to the guest. After selecting the model-specific limit, validate every existing vCPU ID against it. KVM_CREATE_VCPU already enforces the same limit for vCPUs created after the VGIC, making the result independent of creation order. Link: https://lore.kernel.org/r/20260807133051.15D381F000E9@smtp.kernel.org Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> Link: https://patch.msgid.link/20260904113404.4051341-13-sascha.bischoff@arm.com Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'include/kvm')
-rw-r--r--include/kvm/arm_vgic.h16
1 files changed, 12 insertions, 4 deletions
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 3ec3f7e1b88b..593145760812 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -172,9 +172,16 @@ struct vgic_global {
/* Maintenance IRQ number */
unsigned int maint_irq;
- /* maximum number of VCPUs allowed (GICv2 limits us to 8) */
+ /*
+ * Maximum number of VCPUs exposed before userspace has selected a
+ * VGIC model. Individual VGIC models can impose a lower limit
+ * (GICv2 limits us to 8).
+ */
int max_gic_vcpus;
+ /* Maximum number of VCPUs allowed for a GICv5 VM. */
+ int max_gicv5_vcpus;
+
/* Only needed for the legacy KVM_CREATE_IRQCHIP */
bool can_emulate_gicv2;
@@ -622,10 +629,11 @@ void kvm_vgic_process_async_update(struct kvm_vcpu *vcpu);
void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1);
/**
- * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW
+ * kvm_vgic_get_max_vcpus - Get the pre-VGIC-selection VCPU limit
*
- * The host's GIC naturally limits the maximum amount of VCPUs a guest
- * can use.
+ * Userspace can query KVM_CAP_MAX_VCPUS before selecting a VGIC model, so
+ * expose the highest model-specific limit and let kvm_vgic_create() enforce
+ * the selected model's actual limit.
*/
static inline int kvm_vgic_get_max_vcpus(void)
{