19e933f4aSBenjamin Herrenschmidt /* 29e933f4aSBenjamin Herrenschmidt * QEMU PowerPC PowerNV machine model 39e933f4aSBenjamin Herrenschmidt * 49e933f4aSBenjamin Herrenschmidt * Copyright (c) 2016, IBM Corporation. 59e933f4aSBenjamin Herrenschmidt * 69e933f4aSBenjamin Herrenschmidt * This library is free software; you can redistribute it and/or 79e933f4aSBenjamin Herrenschmidt * modify it under the terms of the GNU Lesser General Public 89e933f4aSBenjamin Herrenschmidt * License as published by the Free Software Foundation; either 99e933f4aSBenjamin Herrenschmidt * version 2 of the License, or (at your option) any later version. 109e933f4aSBenjamin Herrenschmidt * 119e933f4aSBenjamin Herrenschmidt * This library is distributed in the hope that it will be useful, 129e933f4aSBenjamin Herrenschmidt * but WITHOUT ANY WARRANTY; without even the implied warranty of 139e933f4aSBenjamin Herrenschmidt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 149e933f4aSBenjamin Herrenschmidt * Lesser General Public License for more details. 159e933f4aSBenjamin Herrenschmidt * 169e933f4aSBenjamin Herrenschmidt * You should have received a copy of the GNU Lesser General Public 179e933f4aSBenjamin Herrenschmidt * License along with this library; if not, see <http://www.gnu.org/licenses/>. 189e933f4aSBenjamin Herrenschmidt */ 199e933f4aSBenjamin Herrenschmidt 209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h" 219e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 229e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 239e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 249e933f4aSBenjamin Herrenschmidt #include "hw/hw.h" 259e933f4aSBenjamin Herrenschmidt #include "target-ppc/cpu.h" 269e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 279e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 289e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 299e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 309e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 319e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 329e933f4aSBenjamin Herrenschmidt #include "qemu/cutils.h" 33*e997040eSCédric Le Goater #include "qapi/visitor.h" 349e933f4aSBenjamin Herrenschmidt 359e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 369e933f4aSBenjamin Herrenschmidt 379e933f4aSBenjamin Herrenschmidt #define FDT_MAX_SIZE 0x00100000 389e933f4aSBenjamin Herrenschmidt 399e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 409e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 419e933f4aSBenjamin Herrenschmidt #define FW_MAX_SIZE 0x00400000 429e933f4aSBenjamin Herrenschmidt 439e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 449e933f4aSBenjamin Herrenschmidt #define INITRD_LOAD_ADDR 0x40000000 459e933f4aSBenjamin Herrenschmidt 469e933f4aSBenjamin Herrenschmidt /* 479e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 489e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 499e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 509e933f4aSBenjamin Herrenschmidt */ 519e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 529e933f4aSBenjamin Herrenschmidt 539e933f4aSBenjamin Herrenschmidt /* 549e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 559e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 569e933f4aSBenjamin Herrenschmidt * per chip. 579e933f4aSBenjamin Herrenschmidt */ 589e933f4aSBenjamin Herrenschmidt static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start, 599e933f4aSBenjamin Herrenschmidt hwaddr size) 609e933f4aSBenjamin Herrenschmidt { 619e933f4aSBenjamin Herrenschmidt char *mem_name; 629e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 639e933f4aSBenjamin Herrenschmidt int off; 649e933f4aSBenjamin Herrenschmidt 659e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 669e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 679e933f4aSBenjamin Herrenschmidt 689e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 699e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 709e933f4aSBenjamin Herrenschmidt g_free(mem_name); 719e933f4aSBenjamin Herrenschmidt 729e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 739e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 749e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 759e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 769e933f4aSBenjamin Herrenschmidt } 779e933f4aSBenjamin Herrenschmidt 78*e997040eSCédric Le Goater static void powernv_populate_chip(PnvChip *chip, void *fdt) 79*e997040eSCédric Le Goater { 80*e997040eSCédric Le Goater if (chip->ram_size) { 81*e997040eSCédric Le Goater powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start, 82*e997040eSCédric Le Goater chip->ram_size); 83*e997040eSCédric Le Goater } 84*e997040eSCédric Le Goater } 85*e997040eSCédric Le Goater 869e933f4aSBenjamin Herrenschmidt static void *powernv_create_fdt(MachineState *machine) 879e933f4aSBenjamin Herrenschmidt { 889e933f4aSBenjamin Herrenschmidt const char plat_compat[] = "qemu,powernv\0ibm,powernv"; 899e933f4aSBenjamin Herrenschmidt PnvMachineState *pnv = POWERNV_MACHINE(machine); 909e933f4aSBenjamin Herrenschmidt void *fdt; 919e933f4aSBenjamin Herrenschmidt char *buf; 929e933f4aSBenjamin Herrenschmidt int off; 93*e997040eSCédric Le Goater int i; 949e933f4aSBenjamin Herrenschmidt 959e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 969e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 979e933f4aSBenjamin Herrenschmidt 989e933f4aSBenjamin Herrenschmidt /* Root node */ 999e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 1009e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 1019e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 1029e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 1039e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat, 1049e933f4aSBenjamin Herrenschmidt sizeof(plat_compat)))); 1059e933f4aSBenjamin Herrenschmidt 1069e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 1079e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 1089e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 1099e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 1109e933f4aSBenjamin Herrenschmidt } 1119e933f4aSBenjamin Herrenschmidt g_free(buf); 1129e933f4aSBenjamin Herrenschmidt 1139e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 1149e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 1159e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 1169e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 1179e933f4aSBenjamin Herrenschmidt } 1189e933f4aSBenjamin Herrenschmidt 1199e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 1209e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 1219e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 1229e933f4aSBenjamin Herrenschmidt 1239e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 1249e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 1259e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 1269e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 1279e933f4aSBenjamin Herrenschmidt } 1289e933f4aSBenjamin Herrenschmidt 129*e997040eSCédric Le Goater /* Populate device tree for each chip */ 130*e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 131*e997040eSCédric Le Goater powernv_populate_chip(pnv->chips[i], fdt); 132*e997040eSCédric Le Goater } 1339e933f4aSBenjamin Herrenschmidt return fdt; 1349e933f4aSBenjamin Herrenschmidt } 1359e933f4aSBenjamin Herrenschmidt 1369e933f4aSBenjamin Herrenschmidt static void ppc_powernv_reset(void) 1379e933f4aSBenjamin Herrenschmidt { 1389e933f4aSBenjamin Herrenschmidt MachineState *machine = MACHINE(qdev_get_machine()); 1399e933f4aSBenjamin Herrenschmidt void *fdt; 1409e933f4aSBenjamin Herrenschmidt 1419e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 1429e933f4aSBenjamin Herrenschmidt 1439e933f4aSBenjamin Herrenschmidt fdt = powernv_create_fdt(machine); 1449e933f4aSBenjamin Herrenschmidt 1459e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 1469e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 1479e933f4aSBenjamin Herrenschmidt 1489e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 1499e933f4aSBenjamin Herrenschmidt } 1509e933f4aSBenjamin Herrenschmidt 1519e933f4aSBenjamin Herrenschmidt static void ppc_powernv_init(MachineState *machine) 1529e933f4aSBenjamin Herrenschmidt { 1539e933f4aSBenjamin Herrenschmidt PnvMachineState *pnv = POWERNV_MACHINE(machine); 1549e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 1559e933f4aSBenjamin Herrenschmidt char *fw_filename; 1569e933f4aSBenjamin Herrenschmidt long fw_size; 157*e997040eSCédric Le Goater int i; 158*e997040eSCédric Le Goater char *chip_typename; 1599e933f4aSBenjamin Herrenschmidt 1609e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 1619e933f4aSBenjamin Herrenschmidt if (machine->ram_size < (1 * G_BYTE)) { 1629e933f4aSBenjamin Herrenschmidt error_report("Warning: skiboot may not work with < 1GB of RAM"); 1639e933f4aSBenjamin Herrenschmidt } 1649e933f4aSBenjamin Herrenschmidt 1659e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 1669e933f4aSBenjamin Herrenschmidt memory_region_allocate_system_memory(ram, NULL, "ppc_powernv.ram", 1679e933f4aSBenjamin Herrenschmidt machine->ram_size); 1689e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 1699e933f4aSBenjamin Herrenschmidt 1709e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 1719e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 1729e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 1739e933f4aSBenjamin Herrenschmidt } 1749e933f4aSBenjamin Herrenschmidt 1759e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 1769e933f4aSBenjamin Herrenschmidt 1779e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 1789e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 1799e933f4aSBenjamin Herrenschmidt hw_error("qemu: could not load OPAL '%s'\n", fw_filename); 1809e933f4aSBenjamin Herrenschmidt exit(1); 1819e933f4aSBenjamin Herrenschmidt } 1829e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 1839e933f4aSBenjamin Herrenschmidt 1849e933f4aSBenjamin Herrenschmidt /* load kernel */ 1859e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 1869e933f4aSBenjamin Herrenschmidt long kernel_size; 1879e933f4aSBenjamin Herrenschmidt 1889e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 1899e933f4aSBenjamin Herrenschmidt KERNEL_LOAD_ADDR, 0x2000000); 1909e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 1919e933f4aSBenjamin Herrenschmidt hw_error("qemu: could not load kernel'%s'\n", 1929e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 1939e933f4aSBenjamin Herrenschmidt exit(1); 1949e933f4aSBenjamin Herrenschmidt } 1959e933f4aSBenjamin Herrenschmidt } 1969e933f4aSBenjamin Herrenschmidt 1979e933f4aSBenjamin Herrenschmidt /* load initrd */ 1989e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 1999e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 2009e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 2019e933f4aSBenjamin Herrenschmidt pnv->initrd_base, 0x10000000); /* 128MB max */ 2029e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 2039e933f4aSBenjamin Herrenschmidt error_report("qemu: could not load initial ram disk '%s'", 2049e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 2059e933f4aSBenjamin Herrenschmidt exit(1); 2069e933f4aSBenjamin Herrenschmidt } 2079e933f4aSBenjamin Herrenschmidt } 208*e997040eSCédric Le Goater 209*e997040eSCédric Le Goater /* We need some cpu model to instantiate the PnvChip class */ 210*e997040eSCédric Le Goater if (machine->cpu_model == NULL) { 211*e997040eSCédric Le Goater machine->cpu_model = "POWER8"; 212*e997040eSCédric Le Goater } 213*e997040eSCédric Le Goater 214*e997040eSCédric Le Goater /* Create the processor chips */ 215*e997040eSCédric Le Goater chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", machine->cpu_model); 216*e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 217*e997040eSCédric Le Goater error_report("qemu: invalid CPU model '%s' for %s machine", 218*e997040eSCédric Le Goater machine->cpu_model, MACHINE_GET_CLASS(machine)->name); 219*e997040eSCédric Le Goater exit(1); 220*e997040eSCédric Le Goater } 221*e997040eSCédric Le Goater 222*e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 223*e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 224*e997040eSCédric Le Goater char chip_name[32]; 225*e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 226*e997040eSCédric Le Goater 227*e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 228*e997040eSCédric Le Goater 229*e997040eSCédric Le Goater /* TODO: put all the memory in one node on chip 0 until we find a 230*e997040eSCédric Le Goater * way to specify different ranges for each chip 231*e997040eSCédric Le Goater */ 232*e997040eSCédric Le Goater if (i == 0) { 233*e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 234*e997040eSCédric Le Goater &error_fatal); 235*e997040eSCédric Le Goater } 236*e997040eSCédric Le Goater 237*e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 238*e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 239*e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 240*e997040eSCédric Le Goater &error_fatal); 241*e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 242*e997040eSCédric Le Goater } 243*e997040eSCédric Le Goater g_free(chip_typename); 244*e997040eSCédric Le Goater } 245*e997040eSCédric Le Goater 246*e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 247*e997040eSCédric Le Goater { 248*e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 249*e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 250*e997040eSCédric Le Goater 251*e997040eSCédric Le Goater k->cpu_model = "POWER8E"; 252*e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 253*e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 254*e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 255*e997040eSCédric Le Goater } 256*e997040eSCédric Le Goater 257*e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8e_info = { 258*e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER8E, 259*e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 260*e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 261*e997040eSCédric Le Goater .class_init = pnv_chip_power8e_class_init, 262*e997040eSCédric Le Goater }; 263*e997040eSCédric Le Goater 264*e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 265*e997040eSCédric Le Goater { 266*e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 267*e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 268*e997040eSCédric Le Goater 269*e997040eSCédric Le Goater k->cpu_model = "POWER8"; 270*e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 271*e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 272*e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 273*e997040eSCédric Le Goater } 274*e997040eSCédric Le Goater 275*e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8_info = { 276*e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER8, 277*e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 278*e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 279*e997040eSCédric Le Goater .class_init = pnv_chip_power8_class_init, 280*e997040eSCédric Le Goater }; 281*e997040eSCédric Le Goater 282*e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 283*e997040eSCédric Le Goater { 284*e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 285*e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 286*e997040eSCédric Le Goater 287*e997040eSCédric Le Goater k->cpu_model = "POWER8NVL"; 288*e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 289*e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 290*e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 291*e997040eSCédric Le Goater } 292*e997040eSCédric Le Goater 293*e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8nvl_info = { 294*e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER8NVL, 295*e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 296*e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 297*e997040eSCédric Le Goater .class_init = pnv_chip_power8nvl_class_init, 298*e997040eSCédric Le Goater }; 299*e997040eSCédric Le Goater 300*e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 301*e997040eSCédric Le Goater { 302*e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 303*e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 304*e997040eSCédric Le Goater 305*e997040eSCédric Le Goater k->cpu_model = "POWER9"; 306*e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 307*e997040eSCédric Le Goater k->chip_cfam_id = 0x100d104980000000ull; /* P9 Nimbus DD1.0 */ 308*e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 309*e997040eSCédric Le Goater } 310*e997040eSCédric Le Goater 311*e997040eSCédric Le Goater static const TypeInfo pnv_chip_power9_info = { 312*e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER9, 313*e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 314*e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 315*e997040eSCédric Le Goater .class_init = pnv_chip_power9_class_init, 316*e997040eSCédric Le Goater }; 317*e997040eSCédric Le Goater 318*e997040eSCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 319*e997040eSCédric Le Goater { 320*e997040eSCédric Le Goater /* left purposely empty */ 321*e997040eSCédric Le Goater } 322*e997040eSCédric Le Goater 323*e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 324*e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 325*e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 326*e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 327*e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 328*e997040eSCédric Le Goater }; 329*e997040eSCédric Le Goater 330*e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 331*e997040eSCédric Le Goater { 332*e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 333*e997040eSCédric Le Goater 334*e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 335*e997040eSCédric Le Goater dc->props = pnv_chip_properties; 336*e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 337*e997040eSCédric Le Goater } 338*e997040eSCédric Le Goater 339*e997040eSCédric Le Goater static const TypeInfo pnv_chip_info = { 340*e997040eSCédric Le Goater .name = TYPE_PNV_CHIP, 341*e997040eSCédric Le Goater .parent = TYPE_SYS_BUS_DEVICE, 342*e997040eSCédric Le Goater .class_init = pnv_chip_class_init, 343*e997040eSCédric Le Goater .class_size = sizeof(PnvChipClass), 344*e997040eSCédric Le Goater .abstract = true, 345*e997040eSCédric Le Goater }; 346*e997040eSCédric Le Goater 347*e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 348*e997040eSCédric Le Goater void *opaque, Error **errp) 349*e997040eSCédric Le Goater { 350*e997040eSCédric Le Goater visit_type_uint32(v, name, &POWERNV_MACHINE(obj)->num_chips, errp); 351*e997040eSCédric Le Goater } 352*e997040eSCédric Le Goater 353*e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 354*e997040eSCédric Le Goater void *opaque, Error **errp) 355*e997040eSCédric Le Goater { 356*e997040eSCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(obj); 357*e997040eSCédric Le Goater uint32_t num_chips; 358*e997040eSCédric Le Goater Error *local_err = NULL; 359*e997040eSCédric Le Goater 360*e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 361*e997040eSCédric Le Goater if (local_err) { 362*e997040eSCédric Le Goater error_propagate(errp, local_err); 363*e997040eSCédric Le Goater return; 364*e997040eSCédric Le Goater } 365*e997040eSCédric Le Goater 366*e997040eSCédric Le Goater /* 367*e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 368*e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 369*e997040eSCédric Le Goater */ 370*e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 371*e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 372*e997040eSCédric Le Goater return; 373*e997040eSCédric Le Goater } 374*e997040eSCédric Le Goater 375*e997040eSCédric Le Goater pnv->num_chips = num_chips; 376*e997040eSCédric Le Goater } 377*e997040eSCédric Le Goater 378*e997040eSCédric Le Goater static void powernv_machine_initfn(Object *obj) 379*e997040eSCédric Le Goater { 380*e997040eSCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(obj); 381*e997040eSCédric Le Goater pnv->num_chips = 1; 382*e997040eSCédric Le Goater } 383*e997040eSCédric Le Goater 384*e997040eSCédric Le Goater static void powernv_machine_class_props_init(ObjectClass *oc) 385*e997040eSCédric Le Goater { 386*e997040eSCédric Le Goater object_class_property_add(oc, "num-chips", "uint32_t", 387*e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 388*e997040eSCédric Le Goater NULL, NULL, NULL); 389*e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 390*e997040eSCédric Le Goater "Specifies the number of processor chips", 391*e997040eSCédric Le Goater NULL); 3929e933f4aSBenjamin Herrenschmidt } 3939e933f4aSBenjamin Herrenschmidt 3949e933f4aSBenjamin Herrenschmidt static void powernv_machine_class_init(ObjectClass *oc, void *data) 3959e933f4aSBenjamin Herrenschmidt { 3969e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 3979e933f4aSBenjamin Herrenschmidt 3989e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 3999e933f4aSBenjamin Herrenschmidt mc->init = ppc_powernv_init; 4009e933f4aSBenjamin Herrenschmidt mc->reset = ppc_powernv_reset; 4019e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 4029e933f4aSBenjamin Herrenschmidt mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for 4039e933f4aSBenjamin Herrenschmidt * storage */ 4049e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 4059e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 4069e933f4aSBenjamin Herrenschmidt mc->default_ram_size = 1 * G_BYTE; 407*e997040eSCédric Le Goater 408*e997040eSCédric Le Goater powernv_machine_class_props_init(oc); 4099e933f4aSBenjamin Herrenschmidt } 4109e933f4aSBenjamin Herrenschmidt 4119e933f4aSBenjamin Herrenschmidt static const TypeInfo powernv_machine_info = { 4129e933f4aSBenjamin Herrenschmidt .name = TYPE_POWERNV_MACHINE, 4139e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 4149e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 415*e997040eSCédric Le Goater .instance_init = powernv_machine_initfn, 4169e933f4aSBenjamin Herrenschmidt .class_init = powernv_machine_class_init, 4179e933f4aSBenjamin Herrenschmidt }; 4189e933f4aSBenjamin Herrenschmidt 4199e933f4aSBenjamin Herrenschmidt static void powernv_machine_register_types(void) 4209e933f4aSBenjamin Herrenschmidt { 4219e933f4aSBenjamin Herrenschmidt type_register_static(&powernv_machine_info); 422*e997040eSCédric Le Goater type_register_static(&pnv_chip_info); 423*e997040eSCédric Le Goater type_register_static(&pnv_chip_power8e_info); 424*e997040eSCédric Le Goater type_register_static(&pnv_chip_power8_info); 425*e997040eSCédric Le Goater type_register_static(&pnv_chip_power8nvl_info); 426*e997040eSCédric Le Goater type_register_static(&pnv_chip_power9_info); 4279e933f4aSBenjamin Herrenschmidt } 4289e933f4aSBenjamin Herrenschmidt 4299e933f4aSBenjamin Herrenschmidt type_init(powernv_machine_register_types) 430