diff options
| -rw-r--r-- | arch/arm/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/arm/kvm/arm.c | 8 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | include/kvm/arm_vgic.h | 8 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic-v2.c | 1 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic-v3.c | 1 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic.c | 16 |
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; |
| 136 | out_free_stage2_pgd: | 139 | out_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 | ||
| 137 | struct vgic_vm_ops { | 139 | struct vgic_vm_ops { |
| @@ -289,6 +291,7 @@ struct kvm_exit_mmio; | |||
| 289 | int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write); | 291 | int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write); |
| 290 | int kvm_vgic_hyp_init(void); | 292 | int kvm_vgic_hyp_init(void); |
| 291 | int kvm_vgic_map_resources(struct kvm *kvm); | 293 | int kvm_vgic_map_resources(struct kvm *kvm); |
| 294 | int kvm_vgic_get_max_vcpus(void); | ||
| 292 | int kvm_vgic_create(struct kvm *kvm, u32 type); | 295 | int kvm_vgic_create(struct kvm *kvm, u32 type); |
| 293 | void kvm_vgic_destroy(struct kvm *kvm); | 296 | void kvm_vgic_destroy(struct kvm *kvm); |
| 294 | void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu); | 297 | void 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 | |||
| 400 | static 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 | */ | ||
| 1887 | int kvm_vgic_get_max_vcpus(void) | ||
| 1888 | { | ||
| 1889 | return vgic->max_gic_vcpus; | ||
| 1890 | } | ||
| 1891 | |||
| 1881 | void kvm_vgic_destroy(struct kvm *kvm) | 1892 | void 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 | ||
| 2077 | static int init_vgic_model(struct kvm *kvm, int type) | 2090 | static 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 | ||
