Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm/arm64: KVM: make the maximum number of vCPUs a per-VM value

Currently the maximum number of vCPUs supported is a global value
limited by the used GIC model. GICv3 will lift this limit, but we
still need to observe it for guests using GICv2.
So the maximum number of vCPUs is per-VM value, depending on the
GIC model the guest uses.
Store and check the value in struct kvm_arch, but keep it down to
8 for now.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

authored by

Andre Przywara and committed by
Christoffer Dall
3caa2d8c 4ce7ebdf

+38
+1
arch/arm/include/asm/kvm_host.h
··· 68 68 69 69 /* Interrupt controller */ 70 70 struct vgic_dist vgic; 71 + int max_vcpus; 71 72 }; 72 73 73 74 #define KVM_NR_MEM_OBJS 40
+8
arch/arm/kvm/arm.c
··· 132 132 /* Mark the initial VMID generation invalid */ 133 133 kvm->arch.vmid_gen = 0; 134 134 135 + /* The maximum number of VCPUs is limited by the host's GIC model */ 136 + kvm->arch.max_vcpus = kvm_vgic_get_max_vcpus(); 137 + 135 138 return ret; 136 139 out_free_stage2_pgd: 137 140 kvm_free_stage2_pgd(kvm); ··· 218 215 219 216 if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { 220 217 err = -EBUSY; 218 + goto out; 219 + } 220 + 221 + if (id >= kvm->arch.max_vcpus) { 222 + err = -EINVAL; 221 223 goto out; 222 224 } 223 225
+3
arch/arm64/include/asm/kvm_host.h
··· 59 59 /* VTTBR value associated with above pgd and vmid */ 60 60 u64 vttbr; 61 61 62 + /* The maximum number of vCPUs depends on the used GIC model */ 63 + int max_vcpus; 64 + 62 65 /* Interrupt controller */ 63 66 struct vgic_dist vgic; 64 67
+8
include/kvm/arm_vgic.h
··· 33 33 #define VGIC_V2_MAX_LRS (1 << 6) 34 34 #define VGIC_V3_MAX_LRS 16 35 35 #define VGIC_MAX_IRQS 1024 36 + #define VGIC_V2_MAX_CPUS 8 36 37 37 38 /* Sanity checks... */ 38 39 #if (KVM_MAX_VCPUS > 8) ··· 133 132 unsigned int maint_irq; 134 133 /* Virtual control interface base address */ 135 134 void __iomem *vctrl_base; 135 + int max_gic_vcpus; 136 136 }; 137 137 138 138 struct vgic_vm_ops { ··· 291 289 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write); 292 290 int kvm_vgic_hyp_init(void); 293 291 int kvm_vgic_map_resources(struct kvm *kvm); 292 + int kvm_vgic_get_max_vcpus(void); 294 293 int kvm_vgic_create(struct kvm *kvm, u32 type); 295 294 void kvm_vgic_destroy(struct kvm *kvm); 296 295 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu); ··· 395 392 static inline bool vgic_ready(struct kvm *kvm) 396 393 { 397 394 return true; 395 + } 396 + 397 + static inline int kvm_vgic_get_max_vcpus(void) 398 + { 399 + return KVM_MAX_VCPUS; 398 400 } 399 401 #endif 400 402
+1
virt/kvm/arm/vgic-v2.c
··· 237 237 vctrl_res.start, vgic->maint_irq); 238 238 239 239 vgic->type = VGIC_V2; 240 + vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS; 240 241 *ops = &vgic_v2_ops; 241 242 *params = vgic; 242 243 goto out;
+1
virt/kvm/arm/vgic-v3.c
··· 235 235 vgic->vcpu_base = vcpu_res.start; 236 236 vgic->vctrl_base = NULL; 237 237 vgic->type = VGIC_V3; 238 + vgic->max_gic_vcpus = KVM_MAX_VCPUS; 238 239 239 240 kvm_info("%s@%llx IRQ%d\n", vgic_node->name, 240 241 vcpu_res.start, vgic->maint_irq);
+16
virt/kvm/arm/vgic.c
··· 1878 1878 return 0; 1879 1879 } 1880 1880 1881 + /** 1882 + * kvm_vgic_get_max_vcpus - Get the maximum number of VCPUs allowed by HW 1883 + * 1884 + * The host's GIC naturally limits the maximum amount of VCPUs a guest 1885 + * can use. 1886 + */ 1887 + int kvm_vgic_get_max_vcpus(void) 1888 + { 1889 + return vgic->max_gic_vcpus; 1890 + } 1891 + 1881 1892 void kvm_vgic_destroy(struct kvm *kvm) 1882 1893 { 1883 1894 struct vgic_dist *dist = &kvm->arch.vgic; ··· 2083 2072 dist->vm_ops.add_sgi_source = vgic_v2_add_sgi_source; 2084 2073 dist->vm_ops.init_model = vgic_v2_init_model; 2085 2074 dist->vm_ops.map_resources = vgic_v2_map_resources; 2075 + 2076 + kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS; 2086 2077 } 2087 2078 2088 2079 static int init_vgic_model(struct kvm *kvm, int type) ··· 2096 2083 default: 2097 2084 return -ENODEV; 2098 2085 } 2086 + 2087 + if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus) 2088 + return -E2BIG; 2099 2089 2100 2090 return 0; 2101 2091 }