Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
4493b1c4 MZ |
2 | /* |
3 | * VGIC MMIO handling functions | |
4493b1c4 MZ |
4 | */ |
5 | ||
6 | #include <linux/bitops.h> | |
7 | #include <linux/bsearch.h> | |
ef1820be MZ |
8 | #include <linux/interrupt.h> |
9 | #include <linux/irq.h> | |
4493b1c4 MZ |
10 | #include <linux/kvm.h> |
11 | #include <linux/kvm_host.h> | |
12 | #include <kvm/iodev.h> | |
df635c5b | 13 | #include <kvm/arm_arch_timer.h> |
4493b1c4 MZ |
14 | #include <kvm/arm_vgic.h> |
15 | ||
16 | #include "vgic.h" | |
17 | #include "vgic-mmio.h" | |
18 | ||
19 | unsigned long vgic_mmio_read_raz(struct kvm_vcpu *vcpu, | |
20 | gpa_t addr, unsigned int len) | |
21 | { | |
22 | return 0; | |
23 | } | |
24 | ||
25 | unsigned long vgic_mmio_read_rao(struct kvm_vcpu *vcpu, | |
26 | gpa_t addr, unsigned int len) | |
27 | { | |
28 | return -1UL; | |
29 | } | |
30 | ||
31 | void vgic_mmio_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, | |
32 | unsigned int len, unsigned long val) | |
33 | { | |
34 | /* Ignore */ | |
35 | } | |
36 | ||
c6e0917b CD |
37 | int vgic_mmio_uaccess_write_wi(struct kvm_vcpu *vcpu, gpa_t addr, |
38 | unsigned int len, unsigned long val) | |
39 | { | |
40 | /* Ignore */ | |
41 | return 0; | |
42 | } | |
43 | ||
d53c2c29 CD |
44 | unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu, |
45 | gpa_t addr, unsigned int len) | |
46 | { | |
47 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
48 | u32 value = 0; | |
49 | int i; | |
50 | ||
51 | /* Loop over all IRQs affected by this read */ | |
52 | for (i = 0; i < len * 8; i++) { | |
53 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
54 | ||
55 | if (irq->group) | |
56 | value |= BIT(i); | |
57 | ||
58 | vgic_put_irq(vcpu->kvm, irq); | |
59 | } | |
60 | ||
61 | return value; | |
62 | } | |
63 | ||
ef1820be MZ |
64 | static void vgic_update_vsgi(struct vgic_irq *irq) |
65 | { | |
66 | WARN_ON(its_prop_update_vsgi(irq->host_irq, irq->priority, irq->group)); | |
67 | } | |
68 | ||
d53c2c29 CD |
69 | void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr, |
70 | unsigned int len, unsigned long val) | |
71 | { | |
72 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
73 | int i; | |
74 | unsigned long flags; | |
75 | ||
76 | for (i = 0; i < len * 8; i++) { | |
77 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
78 | ||
8fa3adb8 | 79 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
d53c2c29 | 80 | irq->group = !!(val & BIT(i)); |
ef1820be MZ |
81 | if (irq->hw && vgic_irq_is_sgi(irq->intid)) { |
82 | vgic_update_vsgi(irq); | |
83 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); | |
84 | } else { | |
85 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); | |
86 | } | |
d53c2c29 CD |
87 | |
88 | vgic_put_irq(vcpu->kvm, irq); | |
89 | } | |
90 | } | |
91 | ||
fd122e62 AP |
92 | /* |
93 | * Read accesses to both GICD_ICENABLER and GICD_ISENABLER return the value | |
94 | * of the enabled bit, so there is only one function for both here. | |
95 | */ | |
96 | unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu, | |
97 | gpa_t addr, unsigned int len) | |
98 | { | |
99 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
100 | u32 value = 0; | |
101 | int i; | |
102 | ||
103 | /* Loop over all IRQs affected by this read */ | |
104 | for (i = 0; i < len * 8; i++) { | |
105 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
106 | ||
107 | if (irq->enabled) | |
108 | value |= (1U << i); | |
5dd4b924 AP |
109 | |
110 | vgic_put_irq(vcpu->kvm, irq); | |
fd122e62 AP |
111 | } |
112 | ||
113 | return value; | |
114 | } | |
115 | ||
116 | void vgic_mmio_write_senable(struct kvm_vcpu *vcpu, | |
117 | gpa_t addr, unsigned int len, | |
118 | unsigned long val) | |
119 | { | |
120 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
121 | int i; | |
006df0f3 | 122 | unsigned long flags; |
fd122e62 AP |
123 | |
124 | for_each_set_bit(i, &val, len * 8) { | |
125 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
126 | ||
8fa3adb8 | 127 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
ef1820be MZ |
128 | if (irq->hw && vgic_irq_is_sgi(irq->intid)) { |
129 | if (!irq->enabled) { | |
130 | struct irq_data *data; | |
131 | ||
132 | irq->enabled = true; | |
133 | data = &irq_to_desc(irq->host_irq)->irq_data; | |
134 | while (irqd_irq_disabled(data)) | |
135 | enable_irq(irq->host_irq); | |
136 | } | |
137 | ||
138 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); | |
139 | vgic_put_irq(vcpu->kvm, irq); | |
140 | ||
141 | continue; | |
142 | } else if (vgic_irq_is_mapped_level(irq)) { | |
16e604a4 AE |
143 | bool was_high = irq->line_level; |
144 | ||
145 | /* | |
146 | * We need to update the state of the interrupt because | |
147 | * the guest might have changed the state of the device | |
148 | * while the interrupt was disabled at the VGIC level. | |
149 | */ | |
150 | irq->line_level = vgic_get_phys_line_level(irq); | |
151 | /* | |
152 | * Deactivate the physical interrupt so the GIC will let | |
153 | * us know when it is asserted again. | |
154 | */ | |
155 | if (!irq->active && was_high && !irq->line_level) | |
156 | vgic_irq_set_phys_active(irq, false); | |
157 | } | |
fd122e62 | 158 | irq->enabled = true; |
006df0f3 | 159 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); |
5dd4b924 AP |
160 | |
161 | vgic_put_irq(vcpu->kvm, irq); | |
fd122e62 AP |
162 | } |
163 | } | |
164 | ||
165 | void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu, | |
166 | gpa_t addr, unsigned int len, | |
167 | unsigned long val) | |
168 | { | |
169 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
170 | int i; | |
006df0f3 | 171 | unsigned long flags; |
fd122e62 AP |
172 | |
173 | for_each_set_bit(i, &val, len * 8) { | |
174 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
175 | ||
8fa3adb8 | 176 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
ef1820be MZ |
177 | if (irq->hw && vgic_irq_is_sgi(irq->intid) && irq->enabled) |
178 | disable_irq_nosync(irq->host_irq); | |
fd122e62 AP |
179 | |
180 | irq->enabled = false; | |
181 | ||
8fa3adb8 | 182 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
5dd4b924 | 183 | vgic_put_irq(vcpu->kvm, irq); |
fd122e62 AP |
184 | } |
185 | } | |
186 | ||
41ee52ec MZ |
187 | int vgic_uaccess_write_senable(struct kvm_vcpu *vcpu, |
188 | gpa_t addr, unsigned int len, | |
189 | unsigned long val) | |
190 | { | |
191 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
192 | int i; | |
193 | unsigned long flags; | |
194 | ||
195 | for_each_set_bit(i, &val, len * 8) { | |
196 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
197 | ||
198 | raw_spin_lock_irqsave(&irq->irq_lock, flags); | |
199 | irq->enabled = true; | |
200 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); | |
201 | ||
202 | vgic_put_irq(vcpu->kvm, irq); | |
203 | } | |
204 | ||
205 | return 0; | |
206 | } | |
207 | ||
208 | int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, | |
209 | gpa_t addr, unsigned int len, | |
210 | unsigned long val) | |
211 | { | |
212 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
213 | int i; | |
214 | unsigned long flags; | |
215 | ||
216 | for_each_set_bit(i, &val, len * 8) { | |
217 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
218 | ||
219 | raw_spin_lock_irqsave(&irq->irq_lock, flags); | |
220 | irq->enabled = false; | |
221 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); | |
222 | ||
223 | vgic_put_irq(vcpu->kvm, irq); | |
224 | } | |
225 | ||
226 | return 0; | |
227 | } | |
228 | ||
96b29800 AP |
229 | unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, |
230 | gpa_t addr, unsigned int len) | |
231 | { | |
232 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
233 | u32 value = 0; | |
234 | int i; | |
235 | ||
236 | /* Loop over all IRQs affected by this read */ | |
237 | for (i = 0; i < len * 8; i++) { | |
238 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
62b06f8f | 239 | unsigned long flags; |
ef1820be | 240 | bool val; |
96b29800 | 241 | |
8fa3adb8 | 242 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
ef1820be MZ |
243 | if (irq->hw && vgic_irq_is_sgi(irq->intid)) { |
244 | int err; | |
245 | ||
246 | val = false; | |
247 | err = irq_get_irqchip_state(irq->host_irq, | |
248 | IRQCHIP_STATE_PENDING, | |
249 | &val); | |
250 | WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); | |
251 | } else { | |
252 | val = irq_is_pending(irq); | |
253 | } | |
254 | ||
255 | value |= ((u32)val << i); | |
8fa3adb8 | 256 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
5dd4b924 AP |
257 | |
258 | vgic_put_irq(vcpu->kvm, irq); | |
96b29800 AP |
259 | } |
260 | ||
261 | return value; | |
262 | } | |
263 | ||
82e40f55 MZ |
264 | static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq) |
265 | { | |
266 | return (vgic_irq_is_sgi(irq->intid) && | |
267 | vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2); | |
268 | } | |
269 | ||
96b29800 AP |
270 | void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, |
271 | gpa_t addr, unsigned int len, | |
272 | unsigned long val) | |
273 | { | |
274 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
275 | int i; | |
006df0f3 | 276 | unsigned long flags; |
96b29800 AP |
277 | |
278 | for_each_set_bit(i, &val, len * 8) { | |
279 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
280 | ||
82e40f55 MZ |
281 | /* GICD_ISPENDR0 SGI bits are WI */ |
282 | if (is_vgic_v2_sgi(vcpu, irq)) { | |
283 | vgic_put_irq(vcpu->kvm, irq); | |
284 | continue; | |
285 | } | |
286 | ||
8fa3adb8 | 287 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
ef1820be MZ |
288 | |
289 | if (irq->hw && vgic_irq_is_sgi(irq->intid)) { | |
290 | /* HW SGI? Ask the GIC to inject it */ | |
291 | int err; | |
292 | err = irq_set_irqchip_state(irq->host_irq, | |
293 | IRQCHIP_STATE_PENDING, | |
294 | true); | |
295 | WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); | |
296 | ||
297 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); | |
298 | vgic_put_irq(vcpu->kvm, irq); | |
299 | ||
300 | continue; | |
301 | } | |
302 | ||
ba1ed9e1 | 303 | irq->pending_latch = true; |
df635c5b | 304 | if (irq->hw) |
ba1ed9e1 MZ |
305 | vgic_irq_set_phys_active(irq, true); |
306 | ||
006df0f3 | 307 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); |
5dd4b924 | 308 | vgic_put_irq(vcpu->kvm, irq); |
96b29800 AP |
309 | } |
310 | } | |
311 | ||
ba1ed9e1 MZ |
312 | int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu, |
313 | gpa_t addr, unsigned int len, | |
314 | unsigned long val) | |
df635c5b | 315 | { |
ba1ed9e1 MZ |
316 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); |
317 | int i; | |
318 | unsigned long flags; | |
df635c5b | 319 | |
ba1ed9e1 MZ |
320 | for_each_set_bit(i, &val, len * 8) { |
321 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
322 | ||
323 | raw_spin_lock_irqsave(&irq->irq_lock, flags); | |
324 | irq->pending_latch = true; | |
325 | ||
326 | /* | |
327 | * GICv2 SGIs are terribly broken. We can't restore | |
328 | * the source of the interrupt, so just pick the vcpu | |
329 | * itself as the source... | |
330 | */ | |
331 | if (is_vgic_v2_sgi(vcpu, irq)) | |
332 | irq->source |= BIT(vcpu->vcpu_id); | |
333 | ||
334 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); | |
335 | ||
336 | vgic_put_irq(vcpu->kvm, irq); | |
337 | } | |
338 | ||
339 | return 0; | |
340 | } | |
341 | ||
342 | /* Must be called with irq->irq_lock held */ | |
343 | static void vgic_hw_irq_cpending(struct kvm_vcpu *vcpu, struct vgic_irq *irq) | |
344 | { | |
df635c5b CD |
345 | irq->pending_latch = false; |
346 | ||
347 | /* | |
348 | * We don't want the guest to effectively mask the physical | |
349 | * interrupt by doing a write to SPENDR followed by a write to | |
350 | * CPENDR for HW interrupts, so we clear the active state on | |
351 | * the physical side if the virtual interrupt is not active. | |
352 | * This may lead to taking an additional interrupt on the | |
353 | * host, but that should not be a problem as the worst that | |
354 | * can happen is an additional vgic injection. We also clear | |
355 | * the pending state to maintain proper semantics for edge HW | |
356 | * interrupts. | |
357 | */ | |
358 | vgic_irq_set_phys_pending(irq, false); | |
359 | if (!irq->active) | |
360 | vgic_irq_set_phys_active(irq, false); | |
361 | } | |
362 | ||
96b29800 AP |
363 | void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu, |
364 | gpa_t addr, unsigned int len, | |
365 | unsigned long val) | |
366 | { | |
367 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
368 | int i; | |
006df0f3 | 369 | unsigned long flags; |
96b29800 AP |
370 | |
371 | for_each_set_bit(i, &val, len * 8) { | |
372 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
373 | ||
82e40f55 MZ |
374 | /* GICD_ICPENDR0 SGI bits are WI */ |
375 | if (is_vgic_v2_sgi(vcpu, irq)) { | |
376 | vgic_put_irq(vcpu->kvm, irq); | |
377 | continue; | |
378 | } | |
379 | ||
8fa3adb8 | 380 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
96b29800 | 381 | |
ef1820be MZ |
382 | if (irq->hw && vgic_irq_is_sgi(irq->intid)) { |
383 | /* HW SGI? Ask the GIC to clear its pending bit */ | |
384 | int err; | |
385 | err = irq_set_irqchip_state(irq->host_irq, | |
386 | IRQCHIP_STATE_PENDING, | |
387 | false); | |
388 | WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); | |
389 | ||
390 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); | |
391 | vgic_put_irq(vcpu->kvm, irq); | |
392 | ||
393 | continue; | |
394 | } | |
395 | ||
df635c5b | 396 | if (irq->hw) |
ba1ed9e1 | 397 | vgic_hw_irq_cpending(vcpu, irq); |
df635c5b CD |
398 | else |
399 | irq->pending_latch = false; | |
96b29800 | 400 | |
8fa3adb8 | 401 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
5dd4b924 | 402 | vgic_put_irq(vcpu->kvm, irq); |
96b29800 AP |
403 | } |
404 | } | |
405 | ||
ba1ed9e1 MZ |
406 | int vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu, |
407 | gpa_t addr, unsigned int len, | |
408 | unsigned long val) | |
409 | { | |
410 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
411 | int i; | |
412 | unsigned long flags; | |
413 | ||
414 | for_each_set_bit(i, &val, len * 8) { | |
415 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
416 | ||
417 | raw_spin_lock_irqsave(&irq->irq_lock, flags); | |
418 | /* | |
419 | * More fun with GICv2 SGIs! If we're clearing one of them | |
420 | * from userspace, which source vcpu to clear? Let's not | |
421 | * even think of it, and blow the whole set. | |
422 | */ | |
423 | if (is_vgic_v2_sgi(vcpu, irq)) | |
424 | irq->source = 0; | |
425 | ||
426 | irq->pending_latch = false; | |
427 | ||
428 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); | |
429 | ||
430 | vgic_put_irq(vcpu->kvm, irq); | |
431 | } | |
432 | ||
433 | return 0; | |
434 | } | |
9a50ebbf MZ |
435 | |
436 | /* | |
437 | * If we are fiddling with an IRQ's active state, we have to make sure the IRQ | |
438 | * is not queued on some running VCPU's LRs, because then the change to the | |
439 | * active state can be overwritten when the VCPU's state is synced coming back | |
440 | * from the guest. | |
441 | * | |
442 | * For shared interrupts as well as GICv3 private interrupts, we have to | |
443 | * stop all the VCPUs because interrupts can be migrated while we don't hold | |
444 | * the IRQ locks and we don't want to be chasing moving targets. | |
445 | * | |
446 | * For GICv2 private interrupts we don't have to do anything because | |
447 | * userspace accesses to the VGIC state already require all VCPUs to be | |
448 | * stopped, and only the VCPU itself can modify its private interrupts | |
449 | * active state, which guarantees that the VCPU is not running. | |
450 | */ | |
451 | static void vgic_access_active_prepare(struct kvm_vcpu *vcpu, u32 intid) | |
452 | { | |
453 | if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 || | |
454 | intid >= VGIC_NR_PRIVATE_IRQS) | |
455 | kvm_arm_halt_guest(vcpu->kvm); | |
456 | } | |
457 | ||
458 | /* See vgic_access_active_prepare */ | |
459 | static void vgic_access_active_finish(struct kvm_vcpu *vcpu, u32 intid) | |
460 | { | |
461 | if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 || | |
462 | intid >= VGIC_NR_PRIVATE_IRQS) | |
463 | kvm_arm_resume_guest(vcpu->kvm); | |
464 | } | |
465 | ||
466 | static unsigned long __vgic_mmio_read_active(struct kvm_vcpu *vcpu, | |
467 | gpa_t addr, unsigned int len) | |
69b6fe0c AP |
468 | { |
469 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
470 | u32 value = 0; | |
471 | int i; | |
472 | ||
473 | /* Loop over all IRQs affected by this read */ | |
474 | for (i = 0; i < len * 8; i++) { | |
475 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
476 | ||
9a50ebbf MZ |
477 | /* |
478 | * Even for HW interrupts, don't evaluate the HW state as | |
479 | * all the guest is interested in is the virtual state. | |
480 | */ | |
69b6fe0c AP |
481 | if (irq->active) |
482 | value |= (1U << i); | |
5dd4b924 AP |
483 | |
484 | vgic_put_irq(vcpu->kvm, irq); | |
69b6fe0c AP |
485 | } |
486 | ||
487 | return value; | |
488 | } | |
489 | ||
9a50ebbf MZ |
490 | unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu, |
491 | gpa_t addr, unsigned int len) | |
492 | { | |
493 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
494 | u32 val; | |
495 | ||
496 | mutex_lock(&vcpu->kvm->lock); | |
497 | vgic_access_active_prepare(vcpu, intid); | |
498 | ||
499 | val = __vgic_mmio_read_active(vcpu, addr, len); | |
500 | ||
501 | vgic_access_active_finish(vcpu, intid); | |
502 | mutex_unlock(&vcpu->kvm->lock); | |
503 | ||
504 | return val; | |
505 | } | |
506 | ||
507 | unsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu, | |
508 | gpa_t addr, unsigned int len) | |
509 | { | |
510 | return __vgic_mmio_read_active(vcpu, addr, len); | |
511 | } | |
512 | ||
df635c5b CD |
513 | /* Must be called with irq->irq_lock held */ |
514 | static void vgic_hw_irq_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq, | |
515 | bool active, bool is_uaccess) | |
516 | { | |
517 | if (is_uaccess) | |
518 | return; | |
519 | ||
520 | irq->active = active; | |
521 | vgic_irq_set_phys_active(irq, active); | |
522 | } | |
523 | ||
35a2d585 | 524 | static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq, |
df635c5b | 525 | bool active) |
35a2d585 | 526 | { |
006df0f3 | 527 | unsigned long flags; |
7495e22b | 528 | struct kvm_vcpu *requester_vcpu = kvm_get_running_vcpu(); |
370a0ec1 | 529 | |
8fa3adb8 | 530 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
370a0ec1 | 531 | |
ef1820be | 532 | if (irq->hw && !vgic_irq_is_sgi(irq->intid)) { |
df635c5b | 533 | vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu); |
ef1820be MZ |
534 | } else if (irq->hw && vgic_irq_is_sgi(irq->intid)) { |
535 | /* | |
536 | * GICv4.1 VSGI feature doesn't track an active state, | |
537 | * so let's not kid ourselves, there is nothing we can | |
538 | * do here. | |
539 | */ | |
540 | irq->active = false; | |
53692908 MZ |
541 | } else { |
542 | u32 model = vcpu->kvm->arch.vgic.vgic_model; | |
60c3ab30 | 543 | u8 active_source; |
53692908 | 544 | |
df635c5b | 545 | irq->active = active; |
60c3ab30 CD |
546 | |
547 | /* | |
548 | * The GICv2 architecture indicates that the source CPUID for | |
549 | * an SGI should be provided during an EOI which implies that | |
550 | * the active state is stored somewhere, but at the same time | |
551 | * this state is not architecturally exposed anywhere and we | |
552 | * have no way of knowing the right source. | |
553 | * | |
554 | * This may lead to a VCPU not being able to receive | |
555 | * additional instances of a particular SGI after migration | |
556 | * for a GICv2 VM on some GIC implementations. Oh well. | |
557 | */ | |
558 | active_source = (requester_vcpu) ? requester_vcpu->vcpu_id : 0; | |
559 | ||
53692908 MZ |
560 | if (model == KVM_DEV_TYPE_ARM_VGIC_V2 && |
561 | active && vgic_irq_is_sgi(irq->intid)) | |
60c3ab30 | 562 | irq->active_source = active_source; |
53692908 | 563 | } |
df635c5b CD |
564 | |
565 | if (irq->active) | |
006df0f3 | 566 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); |
35a2d585 | 567 | else |
8fa3adb8 | 568 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
35a2d585 CD |
569 | } |
570 | ||
3197191e CD |
571 | static void __vgic_mmio_write_cactive(struct kvm_vcpu *vcpu, |
572 | gpa_t addr, unsigned int len, | |
573 | unsigned long val) | |
69b6fe0c AP |
574 | { |
575 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
576 | int i; | |
577 | ||
69b6fe0c AP |
578 | for_each_set_bit(i, &val, len * 8) { |
579 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
35a2d585 | 580 | vgic_mmio_change_active(vcpu, irq, false); |
5dd4b924 | 581 | vgic_put_irq(vcpu->kvm, irq); |
69b6fe0c | 582 | } |
69b6fe0c AP |
583 | } |
584 | ||
3197191e | 585 | void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu, |
69b6fe0c AP |
586 | gpa_t addr, unsigned int len, |
587 | unsigned long val) | |
588 | { | |
589 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
69b6fe0c | 590 | |
abd72296 | 591 | mutex_lock(&vcpu->kvm->lock); |
9a50ebbf | 592 | vgic_access_active_prepare(vcpu, intid); |
3197191e CD |
593 | |
594 | __vgic_mmio_write_cactive(vcpu, addr, len, val); | |
595 | ||
9a50ebbf | 596 | vgic_access_active_finish(vcpu, intid); |
abd72296 | 597 | mutex_unlock(&vcpu->kvm->lock); |
3197191e CD |
598 | } |
599 | ||
c6e0917b | 600 | int vgic_mmio_uaccess_write_cactive(struct kvm_vcpu *vcpu, |
3197191e CD |
601 | gpa_t addr, unsigned int len, |
602 | unsigned long val) | |
603 | { | |
604 | __vgic_mmio_write_cactive(vcpu, addr, len, val); | |
c6e0917b | 605 | return 0; |
3197191e CD |
606 | } |
607 | ||
608 | static void __vgic_mmio_write_sactive(struct kvm_vcpu *vcpu, | |
609 | gpa_t addr, unsigned int len, | |
610 | unsigned long val) | |
611 | { | |
612 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
613 | int i; | |
614 | ||
69b6fe0c AP |
615 | for_each_set_bit(i, &val, len * 8) { |
616 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
35a2d585 | 617 | vgic_mmio_change_active(vcpu, irq, true); |
5dd4b924 | 618 | vgic_put_irq(vcpu->kvm, irq); |
69b6fe0c | 619 | } |
3197191e CD |
620 | } |
621 | ||
622 | void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu, | |
623 | gpa_t addr, unsigned int len, | |
624 | unsigned long val) | |
625 | { | |
626 | u32 intid = VGIC_ADDR_TO_INTID(addr, 1); | |
627 | ||
abd72296 | 628 | mutex_lock(&vcpu->kvm->lock); |
9a50ebbf | 629 | vgic_access_active_prepare(vcpu, intid); |
3197191e CD |
630 | |
631 | __vgic_mmio_write_sactive(vcpu, addr, len, val); | |
632 | ||
9a50ebbf | 633 | vgic_access_active_finish(vcpu, intid); |
abd72296 | 634 | mutex_unlock(&vcpu->kvm->lock); |
69b6fe0c AP |
635 | } |
636 | ||
c6e0917b | 637 | int vgic_mmio_uaccess_write_sactive(struct kvm_vcpu *vcpu, |
3197191e CD |
638 | gpa_t addr, unsigned int len, |
639 | unsigned long val) | |
640 | { | |
641 | __vgic_mmio_write_sactive(vcpu, addr, len, val); | |
c6e0917b | 642 | return 0; |
3197191e CD |
643 | } |
644 | ||
055658bf AP |
645 | unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu, |
646 | gpa_t addr, unsigned int len) | |
647 | { | |
648 | u32 intid = VGIC_ADDR_TO_INTID(addr, 8); | |
649 | int i; | |
650 | u64 val = 0; | |
651 | ||
652 | for (i = 0; i < len; i++) { | |
653 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
654 | ||
655 | val |= (u64)irq->priority << (i * 8); | |
5dd4b924 AP |
656 | |
657 | vgic_put_irq(vcpu->kvm, irq); | |
055658bf AP |
658 | } |
659 | ||
660 | return val; | |
661 | } | |
662 | ||
663 | /* | |
664 | * We currently don't handle changing the priority of an interrupt that | |
665 | * is already pending on a VCPU. If there is a need for this, we would | |
666 | * need to make this VCPU exit and re-evaluate the priorities, potentially | |
667 | * leading to this interrupt getting presented now to the guest (if it has | |
668 | * been masked by the priority mask before). | |
669 | */ | |
670 | void vgic_mmio_write_priority(struct kvm_vcpu *vcpu, | |
671 | gpa_t addr, unsigned int len, | |
672 | unsigned long val) | |
673 | { | |
674 | u32 intid = VGIC_ADDR_TO_INTID(addr, 8); | |
675 | int i; | |
006df0f3 | 676 | unsigned long flags; |
055658bf AP |
677 | |
678 | for (i = 0; i < len; i++) { | |
679 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
680 | ||
8fa3adb8 | 681 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
055658bf AP |
682 | /* Narrow the priority range to what we actually support */ |
683 | irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS); | |
ef1820be MZ |
684 | if (irq->hw && vgic_irq_is_sgi(irq->intid)) |
685 | vgic_update_vsgi(irq); | |
8fa3adb8 | 686 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
5dd4b924 AP |
687 | |
688 | vgic_put_irq(vcpu->kvm, irq); | |
055658bf AP |
689 | } |
690 | } | |
691 | ||
79717e4a AP |
692 | unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu, |
693 | gpa_t addr, unsigned int len) | |
694 | { | |
695 | u32 intid = VGIC_ADDR_TO_INTID(addr, 2); | |
696 | u32 value = 0; | |
697 | int i; | |
698 | ||
699 | for (i = 0; i < len * 4; i++) { | |
700 | struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
701 | ||
702 | if (irq->config == VGIC_CONFIG_EDGE) | |
703 | value |= (2U << (i * 2)); | |
5dd4b924 AP |
704 | |
705 | vgic_put_irq(vcpu->kvm, irq); | |
79717e4a AP |
706 | } |
707 | ||
708 | return value; | |
709 | } | |
710 | ||
711 | void vgic_mmio_write_config(struct kvm_vcpu *vcpu, | |
712 | gpa_t addr, unsigned int len, | |
713 | unsigned long val) | |
714 | { | |
715 | u32 intid = VGIC_ADDR_TO_INTID(addr, 2); | |
716 | int i; | |
006df0f3 | 717 | unsigned long flags; |
79717e4a AP |
718 | |
719 | for (i = 0; i < len * 4; i++) { | |
5dd4b924 | 720 | struct vgic_irq *irq; |
79717e4a AP |
721 | |
722 | /* | |
723 | * The configuration cannot be changed for SGIs in general, | |
724 | * for PPIs this is IMPLEMENTATION DEFINED. The arch timer | |
725 | * code relies on PPIs being level triggered, so we also | |
726 | * make them read-only here. | |
727 | */ | |
728 | if (intid + i < VGIC_NR_PRIVATE_IRQS) | |
729 | continue; | |
730 | ||
5dd4b924 | 731 | irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); |
8fa3adb8 | 732 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
5dd4b924 | 733 | |
8694e4da | 734 | if (test_bit(i * 2 + 1, &val)) |
79717e4a | 735 | irq->config = VGIC_CONFIG_EDGE; |
8694e4da | 736 | else |
79717e4a | 737 | irq->config = VGIC_CONFIG_LEVEL; |
5dd4b924 | 738 | |
8fa3adb8 | 739 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
5dd4b924 | 740 | vgic_put_irq(vcpu->kvm, irq); |
79717e4a AP |
741 | } |
742 | } | |
743 | ||
e96a006c VK |
744 | u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid) |
745 | { | |
746 | int i; | |
747 | u64 val = 0; | |
748 | int nr_irqs = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS; | |
749 | ||
750 | for (i = 0; i < 32; i++) { | |
751 | struct vgic_irq *irq; | |
752 | ||
753 | if ((intid + i) < VGIC_NR_SGIS || (intid + i) >= nr_irqs) | |
754 | continue; | |
755 | ||
756 | irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
757 | if (irq->config == VGIC_CONFIG_LEVEL && irq->line_level) | |
758 | val |= (1U << i); | |
759 | ||
760 | vgic_put_irq(vcpu->kvm, irq); | |
761 | } | |
762 | ||
763 | return val; | |
764 | } | |
765 | ||
766 | void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid, | |
767 | const u64 val) | |
768 | { | |
769 | int i; | |
770 | int nr_irqs = vcpu->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS; | |
006df0f3 | 771 | unsigned long flags; |
e96a006c VK |
772 | |
773 | for (i = 0; i < 32; i++) { | |
774 | struct vgic_irq *irq; | |
775 | bool new_level; | |
776 | ||
777 | if ((intid + i) < VGIC_NR_SGIS || (intid + i) >= nr_irqs) | |
778 | continue; | |
779 | ||
780 | irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); | |
781 | ||
782 | /* | |
783 | * Line level is set irrespective of irq type | |
784 | * (level or edge) to avoid dependency that VM should | |
785 | * restore irq config before line level. | |
786 | */ | |
787 | new_level = !!(val & (1U << i)); | |
8fa3adb8 | 788 | raw_spin_lock_irqsave(&irq->irq_lock, flags); |
e96a006c VK |
789 | irq->line_level = new_level; |
790 | if (new_level) | |
006df0f3 | 791 | vgic_queue_irq_unlock(vcpu->kvm, irq, flags); |
e96a006c | 792 | else |
8fa3adb8 | 793 | raw_spin_unlock_irqrestore(&irq->irq_lock, flags); |
e96a006c VK |
794 | |
795 | vgic_put_irq(vcpu->kvm, irq); | |
796 | } | |
797 | } | |
798 | ||
4493b1c4 MZ |
799 | static int match_region(const void *key, const void *elt) |
800 | { | |
801 | const unsigned int offset = (unsigned long)key; | |
802 | const struct vgic_register_region *region = elt; | |
803 | ||
804 | if (offset < region->reg_offset) | |
805 | return -1; | |
806 | ||
807 | if (offset >= region->reg_offset + region->len) | |
808 | return 1; | |
809 | ||
810 | return 0; | |
811 | } | |
812 | ||
4b7171ac EA |
813 | const struct vgic_register_region * |
814 | vgic_find_mmio_region(const struct vgic_register_region *regions, | |
815 | int nr_regions, unsigned int offset) | |
4493b1c4 | 816 | { |
4b7171ac EA |
817 | return bsearch((void *)(uintptr_t)offset, regions, nr_regions, |
818 | sizeof(regions[0]), match_region); | |
4493b1c4 MZ |
819 | } |
820 | ||
5fb247d7 VK |
821 | void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) |
822 | { | |
823 | if (kvm_vgic_global_state.type == VGIC_V2) | |
824 | vgic_v2_set_vmcr(vcpu, vmcr); | |
825 | else | |
826 | vgic_v3_set_vmcr(vcpu, vmcr); | |
827 | } | |
828 | ||
829 | void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr) | |
830 | { | |
831 | if (kvm_vgic_global_state.type == VGIC_V2) | |
832 | vgic_v2_get_vmcr(vcpu, vmcr); | |
833 | else | |
834 | vgic_v3_get_vmcr(vcpu, vmcr); | |
835 | } | |
836 | ||
4493b1c4 MZ |
837 | /* |
838 | * kvm_mmio_read_buf() returns a value in a format where it can be converted | |
839 | * to a byte array and be directly observed as the guest wanted it to appear | |
840 | * in memory if it had done the store itself, which is LE for the GIC, as the | |
841 | * guest knows the GIC is always LE. | |
842 | * | |
843 | * We convert this value to the CPUs native format to deal with it as a data | |
844 | * value. | |
845 | */ | |
846 | unsigned long vgic_data_mmio_bus_to_host(const void *val, unsigned int len) | |
847 | { | |
848 | unsigned long data = kvm_mmio_read_buf(val, len); | |
849 | ||
850 | switch (len) { | |
851 | case 1: | |
852 | return data; | |
853 | case 2: | |
854 | return le16_to_cpu(data); | |
855 | case 4: | |
856 | return le32_to_cpu(data); | |
857 | default: | |
858 | return le64_to_cpu(data); | |
859 | } | |
860 | } | |
861 | ||
862 | /* | |
863 | * kvm_mmio_write_buf() expects a value in a format such that if converted to | |
864 | * a byte array it is observed as the guest would see it if it could perform | |
865 | * the load directly. Since the GIC is LE, and the guest knows this, the | |
866 | * guest expects a value in little endian format. | |
867 | * | |
868 | * We convert the data value from the CPUs native format to LE so that the | |
869 | * value is returned in the proper format. | |
870 | */ | |
871 | void vgic_data_host_to_mmio_bus(void *buf, unsigned int len, | |
872 | unsigned long data) | |
873 | { | |
874 | switch (len) { | |
875 | case 1: | |
876 | break; | |
877 | case 2: | |
878 | data = cpu_to_le16(data); | |
879 | break; | |
880 | case 4: | |
881 | data = cpu_to_le32(data); | |
882 | break; | |
883 | default: | |
884 | data = cpu_to_le64(data); | |
885 | } | |
886 | ||
887 | kvm_mmio_write_buf(buf, len, data); | |
888 | } | |
889 | ||
890 | static | |
891 | struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev) | |
892 | { | |
893 | return container_of(dev, struct vgic_io_device, dev); | |
894 | } | |
895 | ||
112b0b8f AP |
896 | static bool check_region(const struct kvm *kvm, |
897 | const struct vgic_register_region *region, | |
4493b1c4 MZ |
898 | gpa_t addr, int len) |
899 | { | |
112b0b8f AP |
900 | int flags, nr_irqs = kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS; |
901 | ||
902 | switch (len) { | |
903 | case sizeof(u8): | |
904 | flags = VGIC_ACCESS_8bit; | |
905 | break; | |
906 | case sizeof(u32): | |
907 | flags = VGIC_ACCESS_32bit; | |
908 | break; | |
909 | case sizeof(u64): | |
910 | flags = VGIC_ACCESS_64bit; | |
911 | break; | |
912 | default: | |
913 | return false; | |
914 | } | |
915 | ||
916 | if ((region->access_flags & flags) && IS_ALIGNED(addr, len)) { | |
917 | if (!region->bits_per_irq) | |
918 | return true; | |
919 | ||
920 | /* Do we access a non-allocated IRQ? */ | |
921 | return VGIC_ADDR_TO_INTID(addr, region->bits_per_irq) < nr_irqs; | |
922 | } | |
4493b1c4 MZ |
923 | |
924 | return false; | |
925 | } | |
926 | ||
94574c94 | 927 | const struct vgic_register_region * |
2df903a8 VK |
928 | vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev, |
929 | gpa_t addr, int len) | |
930 | { | |
931 | const struct vgic_register_region *region; | |
932 | ||
933 | region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions, | |
934 | addr - iodev->base_addr); | |
935 | if (!region || !check_region(vcpu->kvm, region, addr, len)) | |
936 | return NULL; | |
937 | ||
938 | return region; | |
939 | } | |
940 | ||
941 | static int vgic_uaccess_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, | |
942 | gpa_t addr, u32 *val) | |
943 | { | |
944 | struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev); | |
945 | const struct vgic_register_region *region; | |
946 | struct kvm_vcpu *r_vcpu; | |
947 | ||
948 | region = vgic_get_mmio_region(vcpu, iodev, addr, sizeof(u32)); | |
949 | if (!region) { | |
950 | *val = 0; | |
951 | return 0; | |
952 | } | |
953 | ||
954 | r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu; | |
955 | if (region->uaccess_read) | |
956 | *val = region->uaccess_read(r_vcpu, addr, sizeof(u32)); | |
957 | else | |
958 | *val = region->read(r_vcpu, addr, sizeof(u32)); | |
959 | ||
960 | return 0; | |
961 | } | |
962 | ||
963 | static int vgic_uaccess_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, | |
964 | gpa_t addr, const u32 *val) | |
965 | { | |
966 | struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev); | |
967 | const struct vgic_register_region *region; | |
968 | struct kvm_vcpu *r_vcpu; | |
969 | ||
970 | region = vgic_get_mmio_region(vcpu, iodev, addr, sizeof(u32)); | |
971 | if (!region) | |
972 | return 0; | |
973 | ||
974 | r_vcpu = iodev->redist_vcpu ? iodev->redist_vcpu : vcpu; | |
975 | if (region->uaccess_write) | |
c6e0917b | 976 | return region->uaccess_write(r_vcpu, addr, sizeof(u32), *val); |
2df903a8 | 977 | |
c6e0917b | 978 | region->write(r_vcpu, addr, sizeof(u32), *val); |
2df903a8 VK |
979 | return 0; |
980 | } | |
981 | ||
982 | /* | |
983 | * Userland access to VGIC registers. | |
984 | */ | |
985 | int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev, | |
986 | bool is_write, int offset, u32 *val) | |
987 | { | |
988 | if (is_write) | |
989 | return vgic_uaccess_write(vcpu, &dev->dev, offset, val); | |
990 | else | |
991 | return vgic_uaccess_read(vcpu, &dev->dev, offset, val); | |
992 | } | |
993 | ||
4493b1c4 MZ |
994 | static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, |
995 | gpa_t addr, int len, void *val) | |
996 | { | |
997 | struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev); | |
998 | const struct vgic_register_region *region; | |
59c5ab40 | 999 | unsigned long data = 0; |
4493b1c4 | 1000 | |
2df903a8 VK |
1001 | region = vgic_get_mmio_region(vcpu, iodev, addr, len); |
1002 | if (!region) { | |
4493b1c4 MZ |
1003 | memset(val, 0, len); |
1004 | return 0; | |
1005 | } | |
1006 | ||
59c5ab40 AP |
1007 | switch (iodev->iodev_type) { |
1008 | case IODEV_CPUIF: | |
9d5fcb9d EA |
1009 | data = region->read(vcpu, addr, len); |
1010 | break; | |
59c5ab40 AP |
1011 | case IODEV_DIST: |
1012 | data = region->read(vcpu, addr, len); | |
1013 | break; | |
1014 | case IODEV_REDIST: | |
1015 | data = region->read(iodev->redist_vcpu, addr, len); | |
1016 | break; | |
1017 | case IODEV_ITS: | |
1018 | data = region->its_read(vcpu->kvm, iodev->its, addr, len); | |
1019 | break; | |
1020 | } | |
1021 | ||
4493b1c4 MZ |
1022 | vgic_data_host_to_mmio_bus(val, len, data); |
1023 | return 0; | |
1024 | } | |
1025 | ||
1026 | static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev, | |
1027 | gpa_t addr, int len, const void *val) | |
1028 | { | |
1029 | struct vgic_io_device *iodev = kvm_to_vgic_iodev(dev); | |
1030 | const struct vgic_register_region *region; | |
4493b1c4 MZ |
1031 | unsigned long data = vgic_data_mmio_bus_to_host(val, len); |
1032 | ||
2df903a8 VK |
1033 | region = vgic_get_mmio_region(vcpu, iodev, addr, len); |
1034 | if (!region) | |
4493b1c4 MZ |
1035 | return 0; |
1036 | ||
59c5ab40 AP |
1037 | switch (iodev->iodev_type) { |
1038 | case IODEV_CPUIF: | |
9d5fcb9d | 1039 | region->write(vcpu, addr, len, data); |
59c5ab40 AP |
1040 | break; |
1041 | case IODEV_DIST: | |
1042 | region->write(vcpu, addr, len, data); | |
1043 | break; | |
1044 | case IODEV_REDIST: | |
1045 | region->write(iodev->redist_vcpu, addr, len, data); | |
1046 | break; | |
1047 | case IODEV_ITS: | |
1048 | region->its_write(vcpu->kvm, iodev->its, addr, len, data); | |
1049 | break; | |
1050 | } | |
1051 | ||
4493b1c4 MZ |
1052 | return 0; |
1053 | } | |
1054 | ||
1055 | struct kvm_io_device_ops kvm_io_gic_ops = { | |
1056 | .read = dispatch_mmio_read, | |
1057 | .write = dispatch_mmio_write, | |
1058 | }; | |
fb848db3 AP |
1059 | |
1060 | int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address, | |
1061 | enum vgic_type type) | |
1062 | { | |
1063 | struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev; | |
1064 | int ret = 0; | |
1065 | unsigned int len; | |
1066 | ||
1067 | switch (type) { | |
1068 | case VGIC_V2: | |
1069 | len = vgic_v2_init_dist_iodev(io_device); | |
1070 | break; | |
ed9b8cef AP |
1071 | case VGIC_V3: |
1072 | len = vgic_v3_init_dist_iodev(io_device); | |
1073 | break; | |
fb848db3 AP |
1074 | default: |
1075 | BUG_ON(1); | |
1076 | } | |
1077 | ||
1078 | io_device->base_addr = dist_base_address; | |
59c5ab40 | 1079 | io_device->iodev_type = IODEV_DIST; |
fb848db3 AP |
1080 | io_device->redist_vcpu = NULL; |
1081 | ||
1082 | mutex_lock(&kvm->slots_lock); | |
1083 | ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address, | |
1084 | len, &io_device->dev); | |
1085 | mutex_unlock(&kvm->slots_lock); | |
1086 | ||
1087 | return ret; | |
1088 | } |