diff options
| author | Sascha Bischoff <Sascha.Bischoff@arm.com> | 2026-09-04 11:40:22 +0000 |
|---|---|---|
| committer | Marc Zyngier <maz@kernel.org> | 2026-09-14 10:49:07 +0100 |
| commit | 21fd40005fb36c24ce0c28758b48da1238ffc909 (patch) | |
| tree | 8f67ebec18cf9bd35560dbb45ddc4454a73a7d78 /include/kvm | |
| parent | 884d518cef62c5f4beb940709bf1920021b773b8 (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.h | 16 |
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) { |
