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