xref: /openbmc/qemu/hw/intc/arm_gicv3_its.c (revision 7eca39e071fc026f06eb3bbe9257d686f1d7e2e1)
1 /*
2  * ITS emulation for a GICv3-based system
3  *
4  * Copyright Linaro.org 2021
5  *
6  * Authors:
7  *  Shashi Mallela <shashi.mallela@linaro.org>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or (at your
10  * option) any later version.  See the COPYING file in the top-level directory.
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 
22 typedef struct GICv3ITSClass GICv3ITSClass;
23 /* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
24 DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
25                      ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
26 
27 struct GICv3ITSClass {
28     GICv3ITSCommonClass parent_class;
29     void (*parent_reset)(DeviceState *dev);
30 };
31 
32 static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
33 {
34     uint64_t result = 0;
35 
36     switch (page_sz) {
37     case GITS_PAGE_SIZE_4K:
38     case GITS_PAGE_SIZE_16K:
39         result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
40         break;
41 
42     case GITS_PAGE_SIZE_64K:
43         result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
44         result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
45         break;
46 
47     default:
48         break;
49     }
50     return result;
51 }
52 
53 static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
54                        uint64_t rdbase)
55 {
56     AddressSpace *as = &s->gicv3->dma_as;
57     uint64_t value;
58     uint64_t l2t_addr;
59     bool valid_l2t;
60     uint32_t l2t_id;
61     uint32_t max_l2_entries;
62     uint64_t cte = 0;
63     MemTxResult res = MEMTX_OK;
64 
65     if (!s->ct.valid) {
66         return true;
67     }
68 
69     if (valid) {
70         /* add mapping entry to collection table */
71         cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
72     }
73 
74     /*
75      * The specification defines the format of level 1 entries of a
76      * 2-level table, but the format of level 2 entries and the format
77      * of flat-mapped tables is IMPDEF.
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             return false;
89         }
90 
91         valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
92 
93         if (valid_l2t) {
94             max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
95 
96             l2t_addr = value & ((1ULL << 51) - 1);
97 
98             address_space_stq_le(as, l2t_addr +
99                                  ((icid % max_l2_entries) * GITS_CTE_SIZE),
100                                  cte, MEMTXATTRS_UNSPECIFIED, &res);
101         }
102     } else {
103         /* Flat level table */
104         address_space_stq_le(as, s->ct.base_addr + (icid * GITS_CTE_SIZE),
105                              cte, MEMTXATTRS_UNSPECIFIED, &res);
106     }
107     if (res != MEMTX_OK) {
108         return false;
109     } else {
110         return true;
111     }
112 }
113 
114 static bool process_mapc(GICv3ITSState *s, uint32_t offset)
115 {
116     AddressSpace *as = &s->gicv3->dma_as;
117     uint16_t icid;
118     uint64_t rdbase;
119     bool valid;
120     MemTxResult res = MEMTX_OK;
121     bool result = false;
122     uint64_t value;
123 
124     offset += NUM_BYTES_IN_DW;
125     offset += NUM_BYTES_IN_DW;
126 
127     value = address_space_ldq_le(as, s->cq.base_addr + offset,
128                                  MEMTXATTRS_UNSPECIFIED, &res);
129 
130     if (res != MEMTX_OK) {
131         return result;
132     }
133 
134     icid = value & ICID_MASK;
135 
136     rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
137     rdbase &= RDBASE_PROCNUM_MASK;
138 
139     valid = (value & CMD_FIELD_VALID_MASK);
140 
141     if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
142         qemu_log_mask(LOG_GUEST_ERROR,
143                       "ITS MAPC: invalid collection table attributes "
144                       "icid %d rdbase %" PRIu64 "\n",  icid, rdbase);
145         /*
146          * in this implementation, in case of error
147          * we ignore this command and move onto the next
148          * command in the queue
149          */
150     } else {
151         result = update_cte(s, icid, valid, rdbase);
152     }
153 
154     return result;
155 }
156 
157 static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
158                        uint8_t size, uint64_t itt_addr)
159 {
160     AddressSpace *as = &s->gicv3->dma_as;
161     uint64_t value;
162     uint64_t l2t_addr;
163     bool valid_l2t;
164     uint32_t l2t_id;
165     uint32_t max_l2_entries;
166     uint64_t dte = 0;
167     MemTxResult res = MEMTX_OK;
168 
169     if (s->dt.valid) {
170         if (valid) {
171             /* add mapping entry to device table */
172             dte = (valid & TABLE_ENTRY_VALID_MASK) |
173                   ((size & SIZE_MASK) << 1U) |
174                   (itt_addr << GITS_DTE_ITTADDR_SHIFT);
175         }
176     } else {
177         return true;
178     }
179 
180     /*
181      * The specification defines the format of level 1 entries of a
182      * 2-level table, but the format of level 2 entries and the format
183      * of flat-mapped tables is IMPDEF.
184      */
185     if (s->dt.indirect) {
186         l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
187 
188         value = address_space_ldq_le(as,
189                                      s->dt.base_addr +
190                                      (l2t_id * L1TABLE_ENTRY_SIZE),
191                                      MEMTXATTRS_UNSPECIFIED, &res);
192 
193         if (res != MEMTX_OK) {
194             return false;
195         }
196 
197         valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
198 
199         if (valid_l2t) {
200             max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
201 
202             l2t_addr = value & ((1ULL << 51) - 1);
203 
204             address_space_stq_le(as, l2t_addr +
205                                  ((devid % max_l2_entries) * GITS_DTE_SIZE),
206                                  dte, MEMTXATTRS_UNSPECIFIED, &res);
207         }
208     } else {
209         /* Flat level table */
210         address_space_stq_le(as, s->dt.base_addr + (devid * GITS_DTE_SIZE),
211                              dte, MEMTXATTRS_UNSPECIFIED, &res);
212     }
213     if (res != MEMTX_OK) {
214         return false;
215     } else {
216         return true;
217     }
218 }
219 
220 static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
221 {
222     AddressSpace *as = &s->gicv3->dma_as;
223     uint32_t devid;
224     uint8_t size;
225     uint64_t itt_addr;
226     bool valid;
227     MemTxResult res = MEMTX_OK;
228     bool result = false;
229 
230     devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
231 
232     offset += NUM_BYTES_IN_DW;
233     value = address_space_ldq_le(as, s->cq.base_addr + offset,
234                                  MEMTXATTRS_UNSPECIFIED, &res);
235 
236     if (res != MEMTX_OK) {
237         return result;
238     }
239 
240     size = (value & SIZE_MASK);
241 
242     offset += NUM_BYTES_IN_DW;
243     value = address_space_ldq_le(as, s->cq.base_addr + offset,
244                                  MEMTXATTRS_UNSPECIFIED, &res);
245 
246     if (res != MEMTX_OK) {
247         return result;
248     }
249 
250     itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
251 
252     valid = (value & CMD_FIELD_VALID_MASK);
253 
254     if ((devid > s->dt.maxids.max_devids) ||
255         (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
256         qemu_log_mask(LOG_GUEST_ERROR,
257                       "ITS MAPD: invalid device table attributes "
258                       "devid %d or size %d\n", devid, size);
259         /*
260          * in this implementation, in case of error
261          * we ignore this command and move onto the next
262          * command in the queue
263          */
264     } else {
265         result = update_dte(s, devid, valid, size, itt_addr);
266     }
267 
268     return result;
269 }
270 
271 /*
272  * Current implementation blocks until all
273  * commands are processed
274  */
275 static void process_cmdq(GICv3ITSState *s)
276 {
277     uint32_t wr_offset = 0;
278     uint32_t rd_offset = 0;
279     uint32_t cq_offset = 0;
280     uint64_t data;
281     AddressSpace *as = &s->gicv3->dma_as;
282     MemTxResult res = MEMTX_OK;
283     bool result = true;
284     uint8_t cmd;
285 
286     if (!(s->ctlr & ITS_CTLR_ENABLED)) {
287         return;
288     }
289 
290     wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
291 
292     if (wr_offset > s->cq.max_entries) {
293         qemu_log_mask(LOG_GUEST_ERROR,
294                       "%s: invalid write offset "
295                       "%d\n", __func__, wr_offset);
296         return;
297     }
298 
299     rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
300 
301     if (rd_offset > s->cq.max_entries) {
302         qemu_log_mask(LOG_GUEST_ERROR,
303                       "%s: invalid read offset "
304                       "%d\n", __func__, rd_offset);
305         return;
306     }
307 
308     while (wr_offset != rd_offset) {
309         cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
310         data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
311                                     MEMTXATTRS_UNSPECIFIED, &res);
312         if (res != MEMTX_OK) {
313             result = false;
314         }
315         cmd = (data & CMD_MASK);
316 
317         switch (cmd) {
318         case GITS_CMD_INT:
319             break;
320         case GITS_CMD_CLEAR:
321             break;
322         case GITS_CMD_SYNC:
323             /*
324              * Current implementation makes a blocking synchronous call
325              * for every command issued earlier, hence the internal state
326              * is already consistent by the time SYNC command is executed.
327              * Hence no further processing is required for SYNC command.
328              */
329             break;
330         case GITS_CMD_MAPD:
331             result = process_mapd(s, data, cq_offset);
332             break;
333         case GITS_CMD_MAPC:
334             result = process_mapc(s, cq_offset);
335             break;
336         case GITS_CMD_MAPTI:
337             break;
338         case GITS_CMD_MAPI:
339             break;
340         case GITS_CMD_DISCARD:
341             break;
342         case GITS_CMD_INV:
343         case GITS_CMD_INVALL:
344             break;
345         default:
346             break;
347         }
348         if (result) {
349             rd_offset++;
350             rd_offset %= s->cq.max_entries;
351             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
352         } else {
353             /*
354              * in this implementation, in case of dma read/write error
355              * we stall the command processing
356              */
357             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
358             qemu_log_mask(LOG_GUEST_ERROR,
359                           "%s: %x cmd processing failed\n", __func__, cmd);
360             break;
361         }
362     }
363 }
364 
365 /*
366  * This function extracts the ITS Device and Collection table specific
367  * parameters (like base_addr, size etc) from GITS_BASER register.
368  * It is called during ITS enable and also during post_load migration
369  */
370 static void extract_table_params(GICv3ITSState *s)
371 {
372     uint16_t num_pages = 0;
373     uint8_t  page_sz_type;
374     uint8_t type;
375     uint32_t page_sz = 0;
376     uint64_t value;
377 
378     for (int i = 0; i < 8; i++) {
379         value = s->baser[i];
380 
381         if (!value) {
382             continue;
383         }
384 
385         page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
386 
387         switch (page_sz_type) {
388         case 0:
389             page_sz = GITS_PAGE_SIZE_4K;
390             break;
391 
392         case 1:
393             page_sz = GITS_PAGE_SIZE_16K;
394             break;
395 
396         case 2:
397         case 3:
398             page_sz = GITS_PAGE_SIZE_64K;
399             break;
400 
401         default:
402             g_assert_not_reached();
403         }
404 
405         num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
406 
407         type = FIELD_EX64(value, GITS_BASER, TYPE);
408 
409         switch (type) {
410 
411         case GITS_BASER_TYPE_DEVICE:
412             memset(&s->dt, 0 , sizeof(s->dt));
413             s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
414 
415             if (!s->dt.valid) {
416                 return;
417             }
418 
419             s->dt.page_sz = page_sz;
420             s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
421             s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
422 
423             if (!s->dt.indirect) {
424                 s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
425             } else {
426                 s->dt.max_entries = (((num_pages * page_sz) /
427                                      L1TABLE_ENTRY_SIZE) *
428                                      (page_sz / s->dt.entry_sz));
429             }
430 
431             s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
432                                        DEVBITS) + 1));
433 
434             s->dt.base_addr = baser_base_addr(value, page_sz);
435 
436             break;
437 
438         case GITS_BASER_TYPE_COLLECTION:
439             memset(&s->ct, 0 , sizeof(s->ct));
440             s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
441 
442             /*
443              * GITS_TYPER.HCC is 0 for this implementation
444              * hence writes are discarded if ct.valid is 0
445              */
446             if (!s->ct.valid) {
447                 return;
448             }
449 
450             s->ct.page_sz = page_sz;
451             s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
452             s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
453 
454             if (!s->ct.indirect) {
455                 s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
456             } else {
457                 s->ct.max_entries = (((num_pages * page_sz) /
458                                      L1TABLE_ENTRY_SIZE) *
459                                      (page_sz / s->ct.entry_sz));
460             }
461 
462             if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
463                 s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
464                                             GITS_TYPER, CIDBITS) + 1));
465             } else {
466                 /* 16-bit CollectionId supported when CIL == 0 */
467                 s->ct.maxids.max_collids = (1UL << 16);
468             }
469 
470             s->ct.base_addr = baser_base_addr(value, page_sz);
471 
472             break;
473 
474         default:
475             break;
476         }
477     }
478 }
479 
480 static void extract_cmdq_params(GICv3ITSState *s)
481 {
482     uint16_t num_pages = 0;
483     uint64_t value = s->cbaser;
484 
485     num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
486 
487     memset(&s->cq, 0 , sizeof(s->cq));
488     s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
489 
490     if (s->cq.valid) {
491         s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
492                              GITS_CMDQ_ENTRY_SIZE;
493         s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
494         s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
495     }
496 }
497 
498 static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
499                                                uint64_t data, unsigned size,
500                                                MemTxAttrs attrs)
501 {
502     return MEMTX_OK;
503 }
504 
505 static bool its_writel(GICv3ITSState *s, hwaddr offset,
506                               uint64_t value, MemTxAttrs attrs)
507 {
508     bool result = true;
509     int index;
510 
511     switch (offset) {
512     case GITS_CTLR:
513         s->ctlr |= (value & ~(s->ctlr));
514 
515         if (s->ctlr & ITS_CTLR_ENABLED) {
516             extract_table_params(s);
517             extract_cmdq_params(s);
518             s->creadr = 0;
519             process_cmdq(s);
520         }
521         break;
522     case GITS_CBASER:
523         /*
524          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
525          *                 already enabled
526          */
527         if (!(s->ctlr & ITS_CTLR_ENABLED)) {
528             s->cbaser = deposit64(s->cbaser, 0, 32, value);
529             s->creadr = 0;
530             s->cwriter = s->creadr;
531         }
532         break;
533     case GITS_CBASER + 4:
534         /*
535          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
536          *                 already enabled
537          */
538         if (!(s->ctlr & ITS_CTLR_ENABLED)) {
539             s->cbaser = deposit64(s->cbaser, 32, 32, value);
540             s->creadr = 0;
541             s->cwriter = s->creadr;
542         }
543         break;
544     case GITS_CWRITER:
545         s->cwriter = deposit64(s->cwriter, 0, 32,
546                                (value & ~R_GITS_CWRITER_RETRY_MASK));
547         if (s->cwriter != s->creadr) {
548             process_cmdq(s);
549         }
550         break;
551     case GITS_CWRITER + 4:
552         s->cwriter = deposit64(s->cwriter, 32, 32, value);
553         break;
554     case GITS_CREADR:
555         if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
556             s->creadr = deposit64(s->creadr, 0, 32,
557                                   (value & ~R_GITS_CREADR_STALLED_MASK));
558         } else {
559             /* RO register, ignore the write */
560             qemu_log_mask(LOG_GUEST_ERROR,
561                           "%s: invalid guest write to RO register at offset "
562                           TARGET_FMT_plx "\n", __func__, offset);
563         }
564         break;
565     case GITS_CREADR + 4:
566         if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
567             s->creadr = deposit64(s->creadr, 32, 32, value);
568         } else {
569             /* RO register, ignore the write */
570             qemu_log_mask(LOG_GUEST_ERROR,
571                           "%s: invalid guest write to RO register at offset "
572                           TARGET_FMT_plx "\n", __func__, offset);
573         }
574         break;
575     case GITS_BASER ... GITS_BASER + 0x3f:
576         /*
577          * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
578          *                 already enabled
579          */
580         if (!(s->ctlr & ITS_CTLR_ENABLED)) {
581             index = (offset - GITS_BASER) / 8;
582 
583             if (offset & 7) {
584                 value <<= 32;
585                 value &= ~GITS_BASER_RO_MASK;
586                 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
587                 s->baser[index] |= value;
588             } else {
589                 value &= ~GITS_BASER_RO_MASK;
590                 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
591                 s->baser[index] |= value;
592             }
593         }
594         break;
595     case GITS_IIDR:
596     case GITS_IDREGS ... GITS_IDREGS + 0x2f:
597         /* RO registers, ignore the write */
598         qemu_log_mask(LOG_GUEST_ERROR,
599                       "%s: invalid guest write to RO register at offset "
600                       TARGET_FMT_plx "\n", __func__, offset);
601         break;
602     default:
603         result = false;
604         break;
605     }
606     return result;
607 }
608 
609 static bool its_readl(GICv3ITSState *s, hwaddr offset,
610                              uint64_t *data, MemTxAttrs attrs)
611 {
612     bool result = true;
613     int index;
614 
615     switch (offset) {
616     case GITS_CTLR:
617         *data = s->ctlr;
618         break;
619     case GITS_IIDR:
620         *data = gicv3_iidr();
621         break;
622     case GITS_IDREGS ... GITS_IDREGS + 0x2f:
623         /* ID registers */
624         *data = gicv3_idreg(offset - GITS_IDREGS);
625         break;
626     case GITS_TYPER:
627         *data = extract64(s->typer, 0, 32);
628         break;
629     case GITS_TYPER + 4:
630         *data = extract64(s->typer, 32, 32);
631         break;
632     case GITS_CBASER:
633         *data = extract64(s->cbaser, 0, 32);
634         break;
635     case GITS_CBASER + 4:
636         *data = extract64(s->cbaser, 32, 32);
637         break;
638     case GITS_CREADR:
639         *data = extract64(s->creadr, 0, 32);
640         break;
641     case GITS_CREADR + 4:
642         *data = extract64(s->creadr, 32, 32);
643         break;
644     case GITS_CWRITER:
645         *data = extract64(s->cwriter, 0, 32);
646         break;
647     case GITS_CWRITER + 4:
648         *data = extract64(s->cwriter, 32, 32);
649         break;
650     case GITS_BASER ... GITS_BASER + 0x3f:
651         index = (offset - GITS_BASER) / 8;
652         if (offset & 7) {
653             *data = extract64(s->baser[index], 32, 32);
654         } else {
655             *data = extract64(s->baser[index], 0, 32);
656         }
657         break;
658     default:
659         result = false;
660         break;
661     }
662     return result;
663 }
664 
665 static bool its_writell(GICv3ITSState *s, hwaddr offset,
666                                uint64_t value, MemTxAttrs attrs)
667 {
668     bool result = true;
669     int index;
670 
671     switch (offset) {
672     case GITS_BASER ... GITS_BASER + 0x3f:
673         /*
674          * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
675          *                 already enabled
676          */
677         if (!(s->ctlr & ITS_CTLR_ENABLED)) {
678             index = (offset - GITS_BASER) / 8;
679             s->baser[index] &= GITS_BASER_RO_MASK;
680             s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
681         }
682         break;
683     case GITS_CBASER:
684         /*
685          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
686          *                 already enabled
687          */
688         if (!(s->ctlr & ITS_CTLR_ENABLED)) {
689             s->cbaser = value;
690             s->creadr = 0;
691             s->cwriter = s->creadr;
692         }
693         break;
694     case GITS_CWRITER:
695         s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
696         if (s->cwriter != s->creadr) {
697             process_cmdq(s);
698         }
699         break;
700     case GITS_CREADR:
701         if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
702             s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
703         } else {
704             /* RO register, ignore the write */
705             qemu_log_mask(LOG_GUEST_ERROR,
706                           "%s: invalid guest write to RO register at offset "
707                           TARGET_FMT_plx "\n", __func__, offset);
708         }
709         break;
710     case GITS_TYPER:
711         /* RO registers, ignore the write */
712         qemu_log_mask(LOG_GUEST_ERROR,
713                       "%s: invalid guest write to RO register at offset "
714                       TARGET_FMT_plx "\n", __func__, offset);
715         break;
716     default:
717         result = false;
718         break;
719     }
720     return result;
721 }
722 
723 static bool its_readll(GICv3ITSState *s, hwaddr offset,
724                               uint64_t *data, MemTxAttrs attrs)
725 {
726     bool result = true;
727     int index;
728 
729     switch (offset) {
730     case GITS_TYPER:
731         *data = s->typer;
732         break;
733     case GITS_BASER ... GITS_BASER + 0x3f:
734         index = (offset - GITS_BASER) / 8;
735         *data = s->baser[index];
736         break;
737     case GITS_CBASER:
738         *data = s->cbaser;
739         break;
740     case GITS_CREADR:
741         *data = s->creadr;
742         break;
743     case GITS_CWRITER:
744         *data = s->cwriter;
745         break;
746     default:
747         result = false;
748         break;
749     }
750     return result;
751 }
752 
753 static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
754                                   unsigned size, MemTxAttrs attrs)
755 {
756     GICv3ITSState *s = (GICv3ITSState *)opaque;
757     bool result;
758 
759     switch (size) {
760     case 4:
761         result = its_readl(s, offset, data, attrs);
762         break;
763     case 8:
764         result = its_readll(s, offset, data, attrs);
765         break;
766     default:
767         result = false;
768         break;
769     }
770 
771     if (!result) {
772         qemu_log_mask(LOG_GUEST_ERROR,
773                       "%s: invalid guest read at offset " TARGET_FMT_plx
774                       "size %u\n", __func__, offset, size);
775         /*
776          * The spec requires that reserved registers are RAZ/WI;
777          * so use false returns from leaf functions as a way to
778          * trigger the guest-error logging but don't return it to
779          * the caller, or we'll cause a spurious guest data abort.
780          */
781         *data = 0;
782     }
783     return MEMTX_OK;
784 }
785 
786 static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
787                                    unsigned size, MemTxAttrs attrs)
788 {
789     GICv3ITSState *s = (GICv3ITSState *)opaque;
790     bool result;
791 
792     switch (size) {
793     case 4:
794         result = its_writel(s, offset, data, attrs);
795         break;
796     case 8:
797         result = its_writell(s, offset, data, attrs);
798         break;
799     default:
800         result = false;
801         break;
802     }
803 
804     if (!result) {
805         qemu_log_mask(LOG_GUEST_ERROR,
806                       "%s: invalid guest write at offset " TARGET_FMT_plx
807                       "size %u\n", __func__, offset, size);
808         /*
809          * The spec requires that reserved registers are RAZ/WI;
810          * so use false returns from leaf functions as a way to
811          * trigger the guest-error logging but don't return it to
812          * the caller, or we'll cause a spurious guest data abort.
813          */
814     }
815     return MEMTX_OK;
816 }
817 
818 static const MemoryRegionOps gicv3_its_control_ops = {
819     .read_with_attrs = gicv3_its_read,
820     .write_with_attrs = gicv3_its_write,
821     .valid.min_access_size = 4,
822     .valid.max_access_size = 8,
823     .impl.min_access_size = 4,
824     .impl.max_access_size = 8,
825     .endianness = DEVICE_NATIVE_ENDIAN,
826 };
827 
828 static const MemoryRegionOps gicv3_its_translation_ops = {
829     .write_with_attrs = gicv3_its_translation_write,
830     .valid.min_access_size = 2,
831     .valid.max_access_size = 4,
832     .impl.min_access_size = 2,
833     .impl.max_access_size = 4,
834     .endianness = DEVICE_NATIVE_ENDIAN,
835 };
836 
837 static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
838 {
839     GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
840     int i;
841 
842     for (i = 0; i < s->gicv3->num_cpu; i++) {
843         if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
844             error_setg(errp, "Physical LPI not supported by CPU %d", i);
845             return;
846         }
847     }
848 
849     gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
850 
851     address_space_init(&s->gicv3->dma_as, s->gicv3->dma,
852                        "gicv3-its-sysmem");
853 
854     /* set the ITS default features supported */
855     s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
856                           GITS_TYPE_PHYSICAL);
857     s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
858                           ITS_ITT_ENTRY_SIZE - 1);
859     s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
860     s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
861     s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
862     s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
863 }
864 
865 static void gicv3_its_reset(DeviceState *dev)
866 {
867     GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
868     GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
869 
870     c->parent_reset(dev);
871 
872     /* Quiescent bit reset to 1 */
873     s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
874 
875     /*
876      * setting GITS_BASER0.Type = 0b001 (Device)
877      *         GITS_BASER1.Type = 0b100 (Collection Table)
878      *         GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
879      *         GITS_BASER<0,1>.Page_Size = 64KB
880      * and default translation table entry size to 16 bytes
881      */
882     s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
883                              GITS_BASER_TYPE_DEVICE);
884     s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
885                              GITS_BASER_PAGESIZE_64K);
886     s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
887                              GITS_DTE_SIZE - 1);
888 
889     s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
890                              GITS_BASER_TYPE_COLLECTION);
891     s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
892                              GITS_BASER_PAGESIZE_64K);
893     s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
894                              GITS_CTE_SIZE - 1);
895 }
896 
897 static void gicv3_its_post_load(GICv3ITSState *s)
898 {
899     if (s->ctlr & ITS_CTLR_ENABLED) {
900         extract_table_params(s);
901         extract_cmdq_params(s);
902     }
903 }
904 
905 static Property gicv3_its_props[] = {
906     DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
907                      GICv3State *),
908     DEFINE_PROP_END_OF_LIST(),
909 };
910 
911 static void gicv3_its_class_init(ObjectClass *klass, void *data)
912 {
913     DeviceClass *dc = DEVICE_CLASS(klass);
914     GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
915     GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
916 
917     dc->realize = gicv3_arm_its_realize;
918     device_class_set_props(dc, gicv3_its_props);
919     device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
920     icc->post_load = gicv3_its_post_load;
921 }
922 
923 static const TypeInfo gicv3_its_info = {
924     .name = TYPE_ARM_GICV3_ITS,
925     .parent = TYPE_ARM_GICV3_ITS_COMMON,
926     .instance_size = sizeof(GICv3ITSState),
927     .class_init = gicv3_its_class_init,
928     .class_size = sizeof(GICv3ITSClass),
929 };
930 
931 static void gicv3_its_register_types(void)
932 {
933     type_register_static(&gicv3_its_info);
934 }
935 
936 type_init(gicv3_its_register_types)
937