1 /* 2 * QEMU PowerPC PowerNV Emulation of a few HOMER related registers 3 * 4 * Copyright (c) 2019, IBM Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License, version 2, as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "qemu/osdep.h" 20 #include "qemu/log.h" 21 #include "qapi/error.h" 22 #include "exec/hwaddr.h" 23 #include "exec/memory.h" 24 #include "system/cpus.h" 25 #include "hw/qdev-core.h" 26 #include "hw/qdev-properties.h" 27 #include "hw/ppc/pnv.h" 28 #include "hw/ppc/pnv_chip.h" 29 #include "hw/ppc/pnv_homer.h" 30 #include "hw/ppc/pnv_xscom.h" 31 32 33 static bool core_max_array(PnvHomer *homer, hwaddr addr) 34 { 35 int i; 36 PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 37 38 for (i = 0; i <= homer->chip->nr_cores; i++) { 39 if (addr == (hmrc->core_max_base + i)) { 40 return true; 41 } 42 } 43 return false; 44 } 45 46 /* P8 Pstate table */ 47 48 #define PNV8_OCC_PSTATE_VERSION 0x1f8001 49 #define PNV8_OCC_PSTATE_MIN 0x1f8003 50 #define PNV8_OCC_PSTATE_VALID 0x1f8000 51 #define PNV8_OCC_PSTATE_THROTTLE 0x1f8002 52 #define PNV8_OCC_PSTATE_NOM 0x1f8004 53 #define PNV8_OCC_PSTATE_TURBO 0x1f8005 54 #define PNV8_OCC_PSTATE_ULTRA_TURBO 0x1f8006 55 #define PNV8_OCC_PSTATE_DATA 0x1f8008 56 #define PNV8_OCC_PSTATE_ID_ZERO 0x1f8010 57 #define PNV8_OCC_PSTATE_ID_ONE 0x1f8018 58 #define PNV8_OCC_PSTATE_ID_TWO 0x1f8020 59 #define PNV8_OCC_VDD_VOLTAGE_IDENTIFIER 0x1f8012 60 #define PNV8_OCC_VCS_VOLTAGE_IDENTIFIER 0x1f8013 61 #define PNV8_OCC_PSTATE_ZERO_FREQUENCY 0x1f8014 62 #define PNV8_OCC_PSTATE_ONE_FREQUENCY 0x1f801c 63 #define PNV8_OCC_PSTATE_TWO_FREQUENCY 0x1f8024 64 #define PNV8_CORE_MAX_BASE 0x1f8810 65 66 67 static uint64_t pnv_power8_homer_read(void *opaque, hwaddr addr, 68 unsigned size) 69 { 70 PnvHomer *homer = PNV_HOMER(opaque); 71 72 switch (addr) { 73 case PNV8_OCC_PSTATE_VALID: 74 return 1; 75 case PNV8_OCC_PSTATE_THROTTLE: 76 return 0; 77 case PNV8_OCC_PSTATE_VERSION: 78 return 0x02; 79 case PNV8_OCC_PSTATE_MIN: 80 return -2; 81 case PNV8_OCC_PSTATE_NOM: 82 case PNV8_OCC_PSTATE_TURBO: 83 return -1; 84 case PNV8_OCC_PSTATE_ULTRA_TURBO: 85 return 0; 86 case PNV8_OCC_PSTATE_ID_ZERO: 87 return 0; 88 case PNV8_OCC_VDD_VOLTAGE_IDENTIFIER: 89 case PNV8_OCC_VCS_VOLTAGE_IDENTIFIER: 90 return 1; 91 case PNV8_OCC_PSTATE_DATA: 92 return 0; 93 /* P8 frequency for 0, 1, and 2 pstates */ 94 case PNV8_OCC_PSTATE_ZERO_FREQUENCY: 95 case PNV8_OCC_PSTATE_ONE_FREQUENCY: 96 case PNV8_OCC_PSTATE_TWO_FREQUENCY: 97 return 3000; 98 case PNV8_OCC_PSTATE_ID_ONE: 99 return -1; 100 case PNV8_OCC_PSTATE_ID_TWO: 101 return -2; 102 } 103 /* pstate table core max array */ 104 if (core_max_array(homer, addr)) { 105 return 1; 106 } 107 return 0; 108 } 109 110 static void pnv_power8_homer_write(void *opaque, hwaddr addr, 111 uint64_t val, unsigned size) 112 { 113 /* callback function defined to homer write */ 114 return; 115 } 116 117 static const MemoryRegionOps pnv_power8_homer_ops = { 118 .read = pnv_power8_homer_read, 119 .write = pnv_power8_homer_write, 120 .valid.min_access_size = 1, 121 .valid.max_access_size = 8, 122 .impl.min_access_size = 1, 123 .impl.max_access_size = 8, 124 .endianness = DEVICE_BIG_ENDIAN, 125 }; 126 127 /* P8 PBA BARs */ 128 #define PBA_BAR0 0x00 129 #define PBA_BAR1 0x01 130 #define PBA_BAR2 0x02 131 #define PBA_BAR3 0x03 132 #define PBA_BARMASK0 0x04 133 #define PBA_BARMASK1 0x05 134 #define PBA_BARMASK2 0x06 135 #define PBA_BARMASK3 0x07 136 137 static uint64_t pnv_homer_power8_pba_read(void *opaque, hwaddr addr, 138 unsigned size) 139 { 140 PnvHomer *homer = PNV_HOMER(opaque); 141 PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 142 uint32_t reg = addr >> 3; 143 uint64_t val = 0; 144 145 switch (reg) { 146 case PBA_BAR0: 147 val = homer->base; 148 break; 149 case PBA_BARMASK0: /* P8 homer region mask */ 150 val = (hmrc->size - 1) & 0x300000; 151 break; 152 case PBA_BAR3: /* P8 occ common area */ 153 val = PNV_OCC_COMMON_AREA_BASE; 154 break; 155 case PBA_BARMASK3: /* P8 occ common area mask */ 156 val = (PNV_OCC_COMMON_AREA_SIZE - 1) & 0x700000; 157 break; 158 default: 159 qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%" 160 HWADDR_PRIx "\n", addr >> 3); 161 } 162 return val; 163 } 164 165 static void pnv_homer_power8_pba_write(void *opaque, hwaddr addr, 166 uint64_t val, unsigned size) 167 { 168 qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%" 169 HWADDR_PRIx "\n", addr >> 3); 170 } 171 172 static const MemoryRegionOps pnv_homer_power8_pba_ops = { 173 .read = pnv_homer_power8_pba_read, 174 .write = pnv_homer_power8_pba_write, 175 .valid.min_access_size = 8, 176 .valid.max_access_size = 8, 177 .impl.min_access_size = 8, 178 .impl.max_access_size = 8, 179 .endianness = DEVICE_BIG_ENDIAN, 180 }; 181 182 static hwaddr pnv_homer_power8_get_base(PnvChip *chip) 183 { 184 return PNV_HOMER_BASE(chip); 185 } 186 187 static void pnv_homer_power8_class_init(ObjectClass *klass, void *data) 188 { 189 PnvHomerClass *homer = PNV_HOMER_CLASS(klass); 190 191 homer->get_base = pnv_homer_power8_get_base; 192 homer->size = PNV_HOMER_SIZE; 193 homer->pba_size = PNV_XSCOM_PBA_SIZE; 194 homer->pba_ops = &pnv_homer_power8_pba_ops; 195 homer->homer_ops = &pnv_power8_homer_ops; 196 homer->core_max_base = PNV8_CORE_MAX_BASE; 197 } 198 199 static const TypeInfo pnv_homer_power8_type_info = { 200 .name = TYPE_PNV8_HOMER, 201 .parent = TYPE_PNV_HOMER, 202 .instance_size = sizeof(PnvHomer), 203 .class_init = pnv_homer_power8_class_init, 204 }; 205 206 /* P9 Pstate table */ 207 208 #define PNV9_OCC_PSTATE_VALID 0xe2000 209 #define PNV9_OCC_PSTATE_ID_ZERO 0xe2018 210 #define PNV9_OCC_PSTATE_ID_ONE 0xe2020 211 #define PNV9_OCC_PSTATE_ID_TWO 0xe2028 212 #define PNV9_OCC_PSTATE_DATA 0xe2000 213 #define PNV9_OCC_PSTATE_MINOR_VERSION 0xe2008 214 #define PNV9_OCC_PSTATE_MIN 0xe2003 215 #define PNV9_OCC_PSTATE_NOM 0xe2004 216 #define PNV9_OCC_PSTATE_TURBO 0xe2005 217 #define PNV9_OCC_PSTATE_ULTRA_TURBO 0xe2818 218 #define PNV9_OCC_MAX_PSTATE_ULTRA_TURBO 0xe2006 219 #define PNV9_OCC_PSTATE_MAJOR_VERSION 0xe2001 220 #define PNV9_OCC_OPAL_RUNTIME_DATA 0xe2b85 221 #define PNV9_CHIP_HOMER_IMAGE_POINTER 0x200008 222 #define PNV9_CHIP_HOMER_BASE 0x0 223 #define PNV9_OCC_PSTATE_ZERO_FREQUENCY 0xe201c 224 #define PNV9_OCC_PSTATE_ONE_FREQUENCY 0xe2024 225 #define PNV9_OCC_PSTATE_TWO_FREQUENCY 0xe202c 226 #define PNV9_OCC_ROLE_MASTER_OR_SLAVE 0xe2002 227 #define PNV9_CORE_MAX_BASE 0xe2819 228 #define PNV9_DYNAMIC_DATA_STATE 0xe2b80 229 230 static uint64_t pnv_power9_homer_read(void *opaque, hwaddr addr, 231 unsigned size) 232 { 233 PnvHomer *homer = PNV_HOMER(opaque); 234 235 switch (addr) { 236 case PNV9_OCC_PSTATE_VALID: 237 return 1; 238 case PNV9_OCC_MAX_PSTATE_ULTRA_TURBO: 239 case PNV9_OCC_PSTATE_ID_ZERO: 240 return 0; 241 case PNV9_OCC_ROLE_MASTER_OR_SLAVE: 242 if (homer->chip->chip_id == 0) { 243 return 0x1; /* master */ 244 } else { 245 return 0x0; /* slave */ 246 } 247 case PNV9_OCC_PSTATE_NOM: 248 case PNV9_OCC_PSTATE_TURBO: 249 case PNV9_OCC_PSTATE_ID_ONE: 250 case PNV9_OCC_PSTATE_ULTRA_TURBO: 251 case PNV9_OCC_OPAL_RUNTIME_DATA: 252 return 1; 253 case PNV9_OCC_PSTATE_MIN: 254 case PNV9_OCC_PSTATE_ID_TWO: 255 return 2; 256 257 /* 3000 khz frequency for 0, 1, and 2 pstates */ 258 case PNV9_OCC_PSTATE_ZERO_FREQUENCY: 259 case PNV9_OCC_PSTATE_ONE_FREQUENCY: 260 case PNV9_OCC_PSTATE_TWO_FREQUENCY: 261 return 3000; 262 case PNV9_OCC_PSTATE_MAJOR_VERSION: 263 return 0x90; 264 case PNV9_OCC_PSTATE_MINOR_VERSION: 265 return 0x01; 266 case PNV9_CHIP_HOMER_BASE: 267 case PNV9_CHIP_HOMER_IMAGE_POINTER: 268 return 0; 269 case PNV9_DYNAMIC_DATA_STATE: 270 return 0x03; /* active */ 271 } 272 /* pstate table core max array */ 273 if (core_max_array(homer, addr)) { 274 return 1; 275 } 276 return 0; 277 } 278 279 static void pnv_power9_homer_write(void *opaque, hwaddr addr, 280 uint64_t val, unsigned size) 281 { 282 /* callback function defined to homer write */ 283 return; 284 } 285 286 static const MemoryRegionOps pnv_power9_homer_ops = { 287 .read = pnv_power9_homer_read, 288 .write = pnv_power9_homer_write, 289 .valid.min_access_size = 1, 290 .valid.max_access_size = 8, 291 .impl.min_access_size = 1, 292 .impl.max_access_size = 8, 293 .endianness = DEVICE_BIG_ENDIAN, 294 }; 295 296 static uint64_t pnv_homer_power9_pba_read(void *opaque, hwaddr addr, 297 unsigned size) 298 { 299 PnvHomer *homer = PNV_HOMER(opaque); 300 PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 301 uint32_t reg = addr >> 3; 302 uint64_t val = 0; 303 304 switch (reg) { 305 case PBA_BAR0: 306 val = homer->base; 307 break; 308 case PBA_BARMASK0: /* P9 homer region mask */ 309 val = (hmrc->size - 1) & 0x300000; 310 break; 311 case PBA_BAR2: /* P9 occ common area */ 312 val = PNV9_OCC_COMMON_AREA_BASE; 313 break; 314 case PBA_BARMASK2: /* P9 occ common area size */ 315 val = (PNV9_OCC_COMMON_AREA_SIZE - 1) & 0x700000; 316 break; 317 default: 318 qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%" 319 HWADDR_PRIx "\n", addr >> 3); 320 } 321 return val; 322 } 323 324 static void pnv_homer_power9_pba_write(void *opaque, hwaddr addr, 325 uint64_t val, unsigned size) 326 { 327 qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%" 328 HWADDR_PRIx "\n", addr >> 3); 329 } 330 331 static const MemoryRegionOps pnv_homer_power9_pba_ops = { 332 .read = pnv_homer_power9_pba_read, 333 .write = pnv_homer_power9_pba_write, 334 .valid.min_access_size = 8, 335 .valid.max_access_size = 8, 336 .impl.min_access_size = 8, 337 .impl.max_access_size = 8, 338 .endianness = DEVICE_BIG_ENDIAN, 339 }; 340 341 static hwaddr pnv_homer_power9_get_base(PnvChip *chip) 342 { 343 return PNV9_HOMER_BASE(chip); 344 } 345 346 static void pnv_homer_power9_class_init(ObjectClass *klass, void *data) 347 { 348 PnvHomerClass *homer = PNV_HOMER_CLASS(klass); 349 350 homer->get_base = pnv_homer_power9_get_base; 351 homer->size = PNV_HOMER_SIZE; 352 homer->pba_size = PNV9_XSCOM_PBA_SIZE; 353 homer->pba_ops = &pnv_homer_power9_pba_ops; 354 homer->homer_ops = &pnv_power9_homer_ops; 355 homer->core_max_base = PNV9_CORE_MAX_BASE; 356 } 357 358 static const TypeInfo pnv_homer_power9_type_info = { 359 .name = TYPE_PNV9_HOMER, 360 .parent = TYPE_PNV_HOMER, 361 .instance_size = sizeof(PnvHomer), 362 .class_init = pnv_homer_power9_class_init, 363 }; 364 365 static uint64_t pnv_homer_power10_pba_read(void *opaque, hwaddr addr, 366 unsigned size) 367 { 368 PnvHomer *homer = PNV_HOMER(opaque); 369 PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 370 uint32_t reg = addr >> 3; 371 uint64_t val = 0; 372 373 switch (reg) { 374 case PBA_BAR0: 375 val = homer->base; 376 break; 377 case PBA_BARMASK0: /* P10 homer region mask */ 378 val = (hmrc->size - 1) & 0x300000; 379 break; 380 case PBA_BAR2: /* P10 occ common area */ 381 val = PNV10_OCC_COMMON_AREA_BASE; 382 break; 383 case PBA_BARMASK2: /* P10 occ common area size */ 384 val = (PNV10_OCC_COMMON_AREA_SIZE - 1) & 0x700000; 385 break; 386 default: 387 qemu_log_mask(LOG_UNIMP, "PBA: read to unimplemented register: Ox%" 388 HWADDR_PRIx "\n", addr >> 3); 389 } 390 return val; 391 } 392 393 static void pnv_homer_power10_pba_write(void *opaque, hwaddr addr, 394 uint64_t val, unsigned size) 395 { 396 qemu_log_mask(LOG_UNIMP, "PBA: write to unimplemented register: Ox%" 397 HWADDR_PRIx "\n", addr >> 3); 398 } 399 400 static const MemoryRegionOps pnv_homer_power10_pba_ops = { 401 .read = pnv_homer_power10_pba_read, 402 .write = pnv_homer_power10_pba_write, 403 .valid.min_access_size = 8, 404 .valid.max_access_size = 8, 405 .impl.min_access_size = 8, 406 .impl.max_access_size = 8, 407 .endianness = DEVICE_BIG_ENDIAN, 408 }; 409 410 static hwaddr pnv_homer_power10_get_base(PnvChip *chip) 411 { 412 return PNV10_HOMER_BASE(chip); 413 } 414 415 static void pnv_homer_power10_class_init(ObjectClass *klass, void *data) 416 { 417 PnvHomerClass *homer = PNV_HOMER_CLASS(klass); 418 419 homer->get_base = pnv_homer_power10_get_base; 420 homer->size = PNV_HOMER_SIZE; 421 homer->pba_size = PNV10_XSCOM_PBA_SIZE; 422 homer->pba_ops = &pnv_homer_power10_pba_ops; 423 homer->homer_ops = &pnv_power9_homer_ops; /* TODO */ 424 homer->core_max_base = PNV9_CORE_MAX_BASE; 425 } 426 427 static const TypeInfo pnv_homer_power10_type_info = { 428 .name = TYPE_PNV10_HOMER, 429 .parent = TYPE_PNV_HOMER, 430 .instance_size = sizeof(PnvHomer), 431 .class_init = pnv_homer_power10_class_init, 432 }; 433 434 static void pnv_homer_realize(DeviceState *dev, Error **errp) 435 { 436 PnvHomer *homer = PNV_HOMER(dev); 437 PnvHomerClass *hmrc = PNV_HOMER_GET_CLASS(homer); 438 439 assert(homer->chip); 440 441 pnv_xscom_region_init(&homer->pba_regs, OBJECT(dev), hmrc->pba_ops, 442 homer, "xscom-pba", hmrc->pba_size); 443 444 /* homer region */ 445 homer->base = hmrc->get_base(homer->chip); 446 447 memory_region_init_io(&homer->regs, OBJECT(dev), 448 hmrc->homer_ops, homer, "homer-main-memory", 449 hmrc->size); 450 } 451 452 static const Property pnv_homer_properties[] = { 453 DEFINE_PROP_LINK("chip", PnvHomer, chip, TYPE_PNV_CHIP, PnvChip *), 454 }; 455 456 static void pnv_homer_class_init(ObjectClass *klass, void *data) 457 { 458 DeviceClass *dc = DEVICE_CLASS(klass); 459 460 dc->realize = pnv_homer_realize; 461 dc->desc = "PowerNV HOMER Memory"; 462 device_class_set_props(dc, pnv_homer_properties); 463 dc->user_creatable = false; 464 } 465 466 static const TypeInfo pnv_homer_type_info = { 467 .name = TYPE_PNV_HOMER, 468 .parent = TYPE_DEVICE, 469 .instance_size = sizeof(PnvHomer), 470 .class_init = pnv_homer_class_init, 471 .class_size = sizeof(PnvHomerClass), 472 .abstract = true, 473 }; 474 475 static void pnv_homer_register_types(void) 476 { 477 type_register_static(&pnv_homer_type_info); 478 type_register_static(&pnv_homer_power8_type_info); 479 type_register_static(&pnv_homer_power9_type_info); 480 type_register_static(&pnv_homer_power10_type_info); 481 } 482 483 type_init(pnv_homer_register_types); 484