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