hw/intc/arm_gicv3_its: Don't clear GITS_CREADR when GITS_CTLR.ENABLED is set
[qemu/rayw.git] / hw / intc / arm_gicv3_its.c
blob1763ba4a671fc7b9094974de9214ae3ba938abbf
1 /*
2 * ITS emulation for a GICv3-based system
4 * Copyright Linaro.org 2021
6 * Authors:
7 * Shashi Mallela <shashi.mallela@linaro.org>
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.
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"
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)
28 struct GICv3ITSClass {
29 GICv3ITSCommonClass parent_class;
30 void (*parent_reset)(DeviceState *dev);
34 * This is an internal enum used to distinguish between LPI triggered
35 * via command queue and LPI triggered via gits_translater write.
37 typedef enum ItsCmdType {
38 NONE = 0, /* internal indication for GITS_TRANSLATER write */
39 CLEAR = 1,
40 DISCARD = 2,
41 INTERRUPT = 3,
42 } ItsCmdType;
44 typedef struct {
45 uint32_t iteh;
46 uint64_t itel;
47 } IteEntry;
50 * The ITS spec permits a range of CONSTRAINED UNPREDICTABLE options
51 * if a command parameter is not correct. These include both "stall
52 * processing of the command queue" and "ignore this command, and
53 * keep processing the queue". In our implementation we choose that
54 * memory transaction errors reading the command packet provoke a
55 * stall, but errors in parameters cause us to ignore the command
56 * and continue processing.
57 * The process_* functions which handle individual ITS commands all
58 * return an ItsCmdResult which tells process_cmdq() whether it should
59 * stall or keep going.
61 typedef enum ItsCmdResult {
62 CMD_STALL = 0,
63 CMD_CONTINUE = 1,
64 } ItsCmdResult;
66 static uint64_t baser_base_addr(uint64_t value, uint32_t page_sz)
68 uint64_t result = 0;
70 switch (page_sz) {
71 case GITS_PAGE_SIZE_4K:
72 case GITS_PAGE_SIZE_16K:
73 result = FIELD_EX64(value, GITS_BASER, PHYADDR) << 12;
74 break;
76 case GITS_PAGE_SIZE_64K:
77 result = FIELD_EX64(value, GITS_BASER, PHYADDRL_64K) << 16;
78 result |= FIELD_EX64(value, GITS_BASER, PHYADDRH_64K) << 48;
79 break;
81 default:
82 break;
84 return result;
87 static uint64_t table_entry_addr(GICv3ITSState *s, TableDesc *td,
88 uint32_t idx, MemTxResult *res)
91 * Given a TableDesc describing one of the ITS in-guest-memory
92 * tables and an index into it, return the guest address
93 * corresponding to that table entry.
94 * If there was a memory error reading the L1 table of an
95 * indirect table, *res is set accordingly, and we return -1.
96 * If the L1 table entry is marked not valid, we return -1 with
97 * *res set to MEMTX_OK.
99 * The specification defines the format of level 1 entries of a
100 * 2-level table, but the format of level 2 entries and the format
101 * of flat-mapped tables is IMPDEF.
103 AddressSpace *as = &s->gicv3->dma_as;
104 uint32_t l2idx;
105 uint64_t l2;
106 uint32_t num_l2_entries;
108 *res = MEMTX_OK;
110 if (!td->indirect) {
111 /* Single level table */
112 return td->base_addr + idx * td->entry_sz;
115 /* Two level table */
116 l2idx = idx / (td->page_sz / L1TABLE_ENTRY_SIZE);
118 l2 = address_space_ldq_le(as,
119 td->base_addr + (l2idx * L1TABLE_ENTRY_SIZE),
120 MEMTXATTRS_UNSPECIFIED, res);
121 if (*res != MEMTX_OK) {
122 return -1;
124 if (!(l2 & L2_TABLE_VALID_MASK)) {
125 return -1;
128 num_l2_entries = td->page_sz / td->entry_sz;
129 return (l2 & ((1ULL << 51) - 1)) + (idx % num_l2_entries) * td->entry_sz;
132 static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
133 MemTxResult *res)
135 AddressSpace *as = &s->gicv3->dma_as;
136 uint64_t entry_addr = table_entry_addr(s, &s->ct, icid, res);
138 if (entry_addr == -1) {
139 return false; /* not valid */
142 *cte = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
143 return FIELD_EX64(*cte, CTE, VALID);
146 static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
147 IteEntry ite)
149 AddressSpace *as = &s->gicv3->dma_as;
150 uint64_t itt_addr;
151 MemTxResult res = MEMTX_OK;
153 itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
154 itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
156 address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
157 sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
158 &res);
160 if (res == MEMTX_OK) {
161 address_space_stl_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
162 sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
163 MEMTXATTRS_UNSPECIFIED, &res);
165 if (res != MEMTX_OK) {
166 return false;
167 } else {
168 return true;
172 static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
173 uint16_t *icid, uint32_t *pIntid, MemTxResult *res)
175 AddressSpace *as = &s->gicv3->dma_as;
176 uint64_t itt_addr;
177 bool status = false;
178 IteEntry ite = {};
180 itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
181 itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
183 ite.itel = address_space_ldq_le(as, itt_addr +
184 (eventid * (sizeof(uint64_t) +
185 sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
186 res);
188 if (*res == MEMTX_OK) {
189 ite.iteh = address_space_ldl_le(as, itt_addr +
190 (eventid * (sizeof(uint64_t) +
191 sizeof(uint32_t))) + sizeof(uint32_t),
192 MEMTXATTRS_UNSPECIFIED, res);
194 if (*res == MEMTX_OK) {
195 if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
196 int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
197 if (inttype == ITE_INTTYPE_PHYSICAL) {
198 *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
199 *icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
200 status = true;
205 return status;
208 static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
210 AddressSpace *as = &s->gicv3->dma_as;
211 uint64_t entry_addr = table_entry_addr(s, &s->dt, devid, res);
213 if (entry_addr == -1) {
214 return 0; /* a DTE entry with the Valid bit clear */
216 return address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, res);
220 * This function handles the processing of following commands based on
221 * the ItsCmdType parameter passed:-
222 * 1. triggering of lpi interrupt translation via ITS INT command
223 * 2. triggering of lpi interrupt translation via gits_translater register
224 * 3. handling of ITS CLEAR command
225 * 4. handling of ITS DISCARD command
227 static ItsCmdResult process_its_cmd(GICv3ITSState *s, uint64_t value,
228 uint32_t offset, ItsCmdType cmd)
230 AddressSpace *as = &s->gicv3->dma_as;
231 uint32_t devid, eventid;
232 MemTxResult res = MEMTX_OK;
233 bool dte_valid;
234 uint64_t dte = 0;
235 uint64_t num_eventids;
236 uint16_t icid = 0;
237 uint32_t pIntid = 0;
238 bool ite_valid = false;
239 uint64_t cte = 0;
240 bool cte_valid = false;
241 uint64_t rdbase;
243 if (cmd == NONE) {
244 devid = offset;
245 } else {
246 devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
248 offset += NUM_BYTES_IN_DW;
249 value = address_space_ldq_le(as, s->cq.base_addr + offset,
250 MEMTXATTRS_UNSPECIFIED, &res);
253 if (res != MEMTX_OK) {
254 return CMD_STALL;
257 eventid = (value & EVENTID_MASK);
259 if (devid >= s->dt.num_ids) {
260 qemu_log_mask(LOG_GUEST_ERROR,
261 "%s: invalid command attributes: devid %d>=%d",
262 __func__, devid, s->dt.num_ids);
263 return CMD_CONTINUE;
266 dte = get_dte(s, devid, &res);
268 if (res != MEMTX_OK) {
269 return CMD_STALL;
271 dte_valid = FIELD_EX64(dte, DTE, VALID);
273 if (!dte_valid) {
274 qemu_log_mask(LOG_GUEST_ERROR,
275 "%s: invalid command attributes: "
276 "invalid dte: %"PRIx64" for %d\n",
277 __func__, dte, devid);
278 return CMD_CONTINUE;
281 num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
283 if (eventid >= num_eventids) {
284 qemu_log_mask(LOG_GUEST_ERROR,
285 "%s: invalid command attributes: eventid %d >= %"
286 PRId64 "\n",
287 __func__, eventid, num_eventids);
288 return CMD_CONTINUE;
291 ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
292 if (res != MEMTX_OK) {
293 return CMD_STALL;
296 if (!ite_valid) {
297 qemu_log_mask(LOG_GUEST_ERROR,
298 "%s: invalid command attributes: invalid ITE\n",
299 __func__);
300 return CMD_CONTINUE;
303 if (icid >= s->ct.num_ids) {
304 qemu_log_mask(LOG_GUEST_ERROR,
305 "%s: invalid ICID 0x%x in ITE (table corrupted?)\n",
306 __func__, icid);
307 return CMD_CONTINUE;
310 cte_valid = get_cte(s, icid, &cte, &res);
311 if (res != MEMTX_OK) {
312 return CMD_STALL;
314 if (!cte_valid) {
315 qemu_log_mask(LOG_GUEST_ERROR,
316 "%s: invalid command attributes: "
317 "invalid cte: %"PRIx64"\n",
318 __func__, cte);
319 return CMD_CONTINUE;
323 * Current implementation only supports rdbase == procnum
324 * Hence rdbase physical address is ignored
326 rdbase = FIELD_EX64(cte, CTE, RDBASE);
328 if (rdbase >= s->gicv3->num_cpu) {
329 return CMD_CONTINUE;
332 if ((cmd == CLEAR) || (cmd == DISCARD)) {
333 gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 0);
334 } else {
335 gicv3_redist_process_lpi(&s->gicv3->cpu[rdbase], pIntid, 1);
338 if (cmd == DISCARD) {
339 IteEntry ite = {};
340 /* remove mapping from interrupt translation table */
341 return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
343 return CMD_CONTINUE;
346 static ItsCmdResult process_mapti(GICv3ITSState *s, uint64_t value,
347 uint32_t offset, bool ignore_pInt)
349 AddressSpace *as = &s->gicv3->dma_as;
350 uint32_t devid, eventid;
351 uint32_t pIntid = 0;
352 uint64_t num_eventids;
353 uint32_t num_intids;
354 bool dte_valid;
355 MemTxResult res = MEMTX_OK;
356 uint16_t icid = 0;
357 uint64_t dte = 0;
358 IteEntry ite = {};
360 devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
361 offset += NUM_BYTES_IN_DW;
362 value = address_space_ldq_le(as, s->cq.base_addr + offset,
363 MEMTXATTRS_UNSPECIFIED, &res);
365 if (res != MEMTX_OK) {
366 return CMD_STALL;
369 eventid = (value & EVENTID_MASK);
371 if (ignore_pInt) {
372 pIntid = eventid;
373 } else {
374 pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
377 offset += NUM_BYTES_IN_DW;
378 value = address_space_ldq_le(as, s->cq.base_addr + offset,
379 MEMTXATTRS_UNSPECIFIED, &res);
381 if (res != MEMTX_OK) {
382 return CMD_STALL;
385 icid = value & ICID_MASK;
387 if (devid >= s->dt.num_ids) {
388 qemu_log_mask(LOG_GUEST_ERROR,
389 "%s: invalid command attributes: devid %d>=%d",
390 __func__, devid, s->dt.num_ids);
391 return CMD_CONTINUE;
394 dte = get_dte(s, devid, &res);
396 if (res != MEMTX_OK) {
397 return CMD_STALL;
399 dte_valid = FIELD_EX64(dte, DTE, VALID);
400 num_eventids = 1ULL << (FIELD_EX64(dte, DTE, SIZE) + 1);
401 num_intids = 1ULL << (GICD_TYPER_IDBITS + 1);
403 if ((icid >= s->ct.num_ids)
404 || !dte_valid || (eventid >= num_eventids) ||
405 (((pIntid < GICV3_LPI_INTID_START) || (pIntid >= num_intids)) &&
406 (pIntid != INTID_SPURIOUS))) {
407 qemu_log_mask(LOG_GUEST_ERROR,
408 "%s: invalid command attributes "
409 "icid %d or eventid %d or pIntid %d or"
410 "unmapped dte %d\n", __func__, icid, eventid,
411 pIntid, dte_valid);
413 * in this implementation, in case of error
414 * we ignore this command and move onto the next
415 * command in the queue
417 return CMD_CONTINUE;
420 /* add ite entry to interrupt translation table */
421 ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
422 ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
423 ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
424 ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
425 ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
427 return update_ite(s, eventid, dte, ite) ? CMD_CONTINUE : CMD_STALL;
430 static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
431 uint64_t rdbase)
433 AddressSpace *as = &s->gicv3->dma_as;
434 uint64_t entry_addr;
435 uint64_t cte = 0;
436 MemTxResult res = MEMTX_OK;
438 if (!s->ct.valid) {
439 return true;
442 if (valid) {
443 /* add mapping entry to collection table */
444 cte = FIELD_DP64(cte, CTE, VALID, 1);
445 cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
448 entry_addr = table_entry_addr(s, &s->ct, icid, &res);
449 if (res != MEMTX_OK) {
450 /* memory access error: stall */
451 return false;
453 if (entry_addr == -1) {
454 /* No L2 table for this index: discard write and continue */
455 return true;
458 address_space_stq_le(as, entry_addr, cte, MEMTXATTRS_UNSPECIFIED, &res);
459 return res == MEMTX_OK;
462 static ItsCmdResult process_mapc(GICv3ITSState *s, uint32_t offset)
464 AddressSpace *as = &s->gicv3->dma_as;
465 uint16_t icid;
466 uint64_t rdbase;
467 bool valid;
468 MemTxResult res = MEMTX_OK;
469 uint64_t value;
471 offset += NUM_BYTES_IN_DW;
472 offset += NUM_BYTES_IN_DW;
474 value = address_space_ldq_le(as, s->cq.base_addr + offset,
475 MEMTXATTRS_UNSPECIFIED, &res);
477 if (res != MEMTX_OK) {
478 return CMD_STALL;
481 icid = value & ICID_MASK;
483 rdbase = (value & R_MAPC_RDBASE_MASK) >> R_MAPC_RDBASE_SHIFT;
484 rdbase &= RDBASE_PROCNUM_MASK;
486 valid = (value & CMD_FIELD_VALID_MASK);
488 if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) {
489 qemu_log_mask(LOG_GUEST_ERROR,
490 "ITS MAPC: invalid collection table attributes "
491 "icid %d rdbase %" PRIu64 "\n", icid, rdbase);
493 * in this implementation, in case of error
494 * we ignore this command and move onto the next
495 * command in the queue
497 return CMD_CONTINUE;
500 return update_cte(s, icid, valid, rdbase) ? CMD_CONTINUE : CMD_STALL;
503 static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
504 uint8_t size, uint64_t itt_addr)
506 AddressSpace *as = &s->gicv3->dma_as;
507 uint64_t entry_addr;
508 uint64_t dte = 0;
509 MemTxResult res = MEMTX_OK;
511 if (s->dt.valid) {
512 if (valid) {
513 /* add mapping entry to device table */
514 dte = FIELD_DP64(dte, DTE, VALID, 1);
515 dte = FIELD_DP64(dte, DTE, SIZE, size);
516 dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr);
518 } else {
519 return true;
522 entry_addr = table_entry_addr(s, &s->dt, devid, &res);
523 if (res != MEMTX_OK) {
524 /* memory access error: stall */
525 return false;
527 if (entry_addr == -1) {
528 /* No L2 table for this index: discard write and continue */
529 return true;
531 address_space_stq_le(as, entry_addr, dte, MEMTXATTRS_UNSPECIFIED, &res);
532 return res == MEMTX_OK;
535 static ItsCmdResult process_mapd(GICv3ITSState *s, uint64_t value,
536 uint32_t offset)
538 AddressSpace *as = &s->gicv3->dma_as;
539 uint32_t devid;
540 uint8_t size;
541 uint64_t itt_addr;
542 bool valid;
543 MemTxResult res = MEMTX_OK;
545 devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
547 offset += NUM_BYTES_IN_DW;
548 value = address_space_ldq_le(as, s->cq.base_addr + offset,
549 MEMTXATTRS_UNSPECIFIED, &res);
551 if (res != MEMTX_OK) {
552 return CMD_STALL;
555 size = (value & SIZE_MASK);
557 offset += NUM_BYTES_IN_DW;
558 value = address_space_ldq_le(as, s->cq.base_addr + offset,
559 MEMTXATTRS_UNSPECIFIED, &res);
561 if (res != MEMTX_OK) {
562 return CMD_STALL;
565 itt_addr = (value & ITTADDR_MASK) >> ITTADDR_SHIFT;
567 valid = (value & CMD_FIELD_VALID_MASK);
569 if ((devid >= s->dt.num_ids) ||
570 (size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
571 qemu_log_mask(LOG_GUEST_ERROR,
572 "ITS MAPD: invalid device table attributes "
573 "devid %d or size %d\n", devid, size);
575 * in this implementation, in case of error
576 * we ignore this command and move onto the next
577 * command in the queue
579 return CMD_CONTINUE;
582 return update_dte(s, devid, valid, size, itt_addr) ? CMD_CONTINUE : CMD_STALL;
586 * Current implementation blocks until all
587 * commands are processed
589 static void process_cmdq(GICv3ITSState *s)
591 uint32_t wr_offset = 0;
592 uint32_t rd_offset = 0;
593 uint32_t cq_offset = 0;
594 uint64_t data;
595 AddressSpace *as = &s->gicv3->dma_as;
596 MemTxResult res = MEMTX_OK;
597 uint8_t cmd;
598 int i;
600 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
601 return;
604 wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
606 if (wr_offset >= s->cq.num_entries) {
607 qemu_log_mask(LOG_GUEST_ERROR,
608 "%s: invalid write offset "
609 "%d\n", __func__, wr_offset);
610 return;
613 rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
615 if (rd_offset >= s->cq.num_entries) {
616 qemu_log_mask(LOG_GUEST_ERROR,
617 "%s: invalid read offset "
618 "%d\n", __func__, rd_offset);
619 return;
622 while (wr_offset != rd_offset) {
623 ItsCmdResult result = CMD_CONTINUE;
625 cq_offset = (rd_offset * GITS_CMDQ_ENTRY_SIZE);
626 data = address_space_ldq_le(as, s->cq.base_addr + cq_offset,
627 MEMTXATTRS_UNSPECIFIED, &res);
628 if (res != MEMTX_OK) {
629 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
630 qemu_log_mask(LOG_GUEST_ERROR,
631 "%s: could not read command at 0x%" PRIx64 "\n",
632 __func__, s->cq.base_addr + cq_offset);
633 break;
636 cmd = (data & CMD_MASK);
638 trace_gicv3_its_process_command(rd_offset, cmd);
640 switch (cmd) {
641 case GITS_CMD_INT:
642 result = process_its_cmd(s, data, cq_offset, INTERRUPT);
643 break;
644 case GITS_CMD_CLEAR:
645 result = process_its_cmd(s, data, cq_offset, CLEAR);
646 break;
647 case GITS_CMD_SYNC:
649 * Current implementation makes a blocking synchronous call
650 * for every command issued earlier, hence the internal state
651 * is already consistent by the time SYNC command is executed.
652 * Hence no further processing is required for SYNC command.
654 break;
655 case GITS_CMD_MAPD:
656 result = process_mapd(s, data, cq_offset);
657 break;
658 case GITS_CMD_MAPC:
659 result = process_mapc(s, cq_offset);
660 break;
661 case GITS_CMD_MAPTI:
662 result = process_mapti(s, data, cq_offset, false);
663 break;
664 case GITS_CMD_MAPI:
665 result = process_mapti(s, data, cq_offset, true);
666 break;
667 case GITS_CMD_DISCARD:
668 result = process_its_cmd(s, data, cq_offset, DISCARD);
669 break;
670 case GITS_CMD_INV:
671 case GITS_CMD_INVALL:
673 * Current implementation doesn't cache any ITS tables,
674 * but the calculated lpi priority information. We only
675 * need to trigger lpi priority re-calculation to be in
676 * sync with LPI config table or pending table changes.
678 for (i = 0; i < s->gicv3->num_cpu; i++) {
679 gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
681 break;
682 default:
683 break;
685 if (result == CMD_CONTINUE) {
686 rd_offset++;
687 rd_offset %= s->cq.num_entries;
688 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
689 } else {
690 /* CMD_STALL */
691 s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, STALLED, 1);
692 qemu_log_mask(LOG_GUEST_ERROR,
693 "%s: 0x%x cmd processing failed, stalling\n",
694 __func__, cmd);
695 break;
701 * This function extracts the ITS Device and Collection table specific
702 * parameters (like base_addr, size etc) from GITS_BASER register.
703 * It is called during ITS enable and also during post_load migration
705 static void extract_table_params(GICv3ITSState *s)
707 uint16_t num_pages = 0;
708 uint8_t page_sz_type;
709 uint8_t type;
710 uint32_t page_sz = 0;
711 uint64_t value;
713 for (int i = 0; i < 8; i++) {
714 TableDesc *td;
715 int idbits;
717 value = s->baser[i];
719 if (!value) {
720 continue;
723 page_sz_type = FIELD_EX64(value, GITS_BASER, PAGESIZE);
725 switch (page_sz_type) {
726 case 0:
727 page_sz = GITS_PAGE_SIZE_4K;
728 break;
730 case 1:
731 page_sz = GITS_PAGE_SIZE_16K;
732 break;
734 case 2:
735 case 3:
736 page_sz = GITS_PAGE_SIZE_64K;
737 break;
739 default:
740 g_assert_not_reached();
743 num_pages = FIELD_EX64(value, GITS_BASER, SIZE) + 1;
745 type = FIELD_EX64(value, GITS_BASER, TYPE);
747 switch (type) {
748 case GITS_BASER_TYPE_DEVICE:
749 td = &s->dt;
750 idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
751 break;
752 case GITS_BASER_TYPE_COLLECTION:
753 td = &s->ct;
754 if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
755 idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
756 } else {
757 /* 16-bit CollectionId supported when CIL == 0 */
758 idbits = 16;
760 break;
761 default:
763 * GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
764 * ensures we will only see type values corresponding to
765 * the values set up in gicv3_its_reset().
767 g_assert_not_reached();
770 memset(td, 0, sizeof(*td));
771 td->valid = FIELD_EX64(value, GITS_BASER, VALID);
773 * If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
774 * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
775 * do not have a special case where the GITS_BASER<n>.Valid bit is 0
776 * for the register corresponding to the Collection table but we
777 * still have to process interrupts using non-memory-backed
778 * Collection table entries.)
780 if (!td->valid) {
781 continue;
783 td->page_sz = page_sz;
784 td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
785 td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
786 td->base_addr = baser_base_addr(value, page_sz);
787 if (!td->indirect) {
788 td->num_entries = (num_pages * page_sz) / td->entry_sz;
789 } else {
790 td->num_entries = (((num_pages * page_sz) /
791 L1TABLE_ENTRY_SIZE) *
792 (page_sz / td->entry_sz));
794 td->num_ids = 1ULL << idbits;
798 static void extract_cmdq_params(GICv3ITSState *s)
800 uint16_t num_pages = 0;
801 uint64_t value = s->cbaser;
803 num_pages = FIELD_EX64(value, GITS_CBASER, SIZE) + 1;
805 memset(&s->cq, 0 , sizeof(s->cq));
806 s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
808 if (s->cq.valid) {
809 s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
810 GITS_CMDQ_ENTRY_SIZE;
811 s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
812 s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
816 static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
817 uint64_t data, unsigned size,
818 MemTxAttrs attrs)
820 GICv3ITSState *s = (GICv3ITSState *)opaque;
821 bool result = true;
822 uint32_t devid = 0;
824 trace_gicv3_its_translation_write(offset, data, size, attrs.requester_id);
826 switch (offset) {
827 case GITS_TRANSLATER:
828 if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
829 devid = attrs.requester_id;
830 result = process_its_cmd(s, data, devid, NONE);
832 break;
833 default:
834 break;
837 if (result) {
838 return MEMTX_OK;
839 } else {
840 return MEMTX_ERROR;
844 static bool its_writel(GICv3ITSState *s, hwaddr offset,
845 uint64_t value, MemTxAttrs attrs)
847 bool result = true;
848 int index;
850 switch (offset) {
851 case GITS_CTLR:
852 if (value & R_GITS_CTLR_ENABLED_MASK) {
853 s->ctlr |= R_GITS_CTLR_ENABLED_MASK;
854 extract_table_params(s);
855 extract_cmdq_params(s);
856 process_cmdq(s);
857 } else {
858 s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK;
860 break;
861 case GITS_CBASER:
863 * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
864 * already enabled
866 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
867 s->cbaser = deposit64(s->cbaser, 0, 32, value);
868 s->creadr = 0;
869 s->cwriter = s->creadr;
871 break;
872 case GITS_CBASER + 4:
874 * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
875 * already enabled
877 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
878 s->cbaser = deposit64(s->cbaser, 32, 32, value);
879 s->creadr = 0;
880 s->cwriter = s->creadr;
882 break;
883 case GITS_CWRITER:
884 s->cwriter = deposit64(s->cwriter, 0, 32,
885 (value & ~R_GITS_CWRITER_RETRY_MASK));
886 if (s->cwriter != s->creadr) {
887 process_cmdq(s);
889 break;
890 case GITS_CWRITER + 4:
891 s->cwriter = deposit64(s->cwriter, 32, 32, value);
892 break;
893 case GITS_CREADR:
894 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
895 s->creadr = deposit64(s->creadr, 0, 32,
896 (value & ~R_GITS_CREADR_STALLED_MASK));
897 } else {
898 /* RO register, ignore the write */
899 qemu_log_mask(LOG_GUEST_ERROR,
900 "%s: invalid guest write to RO register at offset "
901 TARGET_FMT_plx "\n", __func__, offset);
903 break;
904 case GITS_CREADR + 4:
905 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
906 s->creadr = deposit64(s->creadr, 32, 32, value);
907 } else {
908 /* RO register, ignore the write */
909 qemu_log_mask(LOG_GUEST_ERROR,
910 "%s: invalid guest write to RO register at offset "
911 TARGET_FMT_plx "\n", __func__, offset);
913 break;
914 case GITS_BASER ... GITS_BASER + 0x3f:
916 * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
917 * already enabled
919 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
920 index = (offset - GITS_BASER) / 8;
922 if (offset & 7) {
923 value <<= 32;
924 value &= ~GITS_BASER_RO_MASK;
925 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(0, 32);
926 s->baser[index] |= value;
927 } else {
928 value &= ~GITS_BASER_RO_MASK;
929 s->baser[index] &= GITS_BASER_RO_MASK | MAKE_64BIT_MASK(32, 32);
930 s->baser[index] |= value;
933 break;
934 case GITS_IIDR:
935 case GITS_IDREGS ... GITS_IDREGS + 0x2f:
936 /* RO registers, ignore the write */
937 qemu_log_mask(LOG_GUEST_ERROR,
938 "%s: invalid guest write to RO register at offset "
939 TARGET_FMT_plx "\n", __func__, offset);
940 break;
941 default:
942 result = false;
943 break;
945 return result;
948 static bool its_readl(GICv3ITSState *s, hwaddr offset,
949 uint64_t *data, MemTxAttrs attrs)
951 bool result = true;
952 int index;
954 switch (offset) {
955 case GITS_CTLR:
956 *data = s->ctlr;
957 break;
958 case GITS_IIDR:
959 *data = gicv3_iidr();
960 break;
961 case GITS_IDREGS ... GITS_IDREGS + 0x2f:
962 /* ID registers */
963 *data = gicv3_idreg(offset - GITS_IDREGS);
964 break;
965 case GITS_TYPER:
966 *data = extract64(s->typer, 0, 32);
967 break;
968 case GITS_TYPER + 4:
969 *data = extract64(s->typer, 32, 32);
970 break;
971 case GITS_CBASER:
972 *data = extract64(s->cbaser, 0, 32);
973 break;
974 case GITS_CBASER + 4:
975 *data = extract64(s->cbaser, 32, 32);
976 break;
977 case GITS_CREADR:
978 *data = extract64(s->creadr, 0, 32);
979 break;
980 case GITS_CREADR + 4:
981 *data = extract64(s->creadr, 32, 32);
982 break;
983 case GITS_CWRITER:
984 *data = extract64(s->cwriter, 0, 32);
985 break;
986 case GITS_CWRITER + 4:
987 *data = extract64(s->cwriter, 32, 32);
988 break;
989 case GITS_BASER ... GITS_BASER + 0x3f:
990 index = (offset - GITS_BASER) / 8;
991 if (offset & 7) {
992 *data = extract64(s->baser[index], 32, 32);
993 } else {
994 *data = extract64(s->baser[index], 0, 32);
996 break;
997 default:
998 result = false;
999 break;
1001 return result;
1004 static bool its_writell(GICv3ITSState *s, hwaddr offset,
1005 uint64_t value, MemTxAttrs attrs)
1007 bool result = true;
1008 int index;
1010 switch (offset) {
1011 case GITS_BASER ... GITS_BASER + 0x3f:
1013 * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
1014 * already enabled
1016 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1017 index = (offset - GITS_BASER) / 8;
1018 s->baser[index] &= GITS_BASER_RO_MASK;
1019 s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
1021 break;
1022 case GITS_CBASER:
1024 * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
1025 * already enabled
1027 if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
1028 s->cbaser = value;
1029 s->creadr = 0;
1030 s->cwriter = s->creadr;
1032 break;
1033 case GITS_CWRITER:
1034 s->cwriter = value & ~R_GITS_CWRITER_RETRY_MASK;
1035 if (s->cwriter != s->creadr) {
1036 process_cmdq(s);
1038 break;
1039 case GITS_CREADR:
1040 if (s->gicv3->gicd_ctlr & GICD_CTLR_DS) {
1041 s->creadr = value & ~R_GITS_CREADR_STALLED_MASK;
1042 } else {
1043 /* RO register, ignore the write */
1044 qemu_log_mask(LOG_GUEST_ERROR,
1045 "%s: invalid guest write to RO register at offset "
1046 TARGET_FMT_plx "\n", __func__, offset);
1048 break;
1049 case GITS_TYPER:
1050 /* RO registers, ignore the write */
1051 qemu_log_mask(LOG_GUEST_ERROR,
1052 "%s: invalid guest write to RO register at offset "
1053 TARGET_FMT_plx "\n", __func__, offset);
1054 break;
1055 default:
1056 result = false;
1057 break;
1059 return result;
1062 static bool its_readll(GICv3ITSState *s, hwaddr offset,
1063 uint64_t *data, MemTxAttrs attrs)
1065 bool result = true;
1066 int index;
1068 switch (offset) {
1069 case GITS_TYPER:
1070 *data = s->typer;
1071 break;
1072 case GITS_BASER ... GITS_BASER + 0x3f:
1073 index = (offset - GITS_BASER) / 8;
1074 *data = s->baser[index];
1075 break;
1076 case GITS_CBASER:
1077 *data = s->cbaser;
1078 break;
1079 case GITS_CREADR:
1080 *data = s->creadr;
1081 break;
1082 case GITS_CWRITER:
1083 *data = s->cwriter;
1084 break;
1085 default:
1086 result = false;
1087 break;
1089 return result;
1092 static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
1093 unsigned size, MemTxAttrs attrs)
1095 GICv3ITSState *s = (GICv3ITSState *)opaque;
1096 bool result;
1098 switch (size) {
1099 case 4:
1100 result = its_readl(s, offset, data, attrs);
1101 break;
1102 case 8:
1103 result = its_readll(s, offset, data, attrs);
1104 break;
1105 default:
1106 result = false;
1107 break;
1110 if (!result) {
1111 qemu_log_mask(LOG_GUEST_ERROR,
1112 "%s: invalid guest read at offset " TARGET_FMT_plx
1113 "size %u\n", __func__, offset, size);
1114 trace_gicv3_its_badread(offset, size);
1116 * The spec requires that reserved registers are RAZ/WI;
1117 * so use false returns from leaf functions as a way to
1118 * trigger the guest-error logging but don't return it to
1119 * the caller, or we'll cause a spurious guest data abort.
1121 *data = 0;
1122 } else {
1123 trace_gicv3_its_read(offset, *data, size);
1125 return MEMTX_OK;
1128 static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
1129 unsigned size, MemTxAttrs attrs)
1131 GICv3ITSState *s = (GICv3ITSState *)opaque;
1132 bool result;
1134 switch (size) {
1135 case 4:
1136 result = its_writel(s, offset, data, attrs);
1137 break;
1138 case 8:
1139 result = its_writell(s, offset, data, attrs);
1140 break;
1141 default:
1142 result = false;
1143 break;
1146 if (!result) {
1147 qemu_log_mask(LOG_GUEST_ERROR,
1148 "%s: invalid guest write at offset " TARGET_FMT_plx
1149 "size %u\n", __func__, offset, size);
1150 trace_gicv3_its_badwrite(offset, data, size);
1152 * The spec requires that reserved registers are RAZ/WI;
1153 * so use false returns from leaf functions as a way to
1154 * trigger the guest-error logging but don't return it to
1155 * the caller, or we'll cause a spurious guest data abort.
1157 } else {
1158 trace_gicv3_its_write(offset, data, size);
1160 return MEMTX_OK;
1163 static const MemoryRegionOps gicv3_its_control_ops = {
1164 .read_with_attrs = gicv3_its_read,
1165 .write_with_attrs = gicv3_its_write,
1166 .valid.min_access_size = 4,
1167 .valid.max_access_size = 8,
1168 .impl.min_access_size = 4,
1169 .impl.max_access_size = 8,
1170 .endianness = DEVICE_NATIVE_ENDIAN,
1173 static const MemoryRegionOps gicv3_its_translation_ops = {
1174 .write_with_attrs = gicv3_its_translation_write,
1175 .valid.min_access_size = 2,
1176 .valid.max_access_size = 4,
1177 .impl.min_access_size = 2,
1178 .impl.max_access_size = 4,
1179 .endianness = DEVICE_NATIVE_ENDIAN,
1182 static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
1184 GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1185 int i;
1187 for (i = 0; i < s->gicv3->num_cpu; i++) {
1188 if (!(s->gicv3->cpu[i].gicr_typer & GICR_TYPER_PLPIS)) {
1189 error_setg(errp, "Physical LPI not supported by CPU %d", i);
1190 return;
1194 gicv3_its_init_mmio(s, &gicv3_its_control_ops, &gicv3_its_translation_ops);
1196 /* set the ITS default features supported */
1197 s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
1198 s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
1199 ITS_ITT_ENTRY_SIZE - 1);
1200 s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
1201 s->typer = FIELD_DP64(s->typer, GITS_TYPER, DEVBITS, ITS_DEVBITS);
1202 s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIL, 1);
1203 s->typer = FIELD_DP64(s->typer, GITS_TYPER, CIDBITS, ITS_CIDBITS);
1206 static void gicv3_its_reset(DeviceState *dev)
1208 GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
1209 GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
1211 c->parent_reset(dev);
1213 /* Quiescent bit reset to 1 */
1214 s->ctlr = FIELD_DP32(s->ctlr, GITS_CTLR, QUIESCENT, 1);
1217 * setting GITS_BASER0.Type = 0b001 (Device)
1218 * GITS_BASER1.Type = 0b100 (Collection Table)
1219 * GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
1220 * GITS_BASER<0,1>.Page_Size = 64KB
1221 * and default translation table entry size to 16 bytes
1223 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, TYPE,
1224 GITS_BASER_TYPE_DEVICE);
1225 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, PAGESIZE,
1226 GITS_BASER_PAGESIZE_64K);
1227 s->baser[0] = FIELD_DP64(s->baser[0], GITS_BASER, ENTRYSIZE,
1228 GITS_DTE_SIZE - 1);
1230 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, TYPE,
1231 GITS_BASER_TYPE_COLLECTION);
1232 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, PAGESIZE,
1233 GITS_BASER_PAGESIZE_64K);
1234 s->baser[1] = FIELD_DP64(s->baser[1], GITS_BASER, ENTRYSIZE,
1235 GITS_CTE_SIZE - 1);
1238 static void gicv3_its_post_load(GICv3ITSState *s)
1240 if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
1241 extract_table_params(s);
1242 extract_cmdq_params(s);
1246 static Property gicv3_its_props[] = {
1247 DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "arm-gicv3",
1248 GICv3State *),
1249 DEFINE_PROP_END_OF_LIST(),
1252 static void gicv3_its_class_init(ObjectClass *klass, void *data)
1254 DeviceClass *dc = DEVICE_CLASS(klass);
1255 GICv3ITSClass *ic = ARM_GICV3_ITS_CLASS(klass);
1256 GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
1258 dc->realize = gicv3_arm_its_realize;
1259 device_class_set_props(dc, gicv3_its_props);
1260 device_class_set_parent_reset(dc, gicv3_its_reset, &ic->parent_reset);
1261 icc->post_load = gicv3_its_post_load;
1264 static const TypeInfo gicv3_its_info = {
1265 .name = TYPE_ARM_GICV3_ITS,
1266 .parent = TYPE_ARM_GICV3_ITS_COMMON,
1267 .instance_size = sizeof(GICv3ITSState),
1268 .class_init = gicv3_its_class_init,
1269 .class_size = sizeof(GICv3ITSClass),
1272 static void gicv3_its_register_types(void)
1274 type_register_static(&gicv3_its_info);
1277 type_init(gicv3_its_register_types)