aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorChristoffer Dall2017-03-18 07:40:37 -0500
committerChristoffer Dall2017-04-09 09:49:11 -0500
commit966e0149196fe02c6d239f00162e9f92a5bbf3d5 (patch)
tree5af6090832d47c9d63ec421b821eca7515b9c427 /virt
parent096f31c4360f6bab130e3f68513719ec6890128c (diff)
downloadkernel-966e0149196fe02c6d239f00162e9f92a5bbf3d5.tar.gz
kernel-966e0149196fe02c6d239f00162e9f92a5bbf3d5.tar.xz
kernel-966e0149196fe02c6d239f00162e9f92a5bbf3d5.zip
KVM: arm/arm64: vgic: Implement early VGIC init functionality
Implement early initialization for both the distributor and the CPU interfaces. The basic idea is that even though the VGIC is not functional or not requested from user space, the critical path of the run loop can still call VGIC functions that just won't do anything, without them having to check additional initialization flags to ensure they don't look at uninitialized data structures. Acked-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <cdall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c96
1 files changed, 56 insertions, 40 deletions
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index e8e973b72ca5..87de048fe147 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -24,7 +24,12 @@
24 24
25/* 25/*
26 * Initialization rules: there are multiple stages to the vgic 26 * Initialization rules: there are multiple stages to the vgic
27 * initialization, both for the distributor and the CPU interfaces. 27 * initialization, both for the distributor and the CPU interfaces. The basic
28 * idea is that even though the VGIC is not functional or not requested from
29 * user space, the critical path of the run loop can still call VGIC functions
30 * that just won't do anything, without them having to check additional
31 * initialization flags to ensure they don't look at uninitialized data
32 * structures.
28 * 33 *
29 * Distributor: 34 * Distributor:
30 * 35 *
@@ -39,23 +44,67 @@
39 * 44 *
40 * CPU Interface: 45 * CPU Interface:
41 * 46 *
42 * - kvm_vgic_cpu_early_init(): initialization of static data that 47 * - kvm_vgic_vcpu_early_init(): initialization of static data that
43 * doesn't depend on any sizing information or emulation type. No 48 * doesn't depend on any sizing information or emulation type. No
44 * allocation is allowed there. 49 * allocation is allowed there.
45 */ 50 */
46 51
47/* EARLY INIT */ 52/* EARLY INIT */
48 53
49/* 54/**
50 * Those 2 functions should not be needed anymore but they 55 * kvm_vgic_early_init() - Initialize static VGIC VCPU data structures
51 * still are called from arm.c 56 * @kvm: The VM whose VGIC districutor should be initialized
57 *
58 * Only do initialization of static structures that don't require any
59 * allocation or sizing information from userspace. vgic_init() called
60 * kvm_vgic_dist_init() which takes care of the rest.
52 */ 61 */
53void kvm_vgic_early_init(struct kvm *kvm) 62void kvm_vgic_early_init(struct kvm *kvm)
54{ 63{
64 struct vgic_dist *dist = &kvm->arch.vgic;
65
66 INIT_LIST_HEAD(&dist->lpi_list_head);
67 spin_lock_init(&dist->lpi_list_lock);
55} 68}
56 69
70/**
71 * kvm_vgic_vcpu_early_init() - Initialize static VGIC VCPU data structures
72 * @vcpu: The VCPU whose VGIC data structures whould be initialized
73 *
74 * Only do initialization, but do not actually enable the VGIC CPU interface
75 * yet.
76 */
57void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu) 77void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
58{ 78{
79 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
80 int i;
81
82 INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
83 spin_lock_init(&vgic_cpu->ap_list_lock);
84
85 /*
86 * Enable and configure all SGIs to be edge-triggered and
87 * configure all PPIs as level-triggered.
88 */
89 for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
90 struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
91
92 INIT_LIST_HEAD(&irq->ap_list);
93 spin_lock_init(&irq->irq_lock);
94 irq->intid = i;
95 irq->vcpu = NULL;
96 irq->target_vcpu = vcpu;
97 irq->targets = 1U << vcpu->vcpu_id;
98 kref_init(&irq->refcount);
99 if (vgic_irq_is_sgi(i)) {
100 /* SGIs */
101 irq->enabled = 1;
102 irq->config = VGIC_CONFIG_EDGE;
103 } else {
104 /* PPIs */
105 irq->config = VGIC_CONFIG_LEVEL;
106 }
107 }
59} 108}
60 109
61/* CREATION */ 110/* CREATION */
@@ -148,9 +197,6 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
148 struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0); 197 struct kvm_vcpu *vcpu0 = kvm_get_vcpu(kvm, 0);
149 int i; 198 int i;
150 199
151 INIT_LIST_HEAD(&dist->lpi_list_head);
152 spin_lock_init(&dist->lpi_list_lock);
153
154 dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL); 200 dist->spis = kcalloc(nr_spis, sizeof(struct vgic_irq), GFP_KERNEL);
155 if (!dist->spis) 201 if (!dist->spis)
156 return -ENOMEM; 202 return -ENOMEM;
@@ -181,41 +227,11 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
181} 227}
182 228
183/** 229/**
184 * kvm_vgic_vcpu_init: initialize the vcpu data structures and 230 * kvm_vgic_vcpu_init() - Enable the VCPU interface
185 * enable the VCPU interface 231 * @vcpu: the VCPU which's VGIC should be enabled
186 * @vcpu: the VCPU which's VGIC should be initialized
187 */ 232 */
188static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) 233static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
189{ 234{
190 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
191 int i;
192
193 INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
194 spin_lock_init(&vgic_cpu->ap_list_lock);
195
196 /*
197 * Enable and configure all SGIs to be edge-triggered and
198 * configure all PPIs as level-triggered.
199 */
200 for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
201 struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
202
203 INIT_LIST_HEAD(&irq->ap_list);
204 spin_lock_init(&irq->irq_lock);
205 irq->intid = i;
206 irq->vcpu = NULL;
207 irq->target_vcpu = vcpu;
208 irq->targets = 1U << vcpu->vcpu_id;
209 kref_init(&irq->refcount);
210 if (vgic_irq_is_sgi(i)) {
211 /* SGIs */
212 irq->enabled = 1;
213 irq->config = VGIC_CONFIG_EDGE;
214 } else {
215 /* PPIs */
216 irq->config = VGIC_CONFIG_LEVEL;
217 }
218 }
219 if (kvm_vgic_global_state.type == VGIC_V2) 235 if (kvm_vgic_global_state.type == VGIC_V2)
220 vgic_v2_enable(vcpu); 236 vgic_v2_enable(vcpu);
221 else 237 else