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" 21fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 229e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 239e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 249e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 25d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 269e933f4aSBenjamin Herrenschmidt #include "hw/hw.h" 27fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 289e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 299e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 309e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 319e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 32d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 339e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 349e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 35e997040eSCédric Le Goater #include "qapi/visitor.h" 3647fea43aSCédric Le Goater #include "monitor/monitor.h" 3747fea43aSCédric Le Goater #include "hw/intc/intc.h" 38aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 3958969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 409e933f4aSBenjamin Herrenschmidt 4136fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 42967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 43967b7523SCédric Le Goater 443495b6b6SCédric Le Goater #include "hw/isa/isa.h" 453495b6b6SCédric Le Goater #include "hw/char/serial.h" 463495b6b6SCédric Le Goater #include "hw/timer/mc146818rtc.h" 473495b6b6SCédric Le Goater 489e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 499e933f4aSBenjamin Herrenschmidt 50b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 519e933f4aSBenjamin Herrenschmidt 529e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 539e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 54b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 559e933f4aSBenjamin Herrenschmidt 569e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 57b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 58fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 59584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 609e933f4aSBenjamin Herrenschmidt 6140abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 6240abf43fSIgor Mammedov { 6340abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 6440abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 6540abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 6640abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 6740abf43fSIgor Mammedov g_free(s); 6840abf43fSIgor Mammedov return core_type; 6940abf43fSIgor Mammedov } 7040abf43fSIgor Mammedov 719e933f4aSBenjamin Herrenschmidt /* 729e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 739e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 749e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 759e933f4aSBenjamin Herrenschmidt */ 769e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 779e933f4aSBenjamin Herrenschmidt 789e933f4aSBenjamin Herrenschmidt /* 799e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 809e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 819e933f4aSBenjamin Herrenschmidt * per chip. 829e933f4aSBenjamin Herrenschmidt */ 83b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 849e933f4aSBenjamin Herrenschmidt { 859e933f4aSBenjamin Herrenschmidt char *mem_name; 869e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 879e933f4aSBenjamin Herrenschmidt int off; 889e933f4aSBenjamin Herrenschmidt 899e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 909e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 919e933f4aSBenjamin Herrenschmidt 929e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 939e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 949e933f4aSBenjamin Herrenschmidt g_free(mem_name); 959e933f4aSBenjamin Herrenschmidt 969e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 979e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 989e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 999e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1009e933f4aSBenjamin Herrenschmidt } 1019e933f4aSBenjamin Herrenschmidt 102d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 103d2fd9612SCédric Le Goater { 104d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 105d2fd9612SCédric Le Goater 106d2fd9612SCédric Le Goater if (cpus_offset < 0) { 107a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 108d2fd9612SCédric Le Goater if (cpus_offset) { 109d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 110d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 111d2fd9612SCédric Le Goater } 112d2fd9612SCédric Le Goater } 113d2fd9612SCédric Le Goater _FDT(cpus_offset); 114d2fd9612SCédric Le Goater return cpus_offset; 115d2fd9612SCédric Le Goater } 116d2fd9612SCédric Le Goater 117d2fd9612SCédric Le Goater /* 118d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 119d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 120d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 121d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 122d2fd9612SCédric Le Goater * servers. 123d2fd9612SCédric Le Goater */ 124b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 125d2fd9612SCédric Le Goater { 12608304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 12708304a86SDavid Gibson CPUState *cs = CPU(cpu); 128d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1298bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 130d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 131d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 132d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 133d2fd9612SCédric Le Goater int i; 134d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 135d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 136d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 137d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 138d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 139d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 140d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 141d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 142d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 143d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 144d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 145d2fd9612SCédric Le Goater int offset; 146d2fd9612SCédric Le Goater char *nodename; 147d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 148d2fd9612SCédric Le Goater 149d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 150d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 151d2fd9612SCédric Le Goater _FDT(offset); 152d2fd9612SCédric Le Goater g_free(nodename); 153d2fd9612SCédric Le Goater 154d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 155d2fd9612SCédric Le Goater 156d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 157d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 158d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 159d2fd9612SCédric Le Goater 160d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 161d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 162d2fd9612SCédric Le Goater env->dcache_line_size))); 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 164d2fd9612SCédric Le Goater env->dcache_line_size))); 165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 166d2fd9612SCédric Le Goater env->icache_line_size))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 168d2fd9612SCédric Le Goater env->icache_line_size))); 169d2fd9612SCédric Le Goater 170d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 172d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 173d2fd9612SCédric Le Goater } else { 1743dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 175d2fd9612SCédric Le Goater } 176d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 178d2fd9612SCédric Le Goater pcc->l1_icache_size))); 179d2fd9612SCédric Le Goater } else { 1803dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 181d2fd9612SCédric Le Goater } 182d2fd9612SCédric Le Goater 183d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 184d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 18567d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 186d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 187d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 188d2fd9612SCédric Le Goater 189d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 190d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 191d2fd9612SCédric Le Goater } 192d2fd9612SCédric Le Goater 19358969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 194d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 195d2fd9612SCédric Le Goater segs, sizeof(segs)))); 196d2fd9612SCédric Le Goater } 197d2fd9612SCédric Le Goater 198d2fd9612SCédric Le Goater /* Advertise VMX/VSX (vector extensions) if available 199d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 200d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 201d2fd9612SCédric Le Goater * 2 == VSX available */ 202d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 203d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 204d2fd9612SCédric Le Goater 205d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 206d2fd9612SCédric Le Goater } 207d2fd9612SCédric Le Goater 208d2fd9612SCédric Le Goater /* Advertise DFP (Decimal Floating Point) if available 209d2fd9612SCédric Le Goater * 0 / no property == no DFP 210d2fd9612SCédric Le Goater * 1 == DFP available */ 211d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 212d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 213d2fd9612SCédric Le Goater } 214d2fd9612SCédric Le Goater 215644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 216d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 217d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 218d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 219d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 220d2fd9612SCédric Le Goater } 221d2fd9612SCédric Le Goater 222d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 223d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 224d2fd9612SCédric Le Goater 225d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 226d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 227d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 228d2fd9612SCédric Le Goater } 229d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 230d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 231d2fd9612SCédric Le Goater } 232d2fd9612SCédric Le Goater 233b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 234bf5615e7SCédric Le Goater uint32_t nr_threads) 235bf5615e7SCédric Le Goater { 236bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 237bf5615e7SCédric Le Goater char *name; 238bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 239bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 240bf5615e7SCédric Le Goater uint64_t *reg; 241bf5615e7SCédric Le Goater int offset; 242bf5615e7SCédric Le Goater 243bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 244bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 245bf5615e7SCédric Le Goater 246bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 247bf5615e7SCédric Le Goater reg = g_malloc(rsize); 248bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 249bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 250bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 251bf5615e7SCédric Le Goater } 252bf5615e7SCédric Le Goater 253bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 254bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 255bf5615e7SCédric Le Goater _FDT(offset); 256bf5615e7SCédric Le Goater g_free(name); 257bf5615e7SCédric Le Goater 258bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 259bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 260bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 261bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 262bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 263bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 264bf5615e7SCédric Le Goater irange, sizeof(irange)))); 265bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 266bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 267bf5615e7SCédric Le Goater g_free(reg); 268bf5615e7SCédric Le Goater } 269bf5615e7SCédric Le Goater 270eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 271e997040eSCédric Le Goater { 27240abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 273d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 274d2fd9612SCédric Le Goater int i; 275d2fd9612SCédric Le Goater 276b168a138SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 277967b7523SCédric Le Goater 278d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 279d2fd9612SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 280d2fd9612SCédric Le Goater 281b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 282bf5615e7SCédric Le Goater 283bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 284b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 285d2fd9612SCédric Le Goater } 286d2fd9612SCédric Le Goater 287e997040eSCédric Le Goater if (chip->ram_size) { 288b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 289e997040eSCédric Le Goater } 290e997040eSCédric Le Goater } 291e997040eSCédric Le Goater 292eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 293eb859a27SCédric Le Goater { 294eb859a27SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 295eb859a27SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 296eb859a27SCédric Le Goater int i; 297eb859a27SCédric Le Goater 298eb859a27SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 299eb859a27SCédric Le Goater 300eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 301eb859a27SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 302eb859a27SCédric Le Goater 303eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 304eb859a27SCédric Le Goater } 305eb859a27SCédric Le Goater 306eb859a27SCédric Le Goater if (chip->ram_size) { 307eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 308eb859a27SCédric Le Goater } 309eb859a27SCédric Le Goater } 310eb859a27SCédric Le Goater 311b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 312c5ffdcaeSCédric Le Goater { 313c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 314c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 315c5ffdcaeSCédric Le Goater cpu_to_be32(1), 316c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 317c5ffdcaeSCédric Le Goater cpu_to_be32(2) 318c5ffdcaeSCédric Le Goater }; 319c5ffdcaeSCédric Le Goater char *name; 320c5ffdcaeSCédric Le Goater int node; 321c5ffdcaeSCédric Le Goater 322c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 323c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 324c5ffdcaeSCédric Le Goater _FDT(node); 325c5ffdcaeSCédric Le Goater g_free(name); 326c5ffdcaeSCédric Le Goater 327c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 328c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 329c5ffdcaeSCédric Le Goater } 330c5ffdcaeSCédric Le Goater 331b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 332cb228f5aSCédric Le Goater { 333cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 334cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 335cb228f5aSCédric Le Goater uint32_t io_regs[] = { 336cb228f5aSCédric Le Goater cpu_to_be32(1), 337cb228f5aSCédric Le Goater cpu_to_be32(io_base), 338cb228f5aSCédric Le Goater cpu_to_be32(8) 339cb228f5aSCédric Le Goater }; 340cb228f5aSCédric Le Goater char *name; 341cb228f5aSCédric Le Goater int node; 342cb228f5aSCédric Le Goater 343cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 344cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 345cb228f5aSCédric Le Goater _FDT(node); 346cb228f5aSCédric Le Goater g_free(name); 347cb228f5aSCédric Le Goater 348cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 349cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 350cb228f5aSCédric Le Goater sizeof(compatible)))); 351cb228f5aSCédric Le Goater 352cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 353cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 354cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 355cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 356cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 357cb228f5aSCédric Le Goater 358cb228f5aSCédric Le Goater /* This is needed by Linux */ 359cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 360cb228f5aSCédric Le Goater } 361cb228f5aSCédric Le Goater 362b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 36304f6c8b2SCédric Le Goater { 36404f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 36504f6c8b2SCédric Le Goater uint32_t io_base; 36604f6c8b2SCédric Le Goater uint32_t io_regs[] = { 36704f6c8b2SCédric Le Goater cpu_to_be32(1), 36804f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 36904f6c8b2SCédric Le Goater cpu_to_be32(3) 37004f6c8b2SCédric Le Goater }; 37104f6c8b2SCédric Le Goater uint32_t irq; 37204f6c8b2SCédric Le Goater char *name; 37304f6c8b2SCédric Le Goater int node; 37404f6c8b2SCédric Le Goater 37504f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 37604f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 37704f6c8b2SCédric Le Goater 37804f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 37904f6c8b2SCédric Le Goater 38004f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 38104f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 38204f6c8b2SCédric Le Goater _FDT(node); 38304f6c8b2SCédric Le Goater g_free(name); 38404f6c8b2SCédric Le Goater 3857032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 3867032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 3877032d92aSCédric Le Goater sizeof(compatible)))); 38804f6c8b2SCédric Le Goater 38904f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 39004f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 39104f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 39204f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 39304f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 39404f6c8b2SCédric Le Goater } 39504f6c8b2SCédric Le Goater 396e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 397e7a3fee3SCédric Le Goater void *fdt; 398e7a3fee3SCédric Le Goater int offset; 399e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 400e7a3fee3SCédric Le Goater 401b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 402e7a3fee3SCédric Le Goater { 403c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 404c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 405c5ffdcaeSCédric Le Goater 406c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 407b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 408cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 409b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 41004f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 411b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 412c5ffdcaeSCédric Le Goater } else { 413c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 414c5ffdcaeSCédric Le Goater d->ioport_id); 415c5ffdcaeSCédric Le Goater } 416c5ffdcaeSCédric Le Goater 417e7a3fee3SCédric Le Goater return 0; 418e7a3fee3SCédric Le Goater } 419e7a3fee3SCédric Le Goater 420bb7ab95cSCédric Le Goater static int pnv_chip_isa_offset(PnvChip *chip, void *fdt) 421e7a3fee3SCédric Le Goater { 422bb7ab95cSCédric Le Goater char *name; 423bb7ab95cSCédric Le Goater int offset; 424bb7ab95cSCédric Le Goater 425bb7ab95cSCédric Le Goater name = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 426bb7ab95cSCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), PNV_XSCOM_LPC_BASE); 427bb7ab95cSCédric Le Goater offset = fdt_path_offset(fdt, name); 428bb7ab95cSCédric Le Goater g_free(name); 429bb7ab95cSCédric Le Goater return offset; 430bb7ab95cSCédric Le Goater } 431bb7ab95cSCédric Le Goater 432bb7ab95cSCédric Le Goater /* The default LPC bus of a multichip system is on chip 0. It's 433bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 434bb7ab95cSCédric Le Goater */ 435bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 436bb7ab95cSCédric Le Goater { 437bb7ab95cSCédric Le Goater int isa_offset = pnv_chip_isa_offset(pnv->chips[0], fdt); 438e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 439e7a3fee3SCédric Le Goater .fdt = fdt, 440bb7ab95cSCédric Le Goater .offset = isa_offset, 441e7a3fee3SCédric Le Goater }; 442e7a3fee3SCédric Le Goater 443bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 444bb7ab95cSCédric Le Goater 445e7a3fee3SCédric Le Goater /* ISA devices are not necessarily parented to the ISA bus so we 446e7a3fee3SCédric Le Goater * can not use object_child_foreach() */ 447bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 448bb7ab95cSCédric Le Goater &args); 449e7a3fee3SCédric Le Goater } 450e7a3fee3SCédric Le Goater 451b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4529e933f4aSBenjamin Herrenschmidt { 4539e933f4aSBenjamin Herrenschmidt const char plat_compat[] = "qemu,powernv\0ibm,powernv"; 454b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 4559e933f4aSBenjamin Herrenschmidt void *fdt; 4569e933f4aSBenjamin Herrenschmidt char *buf; 4579e933f4aSBenjamin Herrenschmidt int off; 458e997040eSCédric Le Goater int i; 4599e933f4aSBenjamin Herrenschmidt 4609e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 4619e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 4629e933f4aSBenjamin Herrenschmidt 4639e933f4aSBenjamin Herrenschmidt /* Root node */ 4649e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 4659e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 4669e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 4679e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 4689e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat, 4699e933f4aSBenjamin Herrenschmidt sizeof(plat_compat)))); 4709e933f4aSBenjamin Herrenschmidt 4719e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 4729e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 4739e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 4749e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 4759e933f4aSBenjamin Herrenschmidt } 4769e933f4aSBenjamin Herrenschmidt g_free(buf); 4779e933f4aSBenjamin Herrenschmidt 4789e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 4799e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 4809e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 4819e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 4829e933f4aSBenjamin Herrenschmidt } 4839e933f4aSBenjamin Herrenschmidt 4849e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 4859e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 4869e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 4879e933f4aSBenjamin Herrenschmidt 4889e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 4899e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 4909e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 4919e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 4929e933f4aSBenjamin Herrenschmidt } 4939e933f4aSBenjamin Herrenschmidt 494e997040eSCédric Le Goater /* Populate device tree for each chip */ 495e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 496eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 497e997040eSCédric Le Goater } 498e7a3fee3SCédric Le Goater 499e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 500bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 501aeaef83dSCédric Le Goater 502aeaef83dSCédric Le Goater if (pnv->bmc) { 503b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 504aeaef83dSCédric Le Goater } 505aeaef83dSCédric Le Goater 5069e933f4aSBenjamin Herrenschmidt return fdt; 5079e933f4aSBenjamin Herrenschmidt } 5089e933f4aSBenjamin Herrenschmidt 509bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 510bce0b691SCédric Le Goater { 511b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 512bce0b691SCédric Le Goater 513bce0b691SCédric Le Goater if (pnv->bmc) { 514bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 515bce0b691SCédric Le Goater } 516bce0b691SCédric Le Goater } 517bce0b691SCédric Le Goater 518b168a138SCédric Le Goater static void pnv_reset(void) 5199e933f4aSBenjamin Herrenschmidt { 5209e933f4aSBenjamin Herrenschmidt MachineState *machine = MACHINE(qdev_get_machine()); 521b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5229e933f4aSBenjamin Herrenschmidt void *fdt; 523aeaef83dSCédric Le Goater Object *obj; 5249e933f4aSBenjamin Herrenschmidt 5259e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5269e933f4aSBenjamin Herrenschmidt 527aeaef83dSCédric Le Goater /* OpenPOWER systems have a BMC, which can be defined on the 528aeaef83dSCédric Le Goater * command line with: 529aeaef83dSCédric Le Goater * 530aeaef83dSCédric Le Goater * -device ipmi-bmc-sim,id=bmc0 531aeaef83dSCédric Le Goater * 532aeaef83dSCédric Le Goater * This is the internal simulator but it could also be an external 533aeaef83dSCédric Le Goater * BMC. 534aeaef83dSCédric Le Goater */ 535a1a636b8SCédric Le Goater obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL); 536aeaef83dSCédric Le Goater if (obj) { 537aeaef83dSCédric Le Goater pnv->bmc = IPMI_BMC(obj); 538aeaef83dSCédric Le Goater } 539aeaef83dSCédric Le Goater 540b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5419e933f4aSBenjamin Herrenschmidt 5429e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5439e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5449e933f4aSBenjamin Herrenschmidt 5459e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5469e933f4aSBenjamin Herrenschmidt } 5479e933f4aSBenjamin Herrenschmidt 54804026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5493495b6b6SCédric Le Goater { 55077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 55177864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 55204026890SCédric Le Goater } 5533495b6b6SCédric Le Goater 55404026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 55504026890SCédric Le Goater { 55677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 55777864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 55804026890SCédric Le Goater } 5593495b6b6SCédric Le Goater 56004026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 56104026890SCédric Le Goater { 56204026890SCédric Le Goater return NULL; 56304026890SCédric Le Goater } 5643495b6b6SCédric Le Goater 56504026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 56604026890SCédric Le Goater { 56704026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 5683495b6b6SCédric Le Goater } 5693495b6b6SCédric Le Goater 570*d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 571*d8e4aad5SCédric Le Goater { 572*d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 573*d8e4aad5SCédric Le Goater 574*d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 575*d8e4aad5SCédric Le Goater } 576*d8e4aad5SCédric Le Goater 577*d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 578*d8e4aad5SCédric Le Goater { 579*d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 580*d8e4aad5SCédric Le Goater 581*d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 582*d8e4aad5SCédric Le Goater } 583*d8e4aad5SCédric Le Goater 584b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 5859e933f4aSBenjamin Herrenschmidt { 586b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5879e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 5889e933f4aSBenjamin Herrenschmidt char *fw_filename; 5899e933f4aSBenjamin Herrenschmidt long fw_size; 590e997040eSCédric Le Goater int i; 591e997040eSCédric Le Goater char *chip_typename; 5929e933f4aSBenjamin Herrenschmidt 5939e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 594d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 5953dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 5969e933f4aSBenjamin Herrenschmidt } 5979e933f4aSBenjamin Herrenschmidt 5989e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 599b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6009e933f4aSBenjamin Herrenschmidt machine->ram_size); 6019e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6029e933f4aSBenjamin Herrenschmidt 6039e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 6049e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 6059e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 6069e933f4aSBenjamin Herrenschmidt } 6079e933f4aSBenjamin Herrenschmidt 6089e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 60915fcedb2SCédric Le Goater if (!fw_filename) { 61015fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 61115fcedb2SCédric Le Goater exit(1); 61215fcedb2SCédric Le Goater } 6139e933f4aSBenjamin Herrenschmidt 6149e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 6159e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 61615fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 6179e933f4aSBenjamin Herrenschmidt exit(1); 6189e933f4aSBenjamin Herrenschmidt } 6199e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 6209e933f4aSBenjamin Herrenschmidt 6219e933f4aSBenjamin Herrenschmidt /* load kernel */ 6229e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 6239e933f4aSBenjamin Herrenschmidt long kernel_size; 6249e933f4aSBenjamin Herrenschmidt 6259e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 626b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 6279e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 628802fc7abSThomas Huth error_report("Could not load kernel '%s'", 6299e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 6309e933f4aSBenjamin Herrenschmidt exit(1); 6319e933f4aSBenjamin Herrenschmidt } 6329e933f4aSBenjamin Herrenschmidt } 6339e933f4aSBenjamin Herrenschmidt 6349e933f4aSBenjamin Herrenschmidt /* load initrd */ 6359e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 6369e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 6379e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 638584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 6399e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 640802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 6419e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 6429e933f4aSBenjamin Herrenschmidt exit(1); 6439e933f4aSBenjamin Herrenschmidt } 6449e933f4aSBenjamin Herrenschmidt } 645e997040eSCédric Le Goater 646e997040eSCédric Le Goater /* Create the processor chips */ 6474a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 6487fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 6494a12c699SIgor Mammedov i, machine->cpu_type); 650e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 6514a12c699SIgor Mammedov error_report("invalid CPU model '%.*s' for %s machine", 6524a12c699SIgor Mammedov i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name); 653e997040eSCédric Le Goater exit(1); 654e997040eSCédric Le Goater } 655e997040eSCédric Le Goater 656e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 657e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 658e997040eSCédric Le Goater char chip_name[32]; 659e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 660e997040eSCédric Le Goater 661e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 662e997040eSCédric Le Goater 663e997040eSCédric Le Goater /* TODO: put all the memory in one node on chip 0 until we find a 664e997040eSCédric Le Goater * way to specify different ranges for each chip 665e997040eSCédric Le Goater */ 666e997040eSCédric Le Goater if (i == 0) { 667e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 668e997040eSCédric Le Goater &error_fatal); 669e997040eSCédric Le Goater } 670e997040eSCédric Le Goater 671e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 672e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 673e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 674e997040eSCédric Le Goater &error_fatal); 675397a79e7SCédric Le Goater object_property_set_int(chip, smp_cores, "nr-cores", &error_fatal); 676e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 677e997040eSCédric Le Goater } 678e997040eSCédric Le Goater g_free(chip_typename); 6793495b6b6SCédric Le Goater 6803495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 68104026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 6823495b6b6SCédric Le Goater 6833495b6b6SCédric Le Goater /* Create serial port */ 684def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 6853495b6b6SCédric Le Goater 6863495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 6876c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 688bce0b691SCédric Le Goater 689bce0b691SCédric Le Goater /* OpenPOWER systems use a IPMI SEL Event message to notify the 690bce0b691SCédric Le Goater * host to powerdown */ 691bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 692bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 693e997040eSCédric Le Goater } 694e997040eSCédric Le Goater 695631adaffSCédric Le Goater /* 696631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 697631adaffSCédric Le Goater * 22:24 Chip ID 698631adaffSCédric Le Goater * 25:28 Core number 699631adaffSCédric Le Goater * 29:31 Thread ID 700631adaffSCédric Le Goater */ 701631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 702631adaffSCédric Le Goater { 703631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 704631adaffSCédric Le Goater } 705631adaffSCédric Le Goater 7068fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 707d35aefa9SCédric Le Goater Error **errp) 708d35aefa9SCédric Le Goater { 7098fa1f4efSCédric Le Goater Error *local_err = NULL; 7108fa1f4efSCédric Le Goater Object *obj; 7118907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 7128fa1f4efSCédric Le Goater 7138fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 7148fa1f4efSCédric Le Goater &local_err); 7158fa1f4efSCédric Le Goater if (local_err) { 7168fa1f4efSCédric Le Goater error_propagate(errp, local_err); 7178fa1f4efSCédric Le Goater return; 7188fa1f4efSCédric Le Goater } 7198fa1f4efSCédric Le Goater 720956b8f46SCédric Le Goater pnv_cpu->intc = obj; 721d35aefa9SCédric Le Goater } 722d35aefa9SCédric Le Goater 723631adaffSCédric Le Goater /* 724631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 725631adaffSCédric Le Goater * 49:52 Node ID 726631adaffSCédric Le Goater * 53:55 Chip ID 727631adaffSCédric Le Goater * 56 Reserved - Read as zero 728631adaffSCédric Le Goater * 57:61 Core number 729631adaffSCédric Le Goater * 62:63 Thread ID 730631adaffSCédric Le Goater * 731631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 732631adaffSCédric Le Goater */ 733631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 734631adaffSCédric Le Goater { 735631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 736631adaffSCédric Le Goater } 737631adaffSCédric Le Goater 7388fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 739d35aefa9SCédric Le Goater Error **errp) 740d35aefa9SCédric Le Goater { 7412dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 7422dfa91a2SCédric Le Goater Error *local_err = NULL; 7432dfa91a2SCédric Le Goater Object *obj; 7442dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 7452dfa91a2SCédric Le Goater 7462dfa91a2SCédric Le Goater /* 7472dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 7482dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 7492dfa91a2SCédric Le Goater * only used at runtime. 7502dfa91a2SCédric Le Goater */ 7512dfa91a2SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), errp); 7522dfa91a2SCédric Le Goater if (local_err) { 7532dfa91a2SCédric Le Goater error_propagate(errp, local_err); 7548fa1f4efSCédric Le Goater return; 755d35aefa9SCédric Le Goater } 756d35aefa9SCédric Le Goater 7572dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 7582dfa91a2SCédric Le Goater } 7592dfa91a2SCédric Le Goater 760397a79e7SCédric Le Goater /* Allowed core identifiers on a POWER8 Processor Chip : 761397a79e7SCédric Le Goater * 762397a79e7SCédric Le Goater * <EX0 reserved> 763397a79e7SCédric Le Goater * EX1 - Venice only 764397a79e7SCédric Le Goater * EX2 - Venice only 765397a79e7SCédric Le Goater * EX3 - Venice only 766397a79e7SCédric Le Goater * EX4 767397a79e7SCédric Le Goater * EX5 768397a79e7SCédric Le Goater * EX6 769397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 770397a79e7SCédric Le Goater * EX9 - Venice only 771397a79e7SCédric Le Goater * EX10 - Venice only 772397a79e7SCédric Le Goater * EX11 - Venice only 773397a79e7SCédric Le Goater * EX12 774397a79e7SCédric Le Goater * EX13 775397a79e7SCédric Le Goater * EX14 776397a79e7SCédric Le Goater * <EX15 reserved> 777397a79e7SCédric Le Goater */ 778397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 779397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 780397a79e7SCédric Le Goater 781397a79e7SCédric Le Goater /* 78209279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 783397a79e7SCédric Le Goater */ 78409279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 785397a79e7SCédric Le Goater 78677864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 78777864267SCédric Le Goater { 78877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 78977864267SCédric Le Goater 790f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 791f6d4dca8SThomas Huth TYPE_PNV_PSI, &error_abort, NULL); 79277864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 79377864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 79477864267SCédric Le Goater 795f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 796f6d4dca8SThomas Huth TYPE_PNV_LPC, &error_abort, NULL); 79777864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->lpc), "psi", 79877864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 79977864267SCédric Le Goater 800f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 801f6d4dca8SThomas Huth TYPE_PNV_OCC, &error_abort, NULL); 80277864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->occ), "psi", 80377864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 80477864267SCédric Le Goater } 80577864267SCédric Le Goater 80677864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 80777864267SCédric Le Goater { 80877864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 80977864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 81077864267SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 81177864267SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 81277864267SCédric Le Goater int i, j; 81377864267SCédric Le Goater char *name; 81477864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 81577864267SCédric Le Goater 81677864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 81777864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 81877864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 81977864267SCédric Le Goater g_free(name); 82077864267SCédric Le Goater 82177864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 82277864267SCédric Le Goater 82377864267SCédric Le Goater /* Map the ICP registers for each thread */ 82477864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 82577864267SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 82677864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 82777864267SCédric Le Goater 82877864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 82977864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 83077864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 83177864267SCédric Le Goater 83277864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 83377864267SCédric Le Goater &icp->mmio); 83477864267SCédric Le Goater } 83577864267SCédric Le Goater } 83677864267SCédric Le Goater } 83777864267SCédric Le Goater 83877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 83977864267SCédric Le Goater { 84077864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 84177864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 84277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 84377864267SCédric Le Goater Error *local_err = NULL; 84477864267SCédric Le Goater 84577864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 84677864267SCédric Le Goater if (local_err) { 84777864267SCédric Le Goater error_propagate(errp, local_err); 84877864267SCédric Le Goater return; 84977864267SCédric Le Goater } 85077864267SCédric Le Goater 85177864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 85277864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 85377864267SCédric Le Goater "bar", &error_fatal); 85477864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 85577864267SCédric Le Goater if (local_err) { 85677864267SCédric Le Goater error_propagate(errp, local_err); 85777864267SCédric Le Goater return; 85877864267SCédric Le Goater } 85977864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, &chip8->psi.xscom_regs); 86077864267SCédric Le Goater 86177864267SCédric Le Goater /* Create LPC controller */ 86277864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 86377864267SCédric Le Goater &error_fatal); 86477864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 86577864267SCédric Le Goater 86677864267SCédric Le Goater /* Interrupt Management Area. This is the memory region holding 86777864267SCédric Le Goater * all the Interrupt Control Presenter (ICP) registers */ 86877864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 86977864267SCédric Le Goater if (local_err) { 87077864267SCédric Le Goater error_propagate(errp, local_err); 87177864267SCédric Le Goater return; 87277864267SCédric Le Goater } 87377864267SCédric Le Goater 87477864267SCédric Le Goater /* Create the simplified OCC model */ 87577864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 87677864267SCédric Le Goater if (local_err) { 87777864267SCédric Le Goater error_propagate(errp, local_err); 87877864267SCédric Le Goater return; 87977864267SCédric Le Goater } 88077864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 88177864267SCédric Le Goater } 88277864267SCédric Le Goater 883e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 884e997040eSCédric Le Goater { 885e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 886e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 887e997040eSCédric Le Goater 888e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 889e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 890397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 891631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 892d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 89304026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 894eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 895*d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 896967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 897e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 89877864267SCédric Le Goater 89977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 90077864267SCédric Le Goater &k->parent_realize); 901e997040eSCédric Le Goater } 902e997040eSCédric Le Goater 903e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 904e997040eSCédric Le Goater { 905e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 906e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 907e997040eSCédric Le Goater 908e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 909e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 910397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 911631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 912d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 91304026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 914eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 915*d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 916967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 917e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 91877864267SCédric Le Goater 91977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 92077864267SCédric Le Goater &k->parent_realize); 921e997040eSCédric Le Goater } 922e997040eSCédric Le Goater 923e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 924e997040eSCédric Le Goater { 925e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 926e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 927e997040eSCédric Le Goater 928e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 929e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 930397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 931631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 932d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 93304026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 934eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 935*d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 936967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 937e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 93877864267SCédric Le Goater 93977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 94077864267SCédric Le Goater &k->parent_realize); 94177864267SCédric Le Goater } 94277864267SCédric Le Goater 94377864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 94477864267SCédric Le Goater { 9452dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 9462dfa91a2SCédric Le Goater 9472dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 9482dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 9492dfa91a2SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj, 9502dfa91a2SCédric Le Goater &error_abort); 95177864267SCédric Le Goater } 95277864267SCédric Le Goater 95377864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 95477864267SCédric Le Goater { 95577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 9562dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 9572dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 95877864267SCédric Le Goater Error *local_err = NULL; 95977864267SCédric Le Goater 96077864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 96177864267SCédric Le Goater if (local_err) { 96277864267SCédric Le Goater error_propagate(errp, local_err); 96377864267SCédric Le Goater return; 96477864267SCédric Le Goater } 9652dfa91a2SCédric Le Goater 9662dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 9672dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 9682dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 9692dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 9702dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 9712dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 9722dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 9732dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 9742dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 9752dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 9762dfa91a2SCédric Le Goater &local_err); 9772dfa91a2SCédric Le Goater if (local_err) { 9782dfa91a2SCédric Le Goater error_propagate(errp, local_err); 9792dfa91a2SCédric Le Goater return; 9802dfa91a2SCédric Le Goater } 9812dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 9822dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 983e997040eSCédric Le Goater } 984e997040eSCédric Le Goater 985e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 986e997040eSCédric Le Goater { 987e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 988e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 989e997040eSCédric Le Goater 990e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 99183028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 992397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 993631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 994d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 99504026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 996eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 997*d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 998967b7523SCédric Le Goater k->xscom_base = 0x00603fc00000000ull; 999e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 100077864267SCédric Le Goater 100177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 100277864267SCédric Le Goater &k->parent_realize); 1003e997040eSCédric Le Goater } 1004e997040eSCédric Le Goater 1005397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1006397a79e7SCédric Le Goater { 1007397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1008397a79e7SCédric Le Goater int cores_max; 1009397a79e7SCédric Le Goater 1010397a79e7SCédric Le Goater /* 1011397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1012397a79e7SCédric Le Goater * the chip class 1013397a79e7SCédric Le Goater */ 1014397a79e7SCédric Le Goater if (!chip->cores_mask) { 1015397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1016397a79e7SCédric Le Goater } 1017397a79e7SCédric Le Goater 1018397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1019397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1020397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1021397a79e7SCédric Le Goater chip->cores_mask); 1022397a79e7SCédric Le Goater return; 1023397a79e7SCédric Le Goater } 1024397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1025397a79e7SCédric Le Goater 1026397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 102727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1028397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1029397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1030397a79e7SCédric Le Goater cores_max); 1031397a79e7SCédric Le Goater return; 1032397a79e7SCédric Le Goater } 1033397a79e7SCédric Le Goater } 1034397a79e7SCédric Le Goater 103577864267SCédric Le Goater static void pnv_chip_instance_init(Object *obj) 1036967b7523SCédric Le Goater { 103777864267SCédric Le Goater PNV_CHIP(obj)->xscom_base = PNV_CHIP_GET_CLASS(obj)->xscom_base; 1038bf5615e7SCédric Le Goater } 1039bf5615e7SCédric Le Goater 104051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1041e997040eSCédric Le Goater { 1042397a79e7SCédric Le Goater Error *error = NULL; 1043d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 104440abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1045d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 1046d2fd9612SCédric Le Goater int i, core_hwid; 1047397a79e7SCédric Le Goater 1048d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1049d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1050d2fd9612SCédric Le Goater return; 1051d2fd9612SCédric Le Goater } 1052d2fd9612SCédric Le Goater 1053d2fd9612SCédric Le Goater /* Cores */ 1054397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1055397a79e7SCédric Le Goater if (error) { 1056397a79e7SCédric Le Goater error_propagate(errp, error); 1057397a79e7SCédric Le Goater return; 1058397a79e7SCédric Le Goater } 1059d2fd9612SCédric Le Goater 1060d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 1061d2fd9612SCédric Le Goater 1062d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1063d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1064d2fd9612SCédric Le Goater char core_name[32]; 1065d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 1066c035851aSCédric Le Goater uint64_t xscom_core_base; 1067d2fd9612SCédric Le Goater 1068d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1069d2fd9612SCédric Le Goater continue; 1070d2fd9612SCédric Le Goater } 1071d2fd9612SCédric Le Goater 1072d2fd9612SCédric Le Goater object_initialize(pnv_core, typesize, typename); 1073d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1074d2fd9612SCédric Le Goater object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), 1075d2fd9612SCédric Le Goater &error_fatal); 1076d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads", 1077d2fd9612SCédric Le Goater &error_fatal); 1078d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1079d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1080d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1081d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1082d2fd9612SCédric Le Goater "pir", &error_fatal); 1083d35aefa9SCédric Le Goater object_property_add_const_link(OBJECT(pnv_core), "chip", 1084d35aefa9SCédric Le Goater OBJECT(chip), &error_fatal); 1085d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1086d2fd9612SCédric Le Goater &error_fatal); 1087d2fd9612SCédric Le Goater object_unref(OBJECT(pnv_core)); 108824ece072SCédric Le Goater 108924ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1090c035851aSCédric Le Goater if (!pnv_chip_is_power9(chip)) { 1091c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1092c035851aSCédric Le Goater } else { 1093c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_P9_EC_BASE(core_hwid); 1094c035851aSCédric Le Goater } 1095c035851aSCédric Le Goater 1096c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 109724ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 1098d2fd9612SCédric Le Goater i++; 1099d2fd9612SCédric Le Goater } 110051c04728SCédric Le Goater } 110151c04728SCédric Le Goater 110251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 110351c04728SCédric Le Goater { 110451c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 110551c04728SCédric Le Goater Error *error = NULL; 110651c04728SCédric Le Goater 110751c04728SCédric Le Goater /* XSCOM bridge */ 110851c04728SCédric Le Goater pnv_xscom_realize(chip, &error); 110951c04728SCédric Le Goater if (error) { 111051c04728SCédric Le Goater error_propagate(errp, error); 111151c04728SCédric Le Goater return; 111251c04728SCédric Le Goater } 111351c04728SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 111451c04728SCédric Le Goater 111551c04728SCédric Le Goater /* Cores */ 111651c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 111751c04728SCédric Le Goater if (error) { 111851c04728SCédric Le Goater error_propagate(errp, error); 111951c04728SCédric Le Goater return; 112051c04728SCédric Le Goater } 1121e997040eSCédric Le Goater } 1122e997040eSCédric Le Goater 1123e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1124e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1125e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1126e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1127397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1128397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1129e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1130e997040eSCédric Le Goater }; 1131e997040eSCédric Le Goater 1132e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1133e997040eSCédric Le Goater { 1134e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1135e997040eSCédric Le Goater 11369d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1137e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1138e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1139e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1140e997040eSCédric Le Goater } 1141e997040eSCédric Le Goater 114254f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 114354f59d78SCédric Le Goater { 1144b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 114554f59d78SCédric Le Goater int i; 114654f59d78SCédric Le Goater 114754f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 114877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 114977864267SCédric Le Goater 115077864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 115177864267SCédric Le Goater return &chip8->psi.ics; 115254f59d78SCédric Le Goater } 115354f59d78SCédric Le Goater } 115454f59d78SCédric Le Goater return NULL; 115554f59d78SCédric Le Goater } 115654f59d78SCédric Le Goater 115754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 115854f59d78SCédric Le Goater { 1159b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 116054f59d78SCédric Le Goater int i; 116154f59d78SCédric Le Goater 116254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 116377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 116477864267SCédric Le Goater ics_resend(&chip8->psi.ics); 116554f59d78SCédric Le Goater } 116654f59d78SCédric Le Goater } 116754f59d78SCédric Le Goater 116836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 116936fc6f08SCédric Le Goater { 117036fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 117136fc6f08SCédric Le Goater 1172956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 117336fc6f08SCédric Le Goater } 117436fc6f08SCédric Le Goater 117547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 117647fea43aSCédric Le Goater Monitor *mon) 117747fea43aSCédric Le Goater { 1178b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 117954f59d78SCédric Le Goater int i; 118047fea43aSCédric Le Goater CPUState *cs; 118147fea43aSCédric Le Goater 118247fea43aSCédric Le Goater CPU_FOREACH(cs) { 118347fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 118447fea43aSCédric Le Goater 1185*d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1186*d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1187*d8e4aad5SCédric Le Goater } else { 1188956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 118947fea43aSCédric Le Goater } 1190*d8e4aad5SCédric Le Goater } 119154f59d78SCédric Le Goater 119254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1193*d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 119454f59d78SCédric Le Goater } 119547fea43aSCédric Le Goater } 119647fea43aSCédric Le Goater 1197e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1198e997040eSCédric Le Goater void *opaque, Error **errp) 1199e997040eSCédric Le Goater { 1200b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1201e997040eSCédric Le Goater } 1202e997040eSCédric Le Goater 1203e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1204e997040eSCédric Le Goater void *opaque, Error **errp) 1205e997040eSCédric Le Goater { 1206b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1207e997040eSCédric Le Goater uint32_t num_chips; 1208e997040eSCédric Le Goater Error *local_err = NULL; 1209e997040eSCédric Le Goater 1210e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1211e997040eSCédric Le Goater if (local_err) { 1212e997040eSCédric Le Goater error_propagate(errp, local_err); 1213e997040eSCédric Le Goater return; 1214e997040eSCédric Le Goater } 1215e997040eSCédric Le Goater 1216e997040eSCédric Le Goater /* 1217e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1218e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1219e997040eSCédric Le Goater */ 1220e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1221e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1222e997040eSCédric Le Goater return; 1223e997040eSCédric Le Goater } 1224e997040eSCédric Le Goater 1225e997040eSCédric Le Goater pnv->num_chips = num_chips; 1226e997040eSCédric Le Goater } 1227e997040eSCédric Le Goater 122877864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1229e997040eSCédric Le Goater { 1230b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1231e997040eSCédric Le Goater pnv->num_chips = 1; 1232e997040eSCédric Le Goater } 1233e997040eSCédric Le Goater 1234b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1235e997040eSCédric Le Goater { 12361e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1237e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1238e997040eSCédric Le Goater NULL, NULL, NULL); 1239e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1240e997040eSCédric Le Goater "Specifies the number of processor chips", 1241e997040eSCédric Le Goater NULL); 12429e933f4aSBenjamin Herrenschmidt } 12439e933f4aSBenjamin Herrenschmidt 1244b168a138SCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 12459e933f4aSBenjamin Herrenschmidt { 12469e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 124736fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 124847fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 12499e933f4aSBenjamin Herrenschmidt 12509e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1251b168a138SCédric Le Goater mc->init = pnv_init; 1252b168a138SCédric Le Goater mc->reset = pnv_reset; 12539e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 12544a12c699SIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 12559e933f4aSBenjamin Herrenschmidt mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for 12569e933f4aSBenjamin Herrenschmidt * storage */ 12579e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 12589e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1259d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 1 * GiB; 126036fc6f08SCédric Le Goater xic->icp_get = pnv_icp_get; 126154f59d78SCédric Le Goater xic->ics_get = pnv_ics_get; 126254f59d78SCédric Le Goater xic->ics_resend = pnv_ics_resend; 126347fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1264e997040eSCédric Le Goater 1265b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 12669e933f4aSBenjamin Herrenschmidt } 12679e933f4aSBenjamin Herrenschmidt 126877864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1269beba5c0fSIgor Mammedov { \ 1270beba5c0fSIgor Mammedov .name = type, \ 1271beba5c0fSIgor Mammedov .class_init = class_initfn, \ 127277864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 127377864267SCédric Le Goater } 127477864267SCédric Le Goater 127577864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 127677864267SCédric Le Goater { \ 127777864267SCédric Le Goater .name = type, \ 127877864267SCédric Le Goater .class_init = class_initfn, \ 127977864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1280beba5c0fSIgor Mammedov } 1281beba5c0fSIgor Mammedov 1282beba5c0fSIgor Mammedov static const TypeInfo types[] = { 1283beba5c0fSIgor Mammedov { 1284b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 12859e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 12869e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 128777864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1288b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 128936fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 129036fc6f08SCédric Le Goater { TYPE_XICS_FABRIC }, 129147fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 129236fc6f08SCédric Le Goater { }, 129336fc6f08SCédric Le Goater }, 1294beba5c0fSIgor Mammedov }, 1295beba5c0fSIgor Mammedov { 1296beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1297beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1298beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 129977864267SCédric Le Goater .instance_init = pnv_chip_instance_init, 1300beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1301beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1302beba5c0fSIgor Mammedov .abstract = true, 1303beba5c0fSIgor Mammedov }, 130477864267SCédric Le Goater 130577864267SCédric Le Goater /* 130677864267SCédric Le Goater * P9 chip and variants 130777864267SCédric Le Goater */ 130877864267SCédric Le Goater { 130977864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 131077864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 131177864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 131277864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 131377864267SCédric Le Goater }, 131477864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 131577864267SCédric Le Goater 131677864267SCédric Le Goater /* 131777864267SCédric Le Goater * P8 chip and variants 131877864267SCédric Le Goater */ 131977864267SCédric Le Goater { 132077864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 132177864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 132277864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 132377864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 132477864267SCédric Le Goater }, 132577864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 132677864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 132777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1328beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 13299e933f4aSBenjamin Herrenschmidt }; 13309e933f4aSBenjamin Herrenschmidt 1331beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1332