aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2014-06-02 10:26:01 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2015-01-20 12:25:28 -0500
commit3caa2d8c3b2d80f5e342fe8cec07c03c8147dcab (patch)
treea07f89b6bcbd96fa45a65b52591d5fda2490a2f4
parent4ce7ebdfc69d1d5d166eec103ed2976eb45a6173 (diff)
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>
-rw-r--r--arch/arm/include/asm/kvm_host.h1
-rw-r--r--arch/arm/kvm/arm.c8
-rw-r--r--arch/arm64/include/asm/kvm_host.h3
-rw-r--r--include/kvm/arm_vgic.h8
-rw-r--r--virt/kvm/arm/vgic-v2.c1
-rw-r--r--virt/kvm/arm/vgic-v3.c1
-rw-r--r--virt/kvm/arm/vgic.c16
7 files changed, 38 insertions, 0 deletions
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 2fa51740edc2..bde494654bcc 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -68,6 +68,7 @@ struct kvm_arch {
68 68
69 /* Interrupt controller */ 69 /* Interrupt controller */
70 struct vgic_dist vgic; 70 struct vgic_dist vgic;
71 int max_vcpus;
71}; 72};
72 73
73#define KVM_NR_MEM_OBJS 40 74#define KVM_NR_MEM_OBJS 40
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 3a51ffca75e3..6fbfa5fff05d 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -132,6 +132,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
132 /* Mark the initial VMID generation invalid */ 132 /* Mark the initial VMID generation invalid */
133 kvm->arch.vmid_gen = 0; 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 return ret; 138 return ret;
136out_free_stage2_pgd: 139out_free_stage2_pgd:
137 kvm_free_stage2_pgd(kvm); 140 kvm_free_stage2_pgd(kvm);
@@ -218,6 +221,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
218 goto out; 221 goto out;
219 } 222 }
220 223
224 if (id >= kvm->arch.max_vcpus) {
225 err = -EINVAL;
226 goto out;
227 }
228
221 vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); 229 vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
222 if (!vcpu) { 230 if (!vcpu) {
223 err = -ENOMEM; 231 err = -ENOMEM;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ff8ee3ec32f4..2c49aa4ac818 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -59,6 +59,9 @@ struct kvm_arch {
59 /* VTTBR value associated with above pgd and vmid */ 59 /* VTTBR value associated with above pgd and vmid */
60 u64 vttbr; 60 u64 vttbr;
61 61
62 /* The maximum number of vCPUs depends on the used GIC model */
63 int max_vcpus;
64
62 /* Interrupt controller */ 65 /* Interrupt controller */
63 struct vgic_dist vgic; 66 struct vgic_dist vgic;
64 67
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index dd243969bfc3..1c0e9dbabe6d 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -33,6 +33,7 @@
33#define VGIC_V2_MAX_LRS (1 << 6) 33#define VGIC_V2_MAX_LRS (1 << 6)
34#define VGIC_V3_MAX_LRS 16 34#define VGIC_V3_MAX_LRS 16
35#define VGIC_MAX_IRQS 1024 35#define VGIC_MAX_IRQS 1024
36#define VGIC_V2_MAX_CPUS 8
36 37
37/* Sanity checks... */ 38/* Sanity checks... */
38#if (KVM_MAX_VCPUS > 8) 39#if (KVM_MAX_VCPUS > 8)
@@ -132,6 +133,7 @@ struct vgic_params {
132 unsigned int maint_irq; 133 unsigned int maint_irq;
133 /* Virtual control interface base address */ 134 /* Virtual control interface base address */
134 void __iomem *vctrl_base; 135 void __iomem *vctrl_base;
136 int max_gic_vcpus;
135}; 137};
136 138
137struct vgic_vm_ops { 139struct vgic_vm_ops {
@@ -289,6 +291,7 @@ struct kvm_exit_mmio;
289int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write); 291int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
290int kvm_vgic_hyp_init(void); 292int kvm_vgic_hyp_init(void);
291int kvm_vgic_map_resources(struct kvm *kvm); 293int kvm_vgic_map_resources(struct kvm *kvm);
294int kvm_vgic_get_max_vcpus(void);
292int kvm_vgic_create(struct kvm *kvm, u32 type); 295int kvm_vgic_create(struct kvm *kvm, u32 type);
293void kvm_vgic_destroy(struct kvm *kvm); 296void kvm_vgic_destroy(struct kvm *kvm);
294void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu); 297void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
@@ -393,6 +396,11 @@ static inline bool vgic_ready(struct kvm *kvm)
393{ 396{
394 return true; 397 return true;
395} 398}
399
400static inline int kvm_vgic_get_max_vcpus(void)
401{
402 return KVM_MAX_VCPUS;
403}
396#endif 404#endif
397 405
398#endif 406#endif
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index e1cd3cb95903..e8b82b289844 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -237,6 +237,7 @@ int vgic_v2_probe(struct device_node *vgic_node,
237 vctrl_res.start, vgic->maint_irq); 237 vctrl_res.start, vgic->maint_irq);
238 238
239 vgic->type = VGIC_V2; 239 vgic->type = VGIC_V2;
240 vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS;
240 *ops = &vgic_v2_ops; 241 *ops = &vgic_v2_ops;
241 *params = vgic; 242 *params = vgic;
242 goto out; 243 goto out;
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index d14c75f4a33b..ea39bad4b004 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -235,6 +235,7 @@ int vgic_v3_probe(struct device_node *vgic_node,
235 vgic->vcpu_base = vcpu_res.start; 235 vgic->vcpu_base = vcpu_res.start;
236 vgic->vctrl_base = NULL; 236 vgic->vctrl_base = NULL;
237 vgic->type = VGIC_V3; 237 vgic->type = VGIC_V3;
238 vgic->max_gic_vcpus = KVM_MAX_VCPUS;
238 239
239 kvm_info("%s@%llx IRQ%d\n", vgic_node->name, 240 kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
240 vcpu_res.start, vgic->maint_irq); 241 vcpu_res.start, vgic->maint_irq);
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 1c3b75eb28f0..2126bf5b0035 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1878,6 +1878,17 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
1878 return 0; 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 */
1887int kvm_vgic_get_max_vcpus(void)
1888{
1889 return vgic->max_gic_vcpus;
1890}
1891
1881void kvm_vgic_destroy(struct kvm *kvm) 1892void kvm_vgic_destroy(struct kvm *kvm)
1882{ 1893{
1883 struct vgic_dist *dist = &kvm->arch.vgic; 1894 struct vgic_dist *dist = &kvm->arch.vgic;
@@ -2072,6 +2083,8 @@ static void vgic_v2_init_emulation(struct kvm *kvm)
2072 dist->vm_ops.add_sgi_source = vgic_v2_add_sgi_source; 2083 dist->vm_ops.add_sgi_source = vgic_v2_add_sgi_source;
2073 dist->vm_ops.init_model = vgic_v2_init_model; 2084 dist->vm_ops.init_model = vgic_v2_init_model;
2074 dist->vm_ops.map_resources = vgic_v2_map_resources; 2085 dist->vm_ops.map_resources = vgic_v2_map_resources;
2086
2087 kvm->arch.max_vcpus = VGIC_V2_MAX_CPUS;
2075} 2088}
2076 2089
2077static int init_vgic_model(struct kvm *kvm, int type) 2090static int init_vgic_model(struct kvm *kvm, int type)
@@ -2084,6 +2097,9 @@ static int init_vgic_model(struct kvm *kvm, int type)
2084 return -ENODEV; 2097 return -ENODEV;
2085 } 2098 }
2086 2099
2100 if (atomic_read(&kvm->online_vcpus) > kvm->arch.max_vcpus)
2101 return -E2BIG;
2102
2087 return 0; 2103 return 0;
2088} 2104}
2089 2105