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 if (pc->big_core) { 62 /* Clear "small core" bit on Power9/10 (this is set in default PVR) */ 63 env->spr[SPR_PVR] &= ~PPC_BIT(51); 64 } 65 hreg_compute_hflags(env); 66 ppc_maybe_interrupt(env); 67 68 cpu_ppc_tb_reset(env); 69 70 pcc->intc_reset(pc->chip, cpu); 71 } 72 73 /* 74 * These values are read by the PowerNV HW monitors under Linux 75 */ 76 #define PNV_XSCOM_EX_DTS_RESULT0 0x50000 77 #define PNV_XSCOM_EX_DTS_RESULT1 0x50001 78 79 static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr, 80 unsigned int width) 81 { 82 uint32_t offset = addr >> 3; 83 uint64_t val = 0; 84 85 /* The result should be 38 C */ 86 switch (offset) { 87 case PNV_XSCOM_EX_DTS_RESULT0: 88 val = 0x26f024f023f0000ull; 89 break; 90 case PNV_XSCOM_EX_DTS_RESULT1: 91 val = 0x24f000000000000ull; 92 break; 93 default: 94 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 95 offset); 96 } 97 98 return val; 99 } 100 101 static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val, 102 unsigned int width) 103 { 104 uint32_t offset = addr >> 3; 105 106 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 107 offset); 108 } 109 110 static const MemoryRegionOps pnv_core_power8_xscom_ops = { 111 .read = pnv_core_power8_xscom_read, 112 .write = pnv_core_power8_xscom_write, 113 .valid.min_access_size = 8, 114 .valid.max_access_size = 8, 115 .impl.min_access_size = 8, 116 .impl.max_access_size = 8, 117 .endianness = DEVICE_BIG_ENDIAN, 118 }; 119 120 121 /* 122 * POWER9 core controls 123 */ 124 #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d 125 #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a 126 127 #define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3 128 129 static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr, 130 unsigned int width) 131 { 132 uint32_t offset = addr >> 3; 133 uint64_t val = 0; 134 135 /* The result should be 38 C */ 136 switch (offset) { 137 case PNV_XSCOM_EX_DTS_RESULT0: 138 val = 0x26f024f023f0000ull; 139 break; 140 case PNV_XSCOM_EX_DTS_RESULT1: 141 val = 0x24f000000000000ull; 142 break; 143 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP: 144 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: 145 val = 0x0; 146 break; 147 case PNV9_XSCOM_EC_CORE_THREAD_STATE: 148 val = 0; 149 break; 150 default: 151 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 152 offset); 153 } 154 155 return val; 156 } 157 158 static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, 159 unsigned int width) 160 { 161 uint32_t offset = addr >> 3; 162 163 switch (offset) { 164 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP: 165 case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR: 166 break; 167 default: 168 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 169 offset); 170 } 171 } 172 173 static const MemoryRegionOps pnv_core_power9_xscom_ops = { 174 .read = pnv_core_power9_xscom_read, 175 .write = pnv_core_power9_xscom_write, 176 .valid.min_access_size = 8, 177 .valid.max_access_size = 8, 178 .impl.min_access_size = 8, 179 .impl.max_access_size = 8, 180 .endianness = DEVICE_BIG_ENDIAN, 181 }; 182 183 /* 184 * POWER10 core controls 185 */ 186 187 #define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412 188 189 static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr, 190 unsigned int width) 191 { 192 uint32_t offset = addr >> 3; 193 uint64_t val = 0; 194 195 switch (offset) { 196 case PNV10_XSCOM_EC_CORE_THREAD_STATE: 197 val = 0; 198 break; 199 default: 200 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 201 offset); 202 } 203 204 return val; 205 } 206 207 static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr, 208 uint64_t val, unsigned int width) 209 { 210 uint32_t offset = addr >> 3; 211 212 switch (offset) { 213 default: 214 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 215 offset); 216 } 217 } 218 219 static const MemoryRegionOps pnv_core_power10_xscom_ops = { 220 .read = pnv_core_power10_xscom_read, 221 .write = pnv_core_power10_xscom_write, 222 .valid.min_access_size = 8, 223 .valid.max_access_size = 8, 224 .impl.min_access_size = 8, 225 .impl.max_access_size = 8, 226 .endianness = DEVICE_BIG_ENDIAN, 227 }; 228 229 static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp, 230 int thread_index) 231 { 232 CPUPPCState *env = &cpu->env; 233 int core_hwid; 234 ppc_spr_t *pir_spr = &env->spr_cb[SPR_PIR]; 235 ppc_spr_t *tir_spr = &env->spr_cb[SPR_TIR]; 236 uint32_t pir, tir; 237 Error *local_err = NULL; 238 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); 239 240 if (!qdev_realize(DEVICE(cpu), NULL, errp)) { 241 return; 242 } 243 244 pcc->intc_create(pc->chip, cpu, &local_err); 245 if (local_err) { 246 error_propagate(errp, local_err); 247 return; 248 } 249 250 core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort); 251 252 pcc->get_pir_tir(pc->chip, core_hwid, thread_index, &pir, &tir); 253 pir_spr->default_value = pir; 254 tir_spr->default_value = tir; 255 256 if (pc->big_core) { 257 /* 2 "small cores" get the same core index for SMT operations */ 258 env->core_index = core_hwid >> 1; 259 } else { 260 env->core_index = core_hwid; 261 } 262 263 /* Set time-base frequency to 512 MHz */ 264 cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ); 265 } 266 267 static void pnv_core_reset(void *dev) 268 { 269 CPUCore *cc = CPU_CORE(dev); 270 PnvCore *pc = PNV_CORE(dev); 271 int i; 272 273 for (i = 0; i < cc->nr_threads; i++) { 274 pnv_core_cpu_reset(pc, pc->threads[i]); 275 } 276 } 277 278 static void pnv_core_realize(DeviceState *dev, Error **errp) 279 { 280 PnvCore *pc = PNV_CORE(OBJECT(dev)); 281 PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc); 282 CPUCore *cc = CPU_CORE(OBJECT(dev)); 283 const char *typename = pnv_core_cpu_typename(pc); 284 Error *local_err = NULL; 285 void *obj; 286 int i, j; 287 char name[32]; 288 289 assert(pc->chip); 290 291 pc->threads = g_new(PowerPCCPU *, cc->nr_threads); 292 for (i = 0; i < cc->nr_threads; i++) { 293 PowerPCCPU *cpu; 294 PnvCPUState *pnv_cpu; 295 296 obj = object_new(typename); 297 cpu = POWERPC_CPU(obj); 298 299 pc->threads[i] = POWERPC_CPU(obj); 300 if (cc->nr_threads > 1) { 301 cpu->env.has_smt_siblings = true; 302 } 303 304 snprintf(name, sizeof(name), "thread[%d]", i); 305 object_property_add_child(OBJECT(pc), name, obj); 306 307 cpu->machine_data = g_new0(PnvCPUState, 1); 308 pnv_cpu = pnv_cpu_state(cpu); 309 pnv_cpu->pnv_core = pc; 310 311 object_unref(obj); 312 } 313 314 for (j = 0; j < cc->nr_threads; j++) { 315 pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j); 316 if (local_err) { 317 goto err; 318 } 319 } 320 321 snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id); 322 pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops, 323 pc, name, pcc->xscom_size); 324 325 qemu_register_reset(pnv_core_reset, pc); 326 return; 327 328 err: 329 while (--i >= 0) { 330 obj = OBJECT(pc->threads[i]); 331 object_unparent(obj); 332 } 333 g_free(pc->threads); 334 error_propagate(errp, local_err); 335 } 336 337 static void pnv_core_cpu_unrealize(PnvCore *pc, PowerPCCPU *cpu) 338 { 339 PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 340 PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip); 341 342 pcc->intc_destroy(pc->chip, cpu); 343 cpu_remove_sync(CPU(cpu)); 344 cpu->machine_data = NULL; 345 g_free(pnv_cpu); 346 object_unparent(OBJECT(cpu)); 347 } 348 349 static void pnv_core_unrealize(DeviceState *dev) 350 { 351 PnvCore *pc = PNV_CORE(dev); 352 CPUCore *cc = CPU_CORE(dev); 353 int i; 354 355 qemu_unregister_reset(pnv_core_reset, pc); 356 357 for (i = 0; i < cc->nr_threads; i++) { 358 pnv_core_cpu_unrealize(pc, pc->threads[i]); 359 } 360 g_free(pc->threads); 361 } 362 363 static Property pnv_core_properties[] = { 364 DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0), 365 DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0), 366 DEFINE_PROP_BOOL("big-core", PnvCore, big_core, false), 367 DEFINE_PROP_BOOL("quirk-tb-big-core", PnvCore, tod_state.big_core_quirk, 368 false), 369 DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *), 370 DEFINE_PROP_END_OF_LIST(), 371 }; 372 373 static void pnv_core_power8_class_init(ObjectClass *oc, void *data) 374 { 375 PnvCoreClass *pcc = PNV_CORE_CLASS(oc); 376 377 pcc->xscom_ops = &pnv_core_power8_xscom_ops; 378 pcc->xscom_size = PNV_XSCOM_EX_SIZE; 379 } 380 381 static void pnv_core_power9_class_init(ObjectClass *oc, void *data) 382 { 383 PnvCoreClass *pcc = PNV_CORE_CLASS(oc); 384 385 pcc->xscom_ops = &pnv_core_power9_xscom_ops; 386 pcc->xscom_size = PNV_XSCOM_EX_SIZE; 387 } 388 389 static void pnv_core_power10_class_init(ObjectClass *oc, void *data) 390 { 391 PnvCoreClass *pcc = PNV_CORE_CLASS(oc); 392 393 pcc->xscom_ops = &pnv_core_power10_xscom_ops; 394 pcc->xscom_size = PNV10_XSCOM_EC_SIZE; 395 } 396 397 static void pnv_core_class_init(ObjectClass *oc, void *data) 398 { 399 DeviceClass *dc = DEVICE_CLASS(oc); 400 401 dc->realize = pnv_core_realize; 402 dc->unrealize = pnv_core_unrealize; 403 device_class_set_props(dc, pnv_core_properties); 404 dc->user_creatable = false; 405 } 406 407 #define DEFINE_PNV_CORE_TYPE(family, cpu_model) \ 408 { \ 409 .parent = TYPE_PNV_CORE, \ 410 .name = PNV_CORE_TYPE_NAME(cpu_model), \ 411 .class_init = pnv_core_##family##_class_init, \ 412 } 413 414 static const TypeInfo pnv_core_infos[] = { 415 { 416 .name = TYPE_PNV_CORE, 417 .parent = TYPE_CPU_CORE, 418 .instance_size = sizeof(PnvCore), 419 .class_size = sizeof(PnvCoreClass), 420 .class_init = pnv_core_class_init, 421 .abstract = true, 422 }, 423 DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"), 424 DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"), 425 DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"), 426 DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"), 427 DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"), 428 }; 429 430 DEFINE_TYPES(pnv_core_infos) 431 432 /* 433 * POWER9 Quads 434 */ 435 436 #define P9X_EX_NCU_SPEC_BAR 0x11010 437 438 static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr, 439 unsigned int width) 440 { 441 uint32_t offset = addr >> 3; 442 uint64_t val = -1; 443 444 switch (offset) { 445 case P9X_EX_NCU_SPEC_BAR: 446 case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */ 447 val = 0; 448 break; 449 default: 450 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 451 offset); 452 } 453 454 return val; 455 } 456 457 static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val, 458 unsigned int width) 459 { 460 uint32_t offset = addr >> 3; 461 462 switch (offset) { 463 case P9X_EX_NCU_SPEC_BAR: 464 case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */ 465 break; 466 default: 467 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 468 offset); 469 } 470 } 471 472 static const MemoryRegionOps pnv_quad_power9_xscom_ops = { 473 .read = pnv_quad_power9_xscom_read, 474 .write = pnv_quad_power9_xscom_write, 475 .valid.min_access_size = 8, 476 .valid.max_access_size = 8, 477 .impl.min_access_size = 8, 478 .impl.max_access_size = 8, 479 .endianness = DEVICE_BIG_ENDIAN, 480 }; 481 482 /* 483 * POWER10 Quads 484 */ 485 486 static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr, 487 unsigned int width) 488 { 489 uint32_t offset = addr >> 3; 490 uint64_t val = -1; 491 492 switch (offset) { 493 default: 494 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 495 offset); 496 } 497 498 return val; 499 } 500 501 static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr, 502 uint64_t val, unsigned int width) 503 { 504 uint32_t offset = addr >> 3; 505 506 switch (offset) { 507 default: 508 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 509 offset); 510 } 511 } 512 513 static const MemoryRegionOps pnv_quad_power10_xscom_ops = { 514 .read = pnv_quad_power10_xscom_read, 515 .write = pnv_quad_power10_xscom_write, 516 .valid.min_access_size = 8, 517 .valid.max_access_size = 8, 518 .impl.min_access_size = 8, 519 .impl.max_access_size = 8, 520 .endianness = DEVICE_BIG_ENDIAN, 521 }; 522 523 #define P10_QME_SPWU_HYP 0x83c 524 #define P10_QME_SSH_HYP 0x82c 525 526 static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr, 527 unsigned int width) 528 { 529 uint32_t offset = addr >> 3; 530 uint64_t val = -1; 531 532 /* 533 * Forth nibble selects the core within a quad, mask it to process read 534 * for any core. 535 */ 536 switch (offset & ~0xf000) { 537 case P10_QME_SPWU_HYP: 538 case P10_QME_SSH_HYP: 539 return 0; 540 default: 541 qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__, 542 offset); 543 } 544 545 return val; 546 } 547 548 static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr, 549 uint64_t val, unsigned int width) 550 { 551 uint32_t offset = addr >> 3; 552 553 switch (offset) { 554 default: 555 qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__, 556 offset); 557 } 558 } 559 560 static const MemoryRegionOps pnv_qme_power10_xscom_ops = { 561 .read = pnv_qme_power10_xscom_read, 562 .write = pnv_qme_power10_xscom_write, 563 .valid.min_access_size = 8, 564 .valid.max_access_size = 8, 565 .impl.min_access_size = 8, 566 .impl.max_access_size = 8, 567 .endianness = DEVICE_BIG_ENDIAN, 568 }; 569 570 static void pnv_quad_power9_realize(DeviceState *dev, Error **errp) 571 { 572 PnvQuad *eq = PNV_QUAD(dev); 573 PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); 574 char name[32]; 575 576 snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); 577 pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), 578 pqc->xscom_ops, 579 eq, name, 580 pqc->xscom_size); 581 } 582 583 static void pnv_quad_power10_realize(DeviceState *dev, Error **errp) 584 { 585 PnvQuad *eq = PNV_QUAD(dev); 586 PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq); 587 char name[32]; 588 589 snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id); 590 pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev), 591 pqc->xscom_ops, 592 eq, name, 593 pqc->xscom_size); 594 595 snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id); 596 pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev), 597 pqc->xscom_qme_ops, 598 eq, name, 599 pqc->xscom_qme_size); 600 } 601 602 static Property pnv_quad_properties[] = { 603 DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0), 604 DEFINE_PROP_END_OF_LIST(), 605 }; 606 607 static void pnv_quad_power9_class_init(ObjectClass *oc, void *data) 608 { 609 PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); 610 DeviceClass *dc = DEVICE_CLASS(oc); 611 612 dc->realize = pnv_quad_power9_realize; 613 614 pqc->xscom_ops = &pnv_quad_power9_xscom_ops; 615 pqc->xscom_size = PNV9_XSCOM_EQ_SIZE; 616 } 617 618 static void pnv_quad_power10_class_init(ObjectClass *oc, void *data) 619 { 620 PnvQuadClass *pqc = PNV_QUAD_CLASS(oc); 621 DeviceClass *dc = DEVICE_CLASS(oc); 622 623 dc->realize = pnv_quad_power10_realize; 624 625 pqc->xscom_ops = &pnv_quad_power10_xscom_ops; 626 pqc->xscom_size = PNV10_XSCOM_EQ_SIZE; 627 628 pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops; 629 pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE; 630 } 631 632 static void pnv_quad_class_init(ObjectClass *oc, void *data) 633 { 634 DeviceClass *dc = DEVICE_CLASS(oc); 635 636 device_class_set_props(dc, pnv_quad_properties); 637 dc->user_creatable = false; 638 } 639 640 static const TypeInfo pnv_quad_infos[] = { 641 { 642 .name = TYPE_PNV_QUAD, 643 .parent = TYPE_DEVICE, 644 .instance_size = sizeof(PnvQuad), 645 .class_size = sizeof(PnvQuadClass), 646 .class_init = pnv_quad_class_init, 647 .abstract = true, 648 }, 649 { 650 .parent = TYPE_PNV_QUAD, 651 .name = PNV_QUAD_TYPE_NAME("power9"), 652 .class_init = pnv_quad_power9_class_init, 653 }, 654 { 655 .parent = TYPE_PNV_QUAD, 656 .name = PNV_QUAD_TYPE_NAME("power10"), 657 .class_init = pnv_quad_power10_class_init, 658 }, 659 }; 660 661 DEFINE_TYPES(pnv_quad_infos); 662