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" 21a8d25326SMarkus Armbruster #include "qemu-common.h" 22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2671e8a915SMarkus Armbruster #include "sysemu/reset.h" 2754d31236SMarkus Armbruster #include "sysemu/runstate.h" 28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 298d409261SCédric Le Goater #include "sysemu/device_tree.h" 30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 38e997040eSCédric Le Goater #include "qapi/visitor.h" 3947fea43aSCédric Le Goater #include "monitor/monitor.h" 4047fea43aSCédric Le Goater #include "hw/intc/intc.h" 41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 439e933f4aSBenjamin Herrenschmidt 4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 4735dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 48967b7523SCédric Le Goater 493495b6b6SCédric Le Goater #include "hw/isa/isa.h" 5012e9493dSMarkus Armbruster #include "hw/boards.h" 513495b6b6SCédric Le Goater #include "hw/char/serial.h" 52bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 533495b6b6SCédric Le Goater 549e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 559e933f4aSBenjamin Herrenschmidt 56b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 579e933f4aSBenjamin Herrenschmidt 589e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 599e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 60b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 619e933f4aSBenjamin Herrenschmidt 629e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 63b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 64fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 65584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 669e933f4aSBenjamin Herrenschmidt 6740abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 6840abf43fSIgor Mammedov { 6940abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7040abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7140abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7240abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7340abf43fSIgor Mammedov g_free(s); 7440abf43fSIgor Mammedov return core_type; 7540abf43fSIgor Mammedov } 7640abf43fSIgor Mammedov 779e933f4aSBenjamin Herrenschmidt /* 789e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 799e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 809e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 819e933f4aSBenjamin Herrenschmidt */ 829e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 839e933f4aSBenjamin Herrenschmidt 849e933f4aSBenjamin Herrenschmidt /* 859e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 869e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 879e933f4aSBenjamin Herrenschmidt * per chip. 889e933f4aSBenjamin Herrenschmidt */ 89b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 909e933f4aSBenjamin Herrenschmidt { 919e933f4aSBenjamin Herrenschmidt char *mem_name; 929e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 939e933f4aSBenjamin Herrenschmidt int off; 949e933f4aSBenjamin Herrenschmidt 959e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 969e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 979e933f4aSBenjamin Herrenschmidt 989e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 999e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1009e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1019e933f4aSBenjamin Herrenschmidt 1029e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1039e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1049e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1059e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1069e933f4aSBenjamin Herrenschmidt } 1079e933f4aSBenjamin Herrenschmidt 108d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 109d2fd9612SCédric Le Goater { 110d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 111d2fd9612SCédric Le Goater 112d2fd9612SCédric Le Goater if (cpus_offset < 0) { 113a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 114d2fd9612SCédric Le Goater if (cpus_offset) { 115d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 116d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 117d2fd9612SCédric Le Goater } 118d2fd9612SCédric Le Goater } 119d2fd9612SCédric Le Goater _FDT(cpus_offset); 120d2fd9612SCédric Le Goater return cpus_offset; 121d2fd9612SCédric Le Goater } 122d2fd9612SCédric Le Goater 123d2fd9612SCédric Le Goater /* 124d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 125d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 126d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 127d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 128d2fd9612SCédric Le Goater * servers. 129d2fd9612SCédric Le Goater */ 130b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 131d2fd9612SCédric Le Goater { 13208304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13308304a86SDavid Gibson CPUState *cs = CPU(cpu); 134d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1358bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 136d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 137d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 138d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 139d2fd9612SCédric Le Goater int i; 140d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 141d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 142d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 143d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 144d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 145d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 146d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 147d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 148d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 149d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 150d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 151d2fd9612SCédric Le Goater int offset; 152d2fd9612SCédric Le Goater char *nodename; 153d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 154d2fd9612SCédric Le Goater 155d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 156d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 157d2fd9612SCédric Le Goater _FDT(offset); 158d2fd9612SCédric Le Goater g_free(nodename); 159d2fd9612SCédric Le Goater 160d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 161d2fd9612SCédric Le Goater 162d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 164d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 165d2fd9612SCédric Le Goater 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 168d2fd9612SCédric Le Goater env->dcache_line_size))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 170d2fd9612SCédric Le Goater env->dcache_line_size))); 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 172d2fd9612SCédric Le Goater env->icache_line_size))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 174d2fd9612SCédric Le Goater env->icache_line_size))); 175d2fd9612SCédric Le Goater 176d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 178d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 179d2fd9612SCédric Le Goater } else { 1803dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 181d2fd9612SCédric Le Goater } 182d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 183d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 184d2fd9612SCédric Le Goater pcc->l1_icache_size))); 185d2fd9612SCédric Le Goater } else { 1863dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 187d2fd9612SCédric Le Goater } 188d2fd9612SCédric Le Goater 189d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 190d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19159b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19259b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 193d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 194d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 195d2fd9612SCédric Le Goater 196d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 197d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 198d2fd9612SCédric Le Goater } 199d2fd9612SCédric Le Goater 20058969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 201d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 202d2fd9612SCédric Le Goater segs, sizeof(segs)))); 203d2fd9612SCédric Le Goater } 204d2fd9612SCédric Le Goater 20559b7c1c2SBalamuruhan S /* 20659b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 207d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 208d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 20959b7c1c2SBalamuruhan S * 2 == VSX available 21059b7c1c2SBalamuruhan S */ 211d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 212d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 213d2fd9612SCédric Le Goater 214d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 215d2fd9612SCédric Le Goater } 216d2fd9612SCédric Le Goater 21759b7c1c2SBalamuruhan S /* 21859b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 219d2fd9612SCédric Le Goater * 0 / no property == no DFP 22059b7c1c2SBalamuruhan S * 1 == DFP available 22159b7c1c2SBalamuruhan S */ 222d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 223d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 224d2fd9612SCédric Le Goater } 225d2fd9612SCédric Le Goater 226644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 227d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 228d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 229d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 230d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 231d2fd9612SCédric Le Goater } 232d2fd9612SCédric Le Goater 233d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 234d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 235d2fd9612SCédric Le Goater 236d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 237d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 238d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 239d2fd9612SCédric Le Goater } 240d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 241d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 242d2fd9612SCédric Le Goater } 243d2fd9612SCédric Le Goater 244b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 245bf5615e7SCédric Le Goater uint32_t nr_threads) 246bf5615e7SCédric Le Goater { 247bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 248bf5615e7SCédric Le Goater char *name; 249bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 250bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 251bf5615e7SCédric Le Goater uint64_t *reg; 252bf5615e7SCédric Le Goater int offset; 253bf5615e7SCédric Le Goater 254bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 255bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 256bf5615e7SCédric Le Goater 257bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 258bf5615e7SCédric Le Goater reg = g_malloc(rsize); 259bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 260bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 261bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 262bf5615e7SCédric Le Goater } 263bf5615e7SCédric Le Goater 264bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 265bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 266bf5615e7SCédric Le Goater _FDT(offset); 267bf5615e7SCédric Le Goater g_free(name); 268bf5615e7SCédric Le Goater 269bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 270bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 271bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 272bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 273bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 274bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 275bf5615e7SCédric Le Goater irange, sizeof(irange)))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 278bf5615e7SCédric Le Goater g_free(reg); 279bf5615e7SCédric Le Goater } 280bf5615e7SCédric Le Goater 281eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 282e997040eSCédric Le Goater { 283d2fd9612SCédric Le Goater int i; 284d2fd9612SCédric Le Goater 285b168a138SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 286967b7523SCédric Le Goater 287d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2884fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 289d2fd9612SCédric Le Goater 290b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 291bf5615e7SCédric Le Goater 292bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 293b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 294d2fd9612SCédric Le Goater } 295d2fd9612SCédric Le Goater 296e997040eSCédric Le Goater if (chip->ram_size) { 297b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 298e997040eSCédric Le Goater } 299e997040eSCédric Le Goater } 300e997040eSCédric Le Goater 301eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 302eb859a27SCédric Le Goater { 303eb859a27SCédric Le Goater int i; 304eb859a27SCédric Le Goater 305eb859a27SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 306eb859a27SCédric Le Goater 307eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3084fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 309eb859a27SCédric Le Goater 310eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 311eb859a27SCédric Le Goater } 312eb859a27SCédric Le Goater 313eb859a27SCédric Le Goater if (chip->ram_size) { 314eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 315eb859a27SCédric Le Goater } 31615376c66SCédric Le Goater 31715376c66SCédric Le Goater pnv_dt_lpc(chip, fdt, 0); 318eb859a27SCédric Le Goater } 319eb859a27SCédric Le Goater 3202b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3212b548a42SCédric Le Goater { 3222b548a42SCédric Le Goater int i; 3232b548a42SCédric Le Goater 3242b548a42SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 3252b548a42SCédric Le Goater 3262b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3272b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3282b548a42SCédric Le Goater 3292b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3302b548a42SCédric Le Goater } 3312b548a42SCédric Le Goater 3322b548a42SCédric Le Goater if (chip->ram_size) { 3332b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3342b548a42SCédric Le Goater } 3352b548a42SCédric Le Goater } 3362b548a42SCédric Le Goater 337b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 338c5ffdcaeSCédric Le Goater { 339c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 340c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 341c5ffdcaeSCédric Le Goater cpu_to_be32(1), 342c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 343c5ffdcaeSCédric Le Goater cpu_to_be32(2) 344c5ffdcaeSCédric Le Goater }; 345c5ffdcaeSCédric Le Goater char *name; 346c5ffdcaeSCédric Le Goater int node; 347c5ffdcaeSCédric Le Goater 348c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 349c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 350c5ffdcaeSCédric Le Goater _FDT(node); 351c5ffdcaeSCédric Le Goater g_free(name); 352c5ffdcaeSCédric Le Goater 353c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 354c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 355c5ffdcaeSCédric Le Goater } 356c5ffdcaeSCédric Le Goater 357b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 358cb228f5aSCédric Le Goater { 359cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 360cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 361cb228f5aSCédric Le Goater uint32_t io_regs[] = { 362cb228f5aSCédric Le Goater cpu_to_be32(1), 363cb228f5aSCédric Le Goater cpu_to_be32(io_base), 364cb228f5aSCédric Le Goater cpu_to_be32(8) 365cb228f5aSCédric Le Goater }; 366cb228f5aSCédric Le Goater char *name; 367cb228f5aSCédric Le Goater int node; 368cb228f5aSCédric Le Goater 369cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 370cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 371cb228f5aSCédric Le Goater _FDT(node); 372cb228f5aSCédric Le Goater g_free(name); 373cb228f5aSCédric Le Goater 374cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 375cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 376cb228f5aSCédric Le Goater sizeof(compatible)))); 377cb228f5aSCédric Le Goater 378cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 379cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 380cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 381cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 382cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 383cb228f5aSCédric Le Goater 384cb228f5aSCédric Le Goater /* This is needed by Linux */ 385cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 386cb228f5aSCédric Le Goater } 387cb228f5aSCédric Le Goater 388b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 38904f6c8b2SCédric Le Goater { 39004f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 39104f6c8b2SCédric Le Goater uint32_t io_base; 39204f6c8b2SCédric Le Goater uint32_t io_regs[] = { 39304f6c8b2SCédric Le Goater cpu_to_be32(1), 39404f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 39504f6c8b2SCédric Le Goater cpu_to_be32(3) 39604f6c8b2SCédric Le Goater }; 39704f6c8b2SCédric Le Goater uint32_t irq; 39804f6c8b2SCédric Le Goater char *name; 39904f6c8b2SCédric Le Goater int node; 40004f6c8b2SCédric Le Goater 40104f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 40204f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 40304f6c8b2SCédric Le Goater 40404f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 40504f6c8b2SCédric Le Goater 40604f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 40704f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 40804f6c8b2SCédric Le Goater _FDT(node); 40904f6c8b2SCédric Le Goater g_free(name); 41004f6c8b2SCédric Le Goater 4117032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4127032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4137032d92aSCédric Le Goater sizeof(compatible)))); 41404f6c8b2SCédric Le Goater 41504f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 41604f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 41704f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 41804f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 41904f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 42004f6c8b2SCédric Le Goater } 42104f6c8b2SCédric Le Goater 422e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 423e7a3fee3SCédric Le Goater void *fdt; 424e7a3fee3SCédric Le Goater int offset; 425e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 426e7a3fee3SCédric Le Goater 427b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 428e7a3fee3SCédric Le Goater { 429c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 430c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 431c5ffdcaeSCédric Le Goater 432c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 433b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 434cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 435b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 43604f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 437b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 438c5ffdcaeSCédric Le Goater } else { 439c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 440c5ffdcaeSCédric Le Goater d->ioport_id); 441c5ffdcaeSCédric Le Goater } 442c5ffdcaeSCédric Le Goater 443e7a3fee3SCédric Le Goater return 0; 444e7a3fee3SCédric Le Goater } 445e7a3fee3SCédric Le Goater 44659b7c1c2SBalamuruhan S /* 44759b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 448bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 449bb7ab95cSCédric Le Goater */ 450bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 451bb7ab95cSCédric Le Goater { 45264d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 453e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 454e7a3fee3SCédric Le Goater .fdt = fdt, 455bb7ab95cSCédric Le Goater .offset = isa_offset, 456e7a3fee3SCédric Le Goater }; 457f47a08d1SCédric Le Goater uint32_t phandle; 458e7a3fee3SCédric Le Goater 459bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 460bb7ab95cSCédric Le Goater 461f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 462f47a08d1SCédric Le Goater assert(phandle > 0); 463f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 464f47a08d1SCédric Le Goater 46559b7c1c2SBalamuruhan S /* 46659b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 46759b7c1c2SBalamuruhan S * can not use object_child_foreach() 46859b7c1c2SBalamuruhan S */ 469bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 470bb7ab95cSCédric Le Goater &args); 471e7a3fee3SCédric Le Goater } 472e7a3fee3SCédric Le Goater 473e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt) 474e5694793SCédric Le Goater { 475e5694793SCédric Le Goater int off; 476e5694793SCédric Le Goater 477e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 478e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 479e5694793SCédric Le Goater 480e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 481e5694793SCédric Le Goater } 482e5694793SCédric Le Goater 483b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4849e933f4aSBenjamin Herrenschmidt { 48583b90bf0SCédric Le Goater const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 48683b90bf0SCédric Le Goater const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; 4872b548a42SCédric Le Goater const char plat_compat10[] = "qemu,powernv10\0ibm,powernv"; 488b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 4899e933f4aSBenjamin Herrenschmidt void *fdt; 4909e933f4aSBenjamin Herrenschmidt char *buf; 4919e933f4aSBenjamin Herrenschmidt int off; 492e997040eSCédric Le Goater int i; 4939e933f4aSBenjamin Herrenschmidt 4949e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 4959e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 4969e933f4aSBenjamin Herrenschmidt 497ccb099b3SCédric Le Goater /* /qemu node */ 498ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 499ccb099b3SCédric Le Goater 5009e933f4aSBenjamin Herrenschmidt /* Root node */ 5019e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5029e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5039e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5049e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 5052b548a42SCédric Le Goater if (pnv_is_power10(pnv)) { 5062b548a42SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat10, 5072b548a42SCédric Le Goater sizeof(plat_compat10)))); 5082b548a42SCédric Le Goater } else if (pnv_is_power9(pnv)) { 50983b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, 51083b90bf0SCédric Le Goater sizeof(plat_compat9)))); 51183b90bf0SCédric Le Goater } else { 51283b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8, 51383b90bf0SCédric Le Goater sizeof(plat_compat8)))); 51483b90bf0SCédric Le Goater } 51583b90bf0SCédric Le Goater 5169e933f4aSBenjamin Herrenschmidt 5179e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5189e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5199e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 5209e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5219e933f4aSBenjamin Herrenschmidt } 5229e933f4aSBenjamin Herrenschmidt g_free(buf); 5239e933f4aSBenjamin Herrenschmidt 5249e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5259e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5269e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5279e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5289e933f4aSBenjamin Herrenschmidt } 5299e933f4aSBenjamin Herrenschmidt 5309e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5319e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5329e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5339e933f4aSBenjamin Herrenschmidt 5349e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5359e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5369e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5379e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5389e933f4aSBenjamin Herrenschmidt } 5399e933f4aSBenjamin Herrenschmidt 540e997040eSCédric Le Goater /* Populate device tree for each chip */ 541e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 542eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 543e997040eSCédric Le Goater } 544e7a3fee3SCédric Le Goater 545e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 546bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 547aeaef83dSCédric Le Goater 548aeaef83dSCédric Le Goater if (pnv->bmc) { 549b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 550aeaef83dSCédric Le Goater } 551aeaef83dSCédric Le Goater 5522b548a42SCédric Le Goater /* Create an extra node for power management on Power9 and Power10 */ 5532b548a42SCédric Le Goater if (pnv_is_power9(pnv) || pnv_is_power10(pnv)) { 554e5694793SCédric Le Goater pnv_dt_power_mgt(fdt); 555e5694793SCédric Le Goater } 556e5694793SCédric Le Goater 5579e933f4aSBenjamin Herrenschmidt return fdt; 5589e933f4aSBenjamin Herrenschmidt } 5599e933f4aSBenjamin Herrenschmidt 560bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 561bce0b691SCédric Le Goater { 562b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 563bce0b691SCédric Le Goater 564bce0b691SCédric Le Goater if (pnv->bmc) { 565bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 566bce0b691SCédric Le Goater } 567bce0b691SCédric Le Goater } 568bce0b691SCédric Le Goater 569a0628599SLike Xu static void pnv_reset(MachineState *machine) 5709e933f4aSBenjamin Herrenschmidt { 5719e933f4aSBenjamin Herrenschmidt void *fdt; 5729e933f4aSBenjamin Herrenschmidt 5739e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5749e933f4aSBenjamin Herrenschmidt 575b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5769e933f4aSBenjamin Herrenschmidt 5779e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5789e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5799e933f4aSBenjamin Herrenschmidt 5808d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 5819e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5829e933f4aSBenjamin Herrenschmidt } 5839e933f4aSBenjamin Herrenschmidt 58404026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5853495b6b6SCédric Le Goater { 58677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58777864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 58804026890SCédric Le Goater } 5893495b6b6SCédric Le Goater 59004026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 59104026890SCédric Le Goater { 59277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 59377864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 59404026890SCédric Le Goater } 5953495b6b6SCédric Le Goater 59604026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 59704026890SCédric Le Goater { 59815376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 59915376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 60004026890SCédric Le Goater } 6013495b6b6SCédric Le Goater 6022b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6032b548a42SCédric Le Goater { 6042b548a42SCédric Le Goater error_setg(errp, "No ISA bus!"); 6052b548a42SCédric Le Goater return NULL; 6062b548a42SCédric Le Goater } 6072b548a42SCédric Le Goater 60804026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 60904026890SCédric Le Goater { 61004026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6113495b6b6SCédric Le Goater } 6123495b6b6SCédric Le Goater 613d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 614d8e4aad5SCédric Le Goater { 615d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 616d8e4aad5SCédric Le Goater 617d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 618d8e4aad5SCédric Le Goater } 619d8e4aad5SCédric Le Goater 620d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 621d8e4aad5SCédric Le Goater { 622d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 623d8e4aad5SCédric Le Goater 624d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 625c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 626d8e4aad5SCédric Le Goater } 627d8e4aad5SCédric Le Goater 628f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 629f30c843cSCédric Le Goater { 630f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 631f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 632f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 633f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 634f30c843cSCédric Le Goater 635f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 636f30c843cSCédric Le Goater } 637f30c843cSCédric Le Goater 638e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 639e2392d43SCédric Le Goater { 640e2392d43SCédric Le Goater Object *obj; 641e2392d43SCédric Le Goater 642e2392d43SCédric Le Goater obj = OBJECT(isa_create(bus, "isa-ipmi-bt")); 643e2392d43SCédric Le Goater object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal); 644e2392d43SCédric Le Goater object_property_set_int(obj, irq, "irq", &error_fatal); 645e2392d43SCédric Le Goater object_property_set_bool(obj, true, "realized", &error_fatal); 646e2392d43SCédric Le Goater } 647e2392d43SCédric Le Goater 6482b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 6492b548a42SCédric Le Goater { 650*8b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 651*8b50ce85SCédric Le Goater 652*8b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 6532b548a42SCédric Le Goater } 6542b548a42SCédric Le Goater 655b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 6569e933f4aSBenjamin Herrenschmidt { 657b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 658f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 6599e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 6609e933f4aSBenjamin Herrenschmidt char *fw_filename; 6619e933f4aSBenjamin Herrenschmidt long fw_size; 662e997040eSCédric Le Goater int i; 663e997040eSCédric Le Goater char *chip_typename; 66435dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 66535dde576SCédric Le Goater DeviceState *dev; 6669e933f4aSBenjamin Herrenschmidt 6679e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 668d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 6693dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 6709e933f4aSBenjamin Herrenschmidt } 6719e933f4aSBenjamin Herrenschmidt 6729e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 673b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6749e933f4aSBenjamin Herrenschmidt machine->ram_size); 6759e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6769e933f4aSBenjamin Herrenschmidt 67735dde576SCédric Le Goater /* 67835dde576SCédric Le Goater * Create our simple PNOR device 67935dde576SCédric Le Goater */ 68035dde576SCédric Le Goater dev = qdev_create(NULL, TYPE_PNV_PNOR); 68135dde576SCédric Le Goater if (pnor) { 68235dde576SCédric Le Goater qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor), 68335dde576SCédric Le Goater &error_abort); 68435dde576SCédric Le Goater } 68535dde576SCédric Le Goater qdev_init_nofail(dev); 68635dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 68735dde576SCédric Le Goater 6889e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 6899e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 6909e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 6919e933f4aSBenjamin Herrenschmidt } 6929e933f4aSBenjamin Herrenschmidt 6939e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 69415fcedb2SCédric Le Goater if (!fw_filename) { 69515fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 69615fcedb2SCédric Le Goater exit(1); 69715fcedb2SCédric Le Goater } 6989e933f4aSBenjamin Herrenschmidt 6999e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 7009e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 70115fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 7029e933f4aSBenjamin Herrenschmidt exit(1); 7039e933f4aSBenjamin Herrenschmidt } 7049e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 7059e933f4aSBenjamin Herrenschmidt 7069e933f4aSBenjamin Herrenschmidt /* load kernel */ 7079e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 7089e933f4aSBenjamin Herrenschmidt long kernel_size; 7099e933f4aSBenjamin Herrenschmidt 7109e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 711b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 7129e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 713802fc7abSThomas Huth error_report("Could not load kernel '%s'", 7149e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 7159e933f4aSBenjamin Herrenschmidt exit(1); 7169e933f4aSBenjamin Herrenschmidt } 7179e933f4aSBenjamin Herrenschmidt } 7189e933f4aSBenjamin Herrenschmidt 7199e933f4aSBenjamin Herrenschmidt /* load initrd */ 7209e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 7219e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 7229e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 723584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 7249e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 725802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 7269e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 7279e933f4aSBenjamin Herrenschmidt exit(1); 7289e933f4aSBenjamin Herrenschmidt } 7299e933f4aSBenjamin Herrenschmidt } 730e997040eSCédric Le Goater 731f30c843cSCédric Le Goater /* 732f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 733f30c843cSCédric Le Goater * default. 734f30c843cSCédric Le Goater */ 735f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 736f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 737f30c843cSCédric Le Goater machine->cpu_type, mc->name); 738f30c843cSCédric Le Goater exit(1); 739f30c843cSCédric Le Goater } 740f30c843cSCédric Le Goater 741e997040eSCédric Le Goater /* Create the processor chips */ 7424a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7437fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 7444a12c699SIgor Mammedov i, machine->cpu_type); 745e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 746f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 747f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 748e997040eSCédric Le Goater exit(1); 749e997040eSCédric Le Goater } 750e997040eSCédric Le Goater 751e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 752e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 753e997040eSCédric Le Goater char chip_name[32]; 754e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 755e997040eSCédric Le Goater 756e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 757e997040eSCédric Le Goater 75859b7c1c2SBalamuruhan S /* 75959b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 760e997040eSCédric Le Goater * way to specify different ranges for each chip 761e997040eSCédric Le Goater */ 762e997040eSCédric Le Goater if (i == 0) { 763e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 764e997040eSCédric Le Goater &error_fatal); 765e997040eSCédric Le Goater } 766e997040eSCédric Le Goater 767e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 768e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 769e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 770e997040eSCédric Le Goater &error_fatal); 771fe6b6346SLike Xu object_property_set_int(chip, machine->smp.cores, 772fe6b6346SLike Xu "nr-cores", &error_fatal); 773e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 774e997040eSCédric Le Goater } 775e997040eSCédric Le Goater g_free(chip_typename); 7763495b6b6SCédric Le Goater 777e2392d43SCédric Le Goater /* Create the machine BMC simulator */ 778e2392d43SCédric Le Goater pnv->bmc = pnv_bmc_create(); 779e2392d43SCédric Le Goater 7803495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 78104026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 7823495b6b6SCédric Le Goater 7833495b6b6SCédric Le Goater /* Create serial port */ 784def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 7853495b6b6SCédric Le Goater 7863495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 7876c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 788bce0b691SCédric Le Goater 789e2392d43SCédric Le Goater /* Create the IPMI BT device for communication with the BMC */ 790e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 791e2392d43SCédric Le Goater 79259b7c1c2SBalamuruhan S /* 79359b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 79459b7c1c2SBalamuruhan S * host to powerdown 79559b7c1c2SBalamuruhan S */ 796bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 797bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 798e997040eSCédric Le Goater } 799e997040eSCédric Le Goater 800631adaffSCédric Le Goater /* 801631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 802631adaffSCédric Le Goater * 22:24 Chip ID 803631adaffSCédric Le Goater * 25:28 Core number 804631adaffSCédric Le Goater * 29:31 Thread ID 805631adaffSCédric Le Goater */ 806631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 807631adaffSCédric Le Goater { 808631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 809631adaffSCédric Le Goater } 810631adaffSCédric Le Goater 8118fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 812d35aefa9SCédric Le Goater Error **errp) 813d35aefa9SCédric Le Goater { 8148fa1f4efSCédric Le Goater Error *local_err = NULL; 8158fa1f4efSCédric Le Goater Object *obj; 8168907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8178fa1f4efSCédric Le Goater 8188fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 8198fa1f4efSCédric Le Goater &local_err); 8208fa1f4efSCédric Le Goater if (local_err) { 8218fa1f4efSCédric Le Goater error_propagate(errp, local_err); 8228fa1f4efSCédric Le Goater return; 8238fa1f4efSCédric Le Goater } 8248fa1f4efSCédric Le Goater 825956b8f46SCédric Le Goater pnv_cpu->intc = obj; 826d35aefa9SCédric Le Goater } 827d35aefa9SCédric Le Goater 8280990ce6aSGreg Kurz 829d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 830d49e8a9bSCédric Le Goater { 831d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 832d49e8a9bSCédric Le Goater 833d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 834d49e8a9bSCédric Le Goater } 835d49e8a9bSCédric Le Goater 8360990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 8370990ce6aSGreg Kurz { 8380990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8390990ce6aSGreg Kurz 8400990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 8410990ce6aSGreg Kurz pnv_cpu->intc = NULL; 8420990ce6aSGreg Kurz } 8430990ce6aSGreg Kurz 844631adaffSCédric Le Goater /* 845631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 846631adaffSCédric Le Goater * 49:52 Node ID 847631adaffSCédric Le Goater * 53:55 Chip ID 848631adaffSCédric Le Goater * 56 Reserved - Read as zero 849631adaffSCédric Le Goater * 57:61 Core number 850631adaffSCédric Le Goater * 62:63 Thread ID 851631adaffSCédric Le Goater * 852631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 853631adaffSCédric Le Goater */ 854631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 855631adaffSCédric Le Goater { 856631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 857631adaffSCédric Le Goater } 858631adaffSCédric Le Goater 8592b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 8602b548a42SCédric Le Goater { 8612b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 8622b548a42SCédric Le Goater } 8632b548a42SCédric Le Goater 8648fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 865d35aefa9SCédric Le Goater Error **errp) 866d35aefa9SCédric Le Goater { 8672dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 8682dfa91a2SCédric Le Goater Error *local_err = NULL; 8692dfa91a2SCédric Le Goater Object *obj; 8702dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8712dfa91a2SCédric Le Goater 8722dfa91a2SCédric Le Goater /* 8732dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 8742dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 8752dfa91a2SCédric Le Goater * only used at runtime. 8762dfa91a2SCédric Le Goater */ 87726aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 8782dfa91a2SCédric Le Goater if (local_err) { 8792dfa91a2SCédric Le Goater error_propagate(errp, local_err); 8808fa1f4efSCédric Le Goater return; 881d35aefa9SCédric Le Goater } 882d35aefa9SCédric Le Goater 8832dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 8842dfa91a2SCédric Le Goater } 8852dfa91a2SCédric Le Goater 886d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 887d49e8a9bSCédric Le Goater { 888d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 889d49e8a9bSCédric Le Goater 890d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 891d49e8a9bSCédric Le Goater } 892d49e8a9bSCédric Le Goater 8930990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 8940990ce6aSGreg Kurz { 8950990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8960990ce6aSGreg Kurz 8970990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 8980990ce6aSGreg Kurz pnv_cpu->intc = NULL; 8990990ce6aSGreg Kurz } 9000990ce6aSGreg Kurz 9012b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 9022b548a42SCédric Le Goater Error **errp) 9032b548a42SCédric Le Goater { 9042b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9052b548a42SCédric Le Goater 9062b548a42SCédric Le Goater /* Will be defined when the interrupt controller is */ 9072b548a42SCédric Le Goater pnv_cpu->intc = NULL; 9082b548a42SCédric Le Goater } 9092b548a42SCédric Le Goater 9102b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 9112b548a42SCédric Le Goater { 9122b548a42SCédric Le Goater ; 9132b548a42SCédric Le Goater } 9142b548a42SCédric Le Goater 9152b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9162b548a42SCédric Le Goater { 9172b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9182b548a42SCédric Le Goater 9192b548a42SCédric Le Goater pnv_cpu->intc = NULL; 9202b548a42SCédric Le Goater } 9212b548a42SCédric Le Goater 92259b7c1c2SBalamuruhan S /* 92359b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 924397a79e7SCédric Le Goater * 925397a79e7SCédric Le Goater * <EX0 reserved> 926397a79e7SCédric Le Goater * EX1 - Venice only 927397a79e7SCédric Le Goater * EX2 - Venice only 928397a79e7SCédric Le Goater * EX3 - Venice only 929397a79e7SCédric Le Goater * EX4 930397a79e7SCédric Le Goater * EX5 931397a79e7SCédric Le Goater * EX6 932397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 933397a79e7SCédric Le Goater * EX9 - Venice only 934397a79e7SCédric Le Goater * EX10 - Venice only 935397a79e7SCédric Le Goater * EX11 - Venice only 936397a79e7SCédric Le Goater * EX12 937397a79e7SCédric Le Goater * EX13 938397a79e7SCédric Le Goater * EX14 939397a79e7SCédric Le Goater * <EX15 reserved> 940397a79e7SCédric Le Goater */ 941397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 942397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 943397a79e7SCédric Le Goater 944397a79e7SCédric Le Goater /* 94509279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 946397a79e7SCédric Le Goater */ 94709279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 948397a79e7SCédric Le Goater 9492b548a42SCédric Le Goater 9502b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 9512b548a42SCédric Le Goater 95277864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 95377864267SCédric Le Goater { 95477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 95577864267SCédric Le Goater 956f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 957ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 95877864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 95977864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 96077864267SCédric Le Goater 961f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 96282514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 96377864267SCédric Le Goater 964f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 9653233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 9663887d241SBalamuruhan S 9673887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), 9683887d241SBalamuruhan S TYPE_PNV8_HOMER, &error_abort, NULL); 96977864267SCédric Le Goater } 97077864267SCédric Le Goater 97177864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 97277864267SCédric Le Goater { 97377864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 97477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 97577864267SCédric Le Goater int i, j; 97677864267SCédric Le Goater char *name; 97777864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 97877864267SCédric Le Goater 97977864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 98077864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 98177864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 98277864267SCédric Le Goater g_free(name); 98377864267SCédric Le Goater 98477864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 98577864267SCédric Le Goater 98677864267SCédric Le Goater /* Map the ICP registers for each thread */ 98777864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 9884fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 98977864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 99077864267SCédric Le Goater 99177864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 99277864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 99377864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 99477864267SCédric Le Goater 99577864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 99677864267SCédric Le Goater &icp->mmio); 99777864267SCédric Le Goater } 99877864267SCédric Le Goater } 99977864267SCédric Le Goater } 100077864267SCédric Le Goater 100177864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 100277864267SCédric Le Goater { 100377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 100477864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 100577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1006ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 100777864267SCédric Le Goater Error *local_err = NULL; 100877864267SCédric Le Goater 1009709044fdSCédric Le Goater /* XSCOM bridge is first */ 1010709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1011709044fdSCédric Le Goater if (local_err) { 1012709044fdSCédric Le Goater error_propagate(errp, local_err); 1013709044fdSCédric Le Goater return; 1014709044fdSCédric Le Goater } 1015709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1016709044fdSCédric Le Goater 101777864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 101877864267SCédric Le Goater if (local_err) { 101977864267SCédric Le Goater error_propagate(errp, local_err); 102077864267SCédric Le Goater return; 102177864267SCédric Le Goater } 102277864267SCédric Le Goater 102377864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 102477864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 102577864267SCédric Le Goater "bar", &error_fatal); 102677864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 102777864267SCédric Le Goater if (local_err) { 102877864267SCédric Le Goater error_propagate(errp, local_err); 102977864267SCédric Le Goater return; 103077864267SCédric Le Goater } 1031ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1032ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 103377864267SCédric Le Goater 103477864267SCédric Le Goater /* Create LPC controller */ 1035b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi", 1036b63f3893SGreg Kurz &error_abort); 103777864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 103877864267SCédric Le Goater &error_fatal); 103977864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 104077864267SCédric Le Goater 104164d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 104264d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 104364d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 104464d011d5SCédric Le Goater 104559b7c1c2SBalamuruhan S /* 104659b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 104759b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 104859b7c1c2SBalamuruhan S */ 104977864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 105077864267SCédric Le Goater if (local_err) { 105177864267SCédric Le Goater error_propagate(errp, local_err); 105277864267SCédric Le Goater return; 105377864267SCédric Le Goater } 105477864267SCédric Le Goater 105577864267SCédric Le Goater /* Create the simplified OCC model */ 1056ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi", 1057ee3d2713SGreg Kurz &error_abort); 105877864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 105977864267SCédric Le Goater if (local_err) { 106077864267SCédric Le Goater error_propagate(errp, local_err); 106177864267SCédric Le Goater return; 106277864267SCédric Le Goater } 106377864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1064f3db8266SBalamuruhan S 1065f3db8266SBalamuruhan S /* OCC SRAM model */ 1066f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip), 1067f3db8266SBalamuruhan S &chip8->occ.sram_regs); 10683887d241SBalamuruhan S 10693887d241SBalamuruhan S /* HOMER */ 1070f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip", 1071f2582acfSGreg Kurz &error_abort); 10723887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip8->homer), true, "realized", 10733887d241SBalamuruhan S &local_err); 10743887d241SBalamuruhan S if (local_err) { 10753887d241SBalamuruhan S error_propagate(errp, local_err); 10763887d241SBalamuruhan S return; 10773887d241SBalamuruhan S } 10783887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 10793887d241SBalamuruhan S &chip8->homer.regs); 108077864267SCédric Le Goater } 108177864267SCédric Le Goater 1082e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1083e997040eSCédric Le Goater { 1084e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1085e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1086e997040eSCédric Le Goater 1087e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 1088e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1089397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 1090631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1091d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1092d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 10930990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 109404026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1095eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1096d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1097e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 109877864267SCédric Le Goater 109977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 110077864267SCédric Le Goater &k->parent_realize); 1101e997040eSCédric Le Goater } 1102e997040eSCédric Le Goater 1103e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1104e997040eSCédric Le Goater { 1105e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1106e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1107e997040eSCédric Le Goater 1108e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 1109e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1110397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1111631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1112d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1113d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11140990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 111504026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1116eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1117d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1118e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 111977864267SCédric Le Goater 112077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 112177864267SCédric Le Goater &k->parent_realize); 1122e997040eSCédric Le Goater } 1123e997040eSCédric Le Goater 1124e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1125e997040eSCédric Le Goater { 1126e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1127e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1128e997040eSCédric Le Goater 1129e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 1130e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1131397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1132631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1133d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1134d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11350990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 113604026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1137eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1138d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1139e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 114077864267SCédric Le Goater 114177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 114277864267SCédric Le Goater &k->parent_realize); 114377864267SCédric Le Goater } 114477864267SCédric Le Goater 114577864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 114677864267SCédric Le Goater { 11472dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 11482dfa91a2SCédric Le Goater 11492dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 11502dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 1151c38536bcSCédric Le Goater 1152c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1153c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 115415376c66SCédric Le Goater 115515376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 115615376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 11576598a70dSCédric Le Goater 11586598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 11596598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 11603887d241SBalamuruhan S 11613887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 11623887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 116377864267SCédric Le Goater } 116477864267SCédric Le Goater 11655dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 11665dad902cSCédric Le Goater { 11675dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 11685dad902cSCédric Le Goater int i; 11695dad902cSCédric Le Goater 11705dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 11715dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 11725dad902cSCédric Le Goater 11735dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 11745dad902cSCédric Le Goater char eq_name[32]; 11755dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 11764fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 11775dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 11785dad902cSCédric Le Goater 11795dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1180bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1181bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 11825dad902cSCédric Le Goater 11835dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 11845dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 11855dad902cSCédric Le Goater 11865dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 11875dad902cSCédric Le Goater &eq->xscom_regs); 11885dad902cSCédric Le Goater } 11895dad902cSCédric Le Goater } 11905dad902cSCédric Le Goater 119177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 119277864267SCédric Le Goater { 119377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 11942dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 11952dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1196c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 119777864267SCédric Le Goater Error *local_err = NULL; 119877864267SCédric Le Goater 1199709044fdSCédric Le Goater /* XSCOM bridge is first */ 1200709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1201709044fdSCédric Le Goater if (local_err) { 1202709044fdSCédric Le Goater error_propagate(errp, local_err); 1203709044fdSCédric Le Goater return; 1204709044fdSCédric Le Goater } 1205709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1206709044fdSCédric Le Goater 120777864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 120877864267SCédric Le Goater if (local_err) { 120977864267SCédric Le Goater error_propagate(errp, local_err); 121077864267SCédric Le Goater return; 121177864267SCédric Le Goater } 12122dfa91a2SCédric Le Goater 12135dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 12145dad902cSCédric Le Goater if (local_err) { 12155dad902cSCédric Le Goater error_propagate(errp, local_err); 12165dad902cSCédric Le Goater return; 12175dad902cSCédric Le Goater } 12185dad902cSCédric Le Goater 12192dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 12202dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 12212dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 12222dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 12232dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 12242dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 12252dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 12262dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 12272dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 12287ae54cc3SGreg Kurz object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", 12297ae54cc3SGreg Kurz &error_abort); 12302dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 12312dfa91a2SCédric Le Goater &local_err); 12322dfa91a2SCédric Le Goater if (local_err) { 12332dfa91a2SCédric Le Goater error_propagate(errp, local_err); 12342dfa91a2SCédric Le Goater return; 12352dfa91a2SCédric Le Goater } 12362dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 12372dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1238c38536bcSCédric Le Goater 1239c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1240c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1241c38536bcSCédric Le Goater "bar", &error_fatal); 1242c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1243c38536bcSCédric Le Goater if (local_err) { 1244c38536bcSCédric Le Goater error_propagate(errp, local_err); 1245c38536bcSCédric Le Goater return; 1246c38536bcSCédric Le Goater } 1247c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1248c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 124915376c66SCédric Le Goater 125015376c66SCédric Le Goater /* LPC */ 1251b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", 1252b63f3893SGreg Kurz &error_abort); 125315376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 125415376c66SCédric Le Goater if (local_err) { 125515376c66SCédric Le Goater error_propagate(errp, local_err); 125615376c66SCédric Le Goater return; 125715376c66SCédric Le Goater } 125815376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 125915376c66SCédric Le Goater &chip9->lpc.xscom_regs); 126015376c66SCédric Le Goater 126115376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 126215376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 12636598a70dSCédric Le Goater 12646598a70dSCédric Le Goater /* Create the simplified OCC model */ 1265ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", 1266ee3d2713SGreg Kurz &error_abort); 12676598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 12686598a70dSCédric Le Goater if (local_err) { 12696598a70dSCédric Le Goater error_propagate(errp, local_err); 12706598a70dSCédric Le Goater return; 12716598a70dSCédric Le Goater } 12726598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1273f3db8266SBalamuruhan S 1274f3db8266SBalamuruhan S /* OCC SRAM model */ 1275f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip), 1276f3db8266SBalamuruhan S &chip9->occ.sram_regs); 12773887d241SBalamuruhan S 12783887d241SBalamuruhan S /* HOMER */ 1279f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", 1280f2582acfSGreg Kurz &error_abort); 12813887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 12823887d241SBalamuruhan S &local_err); 12833887d241SBalamuruhan S if (local_err) { 12843887d241SBalamuruhan S error_propagate(errp, local_err); 12853887d241SBalamuruhan S return; 12863887d241SBalamuruhan S } 12873887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 12883887d241SBalamuruhan S &chip9->homer.regs); 1289e997040eSCédric Le Goater } 1290e997040eSCédric Le Goater 1291e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1292e997040eSCédric Le Goater { 1293e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1294e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1295e997040eSCédric Le Goater 1296e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 129783028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1298397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1299631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1300d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1301d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 13020990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 130304026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1304eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1305d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1306e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 130777864267SCédric Le Goater 130877864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 130977864267SCédric Le Goater &k->parent_realize); 1310e997040eSCédric Le Goater } 1311e997040eSCédric Le Goater 13122b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 13132b548a42SCédric Le Goater { 1314*8b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 1315*8b50ce85SCédric Le Goater 1316*8b50ce85SCédric Le Goater object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), 1317*8b50ce85SCédric Le Goater TYPE_PNV10_PSI, &error_abort, NULL); 13182b548a42SCédric Le Goater } 13192b548a42SCédric Le Goater 13202b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 13212b548a42SCédric Le Goater { 13222b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 13232b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1324*8b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 13252b548a42SCédric Le Goater Error *local_err = NULL; 13262b548a42SCédric Le Goater 13272b548a42SCédric Le Goater /* XSCOM bridge is first */ 13282b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 13292b548a42SCédric Le Goater if (local_err) { 13302b548a42SCédric Le Goater error_propagate(errp, local_err); 13312b548a42SCédric Le Goater return; 13322b548a42SCédric Le Goater } 13332b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 13342b548a42SCédric Le Goater 13352b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 13362b548a42SCédric Le Goater if (local_err) { 13372b548a42SCédric Le Goater error_propagate(errp, local_err); 13382b548a42SCédric Le Goater return; 13392b548a42SCédric Le Goater } 1340*8b50ce85SCédric Le Goater 1341*8b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1342*8b50ce85SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), 1343*8b50ce85SCédric Le Goater "bar", &error_fatal); 1344*8b50ce85SCédric Le Goater object_property_set_bool(OBJECT(&chip10->psi), true, "realized", 1345*8b50ce85SCédric Le Goater &local_err); 1346*8b50ce85SCédric Le Goater if (local_err) { 1347*8b50ce85SCédric Le Goater error_propagate(errp, local_err); 1348*8b50ce85SCédric Le Goater return; 1349*8b50ce85SCédric Le Goater } 1350*8b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 1351*8b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 13522b548a42SCédric Le Goater } 13532b548a42SCédric Le Goater 13542b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 13552b548a42SCédric Le Goater { 13562b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 13572b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 13582b548a42SCédric Le Goater 13592b548a42SCédric Le Goater k->chip_type = PNV_CHIP_POWER10; 13602b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 13612b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 13622b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 13632b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 13642b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 13652b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 13662b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 13672b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 13682b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 13692b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 13702b548a42SCédric Le Goater 13712b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 13722b548a42SCédric Le Goater &k->parent_realize); 13732b548a42SCédric Le Goater } 13742b548a42SCédric Le Goater 1375397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1376397a79e7SCédric Le Goater { 1377397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1378397a79e7SCédric Le Goater int cores_max; 1379397a79e7SCédric Le Goater 1380397a79e7SCédric Le Goater /* 1381397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1382397a79e7SCédric Le Goater * the chip class 1383397a79e7SCédric Le Goater */ 1384397a79e7SCédric Le Goater if (!chip->cores_mask) { 1385397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1386397a79e7SCédric Le Goater } 1387397a79e7SCédric Le Goater 1388397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1389397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1390397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1391397a79e7SCédric Le Goater chip->cores_mask); 1392397a79e7SCédric Le Goater return; 1393397a79e7SCédric Le Goater } 1394397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1395397a79e7SCédric Le Goater 1396397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 139727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1398397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1399397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1400397a79e7SCédric Le Goater cores_max); 1401397a79e7SCédric Le Goater return; 1402397a79e7SCédric Le Goater } 1403397a79e7SCédric Le Goater } 1404397a79e7SCédric Le Goater 140551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1406e997040eSCédric Le Goater { 1407fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1408397a79e7SCédric Le Goater Error *error = NULL; 1409d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 141040abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1411d2fd9612SCédric Le Goater int i, core_hwid; 1412397a79e7SCédric Le Goater 1413d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1414d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1415d2fd9612SCédric Le Goater return; 1416d2fd9612SCédric Le Goater } 1417d2fd9612SCédric Le Goater 1418d2fd9612SCédric Le Goater /* Cores */ 1419397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1420397a79e7SCédric Le Goater if (error) { 1421397a79e7SCédric Le Goater error_propagate(errp, error); 1422397a79e7SCédric Le Goater return; 1423397a79e7SCédric Le Goater } 1424d2fd9612SCédric Le Goater 14254fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1426d2fd9612SCédric Le Goater 1427d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1428d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1429d2fd9612SCédric Le Goater char core_name[32]; 14304fa28f23SGreg Kurz PnvCore *pnv_core; 1431c035851aSCédric Le Goater uint64_t xscom_core_base; 1432d2fd9612SCédric Le Goater 1433d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1434d2fd9612SCédric Le Goater continue; 1435d2fd9612SCédric Le Goater } 1436d2fd9612SCédric Le Goater 14374fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 14384fa28f23SGreg Kurz 1439d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 14404fa28f23SGreg Kurz object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), 14414fa28f23SGreg Kurz &error_abort); 14424fa28f23SGreg Kurz chip->cores[i] = pnv_core; 1443fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1444d2fd9612SCédric Le Goater &error_fatal); 1445d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1446d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1447d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1448d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1449d2fd9612SCédric Le Goater "pir", &error_fatal); 1450158e17a6SGreg Kurz object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", 1451158e17a6SGreg Kurz &error_abort); 1452d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1453d2fd9612SCédric Le Goater &error_fatal); 145424ece072SCédric Le Goater 145524ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 14562b548a42SCédric Le Goater if (pnv_chip_is_power10(chip)) { 14572b548a42SCédric Le Goater xscom_core_base = PNV10_XSCOM_EC_BASE(core_hwid); 14582b548a42SCédric Le Goater } else if (pnv_chip_is_power9(chip)) { 14595dad902cSCédric Le Goater xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); 14602b548a42SCédric Le Goater } else { 14612b548a42SCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1462c035851aSCédric Le Goater } 1463c035851aSCédric Le Goater 1464c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 14654fa28f23SGreg Kurz &pnv_core->xscom_regs); 1466d2fd9612SCédric Le Goater i++; 1467d2fd9612SCédric Le Goater } 146851c04728SCédric Le Goater } 146951c04728SCédric Le Goater 147051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 147151c04728SCédric Le Goater { 147251c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 147351c04728SCédric Le Goater Error *error = NULL; 147451c04728SCédric Le Goater 147551c04728SCédric Le Goater /* Cores */ 147651c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 147751c04728SCédric Le Goater if (error) { 147851c04728SCédric Le Goater error_propagate(errp, error); 147951c04728SCédric Le Goater return; 148051c04728SCédric Le Goater } 1481e997040eSCédric Le Goater } 1482e997040eSCédric Le Goater 1483e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1484e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1485e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1486e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1487397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1488397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1489e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1490e997040eSCédric Le Goater }; 1491e997040eSCédric Le Goater 1492e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1493e997040eSCédric Le Goater { 1494e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1495e997040eSCédric Le Goater 14969d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1497e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1498e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1499e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1500e997040eSCédric Le Goater } 1501e997040eSCédric Le Goater 1502119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1503119eaa9dSCédric Le Goater { 1504119eaa9dSCédric Le Goater int i, j; 1505119eaa9dSCédric Le Goater 1506119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1507119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1508119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1509119eaa9dSCédric Le Goater 1510119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1511119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1512119eaa9dSCédric Le Goater return pc->threads[j]; 1513119eaa9dSCédric Le Goater } 1514119eaa9dSCédric Le Goater } 1515119eaa9dSCédric Le Goater } 1516119eaa9dSCédric Le Goater return NULL; 1517119eaa9dSCédric Le Goater } 1518119eaa9dSCédric Le Goater 151954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 152054f59d78SCédric Le Goater { 1521b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 152254f59d78SCédric Le Goater int i; 152354f59d78SCédric Le Goater 152454f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 152577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 152677864267SCédric Le Goater 152777864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 152877864267SCédric Le Goater return &chip8->psi.ics; 152954f59d78SCédric Le Goater } 153054f59d78SCédric Le Goater } 153154f59d78SCédric Le Goater return NULL; 153254f59d78SCédric Le Goater } 153354f59d78SCédric Le Goater 153454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 153554f59d78SCédric Le Goater { 1536b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 153754f59d78SCédric Le Goater int i; 153854f59d78SCédric Le Goater 153954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 154077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 154177864267SCédric Le Goater ics_resend(&chip8->psi.ics); 154254f59d78SCédric Le Goater } 154354f59d78SCédric Le Goater } 154454f59d78SCédric Le Goater 154536fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 154636fc6f08SCédric Le Goater { 154736fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 154836fc6f08SCédric Le Goater 1549956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 155036fc6f08SCédric Le Goater } 155136fc6f08SCédric Le Goater 155247fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 155347fea43aSCédric Le Goater Monitor *mon) 155447fea43aSCédric Le Goater { 1555b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 155654f59d78SCédric Le Goater int i; 155747fea43aSCédric Le Goater CPUState *cs; 155847fea43aSCédric Le Goater 155947fea43aSCédric Le Goater CPU_FOREACH(cs) { 156047fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 156147fea43aSCédric Le Goater 1562d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1563d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1564d8e4aad5SCédric Le Goater } else { 1565956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 156647fea43aSCédric Le Goater } 1567d8e4aad5SCédric Le Goater } 156854f59d78SCédric Le Goater 156954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1570d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 157154f59d78SCédric Le Goater } 157247fea43aSCédric Le Goater } 157347fea43aSCédric Le Goater 1574c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1575c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1576c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1577c722579eSCédric Le Goater uint32_t logic_serv, 1578c722579eSCédric Le Goater XiveTCTXMatch *match) 1579c722579eSCédric Le Goater { 1580c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1581c722579eSCédric Le Goater int total_count = 0; 1582c722579eSCédric Le Goater int i; 1583c722579eSCédric Le Goater 1584c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1585c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1586c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1587c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1588c722579eSCédric Le Goater int count; 1589c722579eSCédric Le Goater 1590c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1591c722579eSCédric Le Goater priority, logic_serv, match); 1592c722579eSCédric Le Goater 1593c722579eSCédric Le Goater if (count < 0) { 1594c722579eSCédric Le Goater return count; 1595c722579eSCédric Le Goater } 1596c722579eSCédric Le Goater 1597c722579eSCédric Le Goater total_count += count; 1598c722579eSCédric Le Goater } 1599c722579eSCédric Le Goater 1600c722579eSCédric Le Goater return total_count; 1601c722579eSCédric Le Goater } 1602c722579eSCédric Le Goater 16035373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id) 16045373c61dSCédric Le Goater { 16055373c61dSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 16065373c61dSCédric Le Goater int i; 16075373c61dSCédric Le Goater 16085373c61dSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 16095373c61dSCédric Le Goater PnvChip *chip = pnv->chips[i]; 16105373c61dSCédric Le Goater if (chip->chip_id == chip_id) { 16115373c61dSCédric Le Goater return chip; 16125373c61dSCédric Le Goater } 16135373c61dSCédric Le Goater } 16145373c61dSCédric Le Goater return NULL; 16155373c61dSCédric Le Goater } 16165373c61dSCédric Le Goater 1617e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1618e997040eSCédric Le Goater void *opaque, Error **errp) 1619e997040eSCédric Le Goater { 1620b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1621e997040eSCédric Le Goater } 1622e997040eSCédric Le Goater 1623e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1624e997040eSCédric Le Goater void *opaque, Error **errp) 1625e997040eSCédric Le Goater { 1626b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1627e997040eSCédric Le Goater uint32_t num_chips; 1628e997040eSCédric Le Goater Error *local_err = NULL; 1629e997040eSCédric Le Goater 1630e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1631e997040eSCédric Le Goater if (local_err) { 1632e997040eSCédric Le Goater error_propagate(errp, local_err); 1633e997040eSCédric Le Goater return; 1634e997040eSCédric Le Goater } 1635e997040eSCédric Le Goater 1636e997040eSCédric Le Goater /* 1637e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1638e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1639e997040eSCédric Le Goater */ 1640e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1641e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1642e997040eSCédric Le Goater return; 1643e997040eSCédric Le Goater } 1644e997040eSCédric Le Goater 1645e997040eSCédric Le Goater pnv->num_chips = num_chips; 1646e997040eSCédric Le Goater } 1647e997040eSCédric Le Goater 164877864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1649e997040eSCédric Le Goater { 1650b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1651e997040eSCédric Le Goater pnv->num_chips = 1; 1652e997040eSCédric Le Goater } 1653e997040eSCédric Le Goater 1654b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1655e997040eSCédric Le Goater { 16561e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1657e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1658e997040eSCédric Le Goater NULL, NULL, NULL); 1659e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1660e997040eSCédric Le Goater "Specifies the number of processor chips", 1661e997040eSCédric Le Goater NULL); 16629e933f4aSBenjamin Herrenschmidt } 16639e933f4aSBenjamin Herrenschmidt 1664f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 16659e933f4aSBenjamin Herrenschmidt { 16669e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 166736fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1668f30c843cSCédric Le Goater 1669f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1670f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1671f30c843cSCédric Le Goater 1672f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1673f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1674f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1675f30c843cSCédric Le Goater } 1676f30c843cSCédric Le Goater 1677f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1678f30c843cSCédric Le Goater { 1679f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1680c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1681f30c843cSCédric Le Goater 1682f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1683f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1684c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1685f30c843cSCédric Le Goater 1686f30c843cSCédric Le Goater mc->alias = "powernv"; 1687f30c843cSCédric Le Goater } 1688f30c843cSCédric Le Goater 16892b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 16902b548a42SCédric Le Goater { 16912b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 16922b548a42SCédric Le Goater 16932b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 16942b548a42SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); 16952b548a42SCédric Le Goater } 16962b548a42SCédric Le Goater 1697f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1698f30c843cSCédric Le Goater { 1699f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 170047fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 17019e933f4aSBenjamin Herrenschmidt 17029e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1703b168a138SCédric Le Goater mc->init = pnv_init; 1704b168a138SCédric Le Goater mc->reset = pnv_reset; 17059e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 170659b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 170759b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 17089e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 17099e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1710f1d18b0aSJoel Stanley /* 1711f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1712f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1713f1d18b0aSJoel Stanley */ 1714f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 171547fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1716e997040eSCédric Le Goater 1717b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 17189e933f4aSBenjamin Herrenschmidt } 17199e933f4aSBenjamin Herrenschmidt 172077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1721beba5c0fSIgor Mammedov { \ 1722beba5c0fSIgor Mammedov .name = type, \ 1723beba5c0fSIgor Mammedov .class_init = class_initfn, \ 172477864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 172577864267SCédric Le Goater } 172677864267SCédric Le Goater 172777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 172877864267SCédric Le Goater { \ 172977864267SCédric Le Goater .name = type, \ 173077864267SCédric Le Goater .class_init = class_initfn, \ 173177864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1732beba5c0fSIgor Mammedov } 1733beba5c0fSIgor Mammedov 17342b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 17352b548a42SCédric Le Goater { \ 17362b548a42SCédric Le Goater .name = type, \ 17372b548a42SCédric Le Goater .class_init = class_initfn, \ 17382b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 17392b548a42SCédric Le Goater } 17402b548a42SCédric Le Goater 1741beba5c0fSIgor Mammedov static const TypeInfo types[] = { 17421aba8716SCédric Le Goater { 17432b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 17442b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 17452b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 17462b548a42SCédric Le Goater }, 17472b548a42SCédric Le Goater { 17481aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 17491aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 17501aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 1751c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 1752c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 1753c722579eSCédric Le Goater { }, 1754c722579eSCédric Le Goater }, 17551aba8716SCédric Le Goater }, 17561aba8716SCédric Le Goater { 17571aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 17581aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 17591aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 17601aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 17611aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 17621aba8716SCédric Le Goater { }, 17631aba8716SCédric Le Goater }, 17641aba8716SCédric Le Goater }, 1765beba5c0fSIgor Mammedov { 1766b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 17679e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1768f30c843cSCédric Le Goater .abstract = true, 17699e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 177077864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1771b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 177236fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 177347fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 177436fc6f08SCédric Le Goater { }, 177536fc6f08SCédric Le Goater }, 1776beba5c0fSIgor Mammedov }, 1777beba5c0fSIgor Mammedov { 1778beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1779beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1780beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1781beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1782beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1783beba5c0fSIgor Mammedov .abstract = true, 1784beba5c0fSIgor Mammedov }, 178577864267SCédric Le Goater 178677864267SCédric Le Goater /* 17872b548a42SCédric Le Goater * P10 chip and variants 17882b548a42SCédric Le Goater */ 17892b548a42SCédric Le Goater { 17902b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 17912b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 17922b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 17932b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 17942b548a42SCédric Le Goater }, 17952b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 17962b548a42SCédric Le Goater 17972b548a42SCédric Le Goater /* 179877864267SCédric Le Goater * P9 chip and variants 179977864267SCédric Le Goater */ 180077864267SCédric Le Goater { 180177864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 180277864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 180377864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 180477864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 180577864267SCédric Le Goater }, 180677864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 180777864267SCédric Le Goater 180877864267SCédric Le Goater /* 180977864267SCédric Le Goater * P8 chip and variants 181077864267SCédric Le Goater */ 181177864267SCédric Le Goater { 181277864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 181377864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 181477864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 181577864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 181677864267SCédric Le Goater }, 181777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 181877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 181977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1820beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 18219e933f4aSBenjamin Herrenschmidt }; 18229e933f4aSBenjamin Herrenschmidt 1823beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1824