blob: c794f0cef09e5f74a1b0af9cbfff8eb5623b01a2 [file] [log] [blame]
Marc Zyngier74fe55d2017-10-27 15:28:38 +01001/*
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}