qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

hw: aspeed_scu: Add AST2600 support

The SCU controller on the AST2600 SoC has extra registers. Increase
the number of regs of the model and introduce a new field in the class
to customize the MemoryRegion operations depending on the SoC model.

Signed-off-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20190925143248.10000-4-clg@kaod.org
[clg: - improved commit log
- changed vmstate version
- reworked model integration into new object class
- included AST2600_HPLL_PARAM value ]
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Joel Stanley and committed by
Peter Maydell
e09cf363 2bea128c

+191 -8
+185 -7
hw/misc/aspeed_scu.c
··· 88 88 #define BMC_REV TO_REG(0x19C) 89 89 #define BMC_DEV_ID TO_REG(0x1A4) 90 90 91 + #define AST2600_PROT_KEY TO_REG(0x00) 92 + #define AST2600_SILICON_REV TO_REG(0x04) 93 + #define AST2600_SILICON_REV2 TO_REG(0x14) 94 + #define AST2600_SYS_RST_CTRL TO_REG(0x40) 95 + #define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44) 96 + #define AST2600_SYS_RST_CTRL2 TO_REG(0x50) 97 + #define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54) 98 + #define AST2600_CLK_STOP_CTRL TO_REG(0x80) 99 + #define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84) 100 + #define AST2600_CLK_STOP_CTRL2 TO_REG(0x90) 101 + #define AST2600_CLK_STOP_CTR2L_CLR TO_REG(0x94) 102 + #define AST2600_HPLL_PARAM TO_REG(0x200) 103 + #define AST2600_HPLL_EXT TO_REG(0x204) 104 + #define AST2600_MPLL_EXT TO_REG(0x224) 105 + #define AST2600_EPLL_EXT TO_REG(0x244) 106 + #define AST2600_CLK_SEL TO_REG(0x300) 107 + #define AST2600_CLK_SEL2 TO_REG(0x304) 108 + #define AST2600_CLK_SEL3 TO_REG(0x310) 109 + #define AST2600_HW_STRAP1 TO_REG(0x500) 110 + #define AST2600_HW_STRAP1_CLR TO_REG(0x504) 111 + #define AST2600_HW_STRAP1_PROT TO_REG(0x508) 112 + #define AST2600_HW_STRAP2 TO_REG(0x510) 113 + #define AST2600_HW_STRAP2_CLR TO_REG(0x514) 114 + #define AST2600_HW_STRAP2_PROT TO_REG(0x518) 115 + #define AST2600_RNG_CTRL TO_REG(0x524) 116 + #define AST2600_RNG_DATA TO_REG(0x540) 117 + 118 + #define AST2600_CLK TO_REG(0x40) 119 + 91 120 #define SCU_IO_REGION_SIZE 0x1000 92 121 93 122 static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = { ··· 178 207 AspeedSCUState *s = ASPEED_SCU(opaque); 179 208 int reg = TO_REG(offset); 180 209 181 - if (reg >= ARRAY_SIZE(s->regs)) { 210 + if (reg >= ASPEED_SCU_NR_REGS) { 182 211 qemu_log_mask(LOG_GUEST_ERROR, 183 212 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 184 213 __func__, offset); ··· 208 237 AspeedSCUState *s = ASPEED_SCU(opaque); 209 238 int reg = TO_REG(offset); 210 239 211 - if (reg >= ARRAY_SIZE(s->regs)) { 240 + if (reg >= ASPEED_SCU_NR_REGS) { 212 241 qemu_log_mask(LOG_GUEST_ERROR, 213 242 "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 214 243 __func__, offset); ··· 346 375 AspeedSCUState *s = ASPEED_SCU(dev); 347 376 AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); 348 377 349 - memcpy(s->regs, asc->resets, sizeof(s->regs)); 378 + memcpy(s->regs, asc->resets, asc->nr_regs * 4); 350 379 s->regs[SILICON_REV] = s->silicon_rev; 351 380 s->regs[HW_STRAP1] = s->hw_strap1; 352 381 s->regs[HW_STRAP2] = s->hw_strap2; ··· 358 387 AST2400_A1_SILICON_REV, 359 388 AST2500_A0_SILICON_REV, 360 389 AST2500_A1_SILICON_REV, 390 + AST2600_A0_SILICON_REV, 361 391 }; 362 392 363 393 bool is_supported_silicon_rev(uint32_t silicon_rev) ··· 377 407 { 378 408 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 379 409 AspeedSCUState *s = ASPEED_SCU(dev); 410 + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); 380 411 381 412 if (!is_supported_silicon_rev(s->silicon_rev)) { 382 413 error_setg(errp, "Unknown silicon revision: 0x%" PRIx32, ··· 384 415 return; 385 416 } 386 417 387 - memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_scu_ops, s, 418 + memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s, 388 419 TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE); 389 420 390 421 sysbus_init_mmio(sbd, &s->iomem); ··· 392 423 393 424 static const VMStateDescription vmstate_aspeed_scu = { 394 425 .name = "aspeed.scu", 395 - .version_id = 1, 396 - .minimum_version_id = 1, 426 + .version_id = 2, 427 + .minimum_version_id = 2, 397 428 .fields = (VMStateField[]) { 398 - VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_SCU_NR_REGS), 429 + VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS), 399 430 VMSTATE_END_OF_LIST() 400 431 } 401 432 }; ··· 436 467 asc->resets = ast2400_a0_resets; 437 468 asc->calc_hpll = aspeed_2400_scu_calc_hpll; 438 469 asc->apb_divider = 2; 470 + asc->nr_regs = ASPEED_SCU_NR_REGS; 471 + asc->ops = &aspeed_scu_ops; 439 472 } 440 473 441 474 static const TypeInfo aspeed_2400_scu_info = { ··· 454 487 asc->resets = ast2500_a1_resets; 455 488 asc->calc_hpll = aspeed_2500_scu_calc_hpll; 456 489 asc->apb_divider = 4; 490 + asc->nr_regs = ASPEED_SCU_NR_REGS; 491 + asc->ops = &aspeed_scu_ops; 457 492 } 458 493 459 494 static const TypeInfo aspeed_2500_scu_info = { ··· 463 498 .class_init = aspeed_2500_scu_class_init, 464 499 }; 465 500 501 + static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset, 502 + unsigned size) 503 + { 504 + AspeedSCUState *s = ASPEED_SCU(opaque); 505 + int reg = TO_REG(offset); 506 + 507 + if (reg >= ASPEED_AST2600_SCU_NR_REGS) { 508 + qemu_log_mask(LOG_GUEST_ERROR, 509 + "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n", 510 + __func__, offset); 511 + return 0; 512 + } 513 + 514 + switch (reg) { 515 + case AST2600_HPLL_EXT: 516 + case AST2600_EPLL_EXT: 517 + case AST2600_MPLL_EXT: 518 + /* PLLs are always "locked" */ 519 + return s->regs[reg] | BIT(31); 520 + case AST2600_RNG_DATA: 521 + /* 522 + * On hardware, RNG_DATA works regardless of the state of the 523 + * enable bit in RNG_CTRL 524 + * 525 + * TODO: Check this is true for ast2600 526 + */ 527 + s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random(); 528 + break; 529 + } 530 + 531 + return s->regs[reg]; 532 + } 533 + 534 + static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, uint64_t data, 535 + unsigned size) 536 + { 537 + AspeedSCUState *s = ASPEED_SCU(opaque); 538 + int reg = TO_REG(offset); 539 + 540 + if (reg >= ASPEED_AST2600_SCU_NR_REGS) { 541 + qemu_log_mask(LOG_GUEST_ERROR, 542 + "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n", 543 + __func__, offset); 544 + return; 545 + } 546 + 547 + if (reg > PROT_KEY && !s->regs[PROT_KEY]) { 548 + qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__); 549 + } 550 + 551 + trace_aspeed_scu_write(offset, size, data); 552 + 553 + switch (reg) { 554 + case AST2600_PROT_KEY: 555 + s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0; 556 + return; 557 + case AST2600_HW_STRAP1: 558 + case AST2600_HW_STRAP2: 559 + if (s->regs[reg + 2]) { 560 + return; 561 + } 562 + /* fall through */ 563 + case AST2600_SYS_RST_CTRL: 564 + case AST2600_SYS_RST_CTRL2: 565 + /* W1S (Write 1 to set) registers */ 566 + s->regs[reg] |= data; 567 + return; 568 + case AST2600_SYS_RST_CTRL_CLR: 569 + case AST2600_SYS_RST_CTRL2_CLR: 570 + case AST2600_HW_STRAP1_CLR: 571 + case AST2600_HW_STRAP2_CLR: 572 + /* W1C (Write 1 to clear) registers */ 573 + s->regs[reg] &= ~data; 574 + return; 575 + 576 + case AST2600_RNG_DATA: 577 + case AST2600_SILICON_REV: 578 + case AST2600_SILICON_REV2: 579 + /* Add read only registers here */ 580 + qemu_log_mask(LOG_GUEST_ERROR, 581 + "%s: Write to read-only offset 0x%" HWADDR_PRIx "\n", 582 + __func__, offset); 583 + return; 584 + } 585 + 586 + s->regs[reg] = data; 587 + } 588 + 589 + static const MemoryRegionOps aspeed_ast2600_scu_ops = { 590 + .read = aspeed_ast2600_scu_read, 591 + .write = aspeed_ast2600_scu_write, 592 + .endianness = DEVICE_LITTLE_ENDIAN, 593 + .valid.min_access_size = 4, 594 + .valid.max_access_size = 4, 595 + .valid.unaligned = false, 596 + }; 597 + 598 + static const uint32_t ast2600_a0_resets[ASPEED_AST2600_SCU_NR_REGS] = { 599 + [AST2600_SILICON_REV] = AST2600_SILICON_REV, 600 + [AST2600_SILICON_REV2] = AST2600_SILICON_REV, 601 + [AST2600_SYS_RST_CTRL] = 0xF7CFFEDC | 0x100, 602 + [AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC, 603 + [AST2600_CLK_STOP_CTRL] = 0xEFF43E8B, 604 + [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0, 605 + [AST2600_HPLL_PARAM] = 0x1000405F, 606 + }; 607 + 608 + static void aspeed_ast2600_scu_reset(DeviceState *dev) 609 + { 610 + AspeedSCUState *s = ASPEED_SCU(dev); 611 + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); 612 + 613 + memcpy(s->regs, asc->resets, asc->nr_regs * 4); 614 + 615 + s->regs[AST2600_SILICON_REV] = s->silicon_rev; 616 + s->regs[AST2600_SILICON_REV2] = s->silicon_rev; 617 + s->regs[AST2600_HW_STRAP1] = s->hw_strap1; 618 + s->regs[AST2600_HW_STRAP2] = s->hw_strap2; 619 + s->regs[PROT_KEY] = s->hw_prot_key; 620 + } 621 + 622 + static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data) 623 + { 624 + DeviceClass *dc = DEVICE_CLASS(klass); 625 + AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass); 626 + 627 + dc->desc = "ASPEED 2600 System Control Unit"; 628 + dc->reset = aspeed_ast2600_scu_reset; 629 + asc->resets = ast2600_a0_resets; 630 + asc->calc_hpll = aspeed_2500_scu_calc_hpll; /* No change since AST2500 */ 631 + asc->apb_divider = 4; 632 + asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS; 633 + asc->ops = &aspeed_ast2600_scu_ops; 634 + } 635 + 636 + static const TypeInfo aspeed_2600_scu_info = { 637 + .name = TYPE_ASPEED_2600_SCU, 638 + .parent = TYPE_ASPEED_SCU, 639 + .instance_size = sizeof(AspeedSCUState), 640 + .class_init = aspeed_2600_scu_class_init, 641 + }; 642 + 466 643 static void aspeed_scu_register_types(void) 467 644 { 468 645 type_register_static(&aspeed_scu_info); 469 646 type_register_static(&aspeed_2400_scu_info); 470 647 type_register_static(&aspeed_2500_scu_info); 648 + type_register_static(&aspeed_2600_scu_info); 471 649 } 472 650 473 651 type_init(aspeed_scu_register_types);
+6 -1
include/hw/misc/aspeed_scu.h
··· 17 17 #define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU) 18 18 #define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400" 19 19 #define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500" 20 + #define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600" 20 21 21 22 #define ASPEED_SCU_NR_REGS (0x1A8 >> 2) 23 + #define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2) 22 24 23 25 typedef struct AspeedSCUState { 24 26 /*< private >*/ ··· 27 29 /*< public >*/ 28 30 MemoryRegion iomem; 29 31 30 - uint32_t regs[ASPEED_SCU_NR_REGS]; 32 + uint32_t regs[ASPEED_AST2600_SCU_NR_REGS]; 31 33 uint32_t silicon_rev; 32 34 uint32_t hw_strap1; 33 35 uint32_t hw_strap2; ··· 38 40 #define AST2400_A1_SILICON_REV 0x02010303U 39 41 #define AST2500_A0_SILICON_REV 0x04000303U 40 42 #define AST2500_A1_SILICON_REV 0x04010303U 43 + #define AST2600_A0_SILICON_REV 0x05000303U 41 44 42 45 #define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04) 43 46 ··· 54 57 const uint32_t *resets; 55 58 uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg); 56 59 uint32_t apb_divider; 60 + uint32_t nr_regs; 61 + const MemoryRegionOps *ops; 57 62 } AspeedSCUClass; 58 63 59 64 #define ASPEED_SCU_PROT_KEY 0x1688A8A8