xref: /openbmc/qemu/hw/intc/arm_gicv3_its.c (revision b21e2380)
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 "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 
23 typedef struct GICv3ITSClass GICv3ITSClass;
24 /* This is reusing the GICv3ITSState typedef from ARM_GICV3_ITS_COMMON */
25 DECLARE_OBJ_CHECKERS(GICv3ITSState, GICv3ITSClass,
26                      ARM_GICV3_ITS, TYPE_ARM_GICV3_ITS)
27 
28 struct GICv3ITSClass {
29     GICv3ITSCommonClass parent_class;
30     void (*parent_reset)(DeviceState *dev);
31 };
32 
33 /*
34  * This is an internal enum used to distinguish between LPI triggered
35  * via command queue and LPI triggered via gits_translater write.
36  */
37 typedef enum ItsCmdType {
38     NONE = 0, /* internal indication for GITS_TRANSLATER write */
39     CLEAR = 1,
40     DISCARD = 2,
41     INTERRUPT = 3,
42 } ItsCmdType;
43 
44 typedef struct DTEntry {
45     bool valid;
46     unsigned size;
47     uint64_t ittaddr;
48 } DTEntry;
49 
50 typedef struct CTEntry {
51     bool valid;
52     uint32_t rdbase;
53 } CTEntry;
54 
55 typedef 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 
64 
65 /*
66  * The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
67  * if a command parameter is not correct. These include both "stall
68  * processing of the command queue" and "ignore this command, and
69  * keep processing the queue". In our implementation we choose that
70  * memory transaction errors reading the command packet provoke a
71  * stall, but errors in parameters cause us to ignore the command
72  * and continue processing.
73  * The process_* functions which handle individual ITS commands all
74  * return an ItsCmdResult which tells process_cmdq() whether it should
75  * stall or keep going.
76  */
77 typedef enum ItsCmdResult {
78     CMD_STALL = 0,
79     CMD_CONTINUE = 1,
80 } ItsCmdResult;
81 
82 static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
83 {
84     uint64_t result = 0;
85 
86     switch (page_sz) {
87     case GITS_PAGE_SIZE_4K:
88     case GITS_PAGE_SIZE_16K:
89         result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
90         break;
91 
92     case GITS_PAGE_SIZE_64K:
93         result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
94         result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
95         break;
96 
97     default:
98         break;
99     }
100     return result;
101 }
102 
103 static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
104                                  uint32_t idx, MemTxResult *res)
105 {
106     /*
107      * Given a TableDesc describing one of the ITS in-guest-memory
108      * tables and an index into it, return the guest address
109      * corresponding to that table entry.
110      * If there was a memory error reading the L1 table of an
111      * indirect table, *res is set accordingly, and we return -1.
112      * If the L1 table entry is marked not valid, we return -1 with
113      * *res set to MEMTX_OK.
114      *
115      * The specification defines the format of level 1 entries of a
116      * 2-level table, but the format of level 2 entries and the format
117      * of flat-mapped tables is IMPDEF.
118      */
119     AddressSpace *as = &s->gicv3->dma_as;
120     uint32_t l2idx;
121     uint64_t l2;
122     uint32_t num_l2_entries;
123 
124     *res = MEMTX_OK;
125 
126     if (!td->indirect) {
127         /* Single level table */
128         return td->base_addr + idx * td->entry_sz;
129     }
130 
131     /* Two level table */
132     l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE);
133 
134     l2 = address_space_ldq_le(as,
135                               td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE),
136                               MEMTXATTRS_UNSPECIFIED, res);
137     if (*res != MEMTX_OK) {
138         return -1;
139     }
140     if (!(l2 & L2_TABLE_VALID_MASK)) {
141         return -1;
142     }
143 
144     num_l2_entries = td->page_sz / td->entry_sz;
145     return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz;
146 }
147 
148 /*
149  * Read the Collection Table entry at index @icid. On success (including
150  * successfully determining that there is no valid CTE for this index),
151  * we return MEMTX_OK and populate the CTEntry struct @cte accordingly.
152  * If there is an error reading memory then we return the error code.
153  */
154 static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
155 {
156     AddressSpace *as = &s->gicv3->dma_as;
157     MemTxResult res = MEMTX_OK;
158     uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, &res);
159     uint64_t cteval;
160 
161     if (entry_addr == -1) {
162         /* No L2 table entry, i.e. no valid CTE, or a memory error */
163         cte->valid = false;
164         goto out;
165     }
166 
167     cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
168     if (res != MEMTX_OK) {
169         goto out;
170     }
171     cte->valid = FIELD_EX64(cteval, CTE, VALID);
172     cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE);
173 out:
174     if (res != MEMTX_OK) {
175         trace_gicv3_its_cte_read_fault(icid);
176     } else {
177         trace_gicv3_its_cte_read(icid, cte->valid, cte->rdbase);
178     }
179     return res;
180 }
181 
182 /*
183  * Update the Interrupt Table entry at index @evinted in the table specified
184  * by the dte @dte. Returns true on success, false if there was a memory
185  * access error.
186  */
187 static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
188                        const ITEntry *ite)
189 {
190     AddressSpace *as = &s->gicv3->dma_as;
191     MemTxResult res = MEMTX_OK;
192     hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
193     uint64_t itel = 0;
194     uint32_t iteh = 0;
195 
196     trace_gicv3_its_ite_write(dte->ittaddr, eventid, ite->valid,
197                               ite->inttype, ite->intid, ite->icid,
198                               ite->vpeid, ite->doorbell);
199 
200     if (ite->valid) {
201         itel = FIELD_DP64(itel, ITE_L, VALID, 1);
202         itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype);
203         itel = FIELD_DP64(itel, ITE_L, INTID, ite->intid);
204         itel = FIELD_DP64(itel, ITE_L, ICID, ite->icid);
205         itel = FIELD_DP64(itel, ITE_L, VPEID, ite->vpeid);
206         iteh = FIELD_DP32(iteh, ITE_H, DOORBELL, ite->doorbell);
207     }
208 
209     address_space_stq_le(as, iteaddr, itel, MEMTXATTRS_UNSPECIFIED, &res);
210     if (res != MEMTX_OK) {
211         return false;
212     }
213     address_space_stl_le(as, iteaddr + 8, iteh, MEMTXATTRS_UNSPECIFIED, &res);
214     return res == MEMTX_OK;
215 }
216 
217 /*
218  * Read the Interrupt Table entry at index @eventid from the table specified
219  * by the DTE @dte. On success, we return MEMTX_OK and populate the ITEntry
220  * struct @ite accordingly. If there is an error reading memory then we return
221  * the error code.
222  */
223 static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
224                            const DTEntry *dte, ITEntry *ite)
225 {
226     AddressSpace *as = &s->gicv3->dma_as;
227     MemTxResult res = MEMTX_OK;
228     uint64_t itel;
229     uint32_t iteh;
230     hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
231 
232     itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
233     if (res != MEMTX_OK) {
234         trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
235         return res;
236     }
237 
238     iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res);
239     if (res != MEMTX_OK) {
240         trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
241         return res;
242     }
243 
244     ite->valid = FIELD_EX64(itel, ITE_L, VALID);
245     ite->inttype = FIELD_EX64(itel, ITE_L, INTTYPE);
246     ite->intid = FIELD_EX64(itel, ITE_L, INTID);
247     ite->icid = FIELD_EX64(itel, ITE_L, ICID);
248     ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID);
249     ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL);
250     trace_gicv3_its_ite_read(dte->ittaddr, eventid, ite->valid,
251                              ite->inttype, ite->intid, ite->icid,
252                              ite->vpeid, ite->doorbell);
253     return MEMTX_OK;
254 }
255 
256 /*
257  * Read the Device Table entry at index @devid. On success (including
258  * successfully determining that there is no valid DTE for this index),
259  * we return MEMTX_OK and populate the DTEntry struct accordingly.
260  * If there is an error reading memory then we return the error code.
261  */
262 static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
263 {
264     MemTxResult res = MEMTX_OK;
265     AddressSpace *as = &s->gicv3->dma_as;
266     uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, &res);
267     uint64_t dteval;
268 
269     if (entry_addr == -1) {
270         /* No L2 table entry, i.e. no valid DTE, or a memory error */
271         dte->valid = false;
272         goto out;
273     }
274     dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
275     if (res != MEMTX_OK) {
276         goto out;
277     }
278     dte->valid = FIELD_EX64(dteval, DTE, VALID);
279     dte->size = FIELD_EX64(dteval, DTE, SIZE);
280     /* DTE word field stores bits [51:8] of the ITT address */
281     dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT;
282 out:
283     if (res != MEMTX_OK) {
284         trace_gicv3_its_dte_read_fault(devid);
285     } else {
286         trace_gicv3_its_dte_read(devid, dte->valid, dte->size, dte->ittaddr);
287     }
288     return res;
289 }
290 
291 /*
292  * This function handles the processing of following commands based on
293  * the ItsCmdType parameter passed:-
294  * 1. triggering of lpi interrupt translation via ITS INT command
295  * 2. triggering of lpi interrupt translation via gits_translater register
296  * 3. handling of ITS CLEAR command
297  * 4. handling of ITS DISCARD command
298  */
299 static ItsCmdResult do_process_its_cmd(GICv3ITSState *s, uint32_t devid,
300                                        uint32_t eventid, ItsCmdType cmd)
301 {
302     uint64_t num_eventids;
303     DTEntry dte;
304     CTEntry cte;
305     ITEntry ite;
306 
307     if (devid >= s->dt.num_entries) {
308         qemu_log_mask(LOG_GUEST_ERROR,
309                       "%s: invalid command attributes: devid %d>=%d",
310                       __func__, devid, s->dt.num_entries);
311         return CMD_CONTINUE;
312     }
313 
314     if (get_dte(s, devid, &dte) != MEMTX_OK) {
315         return CMD_STALL;
316     }
317     if (!dte.valid) {
318         qemu_log_mask(LOG_GUEST_ERROR,
319                       "%s: invalid command attributes: "
320                       "invalid dte for %d\n", __func__, devid);
321         return CMD_CONTINUE;
322     }
323 
324     num_eventids = 1ULL << (dte.size + 1);
325     if (eventid >= num_eventids) {
326         qemu_log_mask(LOG_GUEST_ERROR,
327                       "%s: invalid command attributes: eventid %d >= %"
328                       PRId64 "\n",
329                       __func__, eventid, num_eventids);
330         return CMD_CONTINUE;
331     }
332 
333     if (get_ite(s, eventid, &dte, &ite) != MEMTX_OK) {
334         return CMD_STALL;
335     }
336 
337     if (!ite.valid || ite.inttype != ITE_INTTYPE_PHYSICAL) {
338         qemu_log_mask(LOG_GUEST_ERROR,
339                       "%s: invalid command attributes: invalid ITE\n",
340                       __func__);
341         return CMD_CONTINUE;
342     }
343 
344     if (ite.icid >= s->ct.num_entries) {
345         qemu_log_mask(LOG_GUEST_ERROR,
346                       "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
347                       __func__, ite.icid);
348         return CMD_CONTINUE;
349     }
350 
351     if (get_cte(s, ite.icid, &cte) != MEMTX_OK) {
352         return CMD_STALL;
353     }
354     if (!cte.valid) {
355         qemu_log_mask(LOG_GUEST_ERROR,
356                       "%s: invalid command attributes: invalid CTE\n",
357                       __func__);
358         return CMD_CONTINUE;
359     }
360 
361     /*
362      * Current implementation only supports rdbase == procnum
363      * Hence rdbase physical address is ignored
364      */
365     if (cte.rdbase >= s->gicv3->num_cpu) {
366         return CMD_CONTINUE;
367     }
368 
369     if ((cmd == CLEAR) || (cmd == DISCARD)) {
370         gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 0);
371     } else {
372         gicv3_redist_process_lpi(&s->gicv3->cpu[cte.rdbase], ite.intid, 1);
373     }
374 
375     if (cmd == DISCARD) {
376         ITEntry ite = {};
377         /* remove mapping from interrupt translation table */
378         ite.valid = false;
379         return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
380     }
381     return CMD_CONTINUE;
382 }
383 static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
384                                     ItsCmdType cmd)
385 {
386     uint32_t devid, eventid;
387 
388     devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
389     eventid = cmdpkt[1] & EVENTID_MASK;
390     switch (cmd) {
391     case INTERRUPT:
392         trace_gicv3_its_cmd_int(devid, eventid);
393         break;
394     case CLEAR:
395         trace_gicv3_its_cmd_clear(devid, eventid);
396         break;
397     case DISCARD:
398         trace_gicv3_its_cmd_discard(devid, eventid);
399         break;
400     default:
401         g_assert_not_reached();
402     }
403     return do_process_its_cmd(s, devid, eventid, cmd);
404 }
405 
406 static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
407                                   bool ignore_pInt)
408 {
409     uint32_t devid, eventid;
410     uint32_t pIntid = 0;
411     uint64_t num_eventids;
412     uint32_t num_intids;
413     uint16_t icid = 0;
414     DTEntry dte;
415     ITEntry ite;
416 
417     devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
418     eventid = cmdpkt[1] & EVENTID_MASK;
419     icid = cmdpkt[2] & ICID_MASK;
420 
421     if (ignore_pInt) {
422         pIntid = eventid;
423         trace_gicv3_its_cmd_mapi(devid, eventid, icid);
424     } else {
425         pIntid = (cmdpkt[1] & pINTID_MASK) >> pINTID_SHIFT;
426         trace_gicv3_its_cmd_mapti(devid, eventid, icid, pIntid);
427     }
428 
429     if (devid >= s->dt.num_entries) {
430         qemu_log_mask(LOG_GUEST_ERROR,
431                       "%s: invalid command attributes: devid %d>=%d",
432                       __func__, devid, s->dt.num_entries);
433         return CMD_CONTINUE;
434     }
435 
436     if (get_dte(s, devid, &dte) != MEMTX_OK) {
437         return CMD_STALL;
438     }
439     num_eventids = 1ULL << (dte.size + 1);
440     num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
441 
442     if (icid >= s->ct.num_entries) {
443         qemu_log_mask(LOG_GUEST_ERROR,
444                       "%s: invalid ICID 0x%x >= 0x%x\n",
445                       __func__, icid, s->ct.num_entries);
446         return CMD_CONTINUE;
447     }
448 
449     if (!dte.valid) {
450         qemu_log_mask(LOG_GUEST_ERROR,
451                       "%s: no valid DTE for devid 0x%x\n", __func__, devid);
452         return CMD_CONTINUE;
453     }
454 
455     if (eventid >= num_eventids) {
456         qemu_log_mask(LOG_GUEST_ERROR,
457                       "%s: invalid event ID 0x%x >= 0x%" PRIx64 "\n",
458                       __func__, eventid, num_eventids);
459         return CMD_CONTINUE;
460     }
461 
462     if (pIntid < GICV3_LPI_INTID_START || pIntid >= num_intids) {
463         qemu_log_mask(LOG_GUEST_ERROR,
464                       "%s: invalid interrupt ID 0x%x\n", __func__, pIntid);
465         return CMD_CONTINUE;
466     }
467 
468     /* add ite entry to interrupt translation table */
469     ite.valid = true;
470     ite.inttype = ITE_INTTYPE_PHYSICAL;
471     ite.intid = pIntid;
472     ite.icid = icid;
473     ite.doorbell = INTID_SPURIOUS;
474     ite.vpeid = 0;
475     return update_ite(s, eventid, &dte, &ite) ? CMD_CONTINUE : CMD_STALL;
476 }
477 
478 /*
479  * Update the Collection Table entry for @icid to @cte. Returns true
480  * on success, false if there was a memory access error.
481  */
482 static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
483 {
484     AddressSpace *as = &s->gicv3->dma_as;
485     uint64_t entry_addr;
486     uint64_t cteval = 0;
487     MemTxResult res = MEMTX_OK;
488 
489     trace_gicv3_its_cte_write(icid, cte->valid, cte->rdbase);
490 
491     if (cte->valid) {
492         /* add mapping entry to collection table */
493         cteval = FIELD_DP64(cteval, CTE, VALID, 1);
494         cteval = FIELD_DP64(cteval, CTE, RDBASE, cte->rdbase);
495     }
496 
497     entry_addr = table_entry_addr(s, &s->ct, icid, &res);
498     if (res != MEMTX_OK) {
499         /* memory access error: stall */
500         return false;
501     }
502     if (entry_addr == -1) {
503         /* No L2 table for this index: discard write and continue */
504         return true;
505     }
506 
507     address_space_stq_le(as, entry_addr, cteval, MEMTXATTRS_UNSPECIFIED, &res);
508     return res == MEMTX_OK;
509 }
510 
511 static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
512 {
513     uint16_t icid;
514     CTEntry cte;
515 
516     icid = cmdpkt[2] & ICID_MASK;
517     cte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
518     if (cte.valid) {
519         cte.rdbase = (cmdpkt[2] & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
520         cte.rdbase &= RDBASE_PROCNUM_MASK;
521     } else {
522         cte.rdbase = 0;
523     }
524     trace_gicv3_its_cmd_mapc(icid, cte.rdbase, cte.valid);
525 
526     if (icid >= s->ct.num_entries) {
527         qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid ICID 0x%d", icid);
528         return CMD_CONTINUE;
529     }
530     if (cte.valid && cte.rdbase >= s->gicv3->num_cpu) {
531         qemu_log_mask(LOG_GUEST_ERROR,
532                       "ITS MAPC: invalid RDBASE %u ", cte.rdbase);
533         return CMD_CONTINUE;
534     }
535 
536     return update_cte(s, icid, &cte) ? CMD_CONTINUE : CMD_STALL;
537 }
538 
539 /*
540  * Update the Device Table entry for @devid to @dte. Returns true
541  * on success, false if there was a memory access error.
542  */
543 static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
544 {
545     AddressSpace *as = &s->gicv3->dma_as;
546     uint64_t entry_addr;
547     uint64_t dteval = 0;
548     MemTxResult res = MEMTX_OK;
549 
550     trace_gicv3_its_dte_write(devid, dte->valid, dte->size, dte->ittaddr);
551 
552     if (dte->valid) {
553         /* add mapping entry to device table */
554         dteval = FIELD_DP64(dteval, DTE, VALID, 1);
555         dteval = FIELD_DP64(dteval, DTE, SIZE, dte->size);
556         dteval = FIELD_DP64(dteval, DTE, ITTADDR, dte->ittaddr);
557     }
558 
559     entry_addr = table_entry_addr(s, &s->dt, devid, &res);
560     if (res != MEMTX_OK) {
561         /* memory access error: stall */
562         return false;
563     }
564     if (entry_addr == -1) {
565         /* No L2 table for this index: discard write and continue */
566         return true;
567     }
568     address_space_stq_le(as, entry_addr, dteval, MEMTXATTRS_UNSPECIFIED, &res);
569     return res == MEMTX_OK;
570 }
571 
572 static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
573 {
574     uint32_t devid;
575     DTEntry dte;
576 
577     devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
578     dte.size = cmdpkt[1] & SIZE_MASK;
579     dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
580     dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
581 
582     trace_gicv3_its_cmd_mapd(devid, dte.size, dte.ittaddr, dte.valid);
583 
584     if (devid >= s->dt.num_entries) {
585         qemu_log_mask(LOG_GUEST_ERROR,
586                       "ITS MAPD: invalid device ID field 0x%x >= 0x%x\n",
587                       devid, s->dt.num_entries);
588         return CMD_CONTINUE;
589     }
590 
591     if (dte.size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS)) {
592         qemu_log_mask(LOG_GUEST_ERROR,
593                       "ITS MAPD: invalid size %d\n", dte.size);
594         return CMD_CONTINUE;
595     }
596 
597     return update_dte(s, devid, &dte) ? CMD_CONTINUE : CMD_STALL;
598 }
599 
600 static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
601 {
602     uint64_t rd1, rd2;
603 
604     rd1 = FIELD_EX64(cmdpkt[2], MOVALL_2, RDBASE1);
605     rd2 = FIELD_EX64(cmdpkt[3], MOVALL_3, RDBASE2);
606 
607     trace_gicv3_its_cmd_movall(rd1, rd2);
608 
609     if (rd1 >= s->gicv3->num_cpu) {
610         qemu_log_mask(LOG_GUEST_ERROR,
611                       "%s: RDBASE1 %" PRId64
612                       " out of range (must be less than %d)\n",
613                       __func__, rd1, s->gicv3->num_cpu);
614         return CMD_CONTINUE;
615     }
616     if (rd2 >= s->gicv3->num_cpu) {
617         qemu_log_mask(LOG_GUEST_ERROR,
618                       "%s: RDBASE2 %" PRId64
619                       " out of range (must be less than %d)\n",
620                       __func__, rd2, s->gicv3->num_cpu);
621         return CMD_CONTINUE;
622     }
623 
624     if (rd1 == rd2) {
625         /* Move to same target must succeed as a no-op */
626         return CMD_CONTINUE;
627     }
628 
629     /* Move all pending LPIs from redistributor 1 to redistributor 2 */
630     gicv3_redist_movall_lpis(&s->gicv3->cpu[rd1], &s->gicv3->cpu[rd2]);
631 
632     return CMD_CONTINUE;
633 }
634 
635 static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
636 {
637     uint32_t devid, eventid;
638     uint16_t new_icid;
639     uint64_t num_eventids;
640     DTEntry dte;
641     CTEntry old_cte, new_cte;
642     ITEntry old_ite;
643 
644     devid = FIELD_EX64(cmdpkt[0], MOVI_0, DEVICEID);
645     eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
646     new_icid = FIELD_EX64(cmdpkt[2], MOVI_2, ICID);
647 
648     trace_gicv3_its_cmd_movi(devid, eventid, new_icid);
649 
650     if (devid >= s->dt.num_entries) {
651         qemu_log_mask(LOG_GUEST_ERROR,
652                       "%s: invalid command attributes: devid %d>=%d",
653                       __func__, devid, s->dt.num_entries);
654         return CMD_CONTINUE;
655     }
656     if (get_dte(s, devid, &dte) != MEMTX_OK) {
657         return CMD_STALL;
658     }
659 
660     if (!dte.valid) {
661         qemu_log_mask(LOG_GUEST_ERROR,
662                       "%s: invalid command attributes: "
663                       "invalid dte for %d\n", __func__, devid);
664         return CMD_CONTINUE;
665     }
666 
667     num_eventids = 1ULL << (dte.size + 1);
668     if (eventid >= num_eventids) {
669         qemu_log_mask(LOG_GUEST_ERROR,
670                       "%s: invalid command attributes: eventid %d >= %"
671                       PRId64 "\n",
672                       __func__, eventid, num_eventids);
673         return CMD_CONTINUE;
674     }
675 
676     if (get_ite(s, eventid, &dte, &old_ite) != MEMTX_OK) {
677         return CMD_STALL;
678     }
679 
680     if (!old_ite.valid || old_ite.inttype != ITE_INTTYPE_PHYSICAL) {
681         qemu_log_mask(LOG_GUEST_ERROR,
682                       "%s: invalid command attributes: invalid ITE\n",
683                       __func__);
684         return CMD_CONTINUE;
685     }
686 
687     if (old_ite.icid >= s->ct.num_entries) {
688         qemu_log_mask(LOG_GUEST_ERROR,
689                       "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
690                       __func__, old_ite.icid);
691         return CMD_CONTINUE;
692     }
693 
694     if (new_icid >= s->ct.num_entries) {
695         qemu_log_mask(LOG_GUEST_ERROR,
696                       "%s: invalid command attributes: ICID 0x%x\n",
697                       __func__, new_icid);
698         return CMD_CONTINUE;
699     }
700 
701     if (get_cte(s, old_ite.icid, &old_cte) != MEMTX_OK) {
702         return CMD_STALL;
703     }
704     if (!old_cte.valid) {
705         qemu_log_mask(LOG_GUEST_ERROR,
706                       "%s: invalid command attributes: "
707                       "invalid CTE for old ICID 0x%x\n",
708                       __func__, old_ite.icid);
709         return CMD_CONTINUE;
710     }
711 
712     if (get_cte(s, new_icid, &new_cte) != MEMTX_OK) {
713         return CMD_STALL;
714     }
715     if (!new_cte.valid) {
716         qemu_log_mask(LOG_GUEST_ERROR,
717                       "%s: invalid command attributes: "
718                       "invalid CTE for new ICID 0x%x\n",
719                       __func__, new_icid);
720         return CMD_CONTINUE;
721     }
722 
723     if (old_cte.rdbase >= s->gicv3->num_cpu) {
724         qemu_log_mask(LOG_GUEST_ERROR,
725                       "%s: CTE has invalid rdbase 0x%x\n",
726                       __func__, old_cte.rdbase);
727         return CMD_CONTINUE;
728     }
729 
730     if (new_cte.rdbase >= s->gicv3->num_cpu) {
731         qemu_log_mask(LOG_GUEST_ERROR,
732                       "%s: CTE has invalid rdbase 0x%x\n",
733                       __func__, new_cte.rdbase);
734         return CMD_CONTINUE;
735     }
736 
737     if (old_cte.rdbase != new_cte.rdbase) {
738         /* Move the LPI from the old redistributor to the new one */
739         gicv3_redist_mov_lpi(&s->gicv3->cpu[old_cte.rdbase],
740                              &s->gicv3->cpu[new_cte.rdbase],
741                              old_ite.intid);
742     }
743 
744     /* Update the ICID field in the interrupt translation table entry */
745     old_ite.icid = new_icid;
746     return update_ite(s, eventid, &dte, &old_ite) ? CMD_CONTINUE : CMD_STALL;
747 }
748 
749 /*
750  * Current implementation blocks until all
751  * commands are processed
752  */
753 static void process_cmdq(GICv3ITSState *s)
754 {
755     uint32_t wr_offset = 0;
756     uint32_t rd_offset = 0;
757     uint32_t cq_offset = 0;
758     AddressSpace *as = &s->gicv3->dma_as;
759     uint8_t cmd;
760     int i;
761 
762     if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
763         return;
764     }
765 
766     wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
767 
768     if (wr_offset >= s->cq.num_entries) {
769         qemu_log_mask(LOG_GUEST_ERROR,
770                       "%s: invalid write offset "
771                       "%d\n", __func__, wr_offset);
772         return;
773     }
774 
775     rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
776 
777     if (rd_offset >= s->cq.num_entries) {
778         qemu_log_mask(LOG_GUEST_ERROR,
779                       "%s: invalid read offset "
780                       "%d\n", __func__, rd_offset);
781         return;
782     }
783 
784     while (wr_offset != rd_offset) {
785         ItsCmdResult result = CMD_CONTINUE;
786         void *hostmem;
787         hwaddr buflen;
788         uint64_t cmdpkt[GITS_CMDQ_ENTRY_WORDS];
789 
790         cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
791 
792         buflen = GITS_CMDQ_ENTRY_SIZE;
793         hostmem = address_space_map(as, s->cq.base_addr + cq_offset,
794                                     &buflen, false, MEMTXATTRS_UNSPECIFIED);
795         if (!hostmem || buflen != GITS_CMDQ_ENTRY_SIZE) {
796             if (hostmem) {
797                 address_space_unmap(as, hostmem, buflen, false, 0);
798             }
799             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
800             qemu_log_mask(LOG_GUEST_ERROR,
801                           "%s: could not read command at 0x%" PRIx64 "\n",
802                           __func__, s->cq.base_addr + cq_offset);
803             break;
804         }
805         for (i = 0; i < ARRAY_SIZE(cmdpkt); i++) {
806             cmdpkt[i] = ldq_le_p(hostmem + i * sizeof(uint64_t));
807         }
808         address_space_unmap(as, hostmem, buflen, false, 0);
809 
810         cmd = cmdpkt[0] & CMD_MASK;
811 
812         trace_gicv3_its_process_command(rd_offset, cmd);
813 
814         switch (cmd) {
815         case GITS_CMD_INT:
816             result = process_its_cmd(s, cmdpkt, INTERRUPT);
817             break;
818         case GITS_CMD_CLEAR:
819             result = process_its_cmd(s, cmdpkt, CLEAR);
820             break;
821         case GITS_CMD_SYNC:
822             /*
823              * Current implementation makes a blocking synchronous call
824              * for every command issued earlier, hence the internal state
825              * is already consistent by the time SYNC command is executed.
826              * Hence no further processing is required for SYNC command.
827              */
828             trace_gicv3_its_cmd_sync();
829             break;
830         case GITS_CMD_MAPD:
831             result = process_mapd(s, cmdpkt);
832             break;
833         case GITS_CMD_MAPC:
834             result = process_mapc(s, cmdpkt);
835             break;
836         case GITS_CMD_MAPTI:
837             result = process_mapti(s, cmdpkt, false);
838             break;
839         case GITS_CMD_MAPI:
840             result = process_mapti(s, cmdpkt, true);
841             break;
842         case GITS_CMD_DISCARD:
843             result = process_its_cmd(s, cmdpkt, DISCARD);
844             break;
845         case GITS_CMD_INV:
846         case GITS_CMD_INVALL:
847             /*
848              * Current implementation doesn't cache any ITS tables,
849              * but the calculated lpi priority information. We only
850              * need to trigger lpi priority re-calculation to be in
851              * sync with LPI config table or pending table changes.
852              */
853             trace_gicv3_its_cmd_inv();
854             for (i = 0; i < s->gicv3->num_cpu; i++) {
855                 gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
856             }
857             break;
858         case GITS_CMD_MOVI:
859             result = process_movi(s, cmdpkt);
860             break;
861         case GITS_CMD_MOVALL:
862             result = process_movall(s, cmdpkt);
863             break;
864         default:
865             trace_gicv3_its_cmd_unknown(cmd);
866             break;
867         }
868         if (result == CMD_CONTINUE) {
869             rd_offset++;
870             rd_offset %= s->cq.num_entries;
871             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
872         } else {
873             /* CMD_STALL */
874             s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
875             qemu_log_mask(LOG_GUEST_ERROR,
876                           "%s: 0x%x cmd processing failed, stalling\n",
877                           __func__, cmd);
878             break;
879         }
880     }
881 }
882 
883 /*
884  * This function extracts the ITS Device and Collection table specific
885  * parameters (like base_addr, size etc) from GITS_BASER register.
886  * It is called during ITS enable and also during post_load migration
887  */
888 static void extract_table_params(GICv3ITSState *s)
889 {
890     uint16_t num_pages = 0;
891     uint8_t  page_sz_type;
892     uint8_t type;
893     uint32_t page_sz = 0;
894     uint64_t value;
895 
896     for (int i = 0; i < 8; i++) {
897         TableDesc *td;
898         int idbits;
899 
900         value = s->baser[i];
901 
902         if (!value) {
903             continue;
904         }
905 
906         page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
907 
908         switch (page_sz_type) {
909         case 0:
910             page_sz = GITS_PAGE_SIZE_4K;
911             break;
912 
913         case 1:
914             page_sz = GITS_PAGE_SIZE_16K;
915             break;
916 
917         case 2:
918         case 3:
919             page_sz = GITS_PAGE_SIZE_64K;
920             break;
921 
922         default:
923             g_assert_not_reached();
924         }
925 
926         num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
927 
928         type = FIELD_EX64(value, GITS_BASER, TYPE);
929 
930         switch (type) {
931         case GITS_BASER_TYPE_DEVICE:
932             td = &s->dt;
933             idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
934             break;
935         case GITS_BASER_TYPE_COLLECTION:
936             td = &s->ct;
937             if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
938                 idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
939             } else {
940                 /* 16-bit CollectionId supported when CIL == 0 */
941                 idbits = 16;
942             }
943             break;
944         default:
945             /*
946              * GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
947              * ensures we will only see type values corresponding to
948              * the values set up in gicv3_its_reset().
949              */
950             g_assert_not_reached();
951         }
952 
953         memset(td, 0, sizeof(*td));
954         /*
955          * If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
956          * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
957          * do not have a special case where the GITS_BASER<n>.Valid bit is 0
958          * for the register corresponding to the Collection table but we
959          * still have to process interrupts using non-memory-backed
960          * Collection table entries.)
961          * The specification makes it UNPREDICTABLE to enable the ITS without
962          * marking each BASER<n> as valid. We choose to handle these as if
963          * the table was zero-sized, so commands using the table will fail
964          * and interrupts requested via GITS_TRANSLATER writes will be ignored.
965          * This happens automatically by leaving the num_entries field at
966          * zero, which will be caught by the bounds checks we have before
967          * every table lookup anyway.
968          */
969         if (!FIELD_EX64(value, GITS_BASER, VALID)) {
970             continue;
971         }
972         td->page_sz = page_sz;
973         td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
974         td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
975         td->base_addr = baser_base_addr(value, page_sz);
976         if (!td->indirect) {
977             td->num_entries = (num_pages * page_sz) / td->entry_sz;
978         } else {
979             td->num_entries = (((num_pages * page_sz) /
980                                   L1TABLE_ENTRY_SIZE) *
981                                  (page_sz / td->entry_sz));
982         }
983         td->num_entries = MIN(td->num_entries, 1ULL << idbits);
984     }
985 }
986 
987 static void extract_cmdq_params(GICv3ITSState *s)
988 {
989     uint16_t num_pages = 0;
990     uint64_t value = s->cbaser;
991 
992     num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
993 
994     memset(&s->cq, 0 , sizeof(s->cq));
995 
996     if (FIELD_EX64(value, GITS_CBASER, VALID)) {
997         s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
998                              GITS_CMDQ_ENTRY_SIZE;
999         s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
1000         s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
1001     }
1002 }
1003 
1004 static MemTxResult gicv3_its_translation_read(void *opaque, hwaddr offset,
1005                                               uint64_t *data, unsigned size,
1006                                               MemTxAttrs attrs)
1007 {
1008     /*
1009      * GITS_TRANSLATER is write-only, and all other addresses
1010      * in the interrupt translation space frame are RES0.
1011      */
1012     *data = 0;
1013     return MEMTX_OK;
1014 }
1015 
1016 static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
1017                                                uint64_t data, unsigned size,
1018                                                MemTxAttrs attrs)
1019 {
1020     GICv3ITSState *s = (GICv3ITSState *)opaque;
1021     bool result = true;
1022 
1023     trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id);
1024 
1025     switch (offset) {
1026     case GITS_TRANSLATER:
1027         if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
1028             result = do_process_its_cmd(s, attrs.requester_id, data, NONE);
1029         }
1030         break;
1031     default:
1032         break;
1033     }
1034 
1035     if (result) {
1036         return MEMTX_OK;
1037     } else {
1038         return MEMTX_ERROR;
1039     }
1040 }
1041 
1042 static bool its_writel(GICv3ITSState *s, hwaddr offset,
1043                               uint64_t value, MemTxAttrs attrs)
1044 {
1045     bool result = true;
1046     int index;
1047 
1048     switch (offset) {
1049     case GITS_CTLR:
1050         if (value & R_GITS_CTLR_ENABLED_MASK) {
1051             s->ctlr |= R_GITS_CTLR_ENABLED_MASK;
1052             extract_table_params(s);
1053             extract_cmdq_params(s);
1054             process_cmdq(s);
1055         } else {
1056             s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK;
1057         }
1058         break;
1059     case GITS_CBASER:
1060         /*
1061          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
1062          *                 already enabled
1063          */
1064         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1065             s->cbaser = deposit64(s->cbaser, 0, 32, value);
1066             s->creadr = 0;
1067         }
1068         break;
1069     case GITS_CBASER + 4:
1070         /*
1071          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
1072          *                 already enabled
1073          */
1074         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1075             s->cbaser = deposit64(s->cbaser, 32, 32, value);
1076             s->creadr = 0;
1077         }
1078         break;
1079     case GITS_CWRITER:
1080         s->cwriter = deposit64(s->cwriter, 0, 32,
1081                                (value & ~R_GITS_CWRITER_RETRY_MASK));
1082         if (s->cwriter != s->creadr) {
1083             process_cmdq(s);
1084         }
1085         break;
1086     case GITS_CWRITER + 4:
1087         s->cwriter = deposit64(s->cwriter, 32, 32, value);
1088         break;
1089     case GITS_CREADR:
1090         if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1091             s->creadr = deposit64(s->creadr, 0, 32,
1092                                   (value & ~R_GITS_CREADR_STALLED_MASK));
1093         } else {
1094             /* RO register, ignore the write */
1095             qemu_log_mask(LOG_GUEST_ERROR,
1096                           "%s: invalid guest write to RO register at offset "
1097                           TARGET_FMT_plx "\n", __func__, offset);
1098         }
1099         break;
1100     case GITS_CREADR + 4:
1101         if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1102             s->creadr = deposit64(s->creadr, 32, 32, value);
1103         } else {
1104             /* RO register, ignore the write */
1105             qemu_log_mask(LOG_GUEST_ERROR,
1106                           "%s: invalid guest write to RO register at offset "
1107                           TARGET_FMT_plx "\n", __func__, offset);
1108         }
1109         break;
1110     case GITS_BASER ... GITS_BASER + 0x3f:
1111         /*
1112          * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
1113          *                 already enabled
1114          */
1115         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1116             index = (offset - GITS_BASER) / 8;
1117 
1118             if (s->baser[index] == 0) {
1119                 /* Unimplemented GITS_BASERn: RAZ/WI */
1120                 break;
1121             }
1122             if (offset & 7) {
1123                 value <<= 32;
1124                 value &= ~GITS_BASER_RO_MASK;
1125                 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
1126                 s->baser[index] |= value;
1127             } else {
1128                 value &= ~GITS_BASER_RO_MASK;
1129                 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
1130                 s->baser[index] |= value;
1131             }
1132         }
1133         break;
1134     case GITS_IIDR:
1135     case GITS_IDREGS ... GITS_IDREGS + 0x2f:
1136         /* RO registers, ignore the write */
1137         qemu_log_mask(LOG_GUEST_ERROR,
1138                       "%s: invalid guest write to RO register at offset "
1139                       TARGET_FMT_plx "\n", __func__, offset);
1140         break;
1141     default:
1142         result = false;
1143         break;
1144     }
1145     return result;
1146 }
1147 
1148 static bool its_readl(GICv3ITSState *s, hwaddr offset,
1149                              uint64_t *data, MemTxAttrs attrs)
1150 {
1151     bool result = true;
1152     int index;
1153 
1154     switch (offset) {
1155     case GITS_CTLR:
1156         *data = s->ctlr;
1157         break;
1158     case GITS_IIDR:
1159         *data = gicv3_iidr();
1160         break;
1161     case GITS_IDREGS ... GITS_IDREGS + 0x2f:
1162         /* ID registers */
1163         *data = gicv3_idreg(offset - GITS_IDREGS);
1164         break;
1165     case GITS_TYPER:
1166         *data = extract64(s->typer, 0, 32);
1167         break;
1168     case GITS_TYPER + 4:
1169         *data = extract64(s->typer, 32, 32);
1170         break;
1171     case GITS_CBASER:
1172         *data = extract64(s->cbaser, 0, 32);
1173         break;
1174     case GITS_CBASER + 4:
1175         *data = extract64(s->cbaser, 32, 32);
1176         break;
1177     case GITS_CREADR:
1178         *data = extract64(s->creadr, 0, 32);
1179         break;
1180     case GITS_CREADR + 4:
1181         *data = extract64(s->creadr, 32, 32);
1182         break;
1183     case GITS_CWRITER:
1184         *data = extract64(s->cwriter, 0, 32);
1185         break;
1186     case GITS_CWRITER + 4:
1187         *data = extract64(s->cwriter, 32, 32);
1188         break;
1189     case GITS_BASER ... GITS_BASER + 0x3f:
1190         index = (offset - GITS_BASER) / 8;
1191         if (offset & 7) {
1192             *data = extract64(s->baser[index], 32, 32);
1193         } else {
1194             *data = extract64(s->baser[index], 0, 32);
1195         }
1196         break;
1197     default:
1198         result = false;
1199         break;
1200     }
1201     return result;
1202 }
1203 
1204 static bool its_writell(GICv3ITSState *s, hwaddr offset,
1205                                uint64_t value, MemTxAttrs attrs)
1206 {
1207     bool result = true;
1208     int index;
1209 
1210     switch (offset) {
1211     case GITS_BASER ... GITS_BASER + 0x3f:
1212         /*
1213          * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
1214          *                 already enabled
1215          */
1216         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1217             index = (offset - GITS_BASER) / 8;
1218             if (s->baser[index] == 0) {
1219                 /* Unimplemented GITS_BASERn: RAZ/WI */
1220                 break;
1221             }
1222             s->baser[index] &= GITS_BASER_RO_MASK;
1223             s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
1224         }
1225         break;
1226     case GITS_CBASER:
1227         /*
1228          * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
1229          *                 already enabled
1230          */
1231         if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1232             s->cbaser = value;
1233             s->creadr = 0;
1234         }
1235         break;
1236     case GITS_CWRITER:
1237         s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
1238         if (s->cwriter != s->creadr) {
1239             process_cmdq(s);
1240         }
1241         break;
1242     case GITS_CREADR:
1243         if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1244             s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
1245         } else {
1246             /* RO register, ignore the write */
1247             qemu_log_mask(LOG_GUEST_ERROR,
1248                           "%s: invalid guest write to RO register at offset "
1249                           TARGET_FMT_plx "\n", __func__, offset);
1250         }
1251         break;
1252     case GITS_TYPER:
1253         /* RO registers, ignore the write */
1254         qemu_log_mask(LOG_GUEST_ERROR,
1255                       "%s: invalid guest write to RO register at offset "
1256                       TARGET_FMT_plx "\n", __func__, offset);
1257         break;
1258     default:
1259         result = false;
1260         break;
1261     }
1262     return result;
1263 }
1264 
1265 static bool its_readll(GICv3ITSState *s, hwaddr offset,
1266                               uint64_t *data, MemTxAttrs attrs)
1267 {
1268     bool result = true;
1269     int index;
1270 
1271     switch (offset) {
1272     case GITS_TYPER:
1273         *data = s->typer;
1274         break;
1275     case GITS_BASER ... GITS_BASER + 0x3f:
1276         index = (offset - GITS_BASER) / 8;
1277         *data = s->baser[index];
1278         break;
1279     case GITS_CBASER:
1280         *data = s->cbaser;
1281         break;
1282     case GITS_CREADR:
1283         *data = s->creadr;
1284         break;
1285     case GITS_CWRITER:
1286         *data = s->cwriter;
1287         break;
1288     default:
1289         result = false;
1290         break;
1291     }
1292     return result;
1293 }
1294 
1295 static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
1296                                   unsigned size, MemTxAttrs attrs)
1297 {
1298     GICv3ITSState *s = (GICv3ITSState *)opaque;
1299     bool result;
1300 
1301     switch (size) {
1302     case 4:
1303         result = its_readl(s, offset, data, attrs);
1304         break;
1305     case 8:
1306         result = its_readll(s, offset, data, attrs);
1307         break;
1308     default:
1309         result = false;
1310         break;
1311     }
1312 
1313     if (!result) {
1314         qemu_log_mask(LOG_GUEST_ERROR,
1315                       "%s: invalid guest read at offset " TARGET_FMT_plx
1316                       " size %u\n", __func__, offset, size);
1317         trace_gicv3_its_badread(offset, size);
1318         /*
1319          * The spec requires that reserved registers are RAZ/WI;
1320          * so use false returns from leaf functions as a way to
1321          * trigger the guest-error logging but don't return it to
1322          * the caller, or we'll cause a spurious guest data abort.
1323          */
1324         *data = 0;
1325     } else {
1326         trace_gicv3_its_read(offset, *data, size);
1327     }
1328     return MEMTX_OK;
1329 }
1330 
1331 static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
1332                                    unsigned size, MemTxAttrs attrs)
1333 {
1334     GICv3ITSState *s = (GICv3ITSState *)opaque;
1335     bool result;
1336 
1337     switch (size) {
1338     case 4:
1339         result = its_writel(s, offset, data, attrs);
1340         break;
1341     case 8:
1342         result = its_writell(s, offset, data, attrs);
1343         break;
1344     default:
1345         result = false;
1346         break;
1347     }
1348 
1349     if (!result) {
1350         qemu_log_mask(LOG_GUEST_ERROR,
1351                       "%s: invalid guest write at offset " TARGET_FMT_plx
1352                       " size %u\n", __func__, offset, size);
1353         trace_gicv3_its_badwrite(offset, data, size);
1354         /*
1355          * The spec requires that reserved registers are RAZ/WI;
1356          * so use false returns from leaf functions as a way to
1357          * trigger the guest-error logging but don't return it to
1358          * the caller, or we'll cause a spurious guest data abort.
1359          */
1360     } else {
1361         trace_gicv3_its_write(offset, data, size);
1362     }
1363     return MEMTX_OK;
1364 }
1365 
1366 static const MemoryRegionOps gicv3_its_control_ops = {
1367     .read_with_attrs = gicv3_its_read,
1368     .write_with_attrs = gicv3_its_write,
1369     .valid.min_access_size = 4,
1370     .valid.max_access_size = 8,
1371     .impl.min_access_size = 4,
1372     .impl.max_access_size = 8,
1373     .endianness = DEVICE_NATIVE_ENDIAN,
1374 };
1375 
1376 static const MemoryRegionOps gicv3_its_translation_ops = {
1377     .read_with_attrs = gicv3_its_translation_read,
1378     .write_with_attrs = gicv3_its_translation_write,
1379     .valid.min_access_size = 2,
1380     .valid.max_access_size = 4,
1381     .impl.min_access_size = 2,
1382     .impl.max_access_size = 4,
1383     .endianness = DEVICE_NATIVE_ENDIAN,
1384 };
1385 
1386 static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
1387 {
1388     GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1389     int i;
1390 
1391     for (i = 0; i < s->gicv3->num_cpu; i++) {
1392         if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
1393             error_setg(errp, "Physical LPI not supported by CPU %d", i);
1394             return;
1395         }
1396     }
1397 
1398     gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
1399 
1400     /* set the ITS default features supported */
1401     s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
1402     s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
1403                           ITS_ITT_ENTRY_SIZE - 1);
1404     s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
1405     s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
1406     s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
1407     s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
1408 }
1409 
1410 static void gicv3_its_reset(DeviceState *dev)
1411 {
1412     GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1413     GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
1414 
1415     c->parent_reset(dev);
1416 
1417     /* Quiescent bit reset to 1 */
1418     s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
1419 
1420     /*
1421      * setting GITS_BASER0.Type = 0b001 (Device)
1422      *         GITS_BASER1.Type = 0b100 (Collection Table)
1423      *         GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
1424      *         GITS_BASER<0,1>.Page_Size = 64KB
1425      * and default translation table entry size to 16 bytes
1426      */
1427     s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
1428                              GITS_BASER_TYPE_DEVICE);
1429     s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
1430                              GITS_BASER_PAGESIZE_64K);
1431     s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
1432                              GITS_DTE_SIZE - 1);
1433 
1434     s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
1435                              GITS_BASER_TYPE_COLLECTION);
1436     s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
1437                              GITS_BASER_PAGESIZE_64K);
1438     s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
1439                              GITS_CTE_SIZE - 1);
1440 }
1441 
1442 static void gicv3_its_post_load(GICv3ITSState *s)
1443 {
1444     if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
1445         extract_table_params(s);
1446         extract_cmdq_params(s);
1447     }
1448 }
1449 
1450 static Property gicv3_its_props[] = {
1451     DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
1452                      GICv3State *),
1453     DEFINE_PROP_END_OF_LIST(),
1454 };
1455 
1456 static void gicv3_its_class_init(ObjectClass *klass, void *data)
1457 {
1458     DeviceClass *dc = DEVICE_CLASS(klass);
1459     GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
1460     GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
1461 
1462     dc->realize = gicv3_arm_its_realize;
1463     device_class_set_props(dc, gicv3_its_props);
1464     device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
1465     icc->post_load = gicv3_its_post_load;
1466 }
1467 
1468 static const TypeInfo gicv3_its_info = {
1469     .name = TYPE_ARM_GICV3_ITS,
1470     .parent = TYPE_ARM_GICV3_ITS_COMMON,
1471     .instance_size = sizeof(GICv3ITSState),
1472     .class_init = gicv3_its_class_init,
1473     .class_size = sizeof(GICv3ITSClass),
1474 };
1475 
1476 static void gicv3_its_register_types(void)
1477 {
1478     type_register_static(&gicv3_its_info);
1479 }
1480 
1481 type_init(gicv3_its_register_types)
1482