summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
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