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 "hw/qdev-properties.h"
17#include "hw/intc/arm_gicv3_its_common.h"
18#include "gicv3_internal.h"
19#include "qom/object.h"
20#include "qapi/error.h"
21
22typedef struct GICv3ITSClass GICv3ITSClass;
23
24DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
25 ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
26
27struct GICv3ITSClass {
28 GICv3ITSCommonClass parent_class;
29 void (*parent_reset)(DeviceState *dev);
30};
31
32
33
34
35
36typedef enum ItsCmdType {
37 NONE = 0,
38 CLEAR = 1,
39 DISCARD = 2,
40 INTERRUPT = 3,
41} ItsCmdType;
42
43typedef struct {
44 uint32_t iteh;
45 uint64_t itel;
46} IteEntry;
47
48static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
49{
50 uint64_t result = 0;
51
52 switch (page_sz) {
53 case GITS_PAGE_SIZE_4K:
54 case GITS_PAGE_SIZE_16K:
55 result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
56 break;
57
58 case GITS_PAGE_SIZE_64K:
59 result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
60 result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
61 break;
62
63 default:
64 break;
65 }
66 return result;
67}
68
69static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
70 MemTxResult *res)
71{
72 AddressSpace *as = &s->gicv3->dma_as;
73 uint64_t l2t_addr;
74 uint64_t value;
75 bool valid_l2t;
76 uint32_t l2t_id;
77 uint32_t max_l2_entries;
78
79 if (s->ct.indirect) {
80 l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
81
82 value = address_space_ldq_le(as,
83 s->ct.base_addr +
84 (l2t_id * L1TABLE_ENTRY_SIZE),
85 MEMTXATTRS_UNSPECIFIED, res);
86
87 if (*res == MEMTX_OK) {
88 valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
89
90 if (valid_l2t) {
91 max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
92
93 l2t_addr = value & ((1ULL << 51) - 1);
94
95 *cte = address_space_ldq_le(as, l2t_addr +
96 ((icid % max_l2_entries) * GITS_CTE_SIZE),
97 MEMTXATTRS_UNSPECIFIED, res);
98 }
99 }
100 } else {
101
102 *cte = address_space_ldq_le(as, s->ct.base_addr +
103 (icid * GITS_CTE_SIZE),
104 MEMTXATTRS_UNSPECIFIED, res);
105 }
106
107 return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
108}
109
110static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
111 IteEntry ite)
112{
113 AddressSpace *as = &s->gicv3->dma_as;
114 uint64_t itt_addr;
115 MemTxResult res = MEMTX_OK;
116
117 itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
118 itt_addr <<= ITTADDR_SHIFT;
119
120 address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
121 sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
122 &res);
123
124 if (res == MEMTX_OK) {
125 address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
126 sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
127 MEMTXATTRS_UNSPECIFIED, &res);
128 }
129 if (res != MEMTX_OK) {
130 return false;
131 } else {
132 return true;
133 }
134}
135
136static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
137 uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
138{
139 AddressSpace *as = &s->gicv3->dma_as;
140 uint64_t itt_addr;
141 bool status = false;
142 IteEntry ite = {};
143
144 itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
145 itt_addr <<= ITTADDR_SHIFT;
146
147 ite.itel = address_space_ldq_le(as, itt_addr +
148 (eventid * (sizeof(uint64_t) +
149 sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
150 res);
151
152 if (*res == MEMTX_OK) {
153 ite.iteh = address_space_ldl_le(as, itt_addr +
154 (eventid * (sizeof(uint64_t) +
155 sizeof(uint32_t))) + sizeof(uint32_t),
156 MEMTXATTRS_UNSPECIFIED, res);
157
158 if (*res == MEMTX_OK) {
159 if (ite.itel & TABLE_ENTRY_VALID_MASK) {
160 if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
161 GITS_TYPE_PHYSICAL) {
162 *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
163 ITE_ENTRY_INTID_SHIFT;
164 *icid = ite.iteh & ITE_ENTRY_ICID_MASK;
165 status = true;
166 }
167 }
168 }
169 }
170 return status;
171}
172
173static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
174{
175 AddressSpace *as = &s->gicv3->dma_as;
176 uint64_t l2t_addr;
177 uint64_t value;
178 bool valid_l2t;
179 uint32_t l2t_id;
180 uint32_t max_l2_entries;
181
182 if (s->dt.indirect) {
183 l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
184
185 value = address_space_ldq_le(as,
186 s->dt.base_addr +
187 (l2t_id * L1TABLE_ENTRY_SIZE),
188 MEMTXATTRS_UNSPECIFIED, res);
189
190 if (*res == MEMTX_OK) {
191 valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
192
193 if (valid_l2t) {
194 max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
195
196 l2t_addr = value & ((1ULL << 51) - 1);
197
198 value = address_space_ldq_le(as, l2t_addr +
199 ((devid % max_l2_entries) * GITS_DTE_SIZE),
200 MEMTXATTRS_UNSPECIFIED, res);
201 }
202 }
203 } else {
204
205 value = address_space_ldq_le(as, s->dt.base_addr +
206 (devid * GITS_DTE_SIZE),
207 MEMTXATTRS_UNSPECIFIED, res);
208 }
209
210 return value;
211}
212
213
214
215
216
217
218
219
220
221static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
222 ItsCmdType cmd)
223{
224 AddressSpace *as = &s->gicv3->dma_as;
225 uint32_t devid, eventid;
226 MemTxResult res = MEMTX_OK;
227 bool dte_valid;
228 uint64_t dte = 0;
229 uint32_t max_eventid;
230 uint16_t icid = 0;
231 uint32_t pIntid = 0;
232 bool ite_valid = false;
233 uint64_t cte = 0;
234 bool cte_valid = false;
235 bool result = false;
236 uint64_t rdbase;
237
238 if (cmd == NONE) {
239 devid = offset;
240 } else {
241 devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
242
243 offset += NUM_BYTES_IN_DW;
244 value = address_space_ldq_le(as, s->cq.base_addr + offset,
245 MEMTXATTRS_UNSPECIFIED, &res);
246 }
247
248 if (res != MEMTX_OK) {
249 return result;
250 }
251
252 eventid = (value & EVENTID_MASK);
253
254 dte = get_dte(s, devid, &res);
255
256 if (res != MEMTX_OK) {
257 return result;
258 }
259 dte_valid = dte & TABLE_ENTRY_VALID_MASK;
260
261 if (dte_valid) {
262 max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
263
264 ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
265
266 if (res != MEMTX_OK) {
267 return result;
268 }
269
270 if (ite_valid) {
271 cte_valid = get_cte(s, icid, &cte, &res);
272 }
273
274 if (res != MEMTX_OK) {
275 return result;
276 }
277 }
278
279 if ((devid > s->dt.maxids.max_devids) || !dte_valid || !ite_valid ||
280 !cte_valid || (eventid > max_eventid)) {
281 qemu_log_mask(LOG_GUEST_ERROR,
282 "%s: invalid command attributes "
283 "devid %d or eventid %d or invalid dte %d or"
284 "invalid cte %d or invalid ite %d\n",
285 __func__, devid, eventid, dte_valid, cte_valid,
286 ite_valid);
287
288
289
290
291
292 } else {
293
294
295
296
297 rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
298
299 if (rdbase > s->gicv3->num_cpu) {
300 return result;
301 }
302
303 if ((cmd == CLEAR) || (cmd == DISCARD)) {
304 gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
305 } else {
306 gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
307 }
308
309 if (cmd == DISCARD) {
310 IteEntry ite = {};
311
312 result = update_ite(s, eventid, dte, ite);
313 }
314 }
315
316 return result;
317}
318
319static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
320 bool ignore_pInt)
321{
322 AddressSpace *as = &s->gicv3->dma_as;
323 uint32_t devid, eventid;
324 uint32_t pIntid = 0;
325 uint32_t max_eventid, max_Intid;
326 bool dte_valid;
327 MemTxResult res = MEMTX_OK;
328 uint16_t icid = 0;
329 uint64_t dte = 0;
330 IteEntry ite;
331 uint32_t int_spurious = INTID_SPURIOUS;
332 bool result = false;
333
334 devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
335 offset += NUM_BYTES_IN_DW;
336 value = address_space_ldq_le(as, s->cq.base_addr + offset,
337 MEMTXATTRS_UNSPECIFIED, &res);
338
339 if (res != MEMTX_OK) {
340 return result;
341 }
342
343 eventid = (value & EVENTID_MASK);
344
345 if (!ignore_pInt) {
346 pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
347 }
348
349 offset += NUM_BYTES_IN_DW;
350 value = address_space_ldq_le(as, s->cq.base_addr + offset,
351 MEMTXATTRS_UNSPECIFIED, &res);
352
353 if (res != MEMTX_OK) {
354 return result;
355 }
356
357 icid = value & ICID_MASK;
358
359 dte = get_dte(s, devid, &res);
360
361 if (res != MEMTX_OK) {
362 return result;
363 }
364 dte_valid = dte & TABLE_ENTRY_VALID_MASK;
365
366 max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
367
368 if (!ignore_pInt) {
369 max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
370 }
371
372 if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids)
373 || !dte_valid || (eventid > max_eventid) ||
374 (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
375 (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
376 qemu_log_mask(LOG_GUEST_ERROR,
377 "%s: invalid command attributes "
378 "devid %d or icid %d or eventid %d or pIntid %d or"
379 "unmapped dte %d\n", __func__, devid, icid, eventid,
380 pIntid, dte_valid);
381
382
383
384
385
386 } else {
387
388 ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) |
389 (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT);
390
391 if (ignore_pInt) {
392 ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT);
393 } else {
394 ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
395 }
396 ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
397 ite.iteh = icid;
398
399 result = update_ite(s, eventid, dte, ite);
400 }
401
402 return result;
403}
404
405static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
406 uint64_t rdbase)
407{
408 AddressSpace *as = &s->gicv3->dma_as;
409 uint64_t value;
410 uint64_t l2t_addr;
411 bool valid_l2t;
412 uint32_t l2t_id;
413 uint32_t max_l2_entries;
414 uint64_t cte = 0;
415 MemTxResult res = MEMTX_OK;
416
417 if (!s->ct.valid) {
418 return true;
419 }
420
421 if (valid) {
422
423 cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
424 }
425
426
427
428
429
430
431 if (s->ct.indirect) {
432 l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
433
434 value = address_space_ldq_le(as,
435 s->ct.base_addr +
436 (l2t_id * L1TABLE_ENTRY_SIZE),
437 MEMTXATTRS_UNSPECIFIED, &res);
438
439 if (res != MEMTX_OK) {
440 return false;
441 }
442
443 valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
444
445 if (valid_l2t) {
446 max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
447
448 l2t_addr = value & ((1ULL << 51) - 1);
449
450 address_space_stq_le(as, l2t_addr +
451 ((icid % max_l2_entries) * GITS_CTE_SIZE),
452 cte, MEMTXATTRS_UNSPECIFIED, &res);
453 }
454 } else {
455
456 address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
457 cte, MEMTXATTRS_UNSPECIFIED, &res);
458 }
459 if (res != MEMTX_OK) {
460 return false;
461 } else {
462 return true;
463 }
464}
465
466static bool process_mapc(GICv3ITSState *s, uint32_t offset)
467{
468 AddressSpace *as = &s->gicv3->dma_as;
469 uint16_t icid;
470 uint64_t rdbase;
471 bool valid;
472 MemTxResult res = MEMTX_OK;
473 bool result = false;
474 uint64_t value;
475
476 offset += NUM_BYTES_IN_DW;
477 offset += NUM_BYTES_IN_DW;
478
479 value = address_space_ldq_le(as, s->cq.base_addr + offset,
480 MEMTXATTRS_UNSPECIFIED, &res);
481
482 if (res != MEMTX_OK) {
483 return result;
484 }
485
486 icid = value & ICID_MASK;
487
488 rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
489 rdbase &= RDBASE_PROCNUM_MASK;
490
491 valid = (value & CMD_FIELD_VALID_MASK);
492
493 if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
494 qemu_log_mask(LOG_GUEST_ERROR,
495 "ITS MAPC: invalid collection table attributes "
496 "icid %d rdbase %" PRIu64 "\n", icid, rdbase);
497
498
499
500
501
502 } else {
503 result = update_cte(s, icid, valid, rdbase);
504 }
505
506 return result;
507}
508
509static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
510 uint8_t size, uint64_t itt_addr)
511{
512 AddressSpace *as = &s->gicv3->dma_as;
513 uint64_t value;
514 uint64_t l2t_addr;
515 bool valid_l2t;
516 uint32_t l2t_id;
517 uint32_t max_l2_entries;
518 uint64_t dte = 0;
519 MemTxResult res = MEMTX_OK;
520
521 if (s->dt.valid) {
522 if (valid) {
523
524 dte = (valid & TABLE_ENTRY_VALID_MASK) |
525 ((size & SIZE_MASK) << 1U) |
526 (itt_addr << GITS_DTE_ITTADDR_SHIFT);
527 }
528 } else {
529 return true;
530 }
531
532
533
534
535
536
537 if (s->dt.indirect) {
538 l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
539
540 value = address_space_ldq_le(as,
541 s->dt.base_addr +
542 (l2t_id * L1TABLE_ENTRY_SIZE),
543 MEMTXATTRS_UNSPECIFIED, &res);
544
545 if (res != MEMTX_OK) {
546 return false;
547 }
548
549 valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
550
551 if (valid_l2t) {
552 max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
553
554 l2t_addr = value & ((1ULL << 51) - 1);
555
556 address_space_stq_le(as, l2t_addr +
557 ((devid % max_l2_entries) * GITS_DTE_SIZE),
558 dte, MEMTXATTRS_UNSPECIFIED, &res);
559 }
560 } else {
561
562 address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE),
563 dte, MEMTXATTRS_UNSPECIFIED, &res);
564 }
565 if (res != MEMTX_OK) {
566 return false;
567 } else {
568 return true;
569 }
570}
571
572static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
573{
574 AddressSpace *as = &s->gicv3->dma_as;
575 uint32_t devid;
576 uint8_t size;
577 uint64_t itt_addr;
578 bool valid;
579 MemTxResult res = MEMTX_OK;
580 bool result = false;
581
582 devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
583
584 offset += NUM_BYTES_IN_DW;
585 value = address_space_ldq_le(as, s->cq.base_addr + offset,
586 MEMTXATTRS_UNSPECIFIED, &res);
587
588 if (res != MEMTX_OK) {
589 return result;
590 }
591
592 size = (value & SIZE_MASK);
593
594 offset += NUM_BYTES_IN_DW;
595 value = address_space_ldq_le(as, s->cq.base_addr + offset,
596 MEMTXATTRS_UNSPECIFIED, &res);
597
598 if (res != MEMTX_OK) {
599 return result;
600 }
601
602 itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
603
604 valid = (value & CMD_FIELD_VALID_MASK);
605
606 if ((devid > s->dt.maxids.max_devids) ||
607 (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
608 qemu_log_mask(LOG_GUEST_ERROR,
609 "ITS MAPD: invalid device table attributes "
610 "devid %d or size %d\n", devid, size);
611
612
613
614
615
616 } else {
617 result = update_dte(s, devid, valid, size, itt_addr);
618 }
619
620 return result;
621}
622
623
624
625
626
627static void process_cmdq(GICv3ITSState *s)
628{
629 uint32_t wr_offset = 0;
630 uint32_t rd_offset = 0;
631 uint32_t cq_offset = 0;
632 uint64_t data;
633 AddressSpace *as = &s->gicv3->dma_as;
634 MemTxResult res = MEMTX_OK;
635 bool result = true;
636 uint8_t cmd;
637 int i;
638
639 if (!(s->ctlr & ITS_CTLR_ENABLED)) {
640 return;
641 }
642
643 wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
644
645 if (wr_offset > s->cq.max_entries) {
646 qemu_log_mask(LOG_GUEST_ERROR,
647 "%s: invalid write offset "
648 "%d\n", __func__, wr_offset);
649 return;
650 }
651
652 rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
653
654 if (rd_offset > s->cq.max_entries) {
655 qemu_log_mask(LOG_GUEST_ERROR,
656 "%s: invalid read offset "
657 "%d\n", __func__, rd_offset);
658 return;
659 }
660
661 while (wr_offset != rd_offset) {
662 cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
663 data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
664 MEMTXATTRS_UNSPECIFIED, &res);
665 if (res != MEMTX_OK) {
666 result = false;
667 }
668 cmd = (data & CMD_MASK);
669
670 switch (cmd) {
671 case GITS_CMD_INT:
672 res = process_its_cmd(s, data, cq_offset, INTERRUPT);
673 break;
674 case GITS_CMD_CLEAR:
675 res = process_its_cmd(s, data, cq_offset, CLEAR);
676 break;
677 case GITS_CMD_SYNC:
678
679
680
681
682
683
684 break;
685 case GITS_CMD_MAPD:
686 result = process_mapd(s, data, cq_offset);
687 break;
688 case GITS_CMD_MAPC:
689 result = process_mapc(s, cq_offset);
690 break;
691 case GITS_CMD_MAPTI:
692 result = process_mapti(s, data, cq_offset, false);
693 break;
694 case GITS_CMD_MAPI:
695 result = process_mapti(s, data, cq_offset, true);
696 break;
697 case GITS_CMD_DISCARD:
698 result = process_its_cmd(s, data, cq_offset, DISCARD);
699 break;
700 case GITS_CMD_INV:
701 case GITS_CMD_INVALL:
702
703
704
705
706
707
708 for (i = 0; i < s->gicv3->num_cpu; i++) {
709 gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
710 }
711 break;
712 default:
713 break;
714 }
715 if (result) {
716 rd_offset++;
717 rd_offset %= s->cq.max_entries;
718 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
719 } else {
720
721
722
723
724 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
725 qemu_log_mask(LOG_GUEST_ERROR,
726 "%s: %x cmd processing failed\n", __func__, cmd);
727 break;
728 }
729 }
730}
731
732
733
734
735
736
737static void extract_table_params(GICv3ITSState *s)
738{
739 uint16_t num_pages = 0;
740 uint8_t page_sz_type;
741 uint8_t type;
742 uint32_t page_sz = 0;
743 uint64_t value;
744
745 for (int i = 0; i < 8; i++) {
746 value = s->baser[i];
747
748 if (!value) {
749 continue;
750 }
751
752 page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
753
754 switch (page_sz_type) {
755 case 0:
756 page_sz = GITS_PAGE_SIZE_4K;
757 break;
758
759 case 1:
760 page_sz = GITS_PAGE_SIZE_16K;
761 break;
762
763 case 2:
764 case 3:
765 page_sz = GITS_PAGE_SIZE_64K;
766 break;
767
768 default:
769 g_assert_not_reached();
770 }
771
772 num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
773
774 type = FIELD_EX64(value, GITS_BASER, TYPE);
775
776 switch (type) {
777
778 case GITS_BASER_TYPE_DEVICE:
779 memset(&s->dt, 0 , sizeof(s->dt));
780 s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
781
782 if (!s->dt.valid) {
783 return;
784 }
785
786 s->dt.page_sz = page_sz;
787 s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
788 s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
789
790 if (!s->dt.indirect) {
791 s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
792 } else {
793 s->dt.max_entries = (((num_pages * page_sz) /
794 L1TABLE_ENTRY_SIZE) *
795 (page_sz / s->dt.entry_sz));
796 }
797
798 s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
799 DEVBITS) + 1));
800
801 s->dt.base_addr = baser_base_addr(value, page_sz);
802
803 break;
804
805 case GITS_BASER_TYPE_COLLECTION:
806 memset(&s->ct, 0 , sizeof(s->ct));
807 s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
808
809
810
811
812
813 if (!s->ct.valid) {
814 return;
815 }
816
817 s->ct.page_sz = page_sz;
818 s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
819 s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
820
821 if (!s->ct.indirect) {
822 s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
823 } else {
824 s->ct.max_entries = (((num_pages * page_sz) /
825 L1TABLE_ENTRY_SIZE) *
826 (page_sz / s->ct.entry_sz));
827 }
828
829 if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
830 s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
831 GITS_TYPER, CIDBITS) + 1));
832 } else {
833
834 s->ct.maxids.max_collids = (1UL << 16);
835 }
836
837 s->ct.base_addr = baser_base_addr(value, page_sz);
838
839 break;
840
841 default:
842 break;
843 }
844 }
845}
846
847static void extract_cmdq_params(GICv3ITSState *s)
848{
849 uint16_t num_pages = 0;
850 uint64_t value = s->cbaser;
851
852 num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
853
854 memset(&s->cq, 0 , sizeof(s->cq));
855 s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
856
857 if (s->cq.valid) {
858 s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
859 GITS_CMDQ_ENTRY_SIZE;
860 s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
861 s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
862 }
863}
864
865static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
866 uint64_t data, unsigned size,
867 MemTxAttrs attrs)
868{
869 GICv3ITSState *s = (GICv3ITSState *)opaque;
870 bool result = true;
871 uint32_t devid = 0;
872
873 switch (offset) {
874 case GITS_TRANSLATER:
875 if (s->ctlr & ITS_CTLR_ENABLED) {
876 devid = attrs.requester_id;
877 result = process_its_cmd(s, data, devid, NONE);
878 }
879 break;
880 default:
881 break;
882 }
883
884 if (result) {
885 return MEMTX_OK;
886 } else {
887 return MEMTX_ERROR;
888 }
889}
890
891static bool its_writel(GICv3ITSState *s, hwaddr offset,
892 uint64_t value, MemTxAttrs attrs)
893{
894 bool result = true;
895 int index;
896
897 switch (offset) {
898 case GITS_CTLR:
899 if (value & R_GITS_CTLR_ENABLED_MASK) {
900 s->ctlr |= ITS_CTLR_ENABLED;
901 extract_table_params(s);
902 extract_cmdq_params(s);
903 s->creadr = 0;
904 process_cmdq(s);
905 } else {
906 s->ctlr &= ~ITS_CTLR_ENABLED;
907 }
908 break;
909 case GITS_CBASER:
910
911
912
913
914 if (!(s->ctlr & ITS_CTLR_ENABLED)) {
915 s->cbaser = deposit64(s->cbaser, 0, 32, value);
916 s->creadr = 0;
917 s->cwriter = s->creadr;
918 }
919 break;
920 case GITS_CBASER + 4:
921
922
923
924
925 if (!(s->ctlr & ITS_CTLR_ENABLED)) {
926 s->cbaser = deposit64(s->cbaser, 32, 32, value);
927 s->creadr = 0;
928 s->cwriter = s->creadr;
929 }
930 break;
931 case GITS_CWRITER:
932 s->cwriter = deposit64(s->cwriter, 0, 32,
933 (value & ~R_GITS_CWRITER_RETRY_MASK));
934 if (s->cwriter != s->creadr) {
935 process_cmdq(s);
936 }
937 break;
938 case GITS_CWRITER + 4:
939 s->cwriter = deposit64(s->cwriter, 32, 32, value);
940 break;
941 case GITS_CREADR:
942 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
943 s->creadr = deposit64(s->creadr, 0, 32,
944 (value & ~R_GITS_CREADR_STALLED_MASK));
945 } else {
946
947 qemu_log_mask(LOG_GUEST_ERROR,
948 "%s: invalid guest write to RO register at offset "
949 TARGET_FMT_plx "\n", __func__, offset);
950 }
951 break;
952 case GITS_CREADR + 4:
953 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
954 s->creadr = deposit64(s->creadr, 32, 32, value);
955 } else {
956
957 qemu_log_mask(LOG_GUEST_ERROR,
958 "%s: invalid guest write to RO register at offset "
959 TARGET_FMT_plx "\n", __func__, offset);
960 }
961 break;
962 case GITS_BASER ... GITS_BASER + 0x3f:
963
964
965
966
967 if (!(s->ctlr & ITS_CTLR_ENABLED)) {
968 index = (offset - GITS_BASER) / 8;
969
970 if (offset & 7) {
971 value <<= 32;
972 value &= ~GITS_BASER_RO_MASK;
973 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
974 s->baser[index] |= value;
975 } else {
976 value &= ~GITS_BASER_RO_MASK;
977 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
978 s->baser[index] |= value;
979 }
980 }
981 break;
982 case GITS_IIDR:
983 case GITS_IDREGS ... GITS_IDREGS + 0x2f:
984
985 qemu_log_mask(LOG_GUEST_ERROR,
986 "%s: invalid guest write to RO register at offset "
987 TARGET_FMT_plx "\n", __func__, offset);
988 break;
989 default:
990 result = false;
991 break;
992 }
993 return result;
994}
995
996static bool its_readl(GICv3ITSState *s, hwaddr offset,
997 uint64_t *data, MemTxAttrs attrs)
998{
999 bool result = true;
1000 int index;
1001
1002 switch (offset) {
1003 case GITS_CTLR:
1004 *data = s->ctlr;
1005 break;
1006 case GITS_IIDR:
1007 *data = gicv3_iidr();
1008 break;
1009 case GITS_IDREGS ... GITS_IDREGS + 0x2f:
1010
1011 *data = gicv3_idreg(offset - GITS_IDREGS);
1012 break;
1013 case GITS_TYPER:
1014 *data = extract64(s->typer, 0, 32);
1015 break;
1016 case GITS_TYPER + 4:
1017 *data = extract64(s->typer, 32, 32);
1018 break;
1019 case GITS_CBASER:
1020 *data = extract64(s->cbaser, 0, 32);
1021 break;
1022 case GITS_CBASER + 4:
1023 *data = extract64(s->cbaser, 32, 32);
1024 break;
1025 case GITS_CREADR:
1026 *data = extract64(s->creadr, 0, 32);
1027 break;
1028 case GITS_CREADR + 4:
1029 *data = extract64(s->creadr, 32, 32);
1030 break;
1031 case GITS_CWRITER:
1032 *data = extract64(s->cwriter, 0, 32);
1033 break;
1034 case GITS_CWRITER + 4:
1035 *data = extract64(s->cwriter, 32, 32);
1036 break;
1037 case GITS_BASER ... GITS_BASER + 0x3f:
1038 index = (offset - GITS_BASER) / 8;
1039 if (offset & 7) {
1040 *data = extract64(s->baser[index], 32, 32);
1041 } else {
1042 *data = extract64(s->baser[index], 0, 32);
1043 }
1044 break;
1045 default:
1046 result = false;
1047 break;
1048 }
1049 return result;
1050}
1051
1052static bool its_writell(GICv3ITSState *s, hwaddr offset,
1053 uint64_t value, MemTxAttrs attrs)
1054{
1055 bool result = true;
1056 int index;
1057
1058 switch (offset) {
1059 case GITS_BASER ... GITS_BASER + 0x3f:
1060
1061
1062
1063
1064 if (!(s->ctlr & ITS_CTLR_ENABLED)) {
1065 index = (offset - GITS_BASER) / 8;
1066 s->baser[index] &= GITS_BASER_RO_MASK;
1067 s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
1068 }
1069 break;
1070 case GITS_CBASER:
1071
1072
1073
1074
1075 if (!(s->ctlr & ITS_CTLR_ENABLED)) {
1076 s->cbaser = value;
1077 s->creadr = 0;
1078 s->cwriter = s->creadr;
1079 }
1080 break;
1081 case GITS_CWRITER:
1082 s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
1083 if (s->cwriter != s->creadr) {
1084 process_cmdq(s);
1085 }
1086 break;
1087 case GITS_CREADR:
1088 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1089 s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
1090 } else {
1091
1092 qemu_log_mask(LOG_GUEST_ERROR,
1093 "%s: invalid guest write to RO register at offset "
1094 TARGET_FMT_plx "\n", __func__, offset);
1095 }
1096 break;
1097 case GITS_TYPER:
1098
1099 qemu_log_mask(LOG_GUEST_ERROR,
1100 "%s: invalid guest write to RO register at offset "
1101 TARGET_FMT_plx "\n", __func__, offset);
1102 break;
1103 default:
1104 result = false;
1105 break;
1106 }
1107 return result;
1108}
1109
1110static bool its_readll(GICv3ITSState *s, hwaddr offset,
1111 uint64_t *data, MemTxAttrs attrs)
1112{
1113 bool result = true;
1114 int index;
1115
1116 switch (offset) {
1117 case GITS_TYPER:
1118 *data = s->typer;
1119 break;
1120 case GITS_BASER ... GITS_BASER + 0x3f:
1121 index = (offset - GITS_BASER) / 8;
1122 *data = s->baser[index];
1123 break;
1124 case GITS_CBASER:
1125 *data = s->cbaser;
1126 break;
1127 case GITS_CREADR:
1128 *data = s->creadr;
1129 break;
1130 case GITS_CWRITER:
1131 *data = s->cwriter;
1132 break;
1133 default:
1134 result = false;
1135 break;
1136 }
1137 return result;
1138}
1139
1140static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
1141 unsigned size, MemTxAttrs attrs)
1142{
1143 GICv3ITSState *s = (GICv3ITSState *)opaque;
1144 bool result;
1145
1146 switch (size) {
1147 case 4:
1148 result = its_readl(s, offset, data, attrs);
1149 break;
1150 case 8:
1151 result = its_readll(s, offset, data, attrs);
1152 break;
1153 default:
1154 result = false;
1155 break;
1156 }
1157
1158 if (!result) {
1159 qemu_log_mask(LOG_GUEST_ERROR,
1160 "%s: invalid guest read at offset " TARGET_FMT_plx
1161 "size %u\n", __func__, offset, size);
1162
1163
1164
1165
1166
1167
1168 *data = 0;
1169 }
1170 return MEMTX_OK;
1171}
1172
1173static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
1174 unsigned size, MemTxAttrs attrs)
1175{
1176 GICv3ITSState *s = (GICv3ITSState *)opaque;
1177 bool result;
1178
1179 switch (size) {
1180 case 4:
1181 result = its_writel(s, offset, data, attrs);
1182 break;
1183 case 8:
1184 result = its_writell(s, offset, data, attrs);
1185 break;
1186 default:
1187 result = false;
1188 break;
1189 }
1190
1191 if (!result) {
1192 qemu_log_mask(LOG_GUEST_ERROR,
1193 "%s: invalid guest write at offset " TARGET_FMT_plx
1194 "size %u\n", __func__, offset, size);
1195
1196
1197
1198
1199
1200
1201 }
1202 return MEMTX_OK;
1203}
1204
1205static const MemoryRegionOps gicv3_its_control_ops = {
1206 .read_with_attrs = gicv3_its_read,
1207 .write_with_attrs = gicv3_its_write,
1208 .valid.min_access_size = 4,
1209 .valid.max_access_size = 8,
1210 .impl.min_access_size = 4,
1211 .impl.max_access_size = 8,
1212 .endianness = DEVICE_NATIVE_ENDIAN,
1213};
1214
1215static const MemoryRegionOps gicv3_its_translation_ops = {
1216 .write_with_attrs = gicv3_its_translation_write,
1217 .valid.min_access_size = 2,
1218 .valid.max_access_size = 4,
1219 .impl.min_access_size = 2,
1220 .impl.max_access_size = 4,
1221 .endianness = DEVICE_NATIVE_ENDIAN,
1222};
1223
1224static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
1225{
1226 GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1227 int i;
1228
1229 for (i = 0; i < s->gicv3->num_cpu; i++) {
1230 if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
1231 error_setg(errp, "Physical LPI not supported by CPU %d", i);
1232 return;
1233 }
1234 }
1235
1236 gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
1237
1238 address_space_init(&s->gicv3->dma_as, s->gicv3->dma,
1239 "gicv3-its-sysmem");
1240
1241
1242 s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
1243 GITS_TYPE_PHYSICAL);
1244 s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
1245 ITS_ITT_ENTRY_SIZE - 1);
1246 s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
1247 s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
1248 s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
1249 s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
1250}
1251
1252static void gicv3_its_reset(DeviceState *dev)
1253{
1254 GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1255 GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
1256
1257 c->parent_reset(dev);
1258
1259
1260 s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
1261
1262
1263
1264
1265
1266
1267
1268
1269 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
1270 GITS_BASER_TYPE_DEVICE);
1271 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
1272 GITS_BASER_PAGESIZE_64K);
1273 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
1274 GITS_DTE_SIZE - 1);
1275
1276 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
1277 GITS_BASER_TYPE_COLLECTION);
1278 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
1279 GITS_BASER_PAGESIZE_64K);
1280 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
1281 GITS_CTE_SIZE - 1);
1282}
1283
1284static void gicv3_its_post_load(GICv3ITSState *s)
1285{
1286 if (s->ctlr & ITS_CTLR_ENABLED) {
1287 extract_table_params(s);
1288 extract_cmdq_params(s);
1289 }
1290}
1291
1292static Property gicv3_its_props[] = {
1293 DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
1294 GICv3State *),
1295 DEFINE_PROP_END_OF_LIST(),
1296};
1297
1298static void gicv3_its_class_init(ObjectClass *klass, void *data)
1299{
1300 DeviceClass *dc = DEVICE_CLASS(klass);
1301 GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
1302 GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
1303
1304 dc->realize = gicv3_arm_its_realize;
1305 device_class_set_props(dc, gicv3_its_props);
1306 device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
1307 icc->post_load = gicv3_its_post_load;
1308}
1309
1310static const TypeInfo gicv3_its_info = {
1311 .name = TYPE_ARM_GICV3_ITS,
1312 .parent = TYPE_ARM_GICV3_ITS_COMMON,
1313 .instance_size = sizeof(GICv3ITSState),
1314 .class_init = gicv3_its_class_init,
1315 .class_size = sizeof(GICv3ITSClass),
1316};
1317
1318static void gicv3_its_register_types(void)
1319{
1320 type_register_static(&gicv3_its_info);
1321}
1322
1323type_init(gicv3_its_register_types)
1324