summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-10-27 10:28:38 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2017-11-10 03:06:56 -0500
commit74fe55dc9ab77142e3c4783ecc5b87d494164452 (patch)
tree0d9f833e72d07b50f124127dba3dde6e982dd9df /virt
parente7c48059248e013772d8da69351ac8b262d8fce2 (diff)
KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
In order to control the GICv4 view of virtual CPUs, we rely on an irqdomain allocated for that purpose. Let's add a couple of helpers to that effect. At the same time, the vgic data structures gain new fields to track all this... erm... wonderful stuff. The way we hook into the vgic init is slightly convoluted. We need the vgic to be initialized (in order to guarantee that the number of vcpus is now fixed), and we must have a vITS (otherwise this is all very pointless). So we end-up calling the init from both vgic_init and vgic_its_create. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c9
-rw-r--r--virt/kvm/arm/vgic/vgic-its.c8
-rw-r--r--virt/kvm/arm/vgic/vgic-v4.c83
-rw-r--r--virt/kvm/arm/vgic/vgic.h2
4 files changed, 102 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 5801261f3add..40be908da238 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -285,6 +285,12 @@ int vgic_init(struct kvm *kvm)
285 if (ret) 285 if (ret)
286 goto out; 286 goto out;
287 287
288 if (vgic_supports_direct_msis(kvm)) {
289 ret = vgic_v4_init(kvm);
290 if (ret)
291 goto out;
292 }
293
288 kvm_for_each_vcpu(i, vcpu, kvm) 294 kvm_for_each_vcpu(i, vcpu, kvm)
289 kvm_vgic_vcpu_enable(vcpu); 295 kvm_vgic_vcpu_enable(vcpu);
290 296
@@ -320,6 +326,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
320 326
321 kfree(dist->spis); 327 kfree(dist->spis);
322 dist->nr_spis = 0; 328 dist->nr_spis = 0;
329
330 if (vgic_supports_direct_msis(kvm))
331 vgic_v4_teardown(kvm);
323} 332}
324 333
325void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu) 334void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 09accdfed189..54f81eb24a07 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1638,6 +1638,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
1638 if (!its) 1638 if (!its)
1639 return -ENOMEM; 1639 return -ENOMEM;
1640 1640
1641 if (vgic_initialized(dev->kvm)) {
1642 int ret = vgic_v4_init(dev->kvm);
1643 if (ret) {
1644 kfree(its);
1645 return ret;
1646 }
1647 }
1648
1641 mutex_init(&its->its_lock); 1649 mutex_init(&its->its_lock);
1642 mutex_init(&its->cmd_lock); 1650 mutex_init(&its->cmd_lock);
1643 1651
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
new file mode 100644
index 000000000000..c794f0cef09e
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -0,0 +1,83 @@
1/*
2 * Copyright (C) 2017 ARM Ltd.
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/interrupt.h>
19#include <linux/irqdomain.h>
20#include <linux/kvm_host.h>
21
22#include "vgic.h"
23
24/**
25 * vgic_v4_init - Initialize the GICv4 data structures
26 * @kvm: Pointer to the VM being initialized
27 *
28 * We may be called each time a vITS is created, or when the
29 * vgic is initialized. This relies on kvm->lock to be
30 * held. In both cases, the number of vcpus should now be
31 * fixed.
32 */
33int vgic_v4_init(struct kvm *kvm)
34{
35 struct vgic_dist *dist = &kvm->arch.vgic;
36 struct kvm_vcpu *vcpu;
37 int i, nr_vcpus, ret;
38
39 if (dist->its_vm.vpes)
40 return 0;
41
42 nr_vcpus = atomic_read(&kvm->online_vcpus);
43
44 dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
45 GFP_KERNEL);
46 if (!dist->its_vm.vpes)
47 return -ENOMEM;
48
49 dist->its_vm.nr_vpes = nr_vcpus;
50
51 kvm_for_each_vcpu(i, vcpu, kvm)
52 dist->its_vm.vpes[i] = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
53
54 ret = its_alloc_vcpu_irqs(&dist->its_vm);
55 if (ret < 0) {
56 kvm_err("VPE IRQ allocation failure\n");
57 kfree(dist->its_vm.vpes);
58 dist->its_vm.nr_vpes = 0;
59 dist->its_vm.vpes = NULL;
60 return ret;
61 }
62
63 return ret;
64}
65
66/**
67 * vgic_v4_teardown - Free the GICv4 data structures
68 * @kvm: Pointer to the VM being destroyed
69 *
70 * Relies on kvm->lock to be held.
71 */
72void vgic_v4_teardown(struct kvm *kvm)
73{
74 struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
75
76 if (!its_vm->vpes)
77 return;
78
79 its_free_vcpu_irqs(its_vm);
80 kfree(its_vm->vpes);
81 its_vm->nr_vpes = 0;
82 its_vm->vpes = NULL;
83}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 67509b203cf5..bf03a9648fbb 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -242,5 +242,7 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
242struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi); 242struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
243 243
244bool vgic_supports_direct_msis(struct kvm *kvm); 244bool vgic_supports_direct_msis(struct kvm *kvm);
245int vgic_v4_init(struct kvm *kvm);
246void vgic_v4_teardown(struct kvm *kvm);
245 247
246#endif 248#endif