2 * ITS emulation for a GICv3-based system
4 * Copyright Linaro.org 2021
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"
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 */
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
{
66 static uint64_t baser_base_addr(uint64_t value
, uint32_t page_sz
)
71 case GITS_PAGE_SIZE_4K
:
72 case GITS_PAGE_SIZE_16K
:
73 result
= FIELD_EX64(value
, GITS_BASER
, PHYADDR
) << 12;
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;
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
;
106 uint32_t num_l2_entries
;
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
) {
124 if (!(l2
& L2_TABLE_VALID_MASK
)) {
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
,
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
,
149 AddressSpace
*as
= &s
->gicv3
->dma_as
;
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
,
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
) {
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
;
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
,
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
);
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
;
235 uint64_t num_eventids
;
238 bool ite_valid
= false;
240 bool cte_valid
= false;
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
) {
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
);
266 dte
= get_dte(s
, devid
, &res
);
268 if (res
!= MEMTX_OK
) {
271 dte_valid
= FIELD_EX64(dte
, 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
);
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 >= %"
287 __func__
, eventid
, num_eventids
);
291 ite_valid
= get_ite(s
, eventid
, dte
, &icid
, &pIntid
, &res
);
292 if (res
!= MEMTX_OK
) {
297 qemu_log_mask(LOG_GUEST_ERROR
,
298 "%s: invalid command attributes: invalid ITE\n",
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",
310 cte_valid
= get_cte(s
, icid
, &cte
, &res
);
311 if (res
!= MEMTX_OK
) {
315 qemu_log_mask(LOG_GUEST_ERROR
,
316 "%s: invalid command attributes: "
317 "invalid cte: %"PRIx64
"\n",
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
) {
332 if ((cmd
== CLEAR
) || (cmd
== DISCARD
)) {
333 gicv3_redist_process_lpi(&s
->gicv3
->cpu
[rdbase
], pIntid
, 0);
335 gicv3_redist_process_lpi(&s
->gicv3
->cpu
[rdbase
], pIntid
, 1);
338 if (cmd
== DISCARD
) {
340 /* remove mapping from interrupt translation table */
341 return update_ite(s
, eventid
, dte
, ite
) ? CMD_CONTINUE
: CMD_STALL
;
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
;
352 uint64_t num_eventids
;
355 MemTxResult res
= MEMTX_OK
;
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
) {
369 eventid
= (value
& EVENTID_MASK
);
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
) {
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
);
394 dte
= get_dte(s
, devid
, &res
);
396 if (res
!= MEMTX_OK
) {
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
,
413 * in this implementation, in case of error
414 * we ignore this command and move onto the next
415 * command in the queue
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
,
433 AddressSpace
*as
= &s
->gicv3
->dma_as
;
436 MemTxResult res
= MEMTX_OK
;
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 */
453 if (entry_addr
== -1) {
454 /* No L2 table for this index: discard write and continue */
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
;
468 MemTxResult res
= MEMTX_OK
;
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
) {
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
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
;
509 MemTxResult res
= MEMTX_OK
;
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
);
522 entry_addr
= table_entry_addr(s
, &s
->dt
, devid
, &res
);
523 if (res
!= MEMTX_OK
) {
524 /* memory access error: stall */
527 if (entry_addr
== -1) {
528 /* No L2 table for this index: discard write and continue */
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
,
538 AddressSpace
*as
= &s
->gicv3
->dma_as
;
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
) {
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
) {
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
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;
595 AddressSpace
*as
= &s
->gicv3
->dma_as
;
596 MemTxResult res
= MEMTX_OK
;
600 if (!(s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
)) {
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
);
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
);
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
);
636 cmd
= (data
& CMD_MASK
);
638 trace_gicv3_its_process_command(rd_offset
, cmd
);
642 result
= process_its_cmd(s
, data
, cq_offset
, INTERRUPT
);
645 result
= process_its_cmd(s
, data
, cq_offset
, CLEAR
);
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.
656 result
= process_mapd(s
, data
, cq_offset
);
659 result
= process_mapc(s
, cq_offset
);
662 result
= process_mapti(s
, data
, cq_offset
, false);
665 result
= process_mapti(s
, data
, cq_offset
, true);
667 case GITS_CMD_DISCARD
:
668 result
= process_its_cmd(s
, data
, cq_offset
, DISCARD
);
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
]);
685 if (result
== CMD_CONTINUE
) {
687 rd_offset
%= s
->cq
.num_entries
;
688 s
->creadr
= FIELD_DP64(s
->creadr
, GITS_CREADR
, OFFSET
, rd_offset
);
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",
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
;
710 uint32_t page_sz
= 0;
713 for (int i
= 0; i
< 8; i
++) {
723 page_sz_type
= FIELD_EX64(value
, GITS_BASER
, PAGESIZE
);
725 switch (page_sz_type
) {
727 page_sz
= GITS_PAGE_SIZE_4K
;
731 page_sz
= GITS_PAGE_SIZE_16K
;
736 page_sz
= GITS_PAGE_SIZE_64K
;
740 g_assert_not_reached();
743 num_pages
= FIELD_EX64(value
, GITS_BASER
, SIZE
) + 1;
745 type
= FIELD_EX64(value
, GITS_BASER
, TYPE
);
748 case GITS_BASER_TYPE_DEVICE
:
750 idbits
= FIELD_EX64(s
->typer
, GITS_TYPER
, DEVBITS
) + 1;
752 case GITS_BASER_TYPE_COLLECTION
:
754 if (FIELD_EX64(s
->typer
, GITS_TYPER
, CIL
)) {
755 idbits
= FIELD_EX64(s
->typer
, GITS_TYPER
, CIDBITS
) + 1;
757 /* 16-bit CollectionId supported when CIL == 0 */
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.)
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
);
788 td
->num_entries
= (num_pages
* page_sz
) / td
->entry_sz
;
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
);
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
,
820 GICv3ITSState
*s
= (GICv3ITSState
*)opaque
;
824 trace_gicv3_its_translation_write(offset
, data
, size
, attrs
.requester_id
);
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
);
844 static bool its_writel(GICv3ITSState
*s
, hwaddr offset
,
845 uint64_t value
, MemTxAttrs attrs
)
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
);
858 s
->ctlr
&= ~R_GITS_CTLR_ENABLED_MASK
;
863 * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
866 if (!(s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
)) {
867 s
->cbaser
= deposit64(s
->cbaser
, 0, 32, value
);
871 case GITS_CBASER
+ 4:
873 * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
876 if (!(s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
)) {
877 s
->cbaser
= deposit64(s
->cbaser
, 32, 32, value
);
882 s
->cwriter
= deposit64(s
->cwriter
, 0, 32,
883 (value
& ~R_GITS_CWRITER_RETRY_MASK
));
884 if (s
->cwriter
!= s
->creadr
) {
888 case GITS_CWRITER
+ 4:
889 s
->cwriter
= deposit64(s
->cwriter
, 32, 32, value
);
892 if (s
->gicv3
->gicd_ctlr
& GICD_CTLR_DS
) {
893 s
->creadr
= deposit64(s
->creadr
, 0, 32,
894 (value
& ~R_GITS_CREADR_STALLED_MASK
));
896 /* RO register, ignore the write */
897 qemu_log_mask(LOG_GUEST_ERROR
,
898 "%s: invalid guest write to RO register at offset "
899 TARGET_FMT_plx
"\n", __func__
, offset
);
902 case GITS_CREADR
+ 4:
903 if (s
->gicv3
->gicd_ctlr
& GICD_CTLR_DS
) {
904 s
->creadr
= deposit64(s
->creadr
, 32, 32, value
);
906 /* RO register, ignore the write */
907 qemu_log_mask(LOG_GUEST_ERROR
,
908 "%s: invalid guest write to RO register at offset "
909 TARGET_FMT_plx
"\n", __func__
, offset
);
912 case GITS_BASER
... GITS_BASER
+ 0x3f:
914 * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
917 if (!(s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
)) {
918 index
= (offset
- GITS_BASER
) / 8;
922 value
&= ~GITS_BASER_RO_MASK
;
923 s
->baser
[index
] &= GITS_BASER_RO_MASK
| MAKE_64BIT_MASK(0, 32);
924 s
->baser
[index
] |= value
;
926 value
&= ~GITS_BASER_RO_MASK
;
927 s
->baser
[index
] &= GITS_BASER_RO_MASK
| MAKE_64BIT_MASK(32, 32);
928 s
->baser
[index
] |= value
;
933 case GITS_IDREGS
... GITS_IDREGS
+ 0x2f:
934 /* RO registers, ignore the write */
935 qemu_log_mask(LOG_GUEST_ERROR
,
936 "%s: invalid guest write to RO register at offset "
937 TARGET_FMT_plx
"\n", __func__
, offset
);
946 static bool its_readl(GICv3ITSState
*s
, hwaddr offset
,
947 uint64_t *data
, MemTxAttrs attrs
)
957 *data
= gicv3_iidr();
959 case GITS_IDREGS
... GITS_IDREGS
+ 0x2f:
961 *data
= gicv3_idreg(offset
- GITS_IDREGS
);
964 *data
= extract64(s
->typer
, 0, 32);
967 *data
= extract64(s
->typer
, 32, 32);
970 *data
= extract64(s
->cbaser
, 0, 32);
972 case GITS_CBASER
+ 4:
973 *data
= extract64(s
->cbaser
, 32, 32);
976 *data
= extract64(s
->creadr
, 0, 32);
978 case GITS_CREADR
+ 4:
979 *data
= extract64(s
->creadr
, 32, 32);
982 *data
= extract64(s
->cwriter
, 0, 32);
984 case GITS_CWRITER
+ 4:
985 *data
= extract64(s
->cwriter
, 32, 32);
987 case GITS_BASER
... GITS_BASER
+ 0x3f:
988 index
= (offset
- GITS_BASER
) / 8;
990 *data
= extract64(s
->baser
[index
], 32, 32);
992 *data
= extract64(s
->baser
[index
], 0, 32);
1002 static bool its_writell(GICv3ITSState
*s
, hwaddr offset
,
1003 uint64_t value
, MemTxAttrs attrs
)
1009 case GITS_BASER
... GITS_BASER
+ 0x3f:
1011 * IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
1014 if (!(s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
)) {
1015 index
= (offset
- GITS_BASER
) / 8;
1016 s
->baser
[index
] &= GITS_BASER_RO_MASK
;
1017 s
->baser
[index
] |= (value
& ~GITS_BASER_RO_MASK
);
1022 * IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
1025 if (!(s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
)) {
1031 s
->cwriter
= value
& ~R_GITS_CWRITER_RETRY_MASK
;
1032 if (s
->cwriter
!= s
->creadr
) {
1037 if (s
->gicv3
->gicd_ctlr
& GICD_CTLR_DS
) {
1038 s
->creadr
= value
& ~R_GITS_CREADR_STALLED_MASK
;
1040 /* RO register, ignore the write */
1041 qemu_log_mask(LOG_GUEST_ERROR
,
1042 "%s: invalid guest write to RO register at offset "
1043 TARGET_FMT_plx
"\n", __func__
, offset
);
1047 /* RO registers, ignore the write */
1048 qemu_log_mask(LOG_GUEST_ERROR
,
1049 "%s: invalid guest write to RO register at offset "
1050 TARGET_FMT_plx
"\n", __func__
, offset
);
1059 static bool its_readll(GICv3ITSState
*s
, hwaddr offset
,
1060 uint64_t *data
, MemTxAttrs attrs
)
1069 case GITS_BASER
... GITS_BASER
+ 0x3f:
1070 index
= (offset
- GITS_BASER
) / 8;
1071 *data
= s
->baser
[index
];
1089 static MemTxResult
gicv3_its_read(void *opaque
, hwaddr offset
, uint64_t *data
,
1090 unsigned size
, MemTxAttrs attrs
)
1092 GICv3ITSState
*s
= (GICv3ITSState
*)opaque
;
1097 result
= its_readl(s
, offset
, data
, attrs
);
1100 result
= its_readll(s
, offset
, data
, attrs
);
1108 qemu_log_mask(LOG_GUEST_ERROR
,
1109 "%s: invalid guest read at offset " TARGET_FMT_plx
1110 "size %u\n", __func__
, offset
, size
);
1111 trace_gicv3_its_badread(offset
, size
);
1113 * The spec requires that reserved registers are RAZ/WI;
1114 * so use false returns from leaf functions as a way to
1115 * trigger the guest-error logging but don't return it to
1116 * the caller, or we'll cause a spurious guest data abort.
1120 trace_gicv3_its_read(offset
, *data
, size
);
1125 static MemTxResult
gicv3_its_write(void *opaque
, hwaddr offset
, uint64_t data
,
1126 unsigned size
, MemTxAttrs attrs
)
1128 GICv3ITSState
*s
= (GICv3ITSState
*)opaque
;
1133 result
= its_writel(s
, offset
, data
, attrs
);
1136 result
= its_writell(s
, offset
, data
, attrs
);
1144 qemu_log_mask(LOG_GUEST_ERROR
,
1145 "%s: invalid guest write at offset " TARGET_FMT_plx
1146 "size %u\n", __func__
, offset
, size
);
1147 trace_gicv3_its_badwrite(offset
, data
, size
);
1149 * The spec requires that reserved registers are RAZ/WI;
1150 * so use false returns from leaf functions as a way to
1151 * trigger the guest-error logging but don't return it to
1152 * the caller, or we'll cause a spurious guest data abort.
1155 trace_gicv3_its_write(offset
, data
, size
);
1160 static const MemoryRegionOps gicv3_its_control_ops
= {
1161 .read_with_attrs
= gicv3_its_read
,
1162 .write_with_attrs
= gicv3_its_write
,
1163 .valid
.min_access_size
= 4,
1164 .valid
.max_access_size
= 8,
1165 .impl
.min_access_size
= 4,
1166 .impl
.max_access_size
= 8,
1167 .endianness
= DEVICE_NATIVE_ENDIAN
,
1170 static const MemoryRegionOps gicv3_its_translation_ops
= {
1171 .write_with_attrs
= gicv3_its_translation_write
,
1172 .valid
.min_access_size
= 2,
1173 .valid
.max_access_size
= 4,
1174 .impl
.min_access_size
= 2,
1175 .impl
.max_access_size
= 4,
1176 .endianness
= DEVICE_NATIVE_ENDIAN
,
1179 static void gicv3_arm_its_realize(DeviceState
*dev
, Error
**errp
)
1181 GICv3ITSState
*s
= ARM_GICV3_ITS_COMMON(dev
);
1184 for (i
= 0; i
< s
->gicv3
->num_cpu
; i
++) {
1185 if (!(s
->gicv3
->cpu
[i
].gicr_typer
& GICR_TYPER_PLPIS
)) {
1186 error_setg(errp
, "Physical LPI not supported by CPU %d", i
);
1191 gicv3_its_init_mmio(s
, &gicv3_its_control_ops
, &gicv3_its_translation_ops
);
1193 /* set the ITS default features supported */
1194 s
->typer
= FIELD_DP64(s
->typer
, GITS_TYPER
, PHYSICAL
, 1);
1195 s
->typer
= FIELD_DP64(s
->typer
, GITS_TYPER
, ITT_ENTRY_SIZE
,
1196 ITS_ITT_ENTRY_SIZE
- 1);
1197 s
->typer
= FIELD_DP64(s
->typer
, GITS_TYPER
, IDBITS
, ITS_IDBITS
);
1198 s
->typer
= FIELD_DP64(s
->typer
, GITS_TYPER
, DEVBITS
, ITS_DEVBITS
);
1199 s
->typer
= FIELD_DP64(s
->typer
, GITS_TYPER
, CIL
, 1);
1200 s
->typer
= FIELD_DP64(s
->typer
, GITS_TYPER
, CIDBITS
, ITS_CIDBITS
);
1203 static void gicv3_its_reset(DeviceState
*dev
)
1205 GICv3ITSState
*s
= ARM_GICV3_ITS_COMMON(dev
);
1206 GICv3ITSClass
*c
= ARM_GICV3_ITS_GET_CLASS(s
);
1208 c
->parent_reset(dev
);
1210 /* Quiescent bit reset to 1 */
1211 s
->ctlr
= FIELD_DP32(s
->ctlr
, GITS_CTLR
, QUIESCENT
, 1);
1214 * setting GITS_BASER0.Type = 0b001 (Device)
1215 * GITS_BASER1.Type = 0b100 (Collection Table)
1216 * GITS_BASER<n>.Type,where n = 3 to 7 are 0b00 (Unimplemented)
1217 * GITS_BASER<0,1>.Page_Size = 64KB
1218 * and default translation table entry size to 16 bytes
1220 s
->baser
[0] = FIELD_DP64(s
->baser
[0], GITS_BASER
, TYPE
,
1221 GITS_BASER_TYPE_DEVICE
);
1222 s
->baser
[0] = FIELD_DP64(s
->baser
[0], GITS_BASER
, PAGESIZE
,
1223 GITS_BASER_PAGESIZE_64K
);
1224 s
->baser
[0] = FIELD_DP64(s
->baser
[0], GITS_BASER
, ENTRYSIZE
,
1227 s
->baser
[1] = FIELD_DP64(s
->baser
[1], GITS_BASER
, TYPE
,
1228 GITS_BASER_TYPE_COLLECTION
);
1229 s
->baser
[1] = FIELD_DP64(s
->baser
[1], GITS_BASER
, PAGESIZE
,
1230 GITS_BASER_PAGESIZE_64K
);
1231 s
->baser
[1] = FIELD_DP64(s
->baser
[1], GITS_BASER
, ENTRYSIZE
,
1235 static void gicv3_its_post_load(GICv3ITSState
*s
)
1237 if (s
->ctlr
& R_GITS_CTLR_ENABLED_MASK
) {
1238 extract_table_params(s
);
1239 extract_cmdq_params(s
);
1243 static Property gicv3_its_props
[] = {
1244 DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState
, gicv3
, "arm-gicv3",
1246 DEFINE_PROP_END_OF_LIST(),
1249 static void gicv3_its_class_init(ObjectClass
*klass
, void *data
)
1251 DeviceClass
*dc
= DEVICE_CLASS(klass
);
1252 GICv3ITSClass
*ic
= ARM_GICV3_ITS_CLASS(klass
);
1253 GICv3ITSCommonClass
*icc
= ARM_GICV3_ITS_COMMON_CLASS(klass
);
1255 dc
->realize
= gicv3_arm_its_realize
;
1256 device_class_set_props(dc
, gicv3_its_props
);
1257 device_class_set_parent_reset(dc
, gicv3_its_reset
, &ic
->parent_reset
);
1258 icc
->post_load
= gicv3_its_post_load
;
1261 static const TypeInfo gicv3_its_info
= {
1262 .name
= TYPE_ARM_GICV3_ITS
,
1263 .parent
= TYPE_ARM_GICV3_ITS_COMMON
,
1264 .instance_size
= sizeof(GICv3ITSState
),
1265 .class_init
= gicv3_its_class_init
,
1266 .class_size
= sizeof(GICv3ITSClass
),
1269 static void gicv3_its_register_types(void)
1271 type_register_static(&gicv3_its_info
);
1274 type_init(gicv3_its_register_types
)