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" 3001b552b0SNicholas Piggin #include "sysemu/hw_accel.h" 31fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 329e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 36d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 379e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 3801b552b0SNicholas Piggin #include "hw/nmi.h" 399e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 40e997040eSCédric Le Goater #include "qapi/visitor.h" 4147fea43aSCédric Le Goater #include "monitor/monitor.h" 4247fea43aSCédric Le Goater #include "hw/intc/intc.h" 43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h" 469e933f4aSBenjamin Herrenschmidt 4736fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 48a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 49967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 5035dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 51967b7523SCédric Le Goater 523495b6b6SCédric Le Goater #include "hw/isa/isa.h" 5312e9493dSMarkus Armbruster #include "hw/boards.h" 543495b6b6SCédric Le Goater #include "hw/char/serial.h" 55bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 563495b6b6SCédric Le Goater 579e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 589e933f4aSBenjamin Herrenschmidt 59b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 609e933f4aSBenjamin Herrenschmidt 619e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 629e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 63b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 649e933f4aSBenjamin Herrenschmidt 659e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 66b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 67fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 68584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 699e933f4aSBenjamin Herrenschmidt 7040abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 7140abf43fSIgor Mammedov { 7240abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7340abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7440abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7540abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7640abf43fSIgor Mammedov g_free(s); 7740abf43fSIgor Mammedov return core_type; 7840abf43fSIgor Mammedov } 7940abf43fSIgor Mammedov 809e933f4aSBenjamin Herrenschmidt /* 819e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 829e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 839e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 849e933f4aSBenjamin Herrenschmidt */ 859e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 869e933f4aSBenjamin Herrenschmidt 879e933f4aSBenjamin Herrenschmidt /* 889e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 899e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 909e933f4aSBenjamin Herrenschmidt * per chip. 919e933f4aSBenjamin Herrenschmidt */ 92b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 939e933f4aSBenjamin Herrenschmidt { 949e933f4aSBenjamin Herrenschmidt char *mem_name; 959e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 969e933f4aSBenjamin Herrenschmidt int off; 979e933f4aSBenjamin Herrenschmidt 989e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 999e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 1009e933f4aSBenjamin Herrenschmidt 1019e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 1029e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1039e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1049e933f4aSBenjamin Herrenschmidt 1059e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1069e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1079e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1089e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1099e933f4aSBenjamin Herrenschmidt } 1109e933f4aSBenjamin Herrenschmidt 111d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 112d2fd9612SCédric Le Goater { 113d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 114d2fd9612SCédric Le Goater 115d2fd9612SCédric Le Goater if (cpus_offset < 0) { 116a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 117d2fd9612SCédric Le Goater if (cpus_offset) { 118d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 119d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 120d2fd9612SCédric Le Goater } 121d2fd9612SCédric Le Goater } 122d2fd9612SCédric Le Goater _FDT(cpus_offset); 123d2fd9612SCédric Le Goater return cpus_offset; 124d2fd9612SCédric Le Goater } 125d2fd9612SCédric Le Goater 126d2fd9612SCédric Le Goater /* 127d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 128d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 129d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 130d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 131d2fd9612SCédric Le Goater * servers. 132d2fd9612SCédric Le Goater */ 133b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 134d2fd9612SCédric Le Goater { 13508304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13608304a86SDavid Gibson CPUState *cs = CPU(cpu); 137d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1388bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 139d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 140d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 141d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 142d2fd9612SCédric Le Goater int i; 143d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 144d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 145d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 146d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 147d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 148d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 149d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 150d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 151d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 152d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 153d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 154d2fd9612SCédric Le Goater int offset; 155d2fd9612SCédric Le Goater char *nodename; 156d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 157d2fd9612SCédric Le Goater 158d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 159d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 160d2fd9612SCédric Le Goater _FDT(offset); 161d2fd9612SCédric Le Goater g_free(nodename); 162d2fd9612SCédric Le Goater 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 164d2fd9612SCédric Le Goater 165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 168d2fd9612SCédric Le Goater 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 170d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 171d2fd9612SCédric Le Goater env->dcache_line_size))); 172d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 173d2fd9612SCédric Le Goater env->dcache_line_size))); 174d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 175d2fd9612SCédric Le Goater env->icache_line_size))); 176d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 177d2fd9612SCédric Le Goater env->icache_line_size))); 178d2fd9612SCédric Le Goater 179d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 180d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 181d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 182d2fd9612SCédric Le Goater } else { 1833dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 184d2fd9612SCédric Le Goater } 185d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 186d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 187d2fd9612SCédric Le Goater pcc->l1_icache_size))); 188d2fd9612SCédric Le Goater } else { 1893dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 190d2fd9612SCédric Le Goater } 191d2fd9612SCédric Le Goater 192d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 193d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19459b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19559b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 196d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 197d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 198d2fd9612SCédric Le Goater 199d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 200d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 201d2fd9612SCédric Le Goater } 202d2fd9612SCédric Le Goater 20358969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 204d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 205d2fd9612SCédric Le Goater segs, sizeof(segs)))); 206d2fd9612SCédric Le Goater } 207d2fd9612SCédric Le Goater 20859b7c1c2SBalamuruhan S /* 20959b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 210d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 211d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 21259b7c1c2SBalamuruhan S * 2 == VSX available 21359b7c1c2SBalamuruhan S */ 214d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 215d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 216d2fd9612SCédric Le Goater 217d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 218d2fd9612SCédric Le Goater } 219d2fd9612SCédric Le Goater 22059b7c1c2SBalamuruhan S /* 22159b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 222d2fd9612SCédric Le Goater * 0 / no property == no DFP 22359b7c1c2SBalamuruhan S * 1 == DFP available 22459b7c1c2SBalamuruhan S */ 225d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 226d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 227d2fd9612SCédric Le Goater } 228d2fd9612SCédric Le Goater 229644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 230d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 231d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 232d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 233d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 234d2fd9612SCédric Le Goater } 235d2fd9612SCédric Le Goater 236d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 237d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 238d2fd9612SCédric Le Goater 239d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 240d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 241d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 242d2fd9612SCédric Le Goater } 243d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 244d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 245d2fd9612SCédric Le Goater } 246d2fd9612SCédric Le Goater 247b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 248bf5615e7SCédric Le Goater uint32_t nr_threads) 249bf5615e7SCédric Le Goater { 250bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 251bf5615e7SCédric Le Goater char *name; 252bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 253bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 254bf5615e7SCédric Le Goater uint64_t *reg; 255bf5615e7SCédric Le Goater int offset; 256bf5615e7SCédric Le Goater 257bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 258bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 259bf5615e7SCédric Le Goater 260bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 261bf5615e7SCédric Le Goater reg = g_malloc(rsize); 262bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 263bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 264bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 265bf5615e7SCédric Le Goater } 266bf5615e7SCédric Le Goater 267bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 268bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 269bf5615e7SCédric Le Goater _FDT(offset); 270bf5615e7SCédric Le Goater g_free(name); 271bf5615e7SCédric Le Goater 272bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 273bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 274bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 275bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 278bf5615e7SCédric Le Goater irange, sizeof(irange)))); 279bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 280bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 281bf5615e7SCédric Le Goater g_free(reg); 282bf5615e7SCédric Le Goater } 283bf5615e7SCédric Le Goater 284eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 285e997040eSCédric Le Goater { 286c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; 287d2fd9612SCédric Le Goater int i; 288d2fd9612SCédric Le Goater 2893f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 2903f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 291c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE), 292c396c58aSGreg Kurz compat, sizeof(compat)); 293967b7523SCédric Le Goater 294d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2954fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 296d2fd9612SCédric Le Goater 297b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 298bf5615e7SCédric Le Goater 299bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 300b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 301d2fd9612SCédric Le Goater } 302d2fd9612SCédric Le Goater 303e997040eSCédric Le Goater if (chip->ram_size) { 304b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 305e997040eSCédric Le Goater } 306e997040eSCédric Le Goater } 307e997040eSCédric Le Goater 308eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 309eb859a27SCédric Le Goater { 310c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom"; 311eb859a27SCédric Le Goater int i; 312eb859a27SCédric Le Goater 3133f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3143f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 315c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE), 316c396c58aSGreg Kurz compat, sizeof(compat)); 317eb859a27SCédric Le Goater 318eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3194fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 320eb859a27SCédric Le Goater 321eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 322eb859a27SCédric Le Goater } 323eb859a27SCédric Le Goater 324eb859a27SCédric Le Goater if (chip->ram_size) { 325eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 326eb859a27SCédric Le Goater } 32715376c66SCédric Le Goater 3282661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 329eb859a27SCédric Le Goater } 330eb859a27SCédric Le Goater 3312b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3322b548a42SCédric Le Goater { 333c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom"; 3342b548a42SCédric Le Goater int i; 3352b548a42SCédric Le Goater 3363f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3373f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 338c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE), 339c396c58aSGreg Kurz compat, sizeof(compat)); 3402b548a42SCédric Le Goater 3412b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3422b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3432b548a42SCédric Le Goater 3442b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3452b548a42SCédric Le Goater } 3462b548a42SCédric Le Goater 3472b548a42SCédric Le Goater if (chip->ram_size) { 3482b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3492b548a42SCédric Le Goater } 3502661f6abSCédric Le Goater 3512661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 3522b548a42SCédric Le Goater } 3532b548a42SCédric Le Goater 354b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 355c5ffdcaeSCédric Le Goater { 356c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 357c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 358c5ffdcaeSCédric Le Goater cpu_to_be32(1), 359c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 360c5ffdcaeSCédric Le Goater cpu_to_be32(2) 361c5ffdcaeSCédric Le Goater }; 362c5ffdcaeSCédric Le Goater char *name; 363c5ffdcaeSCédric Le Goater int node; 364c5ffdcaeSCédric Le Goater 365c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 366c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 367c5ffdcaeSCédric Le Goater _FDT(node); 368c5ffdcaeSCédric Le Goater g_free(name); 369c5ffdcaeSCédric Le Goater 370c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 371c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 372c5ffdcaeSCédric Le Goater } 373c5ffdcaeSCédric Le Goater 374b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 375cb228f5aSCédric Le Goater { 376cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 377cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 378cb228f5aSCédric Le Goater uint32_t io_regs[] = { 379cb228f5aSCédric Le Goater cpu_to_be32(1), 380cb228f5aSCédric Le Goater cpu_to_be32(io_base), 381cb228f5aSCédric Le Goater cpu_to_be32(8) 382cb228f5aSCédric Le Goater }; 383cb228f5aSCédric Le Goater char *name; 384cb228f5aSCédric Le Goater int node; 385cb228f5aSCédric Le Goater 386cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 387cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 388cb228f5aSCédric Le Goater _FDT(node); 389cb228f5aSCédric Le Goater g_free(name); 390cb228f5aSCédric Le Goater 391cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 392cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 393cb228f5aSCédric Le Goater sizeof(compatible)))); 394cb228f5aSCédric Le Goater 395cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 396cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 397cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 398cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 399cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 400cb228f5aSCédric Le Goater 401cb228f5aSCédric Le Goater /* This is needed by Linux */ 402cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 403cb228f5aSCédric Le Goater } 404cb228f5aSCédric Le Goater 405b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 40604f6c8b2SCédric Le Goater { 40704f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 40804f6c8b2SCédric Le Goater uint32_t io_base; 40904f6c8b2SCédric Le Goater uint32_t io_regs[] = { 41004f6c8b2SCédric Le Goater cpu_to_be32(1), 41104f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 41204f6c8b2SCédric Le Goater cpu_to_be32(3) 41304f6c8b2SCédric Le Goater }; 41404f6c8b2SCédric Le Goater uint32_t irq; 41504f6c8b2SCédric Le Goater char *name; 41604f6c8b2SCédric Le Goater int node; 41704f6c8b2SCédric Le Goater 41804f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 41904f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 42004f6c8b2SCédric Le Goater 42104f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 42204f6c8b2SCédric Le Goater 42304f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 42404f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 42504f6c8b2SCédric Le Goater _FDT(node); 42604f6c8b2SCédric Le Goater g_free(name); 42704f6c8b2SCédric Le Goater 4287032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4297032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4307032d92aSCédric Le Goater sizeof(compatible)))); 43104f6c8b2SCédric Le Goater 43204f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 43304f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 43404f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 43504f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 43604f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 43704f6c8b2SCédric Le Goater } 43804f6c8b2SCédric Le Goater 439e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 440e7a3fee3SCédric Le Goater void *fdt; 441e7a3fee3SCédric Le Goater int offset; 442e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 443e7a3fee3SCédric Le Goater 444b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 445e7a3fee3SCédric Le Goater { 446c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 447c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 448c5ffdcaeSCédric Le Goater 449c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 450b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 451cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 452b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 45304f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 454b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 455c5ffdcaeSCédric Le Goater } else { 456c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 457c5ffdcaeSCédric Le Goater d->ioport_id); 458c5ffdcaeSCédric Le Goater } 459c5ffdcaeSCédric Le Goater 460e7a3fee3SCédric Le Goater return 0; 461e7a3fee3SCédric Le Goater } 462e7a3fee3SCédric Le Goater 46359b7c1c2SBalamuruhan S /* 46459b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 465bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 466bb7ab95cSCédric Le Goater */ 467bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 468bb7ab95cSCédric Le Goater { 46964d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 470e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 471e7a3fee3SCédric Le Goater .fdt = fdt, 472bb7ab95cSCédric Le Goater .offset = isa_offset, 473e7a3fee3SCédric Le Goater }; 474f47a08d1SCédric Le Goater uint32_t phandle; 475e7a3fee3SCédric Le Goater 476bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 477bb7ab95cSCédric Le Goater 478f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 479f47a08d1SCédric Le Goater assert(phandle > 0); 480f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 481f47a08d1SCédric Le Goater 48259b7c1c2SBalamuruhan S /* 48359b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 48459b7c1c2SBalamuruhan S * can not use object_child_foreach() 48559b7c1c2SBalamuruhan S */ 486bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 487bb7ab95cSCédric Le Goater &args); 488e7a3fee3SCédric Le Goater } 489e7a3fee3SCédric Le Goater 4907a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 491e5694793SCédric Le Goater { 492e5694793SCédric Le Goater int off; 493e5694793SCédric Le Goater 494e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 495e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 496e5694793SCédric Le Goater 497e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 498e5694793SCédric Le Goater } 499e5694793SCédric Le Goater 500b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 5019e933f4aSBenjamin Herrenschmidt { 502d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 503b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5049e933f4aSBenjamin Herrenschmidt void *fdt; 5059e933f4aSBenjamin Herrenschmidt char *buf; 5069e933f4aSBenjamin Herrenschmidt int off; 507e997040eSCédric Le Goater int i; 5089e933f4aSBenjamin Herrenschmidt 5099e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5109e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5119e933f4aSBenjamin Herrenschmidt 512ccb099b3SCédric Le Goater /* /qemu node */ 513ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 514ccb099b3SCédric Le Goater 5159e933f4aSBenjamin Herrenschmidt /* Root node */ 5169e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5179e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5189e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5199e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 520d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5219e933f4aSBenjamin Herrenschmidt 5229e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5239e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5249e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 5259e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5269e933f4aSBenjamin Herrenschmidt } 5279e933f4aSBenjamin Herrenschmidt g_free(buf); 5289e933f4aSBenjamin Herrenschmidt 5299e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5309e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5319e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5329e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5339e933f4aSBenjamin Herrenschmidt } 5349e933f4aSBenjamin Herrenschmidt 5359e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5369e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5379e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5389e933f4aSBenjamin Herrenschmidt 5399e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5409e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5419e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5429e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5439e933f4aSBenjamin Herrenschmidt } 5449e933f4aSBenjamin Herrenschmidt 545e997040eSCédric Le Goater /* Populate device tree for each chip */ 546e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 547eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 548e997040eSCédric Le Goater } 549e7a3fee3SCédric Le Goater 550e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 551bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 552aeaef83dSCédric Le Goater 553aeaef83dSCédric Le Goater if (pnv->bmc) { 554b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 555aeaef83dSCédric Le Goater } 556aeaef83dSCédric Le Goater 5577a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5587a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5597a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 560e5694793SCédric Le Goater } 561e5694793SCédric Le Goater 5629e933f4aSBenjamin Herrenschmidt return fdt; 5639e933f4aSBenjamin Herrenschmidt } 5649e933f4aSBenjamin Herrenschmidt 565bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 566bce0b691SCédric Le Goater { 5678f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 568bce0b691SCédric Le Goater 569bce0b691SCédric Le Goater if (pnv->bmc) { 570bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 571bce0b691SCédric Le Goater } 572bce0b691SCédric Le Goater } 573bce0b691SCédric Le Goater 574a0628599SLike Xu static void pnv_reset(MachineState *machine) 5759e933f4aSBenjamin Herrenschmidt { 57625f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 57725f3170bSCédric Le Goater IPMIBmc *bmc; 5789e933f4aSBenjamin Herrenschmidt void *fdt; 5799e933f4aSBenjamin Herrenschmidt 5809e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5819e933f4aSBenjamin Herrenschmidt 58225f3170bSCédric Le Goater /* 58325f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator. 58425f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command 58525f3170bSCédric Le Goater * line. 58625f3170bSCédric Le Goater */ 58725f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal); 58825f3170bSCédric Le Goater if (!pnv->bmc) { 58925f3170bSCédric Le Goater if (!bmc) { 59025f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 59125f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 59225f3170bSCédric Le Goater "to define one"); 59325f3170bSCédric Le Goater } else { 59425f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 59525f3170bSCédric Le Goater pnv->bmc = bmc; 59625f3170bSCédric Le Goater } 59725f3170bSCédric Le Goater } 59825f3170bSCédric Le Goater 599b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6009e933f4aSBenjamin Herrenschmidt 6019e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6029e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6039e933f4aSBenjamin Herrenschmidt 6048d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6059e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 606b2fb7a43SPan Nengyuan 607b2fb7a43SPan Nengyuan g_free(fdt); 6089e933f4aSBenjamin Herrenschmidt } 6099e933f4aSBenjamin Herrenschmidt 61004026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6113495b6b6SCédric Le Goater { 61277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 61377864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 61404026890SCédric Le Goater } 6153495b6b6SCédric Le Goater 61604026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 61704026890SCédric Le Goater { 61877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 61977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 62004026890SCédric Le Goater } 6213495b6b6SCédric Le Goater 62204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 62304026890SCédric Le Goater { 62415376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 62515376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 62604026890SCédric Le Goater } 6273495b6b6SCédric Le Goater 6282b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6292b548a42SCédric Le Goater { 6302661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6312661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6322b548a42SCédric Le Goater } 6332b548a42SCédric Le Goater 63404026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 63504026890SCédric Le Goater { 63604026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6373495b6b6SCédric Le Goater } 6383495b6b6SCédric Le Goater 639d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 640d8e4aad5SCédric Le Goater { 641d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 6429ae1329eSCédric Le Goater int i; 643d8e4aad5SCédric Le Goater 644d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 6459ae1329eSCédric Le Goater for (i = 0; i < chip->num_phbs; i++) { 6469ae1329eSCédric Le Goater pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon); 6479ae1329eSCédric Le Goater ics_pic_print_info(&chip8->phbs[i].lsis, mon); 6489ae1329eSCédric Le Goater } 649d8e4aad5SCédric Le Goater } 650d8e4aad5SCédric Le Goater 651d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 652d8e4aad5SCédric Le Goater { 653d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 6544f9924c4SBenjamin Herrenschmidt int i, j; 655d8e4aad5SCédric Le Goater 656d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 657c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 6584f9924c4SBenjamin Herrenschmidt 6594f9924c4SBenjamin Herrenschmidt for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { 6604f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 6614f9924c4SBenjamin Herrenschmidt for (j = 0; j < pec->num_stacks; j++) { 6624f9924c4SBenjamin Herrenschmidt pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon); 6634f9924c4SBenjamin Herrenschmidt } 6644f9924c4SBenjamin Herrenschmidt } 665d8e4aad5SCédric Le Goater } 666d8e4aad5SCédric Le Goater 667c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 668c4b2c40cSGreg Kurz uint32_t core_id) 669c4b2c40cSGreg Kurz { 670c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 671c4b2c40cSGreg Kurz } 672c4b2c40cSGreg Kurz 673c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 674c4b2c40cSGreg Kurz uint32_t core_id) 675c4b2c40cSGreg Kurz { 676c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 677c4b2c40cSGreg Kurz } 678c4b2c40cSGreg Kurz 679c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 680c4b2c40cSGreg Kurz uint32_t core_id) 681c4b2c40cSGreg Kurz { 682c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 683c4b2c40cSGreg Kurz } 684c4b2c40cSGreg Kurz 685f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 686f30c843cSCédric Le Goater { 687f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 688f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 689f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 690f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 691f30c843cSCédric Le Goater 692f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 693f30c843cSCédric Le Goater } 694f30c843cSCédric Le Goater 695e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 696e2392d43SCédric Le Goater { 697c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 698e2392d43SCédric Le Goater 699c23e0561SMarkus Armbruster object_property_set_link(OBJECT(dev), OBJECT(bmc), "bmc", &error_fatal); 700c23e0561SMarkus Armbruster object_property_set_int(OBJECT(dev), irq, "irq", &error_fatal); 701c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 702e2392d43SCédric Le Goater } 703e2392d43SCédric Le Goater 7042b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 7052b548a42SCédric Le Goater { 7068b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 7078b50ce85SCédric Le Goater 7088b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 7092b548a42SCédric Le Goater } 7102b548a42SCédric Le Goater 711b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 7129e933f4aSBenjamin Herrenschmidt { 713b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 714f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 7159e933f4aSBenjamin Herrenschmidt char *fw_filename; 7169e933f4aSBenjamin Herrenschmidt long fw_size; 717e997040eSCédric Le Goater int i; 718e997040eSCédric Le Goater char *chip_typename; 71935dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 72035dde576SCédric Le Goater DeviceState *dev; 7219e933f4aSBenjamin Herrenschmidt 7229e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 723d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 7243dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 7259e933f4aSBenjamin Herrenschmidt } 726173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 7279e933f4aSBenjamin Herrenschmidt 72835dde576SCédric Le Goater /* 72935dde576SCédric Le Goater * Create our simple PNOR device 73035dde576SCédric Le Goater */ 7313e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 73235dde576SCédric Le Goater if (pnor) { 733*934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 73435dde576SCédric Le Goater } 7353c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 73635dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 73735dde576SCédric Le Goater 7389e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 7399e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 7409e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 7419e933f4aSBenjamin Herrenschmidt } 7429e933f4aSBenjamin Herrenschmidt 7439e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 74415fcedb2SCédric Le Goater if (!fw_filename) { 74515fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 74615fcedb2SCédric Le Goater exit(1); 74715fcedb2SCédric Le Goater } 7489e933f4aSBenjamin Herrenschmidt 74908c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 7509e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 75115fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 7529e933f4aSBenjamin Herrenschmidt exit(1); 7539e933f4aSBenjamin Herrenschmidt } 7549e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 7559e933f4aSBenjamin Herrenschmidt 7569e933f4aSBenjamin Herrenschmidt /* load kernel */ 7579e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 7589e933f4aSBenjamin Herrenschmidt long kernel_size; 7599e933f4aSBenjamin Herrenschmidt 7609e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 761b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 7629e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 763802fc7abSThomas Huth error_report("Could not load kernel '%s'", 7649e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 7659e933f4aSBenjamin Herrenschmidt exit(1); 7669e933f4aSBenjamin Herrenschmidt } 7679e933f4aSBenjamin Herrenschmidt } 7689e933f4aSBenjamin Herrenschmidt 7699e933f4aSBenjamin Herrenschmidt /* load initrd */ 7709e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 7719e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 7729e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 773584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 7749e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 775802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 7769e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 7779e933f4aSBenjamin Herrenschmidt exit(1); 7789e933f4aSBenjamin Herrenschmidt } 7799e933f4aSBenjamin Herrenschmidt } 780e997040eSCédric Le Goater 7814f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 7824f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 7834f9924c4SBenjamin Herrenschmidt 784f30c843cSCédric Le Goater /* 785f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 786f30c843cSCédric Le Goater * default. 787f30c843cSCédric Le Goater */ 788f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 789f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 790f30c843cSCédric Le Goater machine->cpu_type, mc->name); 791f30c843cSCédric Le Goater exit(1); 792f30c843cSCédric Le Goater } 793f30c843cSCédric Le Goater 794e997040eSCédric Le Goater /* Create the processor chips */ 7954a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7967fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 7974a12c699SIgor Mammedov i, machine->cpu_type); 798e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 799f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 800f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 801e997040eSCédric Le Goater exit(1); 802e997040eSCédric Le Goater } 803e997040eSCédric Le Goater 804e44acde2SGreg Kurz pnv->num_chips = 805e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 806e44acde2SGreg Kurz /* 807e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 808e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 809e44acde2SGreg Kurz */ 810e44acde2SGreg Kurz if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 4) { 811e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 812e44acde2SGreg Kurz error_printf("Try '-smp sockets=N'. Valid values are : 1, 2 or 4.\n"); 813e44acde2SGreg Kurz exit(1); 814e44acde2SGreg Kurz } 815e44acde2SGreg Kurz 816e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 817e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 818e997040eSCédric Le Goater char chip_name[32]; 819df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 820e997040eSCédric Le Goater 821e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 822e997040eSCédric Le Goater 82359b7c1c2SBalamuruhan S /* 82459b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 825e997040eSCédric Le Goater * way to specify different ranges for each chip 826e997040eSCédric Le Goater */ 827e997040eSCédric Le Goater if (i == 0) { 828e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 829e997040eSCédric Le Goater &error_fatal); 830e997040eSCédric Le Goater } 831e997040eSCédric Le Goater 832e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 833d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 834e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 835e997040eSCédric Le Goater &error_fatal); 836fe6b6346SLike Xu object_property_set_int(chip, machine->smp.cores, 837fe6b6346SLike Xu "nr-cores", &error_fatal); 838764f9b25SGreg Kurz object_property_set_int(chip, machine->smp.threads, 839764f9b25SGreg Kurz "nr-threads", &error_fatal); 840245cdb7fSCédric Le Goater /* 841245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 842245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 843245cdb7fSCédric Le Goater */ 844245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 845245cdb7fSCédric Le Goater object_property_set_link(chip, OBJECT(pnv), "xics", &error_abort); 846245cdb7fSCédric Le Goater } 847d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 848d1214b81SGreg Kurz object_property_set_link(chip, OBJECT(pnv), "xive-fabric", 849d1214b81SGreg Kurz &error_abort); 850d1214b81SGreg Kurz } 8513c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 852e997040eSCédric Le Goater } 853e997040eSCédric Le Goater g_free(chip_typename); 8543495b6b6SCédric Le Goater 8553495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 85604026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 8573495b6b6SCédric Le Goater 8583495b6b6SCédric Le Goater /* Create serial port */ 859def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 8603495b6b6SCédric Le Goater 8613495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 8626c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 863bce0b691SCédric Le Goater 86425f3170bSCédric Le Goater /* 86525f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 86625f3170bSCédric Le Goater * communication with the BMC 86725f3170bSCédric Le Goater */ 86825f3170bSCédric Le Goater if (defaults_enabled()) { 86925f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 870e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 87125f3170bSCédric Le Goater } 872e2392d43SCédric Le Goater 87359b7c1c2SBalamuruhan S /* 87459b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 87559b7c1c2SBalamuruhan S * host to powerdown 87659b7c1c2SBalamuruhan S */ 877bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 878bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 879e997040eSCédric Le Goater } 880e997040eSCédric Le Goater 881631adaffSCédric Le Goater /* 882631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 883631adaffSCédric Le Goater * 22:24 Chip ID 884631adaffSCédric Le Goater * 25:28 Core number 885631adaffSCédric Le Goater * 29:31 Thread ID 886631adaffSCédric Le Goater */ 887631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 888631adaffSCédric Le Goater { 889631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 890631adaffSCédric Le Goater } 891631adaffSCédric Le Goater 8928fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 893d35aefa9SCédric Le Goater Error **errp) 894d35aefa9SCédric Le Goater { 895245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 8968fa1f4efSCédric Le Goater Error *local_err = NULL; 8978fa1f4efSCédric Le Goater Object *obj; 8988907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8998fa1f4efSCédric Le Goater 900245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 9018fa1f4efSCédric Le Goater if (local_err) { 9028fa1f4efSCédric Le Goater error_propagate(errp, local_err); 9038fa1f4efSCédric Le Goater return; 9048fa1f4efSCédric Le Goater } 9058fa1f4efSCédric Le Goater 906956b8f46SCédric Le Goater pnv_cpu->intc = obj; 907d35aefa9SCédric Le Goater } 908d35aefa9SCédric Le Goater 9090990ce6aSGreg Kurz 910d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 911d49e8a9bSCédric Le Goater { 912d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 913d49e8a9bSCédric Le Goater 914d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 915d49e8a9bSCédric Le Goater } 916d49e8a9bSCédric Le Goater 9170990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9180990ce6aSGreg Kurz { 9190990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9200990ce6aSGreg Kurz 9210990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 9220990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9230990ce6aSGreg Kurz } 9240990ce6aSGreg Kurz 92585913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 92685913070SGreg Kurz Monitor *mon) 92785913070SGreg Kurz { 92885913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 92985913070SGreg Kurz } 93085913070SGreg Kurz 931631adaffSCédric Le Goater /* 932631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 933631adaffSCédric Le Goater * 49:52 Node ID 934631adaffSCédric Le Goater * 53:55 Chip ID 935631adaffSCédric Le Goater * 56 Reserved - Read as zero 936631adaffSCédric Le Goater * 57:61 Core number 937631adaffSCédric Le Goater * 62:63 Thread ID 938631adaffSCédric Le Goater * 939631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 940631adaffSCédric Le Goater */ 941631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 942631adaffSCédric Le Goater { 943631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 944631adaffSCédric Le Goater } 945631adaffSCédric Le Goater 9462b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 9472b548a42SCédric Le Goater { 9482b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 9492b548a42SCédric Le Goater } 9502b548a42SCédric Le Goater 9518fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 952d35aefa9SCédric Le Goater Error **errp) 953d35aefa9SCédric Le Goater { 9542dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 9552dfa91a2SCédric Le Goater Error *local_err = NULL; 9562dfa91a2SCédric Le Goater Object *obj; 9572dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9582dfa91a2SCédric Le Goater 9592dfa91a2SCédric Le Goater /* 9602dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 9612dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 9622dfa91a2SCédric Le Goater * only used at runtime. 9632dfa91a2SCédric Le Goater */ 96447950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 96547950946SCédric Le Goater &local_err); 9662dfa91a2SCédric Le Goater if (local_err) { 9672dfa91a2SCédric Le Goater error_propagate(errp, local_err); 9688fa1f4efSCédric Le Goater return; 969d35aefa9SCédric Le Goater } 970d35aefa9SCédric Le Goater 9712dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 9722dfa91a2SCédric Le Goater } 9732dfa91a2SCédric Le Goater 974d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 975d49e8a9bSCédric Le Goater { 976d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 977d49e8a9bSCédric Le Goater 978d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 979d49e8a9bSCédric Le Goater } 980d49e8a9bSCédric Le Goater 9810990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9820990ce6aSGreg Kurz { 9830990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9840990ce6aSGreg Kurz 9850990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 9860990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9870990ce6aSGreg Kurz } 9880990ce6aSGreg Kurz 98985913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 99085913070SGreg Kurz Monitor *mon) 99185913070SGreg Kurz { 99285913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 99385913070SGreg Kurz } 99485913070SGreg Kurz 9952b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 9962b548a42SCédric Le Goater Error **errp) 9972b548a42SCédric Le Goater { 9982b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9992b548a42SCédric Le Goater 10002b548a42SCédric Le Goater /* Will be defined when the interrupt controller is */ 10012b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10022b548a42SCédric Le Goater } 10032b548a42SCédric Le Goater 10042b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 10052b548a42SCédric Le Goater { 10062b548a42SCédric Le Goater ; 10072b548a42SCédric Le Goater } 10082b548a42SCédric Le Goater 10092b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10102b548a42SCédric Le Goater { 10112b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10122b548a42SCédric Le Goater 10132b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10142b548a42SCédric Le Goater } 10152b548a42SCédric Le Goater 101685913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 101785913070SGreg Kurz Monitor *mon) 101885913070SGreg Kurz { 101985913070SGreg Kurz } 102085913070SGreg Kurz 102159b7c1c2SBalamuruhan S /* 102259b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1023397a79e7SCédric Le Goater * 1024397a79e7SCédric Le Goater * <EX0 reserved> 1025397a79e7SCédric Le Goater * EX1 - Venice only 1026397a79e7SCédric Le Goater * EX2 - Venice only 1027397a79e7SCédric Le Goater * EX3 - Venice only 1028397a79e7SCédric Le Goater * EX4 1029397a79e7SCédric Le Goater * EX5 1030397a79e7SCédric Le Goater * EX6 1031397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1032397a79e7SCédric Le Goater * EX9 - Venice only 1033397a79e7SCédric Le Goater * EX10 - Venice only 1034397a79e7SCédric Le Goater * EX11 - Venice only 1035397a79e7SCédric Le Goater * EX12 1036397a79e7SCédric Le Goater * EX13 1037397a79e7SCédric Le Goater * EX14 1038397a79e7SCédric Le Goater * <EX15 reserved> 1039397a79e7SCédric Le Goater */ 1040397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1041397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1042397a79e7SCédric Le Goater 1043397a79e7SCédric Le Goater /* 104409279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1045397a79e7SCédric Le Goater */ 104609279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1047397a79e7SCédric Le Goater 10482b548a42SCédric Le Goater 10492b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 10502b548a42SCédric Le Goater 105177864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 105277864267SCédric Le Goater { 10539ae1329eSCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 105477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 10559ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 10569ae1329eSCédric Le Goater int i; 105777864267SCédric Le Goater 1058245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1059245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1060245cdb7fSCédric Le Goater object_property_allow_set_link, 1061d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1062245cdb7fSCédric Le Goater 10639fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 106477864267SCédric Le Goater 10659fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 106677864267SCédric Le Goater 10679fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 10683887d241SBalamuruhan S 10699fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 10709ae1329eSCédric Le Goater 10719ae1329eSCédric Le Goater for (i = 0; i < pcc->num_phbs; i++) { 10729fc7fc4dSMarkus Armbruster object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); 10739ae1329eSCédric Le Goater } 10749ae1329eSCédric Le Goater 10759ae1329eSCédric Le Goater /* 10769ae1329eSCédric Le Goater * Number of PHBs is the chip default 10779ae1329eSCédric Le Goater */ 10789ae1329eSCédric Le Goater chip->num_phbs = pcc->num_phbs; 107977864267SCédric Le Goater } 108077864267SCédric Le Goater 108177864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 108277864267SCédric Le Goater { 108377864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 108477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 108577864267SCédric Le Goater int i, j; 108677864267SCédric Le Goater char *name; 108777864267SCédric Le Goater 108877864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 108977864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 109077864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 109177864267SCédric Le Goater g_free(name); 109277864267SCédric Le Goater 109377864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 109477864267SCédric Le Goater 109577864267SCédric Le Goater /* Map the ICP registers for each thread */ 109677864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 10974fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 109877864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 109977864267SCédric Le Goater 110077864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 110177864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1102245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 110377864267SCédric Le Goater 110477864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 110577864267SCédric Le Goater &icp->mmio); 110677864267SCédric Le Goater } 110777864267SCédric Le Goater } 110877864267SCédric Le Goater } 110977864267SCédric Le Goater 111077864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 111177864267SCédric Le Goater { 111277864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 111377864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 111477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1115ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 111677864267SCédric Le Goater Error *local_err = NULL; 11179ae1329eSCédric Le Goater int i; 111877864267SCédric Le Goater 1119245cdb7fSCédric Le Goater assert(chip8->xics); 1120245cdb7fSCédric Le Goater 1121709044fdSCédric Le Goater /* XSCOM bridge is first */ 1122709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1123709044fdSCédric Le Goater if (local_err) { 1124709044fdSCédric Le Goater error_propagate(errp, local_err); 1125709044fdSCédric Le Goater return; 1126709044fdSCédric Le Goater } 1127709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1128709044fdSCédric Le Goater 112977864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 113077864267SCédric Le Goater if (local_err) { 113177864267SCédric Le Goater error_propagate(errp, local_err); 113277864267SCédric Le Goater return; 113377864267SCédric Le Goater } 113477864267SCédric Le Goater 113577864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 113677864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 113777864267SCédric Le Goater "bar", &error_fatal); 1138245cdb7fSCédric Le Goater object_property_set_link(OBJECT(&chip8->psi), OBJECT(chip8->xics), 113934bdca8fSCédric Le Goater ICS_PROP_XICS, &error_abort); 1140ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->psi), NULL, &local_err); 114177864267SCédric Le Goater if (local_err) { 114277864267SCédric Le Goater error_propagate(errp, local_err); 114377864267SCédric Le Goater return; 114477864267SCédric Le Goater } 1145ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1146ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 114777864267SCédric Le Goater 114877864267SCédric Le Goater /* Create LPC controller */ 1149b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi", 1150b63f3893SGreg Kurz &error_abort); 1151ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 115277864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 115377864267SCédric Le Goater 115464d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 115564d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 115664d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 115764d011d5SCédric Le Goater 115859b7c1c2SBalamuruhan S /* 115959b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 116059b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 116159b7c1c2SBalamuruhan S */ 116277864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 116377864267SCédric Le Goater if (local_err) { 116477864267SCédric Le Goater error_propagate(errp, local_err); 116577864267SCédric Le Goater return; 116677864267SCédric Le Goater } 116777864267SCédric Le Goater 116877864267SCédric Le Goater /* Create the simplified OCC model */ 1169ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi", 1170ee3d2713SGreg Kurz &error_abort); 1171ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->occ), NULL, &local_err); 117277864267SCédric Le Goater if (local_err) { 117377864267SCédric Le Goater error_propagate(errp, local_err); 117477864267SCédric Le Goater return; 117577864267SCédric Le Goater } 117677864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1177f3db8266SBalamuruhan S 1178f3db8266SBalamuruhan S /* OCC SRAM model */ 11793a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1180f3db8266SBalamuruhan S &chip8->occ.sram_regs); 11813887d241SBalamuruhan S 11823887d241SBalamuruhan S /* HOMER */ 1183f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip", 1184f2582acfSGreg Kurz &error_abort); 1185ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->homer), NULL, &local_err); 11863887d241SBalamuruhan S if (local_err) { 11873887d241SBalamuruhan S error_propagate(errp, local_err); 11883887d241SBalamuruhan S return; 11893887d241SBalamuruhan S } 11908f092316SCédric Le Goater /* Homer Xscom region */ 11918f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 11928f092316SCédric Le Goater 11938f092316SCédric Le Goater /* Homer mmio region */ 11943887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 11953887d241SBalamuruhan S &chip8->homer.regs); 11969ae1329eSCédric Le Goater 11979ae1329eSCédric Le Goater /* PHB3 controllers */ 11989ae1329eSCédric Le Goater for (i = 0; i < chip->num_phbs; i++) { 11999ae1329eSCédric Le Goater PnvPHB3 *phb = &chip8->phbs[i]; 12009ae1329eSCédric Le Goater PnvPBCQState *pbcq = &phb->pbcq; 12019ae1329eSCédric Le Goater 12029ae1329eSCédric Le Goater object_property_set_int(OBJECT(phb), i, "index", &error_fatal); 12039ae1329eSCédric Le Goater object_property_set_int(OBJECT(phb), chip->chip_id, "chip-id", 12049ae1329eSCédric Le Goater &error_fatal); 12053c6ef471SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(phb), &local_err); 12069ae1329eSCédric Le Goater if (local_err) { 12079ae1329eSCédric Le Goater error_propagate(errp, local_err); 12089ae1329eSCédric Le Goater return; 12099ae1329eSCédric Le Goater } 12109ae1329eSCédric Le Goater 12119ae1329eSCédric Le Goater /* Populate the XSCOM address space. */ 12129ae1329eSCédric Le Goater pnv_xscom_add_subregion(chip, 12139ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id, 12149ae1329eSCédric Le Goater &pbcq->xscom_nest_regs); 12159ae1329eSCédric Le Goater pnv_xscom_add_subregion(chip, 12169ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id, 12179ae1329eSCédric Le Goater &pbcq->xscom_pci_regs); 12189ae1329eSCédric Le Goater pnv_xscom_add_subregion(chip, 12199ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id, 12209ae1329eSCédric Le Goater &pbcq->xscom_spci_regs); 12219ae1329eSCédric Le Goater } 122277864267SCédric Le Goater } 122377864267SCédric Le Goater 122470c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 122570c059e9SGreg Kurz { 122670c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 122770c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 122870c059e9SGreg Kurz } 122970c059e9SGreg Kurz 1230e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1231e997040eSCédric Le Goater { 1232e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1233e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1234e997040eSCédric Le Goater 1235e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1236397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 12379ae1329eSCédric Le Goater k->num_phbs = 3; 1238631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1239d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1240d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12410990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 124285913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 124304026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1244eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1245d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1246c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 124770c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1248e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 124977864267SCédric Le Goater 125077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 125177864267SCédric Le Goater &k->parent_realize); 1252e997040eSCédric Le Goater } 1253e997040eSCédric Le Goater 1254e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1255e997040eSCédric Le Goater { 1256e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1257e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1258e997040eSCédric Le Goater 1259e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1260397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 12619ae1329eSCédric Le Goater k->num_phbs = 3; 1262631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1263d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1264d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12650990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 126685913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 126704026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1268eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1269d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1270c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 127170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1272e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 127377864267SCédric Le Goater 127477864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 127577864267SCédric Le Goater &k->parent_realize); 1276e997040eSCédric Le Goater } 1277e997040eSCédric Le Goater 1278e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1279e997040eSCédric Le Goater { 1280e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1281e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1282e997040eSCédric Le Goater 1283e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1284397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 12859ae1329eSCédric Le Goater k->num_phbs = 3; 1286631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1287d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1288d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12890990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 129085913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 129104026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1292eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1293d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1294c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 129570c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1296e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 129777864267SCédric Le Goater 129877864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 129977864267SCédric Le Goater &k->parent_realize); 130077864267SCédric Le Goater } 130177864267SCédric Le Goater 130277864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 130377864267SCédric Le Goater { 13044f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 13052dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 13064f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 13074f9924c4SBenjamin Herrenschmidt int i; 13082dfa91a2SCédric Le Goater 1309db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1310d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1311d2623129SMarkus Armbruster "xive-fabric"); 1312c38536bcSCédric Le Goater 13139fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 131415376c66SCédric Le Goater 13159fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 13166598a70dSCédric Le Goater 13179fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 13183887d241SBalamuruhan S 13199fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 13204f9924c4SBenjamin Herrenschmidt 13214f9924c4SBenjamin Herrenschmidt for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { 13224f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 13239fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 13244f9924c4SBenjamin Herrenschmidt } 13254f9924c4SBenjamin Herrenschmidt 13264f9924c4SBenjamin Herrenschmidt /* 13274f9924c4SBenjamin Herrenschmidt * Number of PHBs is the chip default 13284f9924c4SBenjamin Herrenschmidt */ 13294f9924c4SBenjamin Herrenschmidt chip->num_phbs = pcc->num_phbs; 133077864267SCédric Le Goater } 133177864267SCédric Le Goater 13325dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 13335dad902cSCédric Le Goater { 13345dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 13355dad902cSCédric Le Goater int i; 13365dad902cSCédric Le Goater 13375dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 13385dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 13395dad902cSCédric Le Goater 13405dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 13415dad902cSCédric Le Goater char eq_name[32]; 13425dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 13434fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 13445dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 13455dad902cSCédric Le Goater 13465dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 13479fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 13489fc7fc4dSMarkus Armbruster sizeof(*eq), TYPE_PNV_QUAD, 13499fc7fc4dSMarkus Armbruster &error_fatal, NULL); 13505dad902cSCédric Le Goater 13515dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 1352ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 13535dad902cSCédric Le Goater 13545dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 13555dad902cSCédric Le Goater &eq->xscom_regs); 13565dad902cSCédric Le Goater } 13575dad902cSCédric Le Goater } 13585dad902cSCédric Le Goater 13594f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp) 13604f9924c4SBenjamin Herrenschmidt { 13614f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 13624f9924c4SBenjamin Herrenschmidt Error *local_err = NULL; 13634f9924c4SBenjamin Herrenschmidt int i, j; 13644f9924c4SBenjamin Herrenschmidt int phb_id = 0; 13654f9924c4SBenjamin Herrenschmidt 13664f9924c4SBenjamin Herrenschmidt for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { 13674f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 13684f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 13694f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 13704f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 13714f9924c4SBenjamin Herrenschmidt 13724f9924c4SBenjamin Herrenschmidt object_property_set_int(OBJECT(pec), i, "index", &error_fatal); 13734f9924c4SBenjamin Herrenschmidt /* 13744f9924c4SBenjamin Herrenschmidt * PEC0 -> 1 stack 13754f9924c4SBenjamin Herrenschmidt * PEC1 -> 2 stacks 13764f9924c4SBenjamin Herrenschmidt * PEC2 -> 3 stacks 13774f9924c4SBenjamin Herrenschmidt */ 13784f9924c4SBenjamin Herrenschmidt object_property_set_int(OBJECT(pec), i + 1, "num-stacks", 13794f9924c4SBenjamin Herrenschmidt &error_fatal); 13804f9924c4SBenjamin Herrenschmidt object_property_set_int(OBJECT(pec), chip->chip_id, "chip-id", 13814f9924c4SBenjamin Herrenschmidt &error_fatal); 13824f9924c4SBenjamin Herrenschmidt object_property_set_link(OBJECT(pec), OBJECT(get_system_memory()), 13834f9924c4SBenjamin Herrenschmidt "system-memory", &error_abort); 1384ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pec), NULL, &local_err); 13854f9924c4SBenjamin Herrenschmidt if (local_err) { 13864f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 13874f9924c4SBenjamin Herrenschmidt return; 13884f9924c4SBenjamin Herrenschmidt } 13894f9924c4SBenjamin Herrenschmidt 13904f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 13914f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 13924f9924c4SBenjamin Herrenschmidt 13934f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 13944f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 13954f9924c4SBenjamin Herrenschmidt 13964f9924c4SBenjamin Herrenschmidt for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs; 13974f9924c4SBenjamin Herrenschmidt j++, phb_id++) { 13984f9924c4SBenjamin Herrenschmidt PnvPhb4PecStack *stack = &pec->stacks[j]; 13994f9924c4SBenjamin Herrenschmidt Object *obj = OBJECT(&stack->phb); 14004f9924c4SBenjamin Herrenschmidt 14014f9924c4SBenjamin Herrenschmidt object_property_set_int(obj, phb_id, "index", &error_fatal); 14024f9924c4SBenjamin Herrenschmidt object_property_set_int(obj, chip->chip_id, "chip-id", 14034f9924c4SBenjamin Herrenschmidt &error_fatal); 14044f9924c4SBenjamin Herrenschmidt object_property_set_int(obj, PNV_PHB4_VERSION, "version", 14054f9924c4SBenjamin Herrenschmidt &error_fatal); 14064f9924c4SBenjamin Herrenschmidt object_property_set_int(obj, PNV_PHB4_DEVICE_ID, "device-id", 14074f9924c4SBenjamin Herrenschmidt &error_fatal); 14084f9924c4SBenjamin Herrenschmidt object_property_set_link(obj, OBJECT(stack), "stack", &error_abort); 14093c6ef471SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(obj), &local_err); 14104f9924c4SBenjamin Herrenschmidt if (local_err) { 14114f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 14124f9924c4SBenjamin Herrenschmidt return; 14134f9924c4SBenjamin Herrenschmidt } 14144f9924c4SBenjamin Herrenschmidt 14154f9924c4SBenjamin Herrenschmidt /* Populate the XSCOM address space. */ 14164f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14174f9924c4SBenjamin Herrenschmidt pec_nest_base + 0x40 * (stack->stack_no + 1), 14184f9924c4SBenjamin Herrenschmidt &stack->nest_regs_mr); 14194f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14204f9924c4SBenjamin Herrenschmidt pec_pci_base + 0x40 * (stack->stack_no + 1), 14214f9924c4SBenjamin Herrenschmidt &stack->pci_regs_mr); 14224f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14234f9924c4SBenjamin Herrenschmidt pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + 14244f9924c4SBenjamin Herrenschmidt 0x40 * stack->stack_no, 14254f9924c4SBenjamin Herrenschmidt &stack->phb_regs_mr); 14264f9924c4SBenjamin Herrenschmidt } 14274f9924c4SBenjamin Herrenschmidt } 14284f9924c4SBenjamin Herrenschmidt } 14294f9924c4SBenjamin Herrenschmidt 143077864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 143177864267SCédric Le Goater { 143277864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 14332dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 14342dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1435c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 143677864267SCédric Le Goater Error *local_err = NULL; 143777864267SCédric Le Goater 1438709044fdSCédric Le Goater /* XSCOM bridge is first */ 1439709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1440709044fdSCédric Le Goater if (local_err) { 1441709044fdSCédric Le Goater error_propagate(errp, local_err); 1442709044fdSCédric Le Goater return; 1443709044fdSCédric Le Goater } 1444709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1445709044fdSCédric Le Goater 144677864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 144777864267SCédric Le Goater if (local_err) { 144877864267SCédric Le Goater error_propagate(errp, local_err); 144977864267SCédric Le Goater return; 145077864267SCédric Le Goater } 14512dfa91a2SCédric Le Goater 14525dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 14535dad902cSCédric Le Goater if (local_err) { 14545dad902cSCédric Le Goater error_propagate(errp, local_err); 14555dad902cSCédric Le Goater return; 14565dad902cSCédric Le Goater } 14575dad902cSCédric Le Goater 14582dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 14592dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 14602dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 14612dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 14622dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 14632dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 14642dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 14652dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 14662dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 14677ae54cc3SGreg Kurz object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", 14687ae54cc3SGreg Kurz &error_abort); 1469db873cc5SMarkus Armbruster sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), &local_err); 14702dfa91a2SCédric Le Goater if (local_err) { 14712dfa91a2SCédric Le Goater error_propagate(errp, local_err); 14722dfa91a2SCédric Le Goater return; 14732dfa91a2SCédric Le Goater } 14742dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 14752dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1476c38536bcSCédric Le Goater 1477c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1478c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1479c38536bcSCédric Le Goater "bar", &error_fatal); 1480ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip9->psi), NULL, &local_err); 1481c38536bcSCédric Le Goater if (local_err) { 1482c38536bcSCédric Le Goater error_propagate(errp, local_err); 1483c38536bcSCédric Le Goater return; 1484c38536bcSCédric Le Goater } 1485c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1486c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 148715376c66SCédric Le Goater 148815376c66SCédric Le Goater /* LPC */ 1489b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", 1490b63f3893SGreg Kurz &error_abort); 1491ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip9->lpc), NULL, &local_err); 149215376c66SCédric Le Goater if (local_err) { 149315376c66SCédric Le Goater error_propagate(errp, local_err); 149415376c66SCédric Le Goater return; 149515376c66SCédric Le Goater } 149615376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 149715376c66SCédric Le Goater &chip9->lpc.xscom_regs); 149815376c66SCédric Le Goater 149915376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 150015376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 15016598a70dSCédric Le Goater 15026598a70dSCédric Le Goater /* Create the simplified OCC model */ 1503ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", 1504ee3d2713SGreg Kurz &error_abort); 1505ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip9->occ), NULL, &local_err); 15066598a70dSCédric Le Goater if (local_err) { 15076598a70dSCédric Le Goater error_propagate(errp, local_err); 15086598a70dSCédric Le Goater return; 15096598a70dSCédric Le Goater } 15106598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1511f3db8266SBalamuruhan S 1512f3db8266SBalamuruhan S /* OCC SRAM model */ 15133a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1514f3db8266SBalamuruhan S &chip9->occ.sram_regs); 15153887d241SBalamuruhan S 15163887d241SBalamuruhan S /* HOMER */ 1517f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", 1518f2582acfSGreg Kurz &error_abort); 1519ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip9->homer), NULL, &local_err); 15203887d241SBalamuruhan S if (local_err) { 15213887d241SBalamuruhan S error_propagate(errp, local_err); 15223887d241SBalamuruhan S return; 15233887d241SBalamuruhan S } 15248f092316SCédric Le Goater /* Homer Xscom region */ 15258f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 15268f092316SCédric Le Goater 15278f092316SCédric Le Goater /* Homer mmio region */ 15283887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 15293887d241SBalamuruhan S &chip9->homer.regs); 15304f9924c4SBenjamin Herrenschmidt 15314f9924c4SBenjamin Herrenschmidt /* PHBs */ 15324f9924c4SBenjamin Herrenschmidt pnv_chip_power9_phb_realize(chip, &local_err); 15334f9924c4SBenjamin Herrenschmidt if (local_err) { 15344f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 15354f9924c4SBenjamin Herrenschmidt return; 15364f9924c4SBenjamin Herrenschmidt } 1537e997040eSCédric Le Goater } 1538e997040eSCédric Le Goater 153970c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 154070c059e9SGreg Kurz { 154170c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 154270c059e9SGreg Kurz return addr >> 3; 154370c059e9SGreg Kurz } 154470c059e9SGreg Kurz 1545e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1546e997040eSCédric Le Goater { 1547e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1548e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1549e997040eSCédric Le Goater 155083028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1551397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1552631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1553d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1554d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 15550990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 155685913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 155704026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1558eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1559d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1560c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 156170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1562e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 15634f9924c4SBenjamin Herrenschmidt k->num_phbs = 6; 156477864267SCédric Le Goater 156577864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 156677864267SCédric Le Goater &k->parent_realize); 1567e997040eSCédric Le Goater } 1568e997040eSCédric Le Goater 15692b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 15702b548a42SCédric Le Goater { 15718b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 15728b50ce85SCédric Le Goater 15739fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 15749fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 15752b548a42SCédric Le Goater } 15762b548a42SCédric Le Goater 15772b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 15782b548a42SCédric Le Goater { 15792b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 15802b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 15818b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 15822b548a42SCédric Le Goater Error *local_err = NULL; 15832b548a42SCédric Le Goater 15842b548a42SCédric Le Goater /* XSCOM bridge is first */ 15852b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 15862b548a42SCédric Le Goater if (local_err) { 15872b548a42SCédric Le Goater error_propagate(errp, local_err); 15882b548a42SCédric Le Goater return; 15892b548a42SCédric Le Goater } 15902b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 15912b548a42SCédric Le Goater 15922b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 15932b548a42SCédric Le Goater if (local_err) { 15942b548a42SCédric Le Goater error_propagate(errp, local_err); 15952b548a42SCédric Le Goater return; 15962b548a42SCédric Le Goater } 15978b50ce85SCédric Le Goater 15988b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 15998b50ce85SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), 16008b50ce85SCédric Le Goater "bar", &error_fatal); 1601ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip10->psi), NULL, &local_err); 16028b50ce85SCédric Le Goater if (local_err) { 16038b50ce85SCédric Le Goater error_propagate(errp, local_err); 16048b50ce85SCédric Le Goater return; 16058b50ce85SCédric Le Goater } 16068b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 16078b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 16082661f6abSCédric Le Goater 16092661f6abSCédric Le Goater /* LPC */ 16102661f6abSCédric Le Goater object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi", 16112661f6abSCédric Le Goater &error_abort); 1612ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip10->lpc), NULL, &local_err); 16132661f6abSCédric Le Goater if (local_err) { 16142661f6abSCédric Le Goater error_propagate(errp, local_err); 16152661f6abSCédric Le Goater return; 16162661f6abSCédric Le Goater } 16172661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 16182661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 16192661f6abSCédric Le Goater 16202661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 16212661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 16222b548a42SCédric Le Goater } 16232b548a42SCédric Le Goater 162470c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 162570c059e9SGreg Kurz { 162670c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 162770c059e9SGreg Kurz return addr >> 3; 162870c059e9SGreg Kurz } 162970c059e9SGreg Kurz 16302b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 16312b548a42SCédric Le Goater { 16322b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 16332b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 16342b548a42SCédric Le Goater 16352b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 16362b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 16372b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 16382b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 16392b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 16402b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 164185913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 16422b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 16432b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 16442b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1645c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 164670c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 16472b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 16482b548a42SCédric Le Goater 16492b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 16502b548a42SCédric Le Goater &k->parent_realize); 16512b548a42SCédric Le Goater } 16522b548a42SCédric Le Goater 1653397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1654397a79e7SCédric Le Goater { 1655397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1656397a79e7SCédric Le Goater int cores_max; 1657397a79e7SCédric Le Goater 1658397a79e7SCédric Le Goater /* 1659397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1660397a79e7SCédric Le Goater * the chip class 1661397a79e7SCédric Le Goater */ 1662397a79e7SCédric Le Goater if (!chip->cores_mask) { 1663397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1664397a79e7SCédric Le Goater } 1665397a79e7SCédric Le Goater 1666397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1667397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1668397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1669397a79e7SCédric Le Goater chip->cores_mask); 1670397a79e7SCédric Le Goater return; 1671397a79e7SCédric Le Goater } 1672397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1673397a79e7SCédric Le Goater 1674397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 167527d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1676397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1677397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1678397a79e7SCédric Le Goater cores_max); 1679397a79e7SCédric Le Goater return; 1680397a79e7SCédric Le Goater } 1681397a79e7SCédric Le Goater } 1682397a79e7SCédric Le Goater 168351c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1684e997040eSCédric Le Goater { 1685397a79e7SCédric Le Goater Error *error = NULL; 1686d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 168740abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1688d2fd9612SCédric Le Goater int i, core_hwid; 168908c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1690397a79e7SCédric Le Goater 1691d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1692d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1693d2fd9612SCédric Le Goater return; 1694d2fd9612SCédric Le Goater } 1695d2fd9612SCédric Le Goater 1696d2fd9612SCédric Le Goater /* Cores */ 1697397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1698397a79e7SCédric Le Goater if (error) { 1699397a79e7SCédric Le Goater error_propagate(errp, error); 1700397a79e7SCédric Le Goater return; 1701397a79e7SCédric Le Goater } 1702d2fd9612SCédric Le Goater 17034fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1704d2fd9612SCédric Le Goater 1705d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1706d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1707d2fd9612SCédric Le Goater char core_name[32]; 17084fa28f23SGreg Kurz PnvCore *pnv_core; 1709c035851aSCédric Le Goater uint64_t xscom_core_base; 1710d2fd9612SCédric Le Goater 1711d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1712d2fd9612SCédric Le Goater continue; 1713d2fd9612SCédric Le Goater } 1714d2fd9612SCédric Le Goater 17154fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 17164fa28f23SGreg Kurz 1717d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1718d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 17194fa28f23SGreg Kurz chip->cores[i] = pnv_core; 1720764f9b25SGreg Kurz object_property_set_int(OBJECT(pnv_core), chip->nr_threads, 1721764f9b25SGreg Kurz "nr-threads", &error_fatal); 1722d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1723d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1724d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1725d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1726d2fd9612SCédric Le Goater "pir", &error_fatal); 172708c3f3a7SCédric Le Goater object_property_set_int(OBJECT(pnv_core), pnv->fw_load_addr, 172808c3f3a7SCédric Le Goater "hrmor", &error_fatal); 1729158e17a6SGreg Kurz object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", 1730158e17a6SGreg Kurz &error_abort); 1731ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 173224ece072SCédric Le Goater 173324ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1734c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1735c035851aSCédric Le Goater 1736c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 17374fa28f23SGreg Kurz &pnv_core->xscom_regs); 1738d2fd9612SCédric Le Goater i++; 1739d2fd9612SCédric Le Goater } 174051c04728SCédric Le Goater } 174151c04728SCédric Le Goater 174251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 174351c04728SCédric Le Goater { 174451c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 174551c04728SCédric Le Goater Error *error = NULL; 174651c04728SCédric Le Goater 174751c04728SCédric Le Goater /* Cores */ 174851c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 174951c04728SCédric Le Goater if (error) { 175051c04728SCédric Le Goater error_propagate(errp, error); 175151c04728SCédric Le Goater return; 175251c04728SCédric Le Goater } 1753e997040eSCédric Le Goater } 1754e997040eSCédric Le Goater 1755e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1756e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1757e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1758e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1759397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1760397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1761764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 17624f9924c4SBenjamin Herrenschmidt DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0), 1763e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1764e997040eSCédric Le Goater }; 1765e997040eSCédric Le Goater 1766e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1767e997040eSCédric Le Goater { 1768e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1769e997040eSCédric Le Goater 17709d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1771e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 17724f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 1773e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1774e997040eSCédric Le Goater } 1775e997040eSCédric Le Goater 1776119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1777119eaa9dSCédric Le Goater { 1778119eaa9dSCédric Le Goater int i, j; 1779119eaa9dSCédric Le Goater 1780119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1781119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1782119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1783119eaa9dSCédric Le Goater 1784119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1785119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1786119eaa9dSCédric Le Goater return pc->threads[j]; 1787119eaa9dSCédric Le Goater } 1788119eaa9dSCédric Le Goater } 1789119eaa9dSCédric Le Goater } 1790119eaa9dSCédric Le Goater return NULL; 1791119eaa9dSCédric Le Goater } 1792119eaa9dSCédric Le Goater 179354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 179454f59d78SCédric Le Goater { 1795b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 17969ae1329eSCédric Le Goater int i, j; 179754f59d78SCédric Le Goater 179854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 17999ae1329eSCédric Le Goater PnvChip *chip = pnv->chips[i]; 180077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 180177864267SCédric Le Goater 180277864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 180377864267SCédric Le Goater return &chip8->psi.ics; 180454f59d78SCédric Le Goater } 18059ae1329eSCédric Le Goater for (j = 0; j < chip->num_phbs; j++) { 18069ae1329eSCédric Le Goater if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) { 18079ae1329eSCédric Le Goater return &chip8->phbs[j].lsis; 18089ae1329eSCédric Le Goater } 18099ae1329eSCédric Le Goater if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) { 18109ae1329eSCédric Le Goater return ICS(&chip8->phbs[j].msis); 18119ae1329eSCédric Le Goater } 18129ae1329eSCédric Le Goater } 181354f59d78SCédric Le Goater } 181454f59d78SCédric Le Goater return NULL; 181554f59d78SCédric Le Goater } 181654f59d78SCédric Le Goater 181754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 181854f59d78SCédric Le Goater { 1819b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 18209ae1329eSCédric Le Goater int i, j; 182154f59d78SCédric Le Goater 182254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 18239ae1329eSCédric Le Goater PnvChip *chip = pnv->chips[i]; 182477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 18259ae1329eSCédric Le Goater 182677864267SCédric Le Goater ics_resend(&chip8->psi.ics); 18279ae1329eSCédric Le Goater for (j = 0; j < chip->num_phbs; j++) { 18289ae1329eSCédric Le Goater ics_resend(&chip8->phbs[j].lsis); 18299ae1329eSCédric Le Goater ics_resend(ICS(&chip8->phbs[j].msis)); 18309ae1329eSCédric Le Goater } 183154f59d78SCédric Le Goater } 183254f59d78SCédric Le Goater } 183354f59d78SCédric Le Goater 183436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 183536fc6f08SCédric Le Goater { 183636fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 183736fc6f08SCédric Le Goater 1838956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 183936fc6f08SCédric Le Goater } 184036fc6f08SCédric Le Goater 184147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 184247fea43aSCédric Le Goater Monitor *mon) 184347fea43aSCédric Le Goater { 1844b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 184554f59d78SCédric Le Goater int i; 184647fea43aSCédric Le Goater CPUState *cs; 184747fea43aSCédric Le Goater 184847fea43aSCédric Le Goater CPU_FOREACH(cs) { 184947fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 185047fea43aSCédric Le Goater 185185913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 185285913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 185385913070SGreg Kurz mon); 1854d8e4aad5SCédric Le Goater } 185554f59d78SCédric Le Goater 185654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1857d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 185854f59d78SCédric Le Goater } 185947fea43aSCédric Le Goater } 186047fea43aSCédric Le Goater 1861c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1862c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1863c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1864c722579eSCédric Le Goater uint32_t logic_serv, 1865c722579eSCédric Le Goater XiveTCTXMatch *match) 1866c722579eSCédric Le Goater { 1867c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1868c722579eSCédric Le Goater int total_count = 0; 1869c722579eSCédric Le Goater int i; 1870c722579eSCédric Le Goater 1871c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1872c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1873c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1874c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1875c722579eSCédric Le Goater int count; 1876c722579eSCédric Le Goater 1877c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1878c722579eSCédric Le Goater priority, logic_serv, match); 1879c722579eSCédric Le Goater 1880c722579eSCédric Le Goater if (count < 0) { 1881c722579eSCédric Le Goater return count; 1882c722579eSCédric Le Goater } 1883c722579eSCédric Le Goater 1884c722579eSCédric Le Goater total_count += count; 1885c722579eSCédric Le Goater } 1886c722579eSCédric Le Goater 1887c722579eSCédric Le Goater return total_count; 1888c722579eSCédric Le Goater } 1889c722579eSCédric Le Goater 1890f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 18919e933f4aSBenjamin Herrenschmidt { 18929e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 189336fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1894d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1895d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 1896f30c843cSCédric Le Goater 1897f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1898f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1899f30c843cSCédric Le Goater 1900f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1901f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1902f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1903d76f2da7SGreg Kurz 1904d76f2da7SGreg Kurz pmc->compat = compat; 1905d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 1906f30c843cSCédric Le Goater } 1907f30c843cSCédric Le Goater 1908f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1909f30c843cSCédric Le Goater { 1910f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1911c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1912d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1913d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 1914f30c843cSCédric Le Goater 1915f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1916f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1917c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1918f30c843cSCédric Le Goater 1919f30c843cSCédric Le Goater mc->alias = "powernv"; 1920d76f2da7SGreg Kurz 1921d76f2da7SGreg Kurz pmc->compat = compat; 1922d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 19237a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 1924f30c843cSCédric Le Goater } 1925f30c843cSCédric Le Goater 19262b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 19272b548a42SCédric Le Goater { 19282b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1929d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1930d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 19312b548a42SCédric Le Goater 19322b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 19332b548a42SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); 1934d76f2da7SGreg Kurz 1935d76f2da7SGreg Kurz pmc->compat = compat; 1936d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 19377a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 19382b548a42SCédric Le Goater } 19392b548a42SCédric Le Goater 194008c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 194108c3f3a7SCédric Le Goater { 194208c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 194308c3f3a7SCédric Le Goater 194408c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 194508c3f3a7SCédric Le Goater } 194608c3f3a7SCédric Le Goater 194708c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 194808c3f3a7SCédric Le Goater { 194908c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 195008c3f3a7SCédric Le Goater 195108c3f3a7SCédric Le Goater if (value) { 195208c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 195308c3f3a7SCédric Le Goater } 195408c3f3a7SCédric Le Goater } 195508c3f3a7SCédric Le Goater 195601b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 195701b552b0SNicholas Piggin { 195801b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 195901b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 196001b552b0SNicholas Piggin 196101b552b0SNicholas Piggin cpu_synchronize_state(cs); 196201b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 19630911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 196401b552b0SNicholas Piggin /* 1965fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 1966fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 1967fe837714SNicholas Piggin * (PPC_BIT(43)). 196801b552b0SNicholas Piggin */ 19690911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 1970fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 19710911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 197201b552b0SNicholas Piggin } 1973fe837714SNicholas Piggin } else { 1974fe837714SNicholas Piggin /* 1975fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 1976fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 1977fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 1978fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 1979fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 1980fe837714SNicholas Piggin */ 19810911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 1982fe837714SNicholas Piggin } 1983fe837714SNicholas Piggin } 198401b552b0SNicholas Piggin 198501b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 198601b552b0SNicholas Piggin { 198701b552b0SNicholas Piggin CPUState *cs; 198801b552b0SNicholas Piggin 198901b552b0SNicholas Piggin CPU_FOREACH(cs) { 199001b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 199101b552b0SNicholas Piggin } 199201b552b0SNicholas Piggin } 199301b552b0SNicholas Piggin 1994f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1995f30c843cSCédric Le Goater { 1996f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 199747fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 199801b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 19999e933f4aSBenjamin Herrenschmidt 20009e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 2001b168a138SCédric Le Goater mc->init = pnv_init; 2002b168a138SCédric Le Goater mc->reset = pnv_reset; 20039e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 200459b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 200559b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 20069e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 20079e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 2008f1d18b0aSJoel Stanley /* 2009f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 2010f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 2011f1d18b0aSJoel Stanley */ 2012f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 2013173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 201447fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 201501b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 201608c3f3a7SCédric Le Goater 201708c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 2018d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 201908c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 20207eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 20219e933f4aSBenjamin Herrenschmidt } 20229e933f4aSBenjamin Herrenschmidt 202377864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2024beba5c0fSIgor Mammedov { \ 2025beba5c0fSIgor Mammedov .name = type, \ 2026beba5c0fSIgor Mammedov .class_init = class_initfn, \ 202777864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 202877864267SCédric Le Goater } 202977864267SCédric Le Goater 203077864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 203177864267SCédric Le Goater { \ 203277864267SCédric Le Goater .name = type, \ 203377864267SCédric Le Goater .class_init = class_initfn, \ 203477864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2035beba5c0fSIgor Mammedov } 2036beba5c0fSIgor Mammedov 20372b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 20382b548a42SCédric Le Goater { \ 20392b548a42SCédric Le Goater .name = type, \ 20402b548a42SCédric Le Goater .class_init = class_initfn, \ 20412b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 20422b548a42SCédric Le Goater } 20432b548a42SCédric Le Goater 2044beba5c0fSIgor Mammedov static const TypeInfo types[] = { 20451aba8716SCédric Le Goater { 20462b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 20472b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20482b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 20492b548a42SCédric Le Goater }, 20502b548a42SCédric Le Goater { 20511aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 20521aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20531aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2054c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2055c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2056c722579eSCédric Le Goater { }, 2057c722579eSCédric Le Goater }, 20581aba8716SCédric Le Goater }, 20591aba8716SCédric Le Goater { 20601aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 20611aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20621aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 20631aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 20641aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 20651aba8716SCédric Le Goater { }, 20661aba8716SCédric Le Goater }, 20671aba8716SCédric Le Goater }, 2068beba5c0fSIgor Mammedov { 2069b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 20709e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2071f30c843cSCédric Le Goater .abstract = true, 20729e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2073b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2074d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 207536fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 207647fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 207701b552b0SNicholas Piggin { TYPE_NMI }, 207836fc6f08SCédric Le Goater { }, 207936fc6f08SCédric Le Goater }, 2080beba5c0fSIgor Mammedov }, 2081beba5c0fSIgor Mammedov { 2082beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2083beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2084beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2085beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2086beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2087beba5c0fSIgor Mammedov .abstract = true, 2088beba5c0fSIgor Mammedov }, 208977864267SCédric Le Goater 209077864267SCédric Le Goater /* 20912b548a42SCédric Le Goater * P10 chip and variants 20922b548a42SCédric Le Goater */ 20932b548a42SCédric Le Goater { 20942b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 20952b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 20962b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 20972b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 20982b548a42SCédric Le Goater }, 20992b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 21002b548a42SCédric Le Goater 21012b548a42SCédric Le Goater /* 210277864267SCédric Le Goater * P9 chip and variants 210377864267SCédric Le Goater */ 210477864267SCédric Le Goater { 210577864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 210677864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 210777864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 210877864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 210977864267SCédric Le Goater }, 211077864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 211177864267SCédric Le Goater 211277864267SCédric Le Goater /* 211377864267SCédric Le Goater * P8 chip and variants 211477864267SCédric Le Goater */ 211577864267SCédric Le Goater { 211677864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 211777864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 211877864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 211977864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 212077864267SCédric Le Goater }, 212177864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 212277864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 212377864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2124beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 21259e933f4aSBenjamin Herrenschmidt }; 21269e933f4aSBenjamin Herrenschmidt 2127beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2128