1 /* 2 * QEMU PowerPC PowerNV CPU Core model 3 * 4 * Copyright (c) 2016, IBM Corporation. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public License 8 * as published by the Free Software Foundation; either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "qemu/osdep.h" 21 #include "sysemu/reset.h" 22 #include "qapi/error.h" 23 #include "qemu/log.h" 24 #include "qemu/module.h" 25 #include "target/ppc/cpu.h" 26 #include "hw/ppc/ppc.h" 27 #include "hw/ppc/pnv.h" 28 #include "hw/ppc/pnv_chip.h" 29 #include "hw/ppc/pnv_core.h" 30 #include "hw/ppc/pnv_xscom.h" 31 #include "hw/ppc/xics.h" 32 #include "hw/qdev-properties.h" 33 #include "helper_regs.h" 34 35 static const char *pnv_core_cpu_typename(PnvCore *pc) 36 { 37 const char *core_type = object_class_get_name(object_get_class(OBJECT(pc))); 38 int len = strlen(core_type) - strlen(PNV_CORE_TYPE_SUFFIX); 39 char *s = g_strdup_printf(POWERPC_CPU_TYPE_NAME("%.*s"), len, core_type); 40 const char *cpu_type = object_class_get_name(object_class_by_name(s)); 41 g_free(s); 42 return cpu_type; 43 } 44 45 static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu) 46 { 47 CPUState *cs = CPU(cpu); 48 CPUPPCState *env = &cpu->env; 49 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); 50 51 cpu_reset(cs); 52 53 /* 54 * the skiboot firmware elects a primary thread to initialize the 55 * system and it can be any. 56 */ 57 env->gpr[3] = PNV_FDT_ADDR; 58 env->nip = 0x10; 59 env->msr |= MSR_HVB; /* Hypervisor mode */ 60 env->spr[SPR_HRMOR] = pc->hrmor; 61 hreg_compute_hflags(env); 62 ppc_maybe_interrupt(env); 63 64 pcc->intc_reset(pc->chip, cpu); 65 } 66 67 /* 68 * These values are read by the PowerNV HW monitors under Linux 69 */ 70 #define PNV_XSCOM_EX_DTS_RESULT0 0x50000 71 #define PNV_XSCOM_EX_DTS_RESULT1 0x50001 72 73 static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr, 74 unsigned int width) 75 { 76 uint32_t offset = addr >> 3; 77 uint64_t val = 0; 78 79 /* The result should be 38 C */ 80 switch (offset) { 81 case PNV_XSCOM_EX_DTS_RESULT0: 82 val = 0x26f024f023f0000ull; 83 break; 84 case PNV_XSCOM_EX_DTS_RESULT1: 85 val = 0x24f000000000000ull; 86 break; 87 default: 88 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 89 offset); 90 } 91 92 return val; 93 } 94 95 static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val, 96 unsigned int width) 97 { 98 uint32_t offset = addr >> 3; 99 100 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 101 offset); 102 } 103 104 static const MemoryRegionOps pnv_core_power8_xscom_ops = { 105 .read = pnv_core_power8_xscom_read, 106 .write = pnv_core_power8_xscom_write, 107 .valid.min_access_size = 8, 108 .valid.max_access_size = 8, 109 .impl.min_access_size = 8, 110 .impl.max_access_size = 8, 111 .endianness = DEVICE_BIG_ENDIAN, 112 }; 113 114 115 /* 116 * POWER9 core controls 117 */ 118 #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d 119 #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a 120 121 #define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3 122 123 static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, 124 unsigned int width) 125 { 126 uint32_t offset = addr >> 3; 127 uint64_t val = 0; 128 129 /* The result should be 38 C */ 130 switch (offset) { 131 case PNV_XSCOM_EX_DTS_RESULT0: 132 val = 0x26f024f023f0000ull; 133 break; 134 case PNV_XSCOM_EX_DTS_RESULT1: 135 val = 0x24f000000000000ull; 136 break; 137 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP: 138 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: 139 val = 0x0; 140 break; 141 case PNV9_XSCOM_EC_CORE_THREAD_STATE: 142 val = 0; 143 break; 144 default: 145 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 146 offset); 147 } 148 149 return val; 150 } 151 152 static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, 153 unsigned int width) 154 { 155 uint32_t offset = addr >> 3; 156 157 switch (offset) { 158 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP: 159 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: 160 break; 161 default: 162 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 163 offset); 164 } 165 } 166 167 static const MemoryRegionOps pnv_core_power9_xscom_ops = { 168 .read = pnv_core_power9_xscom_read, 169 .write = pnv_core_power9_xscom_write, 170 .valid.min_access_size = 8, 171 .valid.max_access_size = 8, 172 .impl.min_access_size = 8, 173 .impl.max_access_size = 8, 174 .endianness = DEVICE_BIG_ENDIAN, 175 }; 176 177 /* 178 * POWER10 core controls 179 */ 180 181 #define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412 182 183 static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, 184 unsigned int width) 185 { 186 uint32_t offset = addr >> 3; 187 uint64_t val = 0; 188 189 switch (offset) { 190 case PNV10_XSCOM_EC_CORE_THREAD_STATE: 191 val = 0; 192 break; 193 default: 194 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 195 offset); 196 } 197 198 return val; 199 } 200 201 static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, 202 uint64_t val, unsigned int width) 203 { 204 uint32_t offset = addr >> 3; 205 206 switch (offset) { 207 default: 208 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 209 offset); 210 } 211 } 212 213 static const MemoryRegionOps pnv_core_power10_xscom_ops = { 214 .read = pnv_core_power10_xscom_read, 215 .write = pnv_core_power10_xscom_write, 216 .valid.min_access_size = 8, 217 .valid.max_access_size = 8, 218 .impl.min_access_size = 8, 219 .impl.max_access_size = 8, 220 .endianness = DEVICE_BIG_ENDIAN, 221 }; 222 223 static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, 224 int thread_index) 225 { 226 CPUPPCState *env = &cpu->env; 227 int core_pir; 228 ppc_spr_t *pir = &env->spr_cb[SPR_PIR]; 229 ppc_spr_t *tir = &env->spr_cb[SPR_TIR]; 230 Error *local_err = NULL; 231 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); 232 233 if (!qdev_realize(DEVICE(cpu), NULL, errp)) { 234 return; 235 } 236 237 pcc->intc_create(pc->chip, cpu, &local_err); 238 if (local_err) { 239 error_propagate(errp, local_err); 240 return; 241 } 242 243 core_pir = object_property_get_uint(OBJECT(pc), "pir", &error_abort); 244 245 tir->default_value = thread_index; 246 pir->default_value = core_pir + thread_index; 247 248 /* Set time-base frequency to 512 MHz */ 249 cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ); 250 } 251 252 static void pnv_core_reset(void *dev) 253 { 254 CPUCore *cc = CPU_CORE(dev); 255 PnvCore *pc = PNV_CORE(dev); 256 int i; 257 258 for (i = 0; i < cc->nr_threads; i++) { 259 pnv_core_cpu_reset(pc, pc->threads[i]); 260 } 261 } 262 263 static void pnv_core_realize(DeviceState *dev, Error **errp) 264 { 265 PnvCore *pc = PNV_CORE(OBJECT(dev)); 266 PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc); 267 CPUCore *cc = CPU_CORE(OBJECT(dev)); 268 const char *typename = pnv_core_cpu_typename(pc); 269 Error *local_err = NULL; 270 void *obj; 271 int i, j; 272 char name[32]; 273 274 assert(pc->chip); 275 276 pc->threads = g_new(PowerPCCPU *, cc->nr_threads); 277 for (i = 0; i < cc->nr_threads; i++) { 278 PowerPCCPU *cpu; 279 280 obj = object_new(typename); 281 cpu = POWERPC_CPU(obj); 282 283 pc->threads[i] = POWERPC_CPU(obj); 284 285 snprintf(name, sizeof(name), "thread[%d]", i); 286 object_property_add_child(OBJECT(pc), name, obj); 287 288 cpu->machine_data = g_new0(PnvCPUState, 1); 289 290 object_unref(obj); 291 } 292 293 for (j = 0; j < cc->nr_threads; j++) { 294 pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j); 295 if (local_err) { 296 goto err; 297 } 298 } 299 300 snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id); 301 pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops, 302 pc, name, pcc->xscom_size); 303 304 qemu_register_reset(pnv_core_reset, pc); 305 return; 306 307 err: 308 while (--i >= 0) { 309 obj = OBJECT(pc->threads[i]); 310 object_unparent(obj); 311 } 312 g_free(pc->threads); 313 error_propagate(errp, local_err); 314 } 315 316 static void pnv_core_cpu_unrealize(PnvCore *pc, PowerPCCPU *cpu) 317 { 318 PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 319 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); 320 321 pcc->intc_destroy(pc->chip, cpu); 322 cpu_remove_sync(CPU(cpu)); 323 cpu->machine_data = NULL; 324 g_free(pnv_cpu); 325 object_unparent(OBJECT(cpu)); 326 } 327 328 static void pnv_core_unrealize(DeviceState *dev) 329 { 330 PnvCore *pc = PNV_CORE(dev); 331 CPUCore *cc = CPU_CORE(dev); 332 int i; 333 334 qemu_unregister_reset(pnv_core_reset, pc); 335 336 for (i = 0; i < cc->nr_threads; i++) { 337 pnv_core_cpu_unrealize(pc, pc->threads[i]); 338 } 339 g_free(pc->threads); 340 } 341 342 static Property pnv_core_properties[] = { 343 DEFINE_PROP_UINT32("pir", PnvCore, pir, 0), 344 DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0), 345 DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *), 346 DEFINE_PROP_END_OF_LIST(), 347 }; 348 349 static void pnv_core_power8_class_init(ObjectClass *oc, void *data) 350 { 351 PnvCoreClass *pcc = PNV_CORE_CLASS(oc); 352 353 pcc->xscom_ops = &pnv_core_power8_xscom_ops; 354 pcc->xscom_size = PNV_XSCOM_EX_SIZE; 355 } 356 357 static void pnv_core_power9_class_init(ObjectClass *oc, void *data) 358 { 359 PnvCoreClass *pcc = PNV_CORE_CLASS(oc); 360 361 pcc->xscom_ops = &pnv_core_power9_xscom_ops; 362 pcc->xscom_size = PNV_XSCOM_EX_SIZE; 363 } 364 365 static void pnv_core_power10_class_init(ObjectClass *oc, void *data) 366 { 367 PnvCoreClass *pcc = PNV_CORE_CLASS(oc); 368 369 pcc->xscom_ops = &pnv_core_power10_xscom_ops; 370 pcc->xscom_size = PNV10_XSCOM_EC_SIZE; 371 } 372 373 static void pnv_core_class_init(ObjectClass *oc, void *data) 374 { 375 DeviceClass *dc = DEVICE_CLASS(oc); 376 377 dc->realize = pnv_core_realize; 378 dc->unrealize = pnv_core_unrealize; 379 device_class_set_props(dc, pnv_core_properties); 380 dc->user_creatable = false; 381 } 382 383 #define DEFINE_PNV_CORE_TYPE(family, cpu_model) \ 384 { \ 385 .parent = TYPE_PNV_CORE, \ 386 .name = PNV_CORE_TYPE_NAME(cpu_model), \ 387 .class_init = pnv_core_##family##_class_init, \ 388 } 389 390 static const TypeInfo pnv_core_infos[] = { 391 { 392 .name = TYPE_PNV_CORE, 393 .parent = TYPE_CPU_CORE, 394 .instance_size = sizeof(PnvCore), 395 .class_size = sizeof(PnvCoreClass), 396 .class_init = pnv_core_class_init, 397 .abstract = true, 398 }, 399 DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"), 400 DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"), 401 DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), 402 DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"), 403 DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"), 404 }; 405 406 DEFINE_TYPES(pnv_core_infos) 407 408 /* 409 * POWER9 Quads 410 */ 411 412 #define P9X_EX_NCU_SPEC_BAR 0x11010 413 414 static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr, 415 unsigned int width) 416 { 417 uint32_t offset = addr >> 3; 418 uint64_t val = -1; 419 420 switch (offset) { 421 case P9X_EX_NCU_SPEC_BAR: 422 case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */ 423 val = 0; 424 break; 425 default: 426 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 427 offset); 428 } 429 430 return val; 431 } 432 433 static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, 434 unsigned int width) 435 { 436 uint32_t offset = addr >> 3; 437 438 switch (offset) { 439 case P9X_EX_NCU_SPEC_BAR: 440 case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */ 441 break; 442 default: 443 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 444 offset); 445 } 446 } 447 448 static const MemoryRegionOps pnv_quad_power9_xscom_ops = { 449 .read = pnv_quad_power9_xscom_read, 450 .write = pnv_quad_power9_xscom_write, 451 .valid.min_access_size = 8, 452 .valid.max_access_size = 8, 453 .impl.min_access_size = 8, 454 .impl.max_access_size = 8, 455 .endianness = DEVICE_BIG_ENDIAN, 456 }; 457 458 /* 459 * POWER10 Quads 460 */ 461 462 static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr, 463 unsigned int width) 464 { 465 uint32_t offset = addr >> 3; 466 uint64_t val = -1; 467 468 switch (offset) { 469 default: 470 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 471 offset); 472 } 473 474 return val; 475 } 476 477 static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr, 478 uint64_t val, unsigned int width) 479 { 480 uint32_t offset = addr >> 3; 481 482 switch (offset) { 483 default: 484 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 485 offset); 486 } 487 } 488 489 static const MemoryRegionOps pnv_quad_power10_xscom_ops = { 490 .read = pnv_quad_power10_xscom_read, 491 .write = pnv_quad_power10_xscom_write, 492 .valid.min_access_size = 8, 493 .valid.max_access_size = 8, 494 .impl.min_access_size = 8, 495 .impl.max_access_size = 8, 496 .endianness = DEVICE_BIG_ENDIAN, 497 }; 498 499 #define P10_QME_SPWU_HYP 0x83c 500 #define P10_QME_SSH_HYP 0x82c 501 502 static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr, 503 unsigned int width) 504 { 505 uint32_t offset = addr >> 3; 506 uint64_t val = -1; 507 508 /* 509 * Forth nibble selects the core within a quad, mask it to process read 510 * for any core. 511 */ 512 switch (offset & ~0xf000) { 513 case P10_QME_SPWU_HYP: 514 case P10_QME_SSH_HYP: 515 return 0; 516 default: 517 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 518 offset); 519 } 520 521 return val; 522 } 523 524 static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr, 525 uint64_t val, unsigned int width) 526 { 527 uint32_t offset = addr >> 3; 528 529 switch (offset) { 530 default: 531 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 532 offset); 533 } 534 } 535 536 static const MemoryRegionOps pnv_qme_power10_xscom_ops = { 537 .read = pnv_qme_power10_xscom_read, 538 .write = pnv_qme_power10_xscom_write, 539 .valid.min_access_size = 8, 540 .valid.max_access_size = 8, 541 .impl.min_access_size = 8, 542 .impl.max_access_size = 8, 543 .endianness = DEVICE_BIG_ENDIAN, 544 }; 545 546 static void pnv_quad_power9_realize(DeviceState *dev, Error **errp) 547 { 548 PnvQuad *eq = PNV_QUAD(dev); 549 PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); 550 char name[32]; 551 552 snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); 553 pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), 554 pqc->xscom_ops, 555 eq, name, 556 pqc->xscom_size); 557 } 558 559 static void pnv_quad_power10_realize(DeviceState *dev, Error **errp) 560 { 561 PnvQuad *eq = PNV_QUAD(dev); 562 PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); 563 char name[32]; 564 565 snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); 566 pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), 567 pqc->xscom_ops, 568 eq, name, 569 pqc->xscom_size); 570 571 snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id); 572 pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev), 573 pqc->xscom_qme_ops, 574 eq, name, 575 pqc->xscom_qme_size); 576 } 577 578 static Property pnv_quad_properties[] = { 579 DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0), 580 DEFINE_PROP_END_OF_LIST(), 581 }; 582 583 static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) 584 { 585 PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); 586 DeviceClass *dc = DEVICE_CLASS(oc); 587 588 dc->realize = pnv_quad_power9_realize; 589 590 pqc->xscom_ops = &pnv_quad_power9_xscom_ops; 591 pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; 592 } 593 594 static void pnv_quad_power10_class_init(ObjectClass *oc, void *data) 595 { 596 PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); 597 DeviceClass *dc = DEVICE_CLASS(oc); 598 599 dc->realize = pnv_quad_power10_realize; 600 601 pqc->xscom_ops = &pnv_quad_power10_xscom_ops; 602 pqc->xscom_size = PNV10_XSCOM_EQ_SIZE; 603 604 pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops; 605 pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE; 606 } 607 608 static void pnv_quad_class_init(ObjectClass *oc, void *data) 609 { 610 DeviceClass *dc = DEVICE_CLASS(oc); 611 612 device_class_set_props(dc, pnv_quad_properties); 613 dc->user_creatable = false; 614 } 615 616 static const TypeInfo pnv_quad_infos[] = { 617 { 618 .name = TYPE_PNV_QUAD, 619 .parent = TYPE_DEVICE, 620 .instance_size = sizeof(PnvQuad), 621 .class_size = sizeof(PnvQuadClass), 622 .class_init = pnv_quad_class_init, 623 .abstract = true, 624 }, 625 { 626 .parent = TYPE_PNV_QUAD, 627 .name = PNV_QUAD_TYPE_NAME("power9"), 628 .class_init = pnv_quad_power9_class_init, 629 }, 630 { 631 .parent = TYPE_PNV_QUAD, 632 .name = PNV_QUAD_TYPE_NAME("power10"), 633 .class_init = pnv_quad_power10_class_init, 634 }, 635 }; 636 637 DEFINE_TYPES(pnv_quad_infos); 638