1
2
3
4
5
6
7
8
9
10
11
12
13
14#include "qemu/osdep.h"
15#include "qemu/log.h"
16#include "trace.h"
17#include "hw/qdev-properties.h"
18#include "hw/intc/arm_gicv3_its_common.h"
19#include "gicv3_internal.h"
20#include "qom/object.h"
21#include "qapi/error.h"
22
23typedef struct GICv3ITSClass GICv3ITSClass;
24
25DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
26 ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
27
28struct GICv3ITSClass {
29 GICv3ITSCommonClass parent_class;
30 void (*parent_reset)(DeviceState *dev);
31};
32
33
34
35
36
37typedef enum ItsCmdType {
38 NONE = 0,
39 CLEAR = 1,
40 DISCARD = 2,
41 INTERRUPT = 3,
42} ItsCmdType;
43
44typedef struct DTEntry {
45 bool valid;
46 unsigned size;
47 uint64_t ittaddr;
48} DTEntry;
49
50typedef struct CTEntry {
51 bool valid;
52 uint32_t rdbase;
53} CTEntry;
54
55typedef struct ITEntry {
56 bool valid;
57 int inttype;
58 uint32_t intid;
59 uint32_t doorbell;
60 uint32_t icid;
61 uint32_t vpeid;
62} ITEntry;
63
64typedef struct VTEntry {
65 bool valid;
66 unsigned vptsize;
67 uint32_t rdbase;
68 uint64_t vptaddr;
69} VTEntry;
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84typedef enum ItsCmdResult {
85 CMD_STALL = 0,
86 CMD_CONTINUE = 1,
87 CMD_CONTINUE_OK = 2,
88} ItsCmdResult;
89
90
91static bool its_feature_virtual(GICv3ITSState *s)
92{
93 return s->typer & R_GITS_TYPER_VIRTUAL_MASK;
94}
95
96static inline bool intid_in_lpi_range(uint32_t id)
97{
98 return id >= GICV3_LPI_INTID_START &&
99 id < (1 << (GICD_TYPER_IDBITS + 1));
100}
101
102static inline bool valid_doorbell(uint32_t id)
103{
104
105 return id == INTID_SPURIOUS || intid_in_lpi_range(id);
106}
107
108static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
109{
110 uint64_t result = 0;
111
112 switch (page_sz) {
113 case GITS_PAGE_SIZE_4K:
114 case GITS_PAGE_SIZE_16K:
115 result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
116 break;
117
118 case GITS_PAGE_SIZE_64K:
119 result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
120 result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
121 break;
122
123 default:
124 break;
125 }
126 return result;
127}
128
129static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
130 uint32_t idx, MemTxResult *res)
131{
132
133
134
135
136
137
138
139
140
141
142
143
144
145 AddressSpace *as = &s->gicv3->dma_as;
146 uint32_t l2idx;
147 uint64_t l2;
148 uint32_t num_l2_entries;
149
150 *res = MEMTX_OK;
151
152 if (!td->indirect) {
153
154 return td->base_addr + idx * td->entry_sz;
155 }
156
157
158 l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE);
159
160 l2 = address_space_ldq_le(as,
161 td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE),
162 MEMTXATTRS_UNSPECIFIED, res);
163 if (*res != MEMTX_OK) {
164 return -1;
165 }
166 if (!(l2 & L2_TABLE_VALID_MASK)) {
167 return -1;
168 }
169
170 num_l2_entries = td->page_sz / td->entry_sz;
171 return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz;
172}
173
174
175
176
177
178
179
180static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
181{
182 AddressSpace *as = &s->gicv3->dma_as;
183 MemTxResult res = MEMTX_OK;
184 uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, &res);
185 uint64_t cteval;
186
187 if (entry_addr == -1) {
188
189 cte->valid = false;
190 goto out;
191 }
192
193 cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
194 if (res != MEMTX_OK) {
195 goto out;
196 }
197 cte->valid = FIELD_EX64(cteval, CTE, VALID);
198 cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE);
199out:
200 if (res != MEMTX_OK) {
201 trace_gicv3_its_cte_read_fault(icid);
202 } else {
203 trace_gicv3_its_cte_read(icid, cte->valid, cte->rdbase);
204 }
205 return res;
206}
207
208
209
210
211
212
213static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
214 const ITEntry *ite)
215{
216 AddressSpace *as = &s->gicv3->dma_as;
217 MemTxResult res = MEMTX_OK;
218 hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
219 uint64_t itel = 0;
220 uint32_t iteh = 0;
221
222 trace_gicv3_its_ite_write(dte->ittaddr, eventid, ite->valid,
223 ite->inttype, ite->intid, ite->icid,
224 ite->vpeid, ite->doorbell);
225
226 if (ite->valid) {
227 itel = FIELD_DP64(itel, ITE_L, VALID, 1);
228 itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype);
229 itel = FIELD_DP64(itel, ITE_L, INTID, ite->intid);
230 itel = FIELD_DP64(itel, ITE_L, ICID, ite->icid);
231 itel = FIELD_DP64(itel, ITE_L, VPEID, ite->vpeid);
232 iteh = FIELD_DP32(iteh, ITE_H, DOORBELL, ite->doorbell);
233 }
234
235 address_space_stq_le(as, iteaddr, itel, MEMTXATTRS_UNSPECIFIED, &res);
236 if (res != MEMTX_OK) {
237 return false;
238 }
239 address_space_stl_le(as, iteaddr + 8, iteh, MEMTXATTRS_UNSPECIFIED, &res);
240 return res == MEMTX_OK;
241}
242
243
244
245
246
247
248
249static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
250 const DTEntry *dte, ITEntry *ite)
251{
252 AddressSpace *as = &s->gicv3->dma_as;
253 MemTxResult res = MEMTX_OK;
254 uint64_t itel;
255 uint32_t iteh;
256 hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
257
258 itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
259 if (res != MEMTX_OK) {
260 trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
261 return res;
262 }
263
264 iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res);
265 if (res != MEMTX_OK) {
266 trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
267 return res;
268 }
269
270 ite->valid = FIELD_EX64(itel, ITE_L, VALID);
271 ite->inttype = FIELD_EX64(itel, ITE_L, INTTYPE);
272 ite->intid = FIELD_EX64(itel, ITE_L, INTID);
273 ite->icid = FIELD_EX64(itel, ITE_L, ICID);
274 ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID);
275 ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL);
276 trace_gicv3_its_ite_read(dte->ittaddr, eventid, ite->valid,
277 ite->inttype, ite->intid, ite->icid,
278 ite->vpeid, ite->doorbell);
279 return MEMTX_OK;
280}
281
282
283
284
285
286
287
288static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
289{
290 MemTxResult res = MEMTX_OK;
291 AddressSpace *as = &s->gicv3->dma_as;
292 uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, &res);
293 uint64_t dteval;
294
295 if (entry_addr == -1) {
296
297 dte->valid = false;
298 goto out;
299 }
300 dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
301 if (res != MEMTX_OK) {
302 goto out;
303 }
304 dte->valid = FIELD_EX64(dteval, DTE, VALID);
305 dte->size = FIELD_EX64(dteval, DTE, SIZE);
306
307 dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT;
308out:
309 if (res != MEMTX_OK) {
310 trace_gicv3_its_dte_read_fault(devid);
311 } else {
312 trace_gicv3_its_dte_read(devid, dte->valid, dte->size, dte->ittaddr);
313 }
314 return res;
315}
316
317
318
319
320
321
322
323static MemTxResult get_vte(GICv3ITSState *s, uint32_t vpeid, VTEntry *vte)
324{
325 MemTxResult res = MEMTX_OK;
326 AddressSpace *as = &s->gicv3->dma_as;
327 uint64_t entry_addr = table_entry_addr(s, &s->vpet, vpeid, &res);
328 uint64_t vteval;
329
330 if (entry_addr == -1) {
331
332 vte->valid = false;
333 goto out;
334 }
335 vteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
336 if (res != MEMTX_OK) {
337 goto out;
338 }
339 vte->valid = FIELD_EX64(vteval, VTE, VALID);
340 vte->vptsize = FIELD_EX64(vteval, VTE, VPTSIZE);
341 vte->vptaddr = FIELD_EX64(vteval, VTE, VPTADDR);
342 vte->rdbase = FIELD_EX64(vteval, VTE, RDBASE);
343out:
344 if (res != MEMTX_OK) {
345 trace_gicv3_its_vte_read_fault(vpeid);
346 } else {
347 trace_gicv3_its_vte_read(vpeid, vte->valid, vte->vptsize,
348 vte->vptaddr, vte->rdbase);
349 }
350 return res;
351}
352
353
354
355
356
357
358
359
360
361
362
363static ItsCmdResult lookup_ite(GICv3ITSState *s, const char *who,
364 uint32_t devid, uint32_t eventid, ITEntry *ite,
365 DTEntry *dte)
366{
367 uint64_t num_eventids;
368
369 if (devid >= s->dt.num_entries) {
370 qemu_log_mask(LOG_GUEST_ERROR,
371 "%s: invalid command attributes: devid %d>=%d",
372 who, devid, s->dt.num_entries);
373 return CMD_CONTINUE;
374 }
375
376 if (get_dte(s, devid, dte) != MEMTX_OK) {
377 return CMD_STALL;
378 }
379 if (!dte->valid) {
380 qemu_log_mask(LOG_GUEST_ERROR,
381 "%s: invalid command attributes: "
382 "invalid dte for %d\n", who, devid);
383 return CMD_CONTINUE;
384 }
385
386 num_eventids = 1ULL << (dte->size + 1);
387 if (eventid >= num_eventids) {
388 qemu_log_mask(LOG_GUEST_ERROR,
389 "%s: invalid command attributes: eventid %d >= %"
390 PRId64 "\n", who, eventid, num_eventids);
391 return CMD_CONTINUE;
392 }
393
394 if (get_ite(s, eventid, dte, ite) != MEMTX_OK) {
395 return CMD_STALL;
396 }
397
398 if (!ite->valid) {
399 qemu_log_mask(LOG_GUEST_ERROR,
400 "%s: invalid command attributes: invalid ITE\n", who);
401 return CMD_CONTINUE;
402 }
403
404 return CMD_CONTINUE_OK;
405}
406
407
408
409
410
411
412
413
414
415
416static ItsCmdResult lookup_cte(GICv3ITSState *s, const char *who,
417 uint32_t icid, CTEntry *cte)
418{
419 if (icid >= s->ct.num_entries) {
420 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid ICID 0x%x\n", who, icid);
421 return CMD_CONTINUE;
422 }
423 if (get_cte(s, icid, cte) != MEMTX_OK) {
424 return CMD_STALL;
425 }
426 if (!cte->valid) {
427 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CTE\n", who);
428 return CMD_CONTINUE;
429 }
430 if (cte->rdbase >= s->gicv3->num_cpu) {
431 return CMD_CONTINUE;
432 }
433 return CMD_CONTINUE_OK;
434}
435
436
437
438
439
440
441
442
443
444
445static ItsCmdResult lookup_vte(GICv3ITSState *s, const char *who,
446 uint32_t vpeid, VTEntry *vte)
447{
448 if (vpeid >= s->vpet.num_entries) {
449 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid VPEID 0x%x\n", who, vpeid);
450 return CMD_CONTINUE;
451 }
452
453 if (get_vte(s, vpeid, vte) != MEMTX_OK) {
454 return CMD_STALL;
455 }
456 if (!vte->valid) {
457 qemu_log_mask(LOG_GUEST_ERROR,
458 "%s: invalid VTE for VPEID 0x%x\n", who, vpeid);
459 return CMD_CONTINUE;
460 }
461
462 if (vte->rdbase >= s->gicv3->num_cpu) {
463 return CMD_CONTINUE;
464 }
465 return CMD_CONTINUE_OK;
466}
467
468static ItsCmdResult process_its_cmd_phys(GICv3ITSState *s, const ITEntry *ite,
469 int irqlevel)
470{
471 CTEntry cte;
472 ItsCmdResult cmdres;
473
474 cmdres = lookup_cte(s, __func__, ite->icid, &cte);
475 if (cmdres != CMD_CONTINUE_OK) {
476 return cmdres;
477 }
478 gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite->intid, irqlevel);
479 return CMD_CONTINUE_OK;
480}
481
482static ItsCmdResult process_its_cmd_virt(GICv3ITSState *s, const ITEntry *ite,
483 int irqlevel)
484{
485 VTEntry vte;
486 ItsCmdResult cmdres;
487
488 cmdres = lookup_vte(s, __func__, ite->vpeid, &vte);
489 if (cmdres != CMD_CONTINUE_OK) {
490 return cmdres;
491 }
492
493 if (!intid_in_lpi_range(ite->intid) ||
494 ite->intid >= (1ULL << (vte.vptsize + 1))) {
495 qemu_log_mask(LOG_GUEST_ERROR, "%s: intid 0x%x out of range\n",
496 __func__, ite->intid);
497 return CMD_CONTINUE;
498 }
499
500
501
502
503
504 gicv3_redist_process_vlpi(&s->gicv3->cpu[vte.rdbase], ite->intid,
505 vte.vptaddr << 16, ite->doorbell, irqlevel);
506 return CMD_CONTINUE_OK;
507}
508
509
510
511
512
513
514
515
516
517static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
518 uint32_t eventid, ItsCmdType cmd)
519{
520 DTEntry dte;
521 ITEntry ite;
522 ItsCmdResult cmdres;
523 int irqlevel;
524
525 cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
526 if (cmdres != CMD_CONTINUE_OK) {
527 return cmdres;
528 }
529
530 irqlevel = (cmd == CLEAR || cmd == DISCARD) ? 0 : 1;
531
532 switch (ite.inttype) {
533 case ITE_INTTYPE_PHYSICAL:
534 cmdres = process_its_cmd_phys(s, &ite, irqlevel);
535 break;
536 case ITE_INTTYPE_VIRTUAL:
537 if (!its_feature_virtual(s)) {
538
539 qemu_log_mask(LOG_GUEST_ERROR,
540 "%s: invalid type %d in ITE (table corrupted?)\n",
541 __func__, ite.inttype);
542 return CMD_CONTINUE;
543 }
544 cmdres = process_its_cmd_virt(s, &ite, irqlevel);
545 break;
546 default:
547 g_assert_not_reached();
548 }
549
550 if (cmdres == CMD_CONTINUE_OK && cmd == DISCARD) {
551 ITEntry ite = {};
552
553 ite.valid = false;
554 return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
555 }
556 return CMD_CONTINUE_OK;
557}
558
559static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
560 ItsCmdType cmd)
561{
562 uint32_t devid, eventid;
563
564 devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
565 eventid = cmdpkt[1] & EVENTID_MASK;
566 switch (cmd) {
567 case INTERRUPT:
568 trace_gicv3_its_cmd_int(devid, eventid);
569 break;
570 case CLEAR:
571 trace_gicv3_its_cmd_clear(devid, eventid);
572 break;
573 case DISCARD:
574 trace_gicv3_its_cmd_discard(devid, eventid);
575 break;
576 default:
577 g_assert_not_reached();
578 }
579 return do_process_its_cmd(s, devid, eventid, cmd);
580}
581
582static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
583 bool ignore_pInt)
584{
585 uint32_t devid, eventid;
586 uint32_t pIntid = 0;
587 uint64_t num_eventids;
588 uint16_t icid = 0;
589 DTEntry dte;
590 ITEntry ite;
591
592 devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
593 eventid = cmdpkt[1] & EVENTID_MASK;
594 icid = cmdpkt[2] & ICID_MASK;
595
596 if (ignore_pInt) {
597 pIntid = eventid;
598 trace_gicv3_its_cmd_mapi(devid, eventid, icid);
599 } else {
600 pIntid = (cmdpkt[1] & pINTID_MASK) >> pINTID_SHIFT;
601 trace_gicv3_its_cmd_mapti(devid, eventid, icid, pIntid);
602 }
603
604 if (devid >= s->dt.num_entries) {
605 qemu_log_mask(LOG_GUEST_ERROR,
606 "%s: invalid command attributes: devid %d>=%d",
607 __func__, devid, s->dt.num_entries);
608 return CMD_CONTINUE;
609 }
610
611 if (get_dte(s, devid, &dte) != MEMTX_OK) {
612 return CMD_STALL;
613 }
614 num_eventids = 1ULL << (dte.size + 1);
615
616 if (icid >= s->ct.num_entries) {
617 qemu_log_mask(LOG_GUEST_ERROR,
618 "%s: invalid ICID 0x%x >= 0x%x\n",
619 __func__, icid, s->ct.num_entries);
620 return CMD_CONTINUE;
621 }
622
623 if (!dte.valid) {
624 qemu_log_mask(LOG_GUEST_ERROR,
625 "%s: no valid DTE for devid 0x%x\n", __func__, devid);
626 return CMD_CONTINUE;
627 }
628
629 if (eventid >= num_eventids) {
630 qemu_log_mask(LOG_GUEST_ERROR,
631 "%s: invalid event ID 0x%x >= 0x%" PRIx64 "\n",
632 __func__, eventid, num_eventids);
633 return CMD_CONTINUE;
634 }
635
636 if (!intid_in_lpi_range(pIntid)) {
637 qemu_log_mask(LOG_GUEST_ERROR,
638 "%s: invalid interrupt ID 0x%x\n", __func__, pIntid);
639 return CMD_CONTINUE;
640 }
641
642
643 ite.valid = true;
644 ite.inttype = ITE_INTTYPE_PHYSICAL;
645 ite.intid = pIntid;
646 ite.icid = icid;
647 ite.doorbell = INTID_SPURIOUS;
648 ite.vpeid = 0;
649 return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
650}
651
652static ItsCmdResult process_vmapti(GICv3ITSState *s, const uint64_t *cmdpkt,
653 bool ignore_vintid)
654{
655 uint32_t devid, eventid, vintid, doorbell, vpeid;
656 uint32_t num_eventids;
657 DTEntry dte;
658 ITEntry ite;
659
660 if (!its_feature_virtual(s)) {
661 return CMD_CONTINUE;
662 }
663
664 devid = FIELD_EX64(cmdpkt[0], VMAPTI_0, DEVICEID);
665 eventid = FIELD_EX64(cmdpkt[1], VMAPTI_1, EVENTID);
666 vpeid = FIELD_EX64(cmdpkt[1], VMAPTI_1, VPEID);
667 doorbell = FIELD_EX64(cmdpkt[2], VMAPTI_2, DOORBELL);
668 if (ignore_vintid) {
669 vintid = eventid;
670 trace_gicv3_its_cmd_vmapi(devid, eventid, vpeid, doorbell);
671 } else {
672 vintid = FIELD_EX64(cmdpkt[2], VMAPTI_2, VINTID);
673 trace_gicv3_its_cmd_vmapti(devid, eventid, vpeid, vintid, doorbell);
674 }
675
676 if (devid >= s->dt.num_entries) {
677 qemu_log_mask(LOG_GUEST_ERROR,
678 "%s: invalid DeviceID 0x%x (must be less than 0x%x)\n",
679 __func__, devid, s->dt.num_entries);
680 return CMD_CONTINUE;
681 }
682
683 if (get_dte(s, devid, &dte) != MEMTX_OK) {
684 return CMD_STALL;
685 }
686
687 if (!dte.valid) {
688 qemu_log_mask(LOG_GUEST_ERROR,
689 "%s: no entry in device table for DeviceID 0x%x\n",
690 __func__, devid);
691 return CMD_CONTINUE;
692 }
693
694 num_eventids = 1ULL << (dte.size + 1);
695
696 if (eventid >= num_eventids) {
697 qemu_log_mask(LOG_GUEST_ERROR,
698 "%s: EventID 0x%x too large for DeviceID 0x%x "
699 "(must be less than 0x%x)\n",
700 __func__, eventid, devid, num_eventids);
701 return CMD_CONTINUE;
702 }
703 if (!intid_in_lpi_range(vintid)) {
704 qemu_log_mask(LOG_GUEST_ERROR,
705 "%s: VIntID 0x%x not a valid LPI\n",
706 __func__, vintid);
707 return CMD_CONTINUE;
708 }
709 if (!valid_doorbell(doorbell)) {
710 qemu_log_mask(LOG_GUEST_ERROR,
711 "%s: Doorbell %d not 1023 and not a valid LPI\n",
712 __func__, doorbell);
713 return CMD_CONTINUE;
714 }
715 if (vpeid >= s->vpet.num_entries) {
716 qemu_log_mask(LOG_GUEST_ERROR,
717 "%s: VPEID 0x%x out of range (must be less than 0x%x)\n",
718 __func__, vpeid, s->vpet.num_entries);
719 return CMD_CONTINUE;
720 }
721
722 ite.valid = true;
723 ite.inttype = ITE_INTTYPE_VIRTUAL;
724 ite.intid = vintid;
725 ite.icid = 0;
726 ite.doorbell = doorbell;
727 ite.vpeid = vpeid;
728 return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
729}
730
731
732
733
734
735static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
736{
737 AddressSpace *as = &s->gicv3->dma_as;
738 uint64_t entry_addr;
739 uint64_t cteval = 0;
740 MemTxResult res = MEMTX_OK;
741
742 trace_gicv3_its_cte_write(icid, cte->valid, cte->rdbase);
743
744 if (cte->valid) {
745
746 cteval = FIELD_DP64(cteval, CTE, VALID, 1);
747 cteval = FIELD_DP64(cteval, CTE, RDBASE, cte->rdbase);
748 }
749
750 entry_addr = table_entry_addr(s, &s->ct, icid, &res);
751 if (res != MEMTX_OK) {
752
753 return false;
754 }
755 if (entry_addr == -1) {
756
757 return true;
758 }
759
760 address_space_stq_le(as, entry_addr, cteval, MEMTXATTRS_UNSPECIFIED, &res);
761 return res == MEMTX_OK;
762}
763
764static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
765{
766 uint16_t icid;
767 CTEntry cte;
768
769 icid = cmdpkt[2] & ICID_MASK;
770 cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
771 if (cte.valid) {
772 cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
773 cte.rdbase &= RDBASE_PROCNUM_MASK;
774 } else {
775 cte.rdbase = 0;
776 }
777 trace_gicv3_its_cmd_mapc(icid, cte.rdbase, cte.valid);
778
779 if (icid >= s->ct.num_entries) {
780 qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid ICID 0x%x\n", icid);
781 return CMD_CONTINUE;
782 }
783 if (cte.valid && cte.rdbase >= s->gicv3->num_cpu) {
784 qemu_log_mask(LOG_GUEST_ERROR,
785 "ITS MAPC: invalid RDBASE %u\n", cte.rdbase);
786 return CMD_CONTINUE;
787 }
788
789 return update_cte(s, icid, &cte) ? CMD_CONTINUE_OK : CMD_STALL;
790}
791
792
793
794
795
796static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
797{
798 AddressSpace *as = &s->gicv3->dma_as;
799 uint64_t entry_addr;
800 uint64_t dteval = 0;
801 MemTxResult res = MEMTX_OK;
802
803 trace_gicv3_its_dte_write(devid, dte->valid, dte->size, dte->ittaddr);
804
805 if (dte->valid) {
806
807 dteval = FIELD_DP64(dteval, DTE, VALID, 1);
808 dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
809 dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
810 }
811
812 entry_addr = table_entry_addr(s, &s->dt, devid, &res);
813 if (res != MEMTX_OK) {
814
815 return false;
816 }
817 if (entry_addr == -1) {
818
819 return true;
820 }
821 address_space_stq_le(as, entry_addr, dteval, MEMTXATTRS_UNSPECIFIED, &res);
822 return res == MEMTX_OK;
823}
824
825static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
826{
827 uint32_t devid;
828 DTEntry dte;
829
830 devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
831 dte.size = cmdpkt[1] & SIZE_MASK;
832 dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
833 dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
834
835 trace_gicv3_its_cmd_mapd(devid, dte.size, dte.ittaddr, dte.valid);
836
837 if (devid >= s->dt.num_entries) {
838 qemu_log_mask(LOG_GUEST_ERROR,
839 "ITS MAPD: invalid device ID field 0x%x >= 0x%x\n",
840 devid, s->dt.num_entries);
841 return CMD_CONTINUE;
842 }
843
844 if (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
845 qemu_log_mask(LOG_GUEST_ERROR,
846 "ITS MAPD: invalid size %d\n", dte.size);
847 return CMD_CONTINUE;
848 }
849
850 return update_dte(s, devid, &dte) ? CMD_CONTINUE_OK : CMD_STALL;
851}
852
853static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
854{
855 uint64_t rd1, rd2;
856
857 rd1 = FIELD_EX64(cmdpkt[2], MOVALL_2, RDBASE1);
858 rd2 = FIELD_EX64(cmdpkt[3], MOVALL_3, RDBASE2);
859
860 trace_gicv3_its_cmd_movall(rd1, rd2);
861
862 if (rd1 >= s->gicv3->num_cpu) {
863 qemu_log_mask(LOG_GUEST_ERROR,
864 "%s: RDBASE1 %" PRId64
865 " out of range (must be less than %d)\n",
866 __func__, rd1, s->gicv3->num_cpu);
867 return CMD_CONTINUE;
868 }
869 if (rd2 >= s->gicv3->num_cpu) {
870 qemu_log_mask(LOG_GUEST_ERROR,
871 "%s: RDBASE2 %" PRId64
872 " out of range (must be less than %d)\n",
873 __func__, rd2, s->gicv3->num_cpu);
874 return CMD_CONTINUE;
875 }
876
877 if (rd1 == rd2) {
878
879 return CMD_CONTINUE_OK;
880 }
881
882
883 gicv3_redist_movall_lpis(&s->gicv3->cpu[rd1], &s->gicv3->cpu[rd2]);
884
885 return CMD_CONTINUE_OK;
886}
887
888static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
889{
890 uint32_t devid, eventid;
891 uint16_t new_icid;
892 DTEntry dte;
893 CTEntry old_cte, new_cte;
894 ITEntry old_ite;
895 ItsCmdResult cmdres;
896
897 devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
898 eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
899 new_icid = FIELD_EX64(cmdpkt[2], MOVI_2, ICID);
900
901 trace_gicv3_its_cmd_movi(devid, eventid, new_icid);
902
903 cmdres = lookup_ite(s, __func__, devid, eventid, &old_ite, &dte);
904 if (cmdres != CMD_CONTINUE_OK) {
905 return cmdres;
906 }
907
908 if (old_ite.inttype != ITE_INTTYPE_PHYSICAL) {
909 qemu_log_mask(LOG_GUEST_ERROR,
910 "%s: invalid command attributes: invalid ITE\n",
911 __func__);
912 return CMD_CONTINUE;
913 }
914
915 cmdres = lookup_cte(s, __func__, old_ite.icid, &old_cte);
916 if (cmdres != CMD_CONTINUE_OK) {
917 return cmdres;
918 }
919 cmdres = lookup_cte(s, __func__, new_icid, &new_cte);
920 if (cmdres != CMD_CONTINUE_OK) {
921 return cmdres;
922 }
923
924 if (old_cte.rdbase != new_cte.rdbase) {
925
926 gicv3_redist_mov_lpi(&s->gicv3->cpu[old_cte.rdbase],
927 &s->gicv3->cpu[new_cte.rdbase],
928 old_ite.intid);
929 }
930
931
932 old_ite.icid = new_icid;
933 return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE_OK : CMD_STALL;
934}
935
936
937
938
939
940static bool update_vte(GICv3ITSState *s, uint32_t vpeid, const VTEntry *vte)
941{
942 AddressSpace *as = &s->gicv3->dma_as;
943 uint64_t entry_addr;
944 uint64_t vteval = 0;
945 MemTxResult res = MEMTX_OK;
946
947 trace_gicv3_its_vte_write(vpeid, vte->valid, vte->vptsize, vte->vptaddr,
948 vte->rdbase);
949
950 if (vte->valid) {
951 vteval = FIELD_DP64(vteval, VTE, VALID, 1);
952 vteval = FIELD_DP64(vteval, VTE, VPTSIZE, vte->vptsize);
953 vteval = FIELD_DP64(vteval, VTE, VPTADDR, vte->vptaddr);
954 vteval = FIELD_DP64(vteval, VTE, RDBASE, vte->rdbase);
955 }
956
957 entry_addr = table_entry_addr(s, &s->vpet, vpeid, &res);
958 if (res != MEMTX_OK) {
959 return false;
960 }
961 if (entry_addr == -1) {
962
963 return true;
964 }
965 address_space_stq_le(as, entry_addr, vteval, MEMTXATTRS_UNSPECIFIED, &res);
966 return res == MEMTX_OK;
967}
968
969static ItsCmdResult process_vmapp(GICv3ITSState *s, const uint64_t *cmdpkt)
970{
971 VTEntry vte;
972 uint32_t vpeid;
973
974 if (!its_feature_virtual(s)) {
975 return CMD_CONTINUE;
976 }
977
978 vpeid = FIELD_EX64(cmdpkt[1], VMAPP_1, VPEID);
979 vte.rdbase = FIELD_EX64(cmdpkt[2], VMAPP_2, RDBASE);
980 vte.valid = FIELD_EX64(cmdpkt[2], VMAPP_2, V);
981 vte.vptsize = FIELD_EX64(cmdpkt[3], VMAPP_3, VPTSIZE);
982 vte.vptaddr = FIELD_EX64(cmdpkt[3], VMAPP_3, VPTADDR);
983
984 trace_gicv3_its_cmd_vmapp(vpeid, vte.rdbase, vte.valid,
985 vte.vptaddr, vte.vptsize);
986
987
988
989
990
991
992
993 if (vte.vptsize > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
994 qemu_log_mask(LOG_GUEST_ERROR,
995 "%s: invalid VPT_size 0x%x\n", __func__, vte.vptsize);
996 return CMD_CONTINUE;
997 }
998
999 if (vte.valid && vte.rdbase >= s->gicv3->num_cpu) {
1000 qemu_log_mask(LOG_GUEST_ERROR,
1001 "%s: invalid rdbase 0x%x\n", __func__, vte.rdbase);
1002 return CMD_CONTINUE;
1003 }
1004
1005 if (vpeid >= s->vpet.num_entries) {
1006 qemu_log_mask(LOG_GUEST_ERROR,
1007 "%s: VPEID 0x%x out of range (must be less than 0x%x)\n",
1008 __func__, vpeid, s->vpet.num_entries);
1009 return CMD_CONTINUE;
1010 }
1011
1012 return update_vte(s, vpeid, &vte) ? CMD_CONTINUE_OK : CMD_STALL;
1013}
1014
1015typedef struct VmovpCallbackData {
1016 uint64_t rdbase;
1017 uint32_t vpeid;
1018
1019
1020
1021
1022 ItsCmdResult result;
1023} VmovpCallbackData;
1024
1025static void vmovp_callback(gpointer data, gpointer opaque)
1026{
1027
1028
1029
1030
1031
1032
1033
1034 GICv3ITSState *s = data;
1035 VmovpCallbackData *cbdata = opaque;
1036 VTEntry vte;
1037 ItsCmdResult cmdres;
1038
1039 cmdres = lookup_vte(s, __func__, cbdata->vpeid, &vte);
1040 switch (cmdres) {
1041 case CMD_STALL:
1042 cbdata->result = CMD_STALL;
1043 return;
1044 case CMD_CONTINUE:
1045 if (cbdata->result != CMD_STALL) {
1046 cbdata->result = CMD_CONTINUE;
1047 }
1048 return;
1049 case CMD_CONTINUE_OK:
1050 break;
1051 }
1052
1053 vte.rdbase = cbdata->rdbase;
1054 if (!update_vte(s, cbdata->vpeid, &vte)) {
1055 cbdata->result = CMD_STALL;
1056 }
1057}
1058
1059static ItsCmdResult process_vmovp(GICv3ITSState *s, const uint64_t *cmdpkt)
1060{
1061 VmovpCallbackData cbdata;
1062
1063 if (!its_feature_virtual(s)) {
1064 return CMD_CONTINUE;
1065 }
1066
1067 cbdata.vpeid = FIELD_EX64(cmdpkt[1], VMOVP_1, VPEID);
1068 cbdata.rdbase = FIELD_EX64(cmdpkt[2], VMOVP_2, RDBASE);
1069
1070 trace_gicv3_its_cmd_vmovp(cbdata.vpeid, cbdata.rdbase);
1071
1072 if (cbdata.rdbase >= s->gicv3->num_cpu) {
1073 return CMD_CONTINUE;
1074 }
1075
1076
1077
1078
1079
1080
1081
1082 cbdata.result = CMD_CONTINUE_OK;
1083 gicv3_foreach_its(s->gicv3, vmovp_callback, &cbdata);
1084 return cbdata.result;
1085}
1086
1087static ItsCmdResult process_vmovi(GICv3ITSState *s, const uint64_t *cmdpkt)
1088{
1089 uint32_t devid, eventid, vpeid, doorbell;
1090 bool doorbell_valid;
1091 DTEntry dte;
1092 ITEntry ite;
1093 VTEntry old_vte, new_vte;
1094 ItsCmdResult cmdres;
1095
1096 if (!its_feature_virtual(s)) {
1097 return CMD_CONTINUE;
1098 }
1099
1100 devid = FIELD_EX64(cmdpkt[0], VMOVI_0, DEVICEID);
1101 eventid = FIELD_EX64(cmdpkt[1], VMOVI_1, EVENTID);
1102 vpeid = FIELD_EX64(cmdpkt[1], VMOVI_1, VPEID);
1103 doorbell_valid = FIELD_EX64(cmdpkt[2], VMOVI_2, D);
1104 doorbell = FIELD_EX64(cmdpkt[2], VMOVI_2, DOORBELL);
1105
1106 trace_gicv3_its_cmd_vmovi(devid, eventid, vpeid, doorbell_valid, doorbell);
1107
1108 if (doorbell_valid && !valid_doorbell(doorbell)) {
1109 qemu_log_mask(LOG_GUEST_ERROR,
1110 "%s: invalid doorbell 0x%x\n", __func__, doorbell);
1111 return CMD_CONTINUE;
1112 }
1113
1114 cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
1115 if (cmdres != CMD_CONTINUE_OK) {
1116 return cmdres;
1117 }
1118
1119 if (ite.inttype != ITE_INTTYPE_VIRTUAL) {
1120 qemu_log_mask(LOG_GUEST_ERROR, "%s: ITE is not for virtual interrupt\n",
1121 __func__);
1122 return CMD_CONTINUE;
1123 }
1124
1125 cmdres = lookup_vte(s, __func__, ite.vpeid, &old_vte);
1126 if (cmdres != CMD_CONTINUE_OK) {
1127 return cmdres;
1128 }
1129 cmdres = lookup_vte(s, __func__, vpeid, &new_vte);
1130 if (cmdres != CMD_CONTINUE_OK) {
1131 return cmdres;
1132 }
1133
1134 if (!intid_in_lpi_range(ite.intid) ||
1135 ite.intid >= (1ULL << (old_vte.vptsize + 1)) ||
1136 ite.intid >= (1ULL << (new_vte.vptsize + 1))) {
1137 qemu_log_mask(LOG_GUEST_ERROR,
1138 "%s: ITE intid 0x%x out of range\n",
1139 __func__, ite.intid);
1140 return CMD_CONTINUE;
1141 }
1142
1143 ite.vpeid = vpeid;
1144 if (doorbell_valid) {
1145 ite.doorbell = doorbell;
1146 }
1147
1148
1149
1150
1151
1152
1153 if (old_vte.vptaddr != new_vte.vptaddr) {
1154 gicv3_redist_mov_vlpi(&s->gicv3->cpu[old_vte.rdbase],
1155 old_vte.vptaddr << 16,
1156 &s->gicv3->cpu[new_vte.rdbase],
1157 new_vte.vptaddr << 16,
1158 ite.intid,
1159 ite.doorbell);
1160 }
1161
1162
1163 return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE_OK : CMD_STALL;
1164}
1165
1166static ItsCmdResult process_vinvall(GICv3ITSState *s, const uint64_t *cmdpkt)
1167{
1168 VTEntry vte;
1169 uint32_t vpeid;
1170 ItsCmdResult cmdres;
1171
1172 if (!its_feature_virtual(s)) {
1173 return CMD_CONTINUE;
1174 }
1175
1176 vpeid = FIELD_EX64(cmdpkt[1], VINVALL_1, VPEID);
1177
1178 trace_gicv3_its_cmd_vinvall(vpeid);
1179
1180 cmdres = lookup_vte(s, __func__, vpeid, &vte);
1181 if (cmdres != CMD_CONTINUE_OK) {
1182 return cmdres;
1183 }
1184
1185 gicv3_redist_vinvall(&s->gicv3->cpu[vte.rdbase], vte.vptaddr << 16);
1186 return CMD_CONTINUE_OK;
1187}
1188
1189static ItsCmdResult process_inv(GICv3ITSState *s, const uint64_t *cmdpkt)
1190{
1191 uint32_t devid, eventid;
1192 ITEntry ite;
1193 DTEntry dte;
1194 CTEntry cte;
1195 VTEntry vte;
1196 ItsCmdResult cmdres;
1197
1198 devid = FIELD_EX64(cmdpkt[0], INV_0, DEVICEID);
1199 eventid = FIELD_EX64(cmdpkt[1], INV_1, EVENTID);
1200
1201 trace_gicv3_its_cmd_inv(devid, eventid);
1202
1203 cmdres = lookup_ite(s, __func__, devid, eventid, &ite, &dte);
1204 if (cmdres != CMD_CONTINUE_OK) {
1205 return cmdres;
1206 }
1207
1208 switch (ite.inttype) {
1209 case ITE_INTTYPE_PHYSICAL:
1210 cmdres = lookup_cte(s, __func__, ite.icid, &cte);
1211 if (cmdres != CMD_CONTINUE_OK) {
1212 return cmdres;
1213 }
1214 gicv3_redist_inv_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid);
1215 break;
1216 case ITE_INTTYPE_VIRTUAL:
1217 if (!its_feature_virtual(s)) {
1218
1219 qemu_log_mask(LOG_GUEST_ERROR,
1220 "%s: invalid type %d in ITE (table corrupted?)\n",
1221 __func__, ite.inttype);
1222 return CMD_CONTINUE;
1223 }
1224
1225 cmdres = lookup_vte(s, __func__, ite.vpeid, &vte);
1226 if (cmdres != CMD_CONTINUE_OK) {
1227 return cmdres;
1228 }
1229 if (!intid_in_lpi_range(ite.intid) ||
1230 ite.intid >= (1ULL << (vte.vptsize + 1))) {
1231 qemu_log_mask(LOG_GUEST_ERROR, "%s: intid 0x%x out of range\n",
1232 __func__, ite.intid);
1233 return CMD_CONTINUE;
1234 }
1235 gicv3_redist_inv_vlpi(&s->gicv3->cpu[vte.rdbase], ite.intid,
1236 vte.vptaddr << 16);
1237 break;
1238 default:
1239 g_assert_not_reached();
1240 }
1241
1242 return CMD_CONTINUE_OK;
1243}
1244
1245
1246
1247
1248
1249static void process_cmdq(GICv3ITSState *s)
1250{
1251 uint32_t wr_offset = 0;
1252 uint32_t rd_offset = 0;
1253 uint32_t cq_offset = 0;
1254 AddressSpace *as = &s->gicv3->dma_as;
1255 uint8_t cmd;
1256 int i;
1257
1258 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1259 return;
1260 }
1261
1262 wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
1263
1264 if (wr_offset >= s->cq.num_entries) {
1265 qemu_log_mask(LOG_GUEST_ERROR,
1266 "%s: invalid write offset "
1267 "%d\n", __func__, wr_offset);
1268 return;
1269 }
1270
1271 rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
1272
1273 if (rd_offset >= s->cq.num_entries) {
1274 qemu_log_mask(LOG_GUEST_ERROR,
1275 "%s: invalid read offset "
1276 "%d\n", __func__, rd_offset);
1277 return;
1278 }
1279
1280 while (wr_offset != rd_offset) {
1281 ItsCmdResult result = CMD_CONTINUE_OK;
1282 void *hostmem;
1283 hwaddr buflen;
1284 uint64_t cmdpkt[GITS_CMDQ_ENTRY_WORDS];
1285
1286 cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
1287
1288 buflen = GITS_CMDQ_ENTRY_SIZE;
1289 hostmem = address_space_map(as, s->cq.base_addr + cq_offset,
1290 &buflen, false, MEMTXATTRS_UNSPECIFIED);
1291 if (!hostmem || buflen != GITS_CMDQ_ENTRY_SIZE) {
1292 if (hostmem) {
1293 address_space_unmap(as, hostmem, buflen, false, 0);
1294 }
1295 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
1296 qemu_log_mask(LOG_GUEST_ERROR,
1297 "%s: could not read command at 0x%" PRIx64 "\n",
1298 __func__, s->cq.base_addr + cq_offset);
1299 break;
1300 }
1301 for (i = 0; i < ARRAY_SIZE(cmdpkt); i++) {
1302 cmdpkt[i] = ldq_le_p(hostmem + i * sizeof(uint64_t));
1303 }
1304 address_space_unmap(as, hostmem, buflen, false, 0);
1305
1306 cmd = cmdpkt[0] & CMD_MASK;
1307
1308 trace_gicv3_its_process_command(rd_offset, cmd);
1309
1310 switch (cmd) {
1311 case GITS_CMD_INT:
1312 result = process_its_cmd(s, cmdpkt, INTERRUPT);
1313 break;
1314 case GITS_CMD_CLEAR:
1315 result = process_its_cmd(s, cmdpkt, CLEAR);
1316 break;
1317 case GITS_CMD_SYNC:
1318
1319
1320
1321
1322
1323
1324 trace_gicv3_its_cmd_sync();
1325 break;
1326 case GITS_CMD_VSYNC:
1327
1328
1329
1330
1331 if (!its_feature_virtual(s)) {
1332 result = CMD_CONTINUE;
1333 break;
1334 }
1335 trace_gicv3_its_cmd_vsync();
1336 break;
1337 case GITS_CMD_MAPD:
1338 result = process_mapd(s, cmdpkt);
1339 break;
1340 case GITS_CMD_MAPC:
1341 result = process_mapc(s, cmdpkt);
1342 break;
1343 case GITS_CMD_MAPTI:
1344 result = process_mapti(s, cmdpkt, false);
1345 break;
1346 case GITS_CMD_MAPI:
1347 result = process_mapti(s, cmdpkt, true);
1348 break;
1349 case GITS_CMD_DISCARD:
1350 result = process_its_cmd(s, cmdpkt, DISCARD);
1351 break;
1352 case GITS_CMD_INV:
1353 result = process_inv(s, cmdpkt);
1354 break;
1355 case GITS_CMD_INVALL:
1356
1357
1358
1359
1360
1361
1362
1363
1364 trace_gicv3_its_cmd_invall();
1365 for (i = 0; i < s->gicv3->num_cpu; i++) {
1366 gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
1367 }
1368 break;
1369 case GITS_CMD_MOVI:
1370 result = process_movi(s, cmdpkt);
1371 break;
1372 case GITS_CMD_MOVALL:
1373 result = process_movall(s, cmdpkt);
1374 break;
1375 case GITS_CMD_VMAPTI:
1376 result = process_vmapti(s, cmdpkt, false);
1377 break;
1378 case GITS_CMD_VMAPI:
1379 result = process_vmapti(s, cmdpkt, true);
1380 break;
1381 case GITS_CMD_VMAPP:
1382 result = process_vmapp(s, cmdpkt);
1383 break;
1384 case GITS_CMD_VMOVP:
1385 result = process_vmovp(s, cmdpkt);
1386 break;
1387 case GITS_CMD_VMOVI:
1388 result = process_vmovi(s, cmdpkt);
1389 break;
1390 case GITS_CMD_VINVALL:
1391 result = process_vinvall(s, cmdpkt);
1392 break;
1393 default:
1394 trace_gicv3_its_cmd_unknown(cmd);
1395 break;
1396 }
1397 if (result != CMD_STALL) {
1398
1399 rd_offset++;
1400 rd_offset %= s->cq.num_entries;
1401 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
1402 } else {
1403
1404 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
1405 qemu_log_mask(LOG_GUEST_ERROR,
1406 "%s: 0x%x cmd processing failed, stalling\n",
1407 __func__, cmd);
1408 break;
1409 }
1410 }
1411}
1412
1413
1414
1415
1416
1417
1418static void extract_table_params(GICv3ITSState *s)
1419{
1420 uint16_t num_pages = 0;
1421 uint8_t page_sz_type;
1422 uint8_t type;
1423 uint32_t page_sz = 0;
1424 uint64_t value;
1425
1426 for (int i = 0; i < 8; i++) {
1427 TableDesc *td;
1428 int idbits;
1429
1430 value = s->baser[i];
1431
1432 if (!value) {
1433 continue;
1434 }
1435
1436 page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
1437
1438 switch (page_sz_type) {
1439 case 0:
1440 page_sz = GITS_PAGE_SIZE_4K;
1441 break;
1442
1443 case 1:
1444 page_sz = GITS_PAGE_SIZE_16K;
1445 break;
1446
1447 case 2:
1448 case 3:
1449 page_sz = GITS_PAGE_SIZE_64K;
1450 break;
1451
1452 default:
1453 g_assert_not_reached();
1454 }
1455
1456 num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
1457
1458 type = FIELD_EX64(value, GITS_BASER, TYPE);
1459
1460 switch (type) {
1461 case GITS_BASER_TYPE_DEVICE:
1462 td = &s->dt;
1463 idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
1464 break;
1465 case GITS_BASER_TYPE_COLLECTION:
1466 td = &s->ct;
1467 if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
1468 idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
1469 } else {
1470
1471 idbits = 16;
1472 }
1473 break;
1474 case GITS_BASER_TYPE_VPE:
1475 td = &s->vpet;
1476
1477
1478
1479
1480
1481 idbits = 16;
1482 break;
1483 default:
1484
1485
1486
1487
1488
1489 g_assert_not_reached();
1490 }
1491
1492 memset(td, 0, sizeof(*td));
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508 if (!FIELD_EX64(value, GITS_BASER, VALID)) {
1509 continue;
1510 }
1511 td->page_sz = page_sz;
1512 td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
1513 td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
1514 td->base_addr = baser_base_addr(value, page_sz);
1515 if (!td->indirect) {
1516 td->num_entries = (num_pages * page_sz) / td->entry_sz;
1517 } else {
1518 td->num_entries = (((num_pages * page_sz) /
1519 L1TABLE_ENTRY_SIZE) *
1520 (page_sz / td->entry_sz));
1521 }
1522 td->num_entries = MIN(td->num_entries, 1ULL << idbits);
1523 }
1524}
1525
1526static void extract_cmdq_params(GICv3ITSState *s)
1527{
1528 uint16_t num_pages = 0;
1529 uint64_t value = s->cbaser;
1530
1531 num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
1532
1533 memset(&s->cq, 0 , sizeof(s->cq));
1534
1535 if (FIELD_EX64(value, GITS_CBASER, VALID)) {
1536 s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
1537 GITS_CMDQ_ENTRY_SIZE;
1538 s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
1539 s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
1540 }
1541}
1542
1543static MemTxResult gicv3_its_translation_read(void *opaque, hwaddr offset,
1544 uint64_t *data, unsigned size,
1545 MemTxAttrs attrs)
1546{
1547
1548
1549
1550
1551 *data = 0;
1552 return MEMTX_OK;
1553}
1554
1555static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
1556 uint64_t data, unsigned size,
1557 MemTxAttrs attrs)
1558{
1559 GICv3ITSState *s = (GICv3ITSState *)opaque;
1560 bool result = true;
1561
1562 trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id);
1563
1564 switch (offset) {
1565 case GITS_TRANSLATER:
1566 if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
1567 result = do_process_its_cmd(s, attrs.requester_id, data, NONE);
1568 }
1569 break;
1570 default:
1571 break;
1572 }
1573
1574 if (result) {
1575 return MEMTX_OK;
1576 } else {
1577 return MEMTX_ERROR;
1578 }
1579}
1580
1581static bool its_writel(GICv3ITSState *s, hwaddr offset,
1582 uint64_t value, MemTxAttrs attrs)
1583{
1584 bool result = true;
1585 int index;
1586
1587 switch (offset) {
1588 case GITS_CTLR:
1589 if (value & R_GITS_CTLR_ENABLED_MASK) {
1590 s->ctlr |= R_GITS_CTLR_ENABLED_MASK;
1591 extract_table_params(s);
1592 extract_cmdq_params(s);
1593 process_cmdq(s);
1594 } else {
1595 s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK;
1596 }
1597 break;
1598 case GITS_CBASER:
1599
1600
1601
1602
1603 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1604 s->cbaser = deposit64(s->cbaser, 0, 32, value);
1605 s->creadr = 0;
1606 }
1607 break;
1608 case GITS_CBASER + 4:
1609
1610
1611
1612
1613 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1614 s->cbaser = deposit64(s->cbaser, 32, 32, value);
1615 s->creadr = 0;
1616 }
1617 break;
1618 case GITS_CWRITER:
1619 s->cwriter = deposit64(s->cwriter, 0, 32,
1620 (value & ~R_GITS_CWRITER_RETRY_MASK));
1621 if (s->cwriter != s->creadr) {
1622 process_cmdq(s);
1623 }
1624 break;
1625 case GITS_CWRITER + 4:
1626 s->cwriter = deposit64(s->cwriter, 32, 32, value);
1627 break;
1628 case GITS_CREADR:
1629 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1630 s->creadr = deposit64(s->creadr, 0, 32,
1631 (value & ~R_GITS_CREADR_STALLED_MASK));
1632 } else {
1633
1634 qemu_log_mask(LOG_GUEST_ERROR,
1635 "%s: invalid guest write to RO register at offset "
1636 TARGET_FMT_plx "\n", __func__, offset);
1637 }
1638 break;
1639 case GITS_CREADR + 4:
1640 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1641 s->creadr = deposit64(s->creadr, 32, 32, value);
1642 } else {
1643
1644 qemu_log_mask(LOG_GUEST_ERROR,
1645 "%s: invalid guest write to RO register at offset "
1646 TARGET_FMT_plx "\n", __func__, offset);
1647 }
1648 break;
1649 case GITS_BASER ... GITS_BASER + 0x3f:
1650
1651
1652
1653
1654 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1655 index = (offset - GITS_BASER) / 8;
1656
1657 if (s->baser[index] == 0) {
1658
1659 break;
1660 }
1661 if (offset & 7) {
1662 value <<= 32;
1663 value &= ~GITS_BASER_RO_MASK;
1664 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
1665 s->baser[index] |= value;
1666 } else {
1667 value &= ~GITS_BASER_RO_MASK;
1668 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
1669 s->baser[index] |= value;
1670 }
1671 }
1672 break;
1673 case GITS_IIDR:
1674 case GITS_IDREGS ... GITS_IDREGS + 0x2f:
1675
1676 qemu_log_mask(LOG_GUEST_ERROR,
1677 "%s: invalid guest write to RO register at offset "
1678 TARGET_FMT_plx "\n", __func__, offset);
1679 break;
1680 default:
1681 result = false;
1682 break;
1683 }
1684 return result;
1685}
1686
1687static bool its_readl(GICv3ITSState *s, hwaddr offset,
1688 uint64_t *data, MemTxAttrs attrs)
1689{
1690 bool result = true;
1691 int index;
1692
1693 switch (offset) {
1694 case GITS_CTLR:
1695 *data = s->ctlr;
1696 break;
1697 case GITS_IIDR:
1698 *data = gicv3_iidr();
1699 break;
1700 case GITS_IDREGS ... GITS_IDREGS + 0x2f:
1701
1702 *data = gicv3_idreg(s->gicv3, offset - GITS_IDREGS, GICV3_PIDR0_ITS);
1703 break;
1704 case GITS_TYPER:
1705 *data = extract64(s->typer, 0, 32);
1706 break;
1707 case GITS_TYPER + 4:
1708 *data = extract64(s->typer, 32, 32);
1709 break;
1710 case GITS_CBASER:
1711 *data = extract64(s->cbaser, 0, 32);
1712 break;
1713 case GITS_CBASER + 4:
1714 *data = extract64(s->cbaser, 32, 32);
1715 break;
1716 case GITS_CREADR:
1717 *data = extract64(s->creadr, 0, 32);
1718 break;
1719 case GITS_CREADR + 4:
1720 *data = extract64(s->creadr, 32, 32);
1721 break;
1722 case GITS_CWRITER:
1723 *data = extract64(s->cwriter, 0, 32);
1724 break;
1725 case GITS_CWRITER + 4:
1726 *data = extract64(s->cwriter, 32, 32);
1727 break;
1728 case GITS_BASER ... GITS_BASER + 0x3f:
1729 index = (offset - GITS_BASER) / 8;
1730 if (offset & 7) {
1731 *data = extract64(s->baser[index], 32, 32);
1732 } else {
1733 *data = extract64(s->baser[index], 0, 32);
1734 }
1735 break;
1736 default:
1737 result = false;
1738 break;
1739 }
1740 return result;
1741}
1742
1743static bool its_writell(GICv3ITSState *s, hwaddr offset,
1744 uint64_t value, MemTxAttrs attrs)
1745{
1746 bool result = true;
1747 int index;
1748
1749 switch (offset) {
1750 case GITS_BASER ... GITS_BASER + 0x3f:
1751
1752
1753
1754
1755 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1756 index = (offset - GITS_BASER) / 8;
1757 if (s->baser[index] == 0) {
1758
1759 break;
1760 }
1761 s->baser[index] &= GITS_BASER_RO_MASK;
1762 s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
1763 }
1764 break;
1765 case GITS_CBASER:
1766
1767
1768
1769
1770 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1771 s->cbaser = value;
1772 s->creadr = 0;
1773 }
1774 break;
1775 case GITS_CWRITER:
1776 s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
1777 if (s->cwriter != s->creadr) {
1778 process_cmdq(s);
1779 }
1780 break;
1781 case GITS_CREADR:
1782 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1783 s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
1784 } else {
1785
1786 qemu_log_mask(LOG_GUEST_ERROR,
1787 "%s: invalid guest write to RO register at offset "
1788 TARGET_FMT_plx "\n", __func__, offset);
1789 }
1790 break;
1791 case GITS_TYPER:
1792
1793 qemu_log_mask(LOG_GUEST_ERROR,
1794 "%s: invalid guest write to RO register at offset "
1795 TARGET_FMT_plx "\n", __func__, offset);
1796 break;
1797 default:
1798 result = false;
1799 break;
1800 }
1801 return result;
1802}
1803
1804static bool its_readll(GICv3ITSState *s, hwaddr offset,
1805 uint64_t *data, MemTxAttrs attrs)
1806{
1807 bool result = true;
1808 int index;
1809
1810 switch (offset) {
1811 case GITS_TYPER:
1812 *data = s->typer;
1813 break;
1814 case GITS_BASER ... GITS_BASER + 0x3f:
1815 index = (offset - GITS_BASER) / 8;
1816 *data = s->baser[index];
1817 break;
1818 case GITS_CBASER:
1819 *data = s->cbaser;
1820 break;
1821 case GITS_CREADR:
1822 *data = s->creadr;
1823 break;
1824 case GITS_CWRITER:
1825 *data = s->cwriter;
1826 break;
1827 default:
1828 result = false;
1829 break;
1830 }
1831 return result;
1832}
1833
1834static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
1835 unsigned size, MemTxAttrs attrs)
1836{
1837 GICv3ITSState *s = (GICv3ITSState *)opaque;
1838 bool result;
1839
1840 switch (size) {
1841 case 4:
1842 result = its_readl(s, offset, data, attrs);
1843 break;
1844 case 8:
1845 result = its_readll(s, offset, data, attrs);
1846 break;
1847 default:
1848 result = false;
1849 break;
1850 }
1851
1852 if (!result) {
1853 qemu_log_mask(LOG_GUEST_ERROR,
1854 "%s: invalid guest read at offset " TARGET_FMT_plx
1855 " size %u\n", __func__, offset, size);
1856 trace_gicv3_its_badread(offset, size);
1857
1858
1859
1860
1861
1862
1863 *data = 0;
1864 } else {
1865 trace_gicv3_its_read(offset, *data, size);
1866 }
1867 return MEMTX_OK;
1868}
1869
1870static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
1871 unsigned size, MemTxAttrs attrs)
1872{
1873 GICv3ITSState *s = (GICv3ITSState *)opaque;
1874 bool result;
1875
1876 switch (size) {
1877 case 4:
1878 result = its_writel(s, offset, data, attrs);
1879 break;
1880 case 8:
1881 result = its_writell(s, offset, data, attrs);
1882 break;
1883 default:
1884 result = false;
1885 break;
1886 }
1887
1888 if (!result) {
1889 qemu_log_mask(LOG_GUEST_ERROR,
1890 "%s: invalid guest write at offset " TARGET_FMT_plx
1891 " size %u\n", __func__, offset, size);
1892 trace_gicv3_its_badwrite(offset, data, size);
1893
1894
1895
1896
1897
1898
1899 } else {
1900 trace_gicv3_its_write(offset, data, size);
1901 }
1902 return MEMTX_OK;
1903}
1904
1905static const MemoryRegionOps gicv3_its_control_ops = {
1906 .read_with_attrs = gicv3_its_read,
1907 .write_with_attrs = gicv3_its_write,
1908 .valid.min_access_size = 4,
1909 .valid.max_access_size = 8,
1910 .impl.min_access_size = 4,
1911 .impl.max_access_size = 8,
1912 .endianness = DEVICE_NATIVE_ENDIAN,
1913};
1914
1915static const MemoryRegionOps gicv3_its_translation_ops = {
1916 .read_with_attrs = gicv3_its_translation_read,
1917 .write_with_attrs = gicv3_its_translation_write,
1918 .valid.min_access_size = 2,
1919 .valid.max_access_size = 4,
1920 .impl.min_access_size = 2,
1921 .impl.max_access_size = 4,
1922 .endianness = DEVICE_NATIVE_ENDIAN,
1923};
1924
1925static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
1926{
1927 GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1928 int i;
1929
1930 for (i = 0; i < s->gicv3->num_cpu; i++) {
1931 if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
1932 error_setg(errp, "Physical LPI not supported by CPU %d", i);
1933 return;
1934 }
1935 }
1936
1937 gicv3_add_its(s->gicv3, dev);
1938
1939 gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
1940
1941
1942 s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
1943 s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
1944 ITS_ITT_ENTRY_SIZE - 1);
1945 s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
1946 s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
1947 s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
1948 s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
1949 if (s->gicv3->revision >= 4) {
1950
1951 s->typer = FIELD_DP64(s->typer, GITS_TYPER, VMOVP, 1);
1952 s->typer = FIELD_DP64(s->typer, GITS_TYPER, VIRTUAL, 1);
1953 }
1954}
1955
1956static void gicv3_its_reset(DeviceState *dev)
1957{
1958 GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1959 GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
1960
1961 c->parent_reset(dev);
1962
1963
1964 s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
1975 GITS_BASER_TYPE_DEVICE);
1976 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
1977 GITS_BASER_PAGESIZE_64K);
1978 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
1979 GITS_DTE_SIZE - 1);
1980
1981 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
1982 GITS_BASER_TYPE_COLLECTION);
1983 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
1984 GITS_BASER_PAGESIZE_64K);
1985 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
1986 GITS_CTE_SIZE - 1);
1987
1988 if (its_feature_virtual(s)) {
1989 s->baser[2] = FIELD_DP64(s->baser[2], GITS_BASER, TYPE,
1990 GITS_BASER_TYPE_VPE);
1991 s->baser[2] = FIELD_DP64(s->baser[2], GITS_BASER, PAGESIZE,
1992 GITS_BASER_PAGESIZE_64K);
1993 s->baser[2] = FIELD_DP64(s->baser[2], GITS_BASER, ENTRYSIZE,
1994 GITS_VPE_SIZE - 1);
1995 }
1996}
1997
1998static void gicv3_its_post_load(GICv3ITSState *s)
1999{
2000 if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
2001 extract_table_params(s);
2002 extract_cmdq_params(s);
2003 }
2004}
2005
2006static Property gicv3_its_props[] = {
2007 DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
2008 GICv3State *),
2009 DEFINE_PROP_END_OF_LIST(),
2010};
2011
2012static void gicv3_its_class_init(ObjectClass *klass, void *data)
2013{
2014 DeviceClass *dc = DEVICE_CLASS(klass);
2015 GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
2016 GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
2017
2018 dc->realize = gicv3_arm_its_realize;
2019 device_class_set_props(dc, gicv3_its_props);
2020 device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
2021 icc->post_load = gicv3_its_post_load;
2022}
2023
2024static const TypeInfo gicv3_its_info = {
2025 .name = TYPE_ARM_GICV3_ITS,
2026 .parent = TYPE_ARM_GICV3_ITS_COMMON,
2027 .instance_size = sizeof(GICv3ITSState),
2028 .class_init = gicv3_its_class_init,
2029 .class_size = sizeof(GICv3ITSClass),
2030};
2031
2032static void gicv3_its_register_types(void)
2033{
2034 type_register_static(&gicv3_its_info);
2035}
2036
2037type_init(gicv3_its_register_types)
2038