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 9f70c5966SChetan Pant * version 2.1 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" 222c65db5eSPaolo Bonzini #include "qemu/datadir.h" 23fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 24dd7ef911SCédric Le Goater #include "qemu/cutils.h" 259e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 2638d2448aSGreg Kurz #include "sysemu/qtest.h" 279e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 289e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2971e8a915SMarkus Armbruster #include "sysemu/reset.h" 3054d31236SMarkus Armbruster #include "sysemu/runstate.h" 31d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 328d409261SCédric Le Goater #include "sysemu/device_tree.h" 3301b552b0SNicholas Piggin #include "sysemu/hw_accel.h" 34fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 379e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 38d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 399e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 4001b552b0SNicholas Piggin #include "hw/nmi.h" 41e997040eSCédric Le Goater #include "qapi/visitor.h" 4247fea43aSCédric Le Goater #include "monitor/monitor.h" 4347fea43aSCédric Le Goater #include "hw/intc/intc.h" 44aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4558969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 464f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h" 479e933f4aSBenjamin Herrenschmidt 4836fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 49a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 50967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 5135dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 52967b7523SCédric Le Goater 533495b6b6SCédric Le Goater #include "hw/isa/isa.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 6383fa6e2aSCédric Le Goater #define FW_MAX_SIZE (16 * MiB) 649e933f4aSBenjamin Herrenschmidt 659e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 6605ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE (128 * MiB) 6705ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR 0x28000000 6805ce9b73SCédric Le Goater #define INITRD_MAX_SIZE (128 * 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 19903282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) { 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) { 525bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "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) { 59038d2448aSGreg Kurz if (!qtest_enabled()) { 59125f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 59225f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 59325f3170bSCédric Le Goater "to define one"); 59438d2448aSGreg Kurz } 59525f3170bSCédric Le Goater } else { 59625f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 59725f3170bSCédric Le Goater pnv->bmc = bmc; 59825f3170bSCédric Le Goater } 59925f3170bSCédric Le Goater } 60025f3170bSCédric Le Goater 601b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6029e933f4aSBenjamin Herrenschmidt 6039e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6049e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6059e933f4aSBenjamin Herrenschmidt 6068d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6079e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 608b2fb7a43SPan Nengyuan 609b2fb7a43SPan Nengyuan g_free(fdt); 6109e933f4aSBenjamin Herrenschmidt } 6119e933f4aSBenjamin Herrenschmidt 61204026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6133495b6b6SCédric Le Goater { 61477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 61577864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 61604026890SCédric Le Goater } 6173495b6b6SCédric Le Goater 61804026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 61904026890SCédric Le Goater { 62077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 62177864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 62204026890SCédric Le Goater } 6233495b6b6SCédric Le Goater 62404026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 62504026890SCédric Le Goater { 62615376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 62715376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 62804026890SCédric Le Goater } 6293495b6b6SCédric Le Goater 6302b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6312b548a42SCédric Le Goater { 6322661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6332661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6342b548a42SCédric Le Goater } 6352b548a42SCédric Le Goater 63604026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 63704026890SCédric Le Goater { 63804026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6393495b6b6SCédric Le Goater } 6403495b6b6SCédric Le Goater 6412ff73ddaSCédric Le Goater static int pnv_chip_power8_pic_print_info_child(Object *child, void *opaque) 6422ff73ddaSCédric Le Goater { 6432ff73ddaSCédric Le Goater Monitor *mon = opaque; 6442ff73ddaSCédric Le Goater PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3); 6452ff73ddaSCédric Le Goater 6462ff73ddaSCédric Le Goater if (phb3) { 6472ff73ddaSCédric Le Goater pnv_phb3_msi_pic_print_info(&phb3->msis, mon); 6482ff73ddaSCédric Le Goater ics_pic_print_info(&phb3->lsis, mon); 6492ff73ddaSCédric Le Goater } 6502ff73ddaSCédric Le Goater return 0; 6512ff73ddaSCédric Le Goater } 6522ff73ddaSCédric Le Goater 653d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 654d8e4aad5SCédric Le Goater { 655d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 656d8e4aad5SCédric Le Goater 657d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 6582ff73ddaSCédric Le Goater object_child_foreach(OBJECT(chip), 6592ff73ddaSCédric Le Goater pnv_chip_power8_pic_print_info_child, mon); 660d8e4aad5SCédric Le Goater } 661d8e4aad5SCédric Le Goater 662d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 663d8e4aad5SCédric Le Goater { 664d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 6654f9924c4SBenjamin Herrenschmidt int i, j; 666d8e4aad5SCédric Le Goater 667d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 668c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 6694f9924c4SBenjamin Herrenschmidt 670422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 6714f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 6724f9924c4SBenjamin Herrenschmidt for (j = 0; j < pec->num_stacks; j++) { 6734f9924c4SBenjamin Herrenschmidt pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon); 6744f9924c4SBenjamin Herrenschmidt } 6754f9924c4SBenjamin Herrenschmidt } 676d8e4aad5SCédric Le Goater } 677d8e4aad5SCédric Le Goater 678c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 679c4b2c40cSGreg Kurz uint32_t core_id) 680c4b2c40cSGreg Kurz { 681c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 682c4b2c40cSGreg Kurz } 683c4b2c40cSGreg Kurz 684c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 685c4b2c40cSGreg Kurz uint32_t core_id) 686c4b2c40cSGreg Kurz { 687c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 688c4b2c40cSGreg Kurz } 689c4b2c40cSGreg Kurz 690c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 691c4b2c40cSGreg Kurz uint32_t core_id) 692c4b2c40cSGreg Kurz { 693c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 694c4b2c40cSGreg Kurz } 695c4b2c40cSGreg Kurz 696f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 697f30c843cSCédric Le Goater { 698f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 699f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 700f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 701f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 702f30c843cSCédric Le Goater 703f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 704f30c843cSCédric Le Goater } 705f30c843cSCédric Le Goater 706e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 707e2392d43SCédric Le Goater { 708c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 709e2392d43SCédric Le Goater 7105325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); 7115325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); 712c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 713e2392d43SCédric Le Goater } 714e2392d43SCédric Le Goater 7152b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 7162b548a42SCédric Le Goater { 7178b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 7188b50ce85SCédric Le Goater 7198b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 7202b548a42SCédric Le Goater } 7212b548a42SCédric Le Goater 722458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */ 723458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id) 724458c6f01SCédric Le Goater { 725458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv); 726458c6f01SCédric Le Goater uint64_t ram_per_chip; 727458c6f01SCédric Le Goater 728458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB); 729458c6f01SCédric Le Goater 730458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips; 731458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) { 732458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 733458c6f01SCédric Le Goater } 734458c6f01SCédric Le Goater 735f640afecSCédric Le Goater assert(pnv->num_chips > 1); 736f640afecSCédric Le Goater 737458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1); 738458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 739458c6f01SCédric Le Goater } 740458c6f01SCédric Le Goater 741b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 7429e933f4aSBenjamin Herrenschmidt { 743cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME; 744b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 745f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 7469e933f4aSBenjamin Herrenschmidt char *fw_filename; 7479e933f4aSBenjamin Herrenschmidt long fw_size; 748458c6f01SCédric Le Goater uint64_t chip_ram_start = 0; 749e997040eSCédric Le Goater int i; 750e997040eSCédric Le Goater char *chip_typename; 75135dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 75235dde576SCédric Le Goater DeviceState *dev; 7539e933f4aSBenjamin Herrenschmidt 754ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) { 755ebe6c3faSDaniel Henrique Barboza error_report("The powernv machine does not work with KVM acceleration"); 756ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE); 757ebe6c3faSDaniel Henrique Barboza } 758ebe6c3faSDaniel Henrique Barboza 7599e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 760dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) { 761dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size); 762dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz); 763dd7ef911SCédric Le Goater g_free(sz); 764dd7ef911SCédric Le Goater exit(EXIT_FAILURE); 7659e933f4aSBenjamin Herrenschmidt } 766173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 7679e933f4aSBenjamin Herrenschmidt 76835dde576SCédric Le Goater /* 76935dde576SCédric Le Goater * Create our simple PNOR device 77035dde576SCédric Le Goater */ 7713e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 77235dde576SCédric Le Goater if (pnor) { 773934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 77435dde576SCédric Le Goater } 7753c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 77635dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 77735dde576SCédric Le Goater 7789e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 7799e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 78015fcedb2SCédric Le Goater if (!fw_filename) { 78115fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 78215fcedb2SCédric Le Goater exit(1); 78315fcedb2SCédric Le Goater } 7849e933f4aSBenjamin Herrenschmidt 78508c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 7869e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 78715fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 7889e933f4aSBenjamin Herrenschmidt exit(1); 7899e933f4aSBenjamin Herrenschmidt } 7909e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 7919e933f4aSBenjamin Herrenschmidt 7929e933f4aSBenjamin Herrenschmidt /* load kernel */ 7939e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 7949e933f4aSBenjamin Herrenschmidt long kernel_size; 7959e933f4aSBenjamin Herrenschmidt 7969e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 797b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 7989e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 799802fc7abSThomas Huth error_report("Could not load kernel '%s'", 8009e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 8019e933f4aSBenjamin Herrenschmidt exit(1); 8029e933f4aSBenjamin Herrenschmidt } 8039e933f4aSBenjamin Herrenschmidt } 8049e933f4aSBenjamin Herrenschmidt 8059e933f4aSBenjamin Herrenschmidt /* load initrd */ 8069e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 8079e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 8089e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 809584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 8109e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 811802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 8129e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 8139e933f4aSBenjamin Herrenschmidt exit(1); 8149e933f4aSBenjamin Herrenschmidt } 8159e933f4aSBenjamin Herrenschmidt } 816e997040eSCédric Le Goater 8174f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 8184f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 8194f9924c4SBenjamin Herrenschmidt 820f30c843cSCédric Le Goater /* 821f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 822f30c843cSCédric Le Goater * default. 823f30c843cSCédric Le Goater */ 824f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 825f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 826f30c843cSCédric Le Goater machine->cpu_type, mc->name); 827f30c843cSCédric Le Goater exit(1); 828f30c843cSCédric Le Goater } 829f30c843cSCédric Le Goater 830e997040eSCédric Le Goater /* Create the processor chips */ 8314a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 8327fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 8334a12c699SIgor Mammedov i, machine->cpu_type); 834e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 835f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 836f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 837e997040eSCédric Le Goater exit(1); 838e997040eSCédric Le Goater } 839e997040eSCédric Le Goater 840e44acde2SGreg Kurz pnv->num_chips = 841e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 842e44acde2SGreg Kurz /* 843e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 844e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 845e44acde2SGreg Kurz */ 846ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) { 847e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 848ab17a3feSCédric Le Goater error_printf( 849ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n"); 850e44acde2SGreg Kurz exit(1); 851e44acde2SGreg Kurz } 852e44acde2SGreg Kurz 853e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 854e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 855e997040eSCédric Le Goater char chip_name[32]; 856df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 8570e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i); 858e997040eSCédric Le Goater 859e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 860e997040eSCédric Le Goater 861458c6f01SCédric Le Goater /* Distribute RAM among the chips */ 862458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start, 863e997040eSCédric Le Goater &error_fatal); 864458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size, 865458c6f01SCédric Le Goater &error_fatal); 866458c6f01SCédric Le Goater chip_ram_start += chip_ram_size; 867e997040eSCédric Le Goater 8680e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i); 869d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 8700e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal); 8715325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores, 8725325cc34SMarkus Armbruster &error_fatal); 8735325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads, 8745325cc34SMarkus Armbruster &error_fatal); 875245cdb7fSCédric Le Goater /* 876245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 877245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 878245cdb7fSCédric Le Goater */ 879245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 8805325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); 881245cdb7fSCédric Le Goater } 882d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 8835325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv), 884d1214b81SGreg Kurz &error_abort); 885d1214b81SGreg Kurz } 8863c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 887e997040eSCédric Le Goater } 888e997040eSCédric Le Goater g_free(chip_typename); 8893495b6b6SCédric Le Goater 8903495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 89104026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 8923495b6b6SCédric Le Goater 8933495b6b6SCédric Le Goater /* Create serial port */ 894def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 8953495b6b6SCédric Le Goater 8963495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 8976c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 898bce0b691SCédric Le Goater 89925f3170bSCédric Le Goater /* 90025f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 90125f3170bSCédric Le Goater * communication with the BMC 90225f3170bSCédric Le Goater */ 90325f3170bSCédric Le Goater if (defaults_enabled()) { 90425f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 905e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 90625f3170bSCédric Le Goater } 907e2392d43SCédric Le Goater 90859b7c1c2SBalamuruhan S /* 909032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC. 910032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops, 911032c226bSCédric Le Goater * map it always for now. 912032c226bSCédric Le Goater */ 913032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, 914032c226bSCédric Le Goater &pnv->pnor->mmio); 915032c226bSCédric Le Goater 916032c226bSCédric Le Goater /* 91759b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 91859b7c1c2SBalamuruhan S * host to powerdown 91959b7c1c2SBalamuruhan S */ 920bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 921bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 922e997040eSCédric Le Goater } 923e997040eSCédric Le Goater 924631adaffSCédric Le Goater /* 925631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 926631adaffSCédric Le Goater * 22:24 Chip ID 927631adaffSCédric Le Goater * 25:28 Core number 928631adaffSCédric Le Goater * 29:31 Thread ID 929631adaffSCédric Le Goater */ 930631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 931631adaffSCédric Le Goater { 932631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 933631adaffSCédric Le Goater } 934631adaffSCédric Le Goater 9358fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 936d35aefa9SCédric Le Goater Error **errp) 937d35aefa9SCédric Le Goater { 938245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 9398fa1f4efSCédric Le Goater Error *local_err = NULL; 9408fa1f4efSCédric Le Goater Object *obj; 9418907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9428fa1f4efSCédric Le Goater 943245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 9448fa1f4efSCédric Le Goater if (local_err) { 9458fa1f4efSCédric Le Goater error_propagate(errp, local_err); 9468fa1f4efSCédric Le Goater return; 9478fa1f4efSCédric Le Goater } 9488fa1f4efSCédric Le Goater 949956b8f46SCédric Le Goater pnv_cpu->intc = obj; 950d35aefa9SCédric Le Goater } 951d35aefa9SCédric Le Goater 9520990ce6aSGreg Kurz 953d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 954d49e8a9bSCédric Le Goater { 955d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 956d49e8a9bSCédric Le Goater 957d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 958d49e8a9bSCédric Le Goater } 959d49e8a9bSCédric Le Goater 9600990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9610990ce6aSGreg Kurz { 9620990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9630990ce6aSGreg Kurz 9640990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 9650990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9660990ce6aSGreg Kurz } 9670990ce6aSGreg Kurz 96885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 96985913070SGreg Kurz Monitor *mon) 97085913070SGreg Kurz { 97185913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 97285913070SGreg Kurz } 97385913070SGreg Kurz 974631adaffSCédric Le Goater /* 975631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 976631adaffSCédric Le Goater * 49:52 Node ID 977631adaffSCédric Le Goater * 53:55 Chip ID 978631adaffSCédric Le Goater * 56 Reserved - Read as zero 979631adaffSCédric Le Goater * 57:61 Core number 980631adaffSCédric Le Goater * 62:63 Thread ID 981631adaffSCédric Le Goater * 982631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 983631adaffSCédric Le Goater */ 984631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 985631adaffSCédric Le Goater { 986631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 987631adaffSCédric Le Goater } 988631adaffSCédric Le Goater 9892b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 9902b548a42SCédric Le Goater { 9912b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 9922b548a42SCédric Le Goater } 9932b548a42SCédric Le Goater 9948fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 995d35aefa9SCédric Le Goater Error **errp) 996d35aefa9SCédric Le Goater { 9972dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 9982dfa91a2SCédric Le Goater Error *local_err = NULL; 9992dfa91a2SCédric Le Goater Object *obj; 10002dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10012dfa91a2SCédric Le Goater 10022dfa91a2SCédric Le Goater /* 10032dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 10042dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 10052dfa91a2SCédric Le Goater * only used at runtime. 10062dfa91a2SCédric Le Goater */ 100747950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 100847950946SCédric Le Goater &local_err); 10092dfa91a2SCédric Le Goater if (local_err) { 10102dfa91a2SCédric Le Goater error_propagate(errp, local_err); 10118fa1f4efSCédric Le Goater return; 1012d35aefa9SCédric Le Goater } 1013d35aefa9SCédric Le Goater 10142dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 10152dfa91a2SCédric Le Goater } 10162dfa91a2SCédric Le Goater 1017d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1018d49e8a9bSCédric Le Goater { 1019d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1020d49e8a9bSCédric Le Goater 1021d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 1022d49e8a9bSCédric Le Goater } 1023d49e8a9bSCédric Le Goater 10240990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10250990ce6aSGreg Kurz { 10260990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10270990ce6aSGreg Kurz 10280990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 10290990ce6aSGreg Kurz pnv_cpu->intc = NULL; 10300990ce6aSGreg Kurz } 10310990ce6aSGreg Kurz 103285913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 103385913070SGreg Kurz Monitor *mon) 103485913070SGreg Kurz { 103585913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 103685913070SGreg Kurz } 103785913070SGreg Kurz 10382b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 10392b548a42SCédric Le Goater Error **errp) 10402b548a42SCédric Le Goater { 10412b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10422b548a42SCédric Le Goater 10432b548a42SCédric Le Goater /* Will be defined when the interrupt controller is */ 10442b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10452b548a42SCédric Le Goater } 10462b548a42SCédric Le Goater 10472b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 10482b548a42SCédric Le Goater { 10492b548a42SCédric Le Goater ; 10502b548a42SCédric Le Goater } 10512b548a42SCédric Le Goater 10522b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10532b548a42SCédric Le Goater { 10542b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10552b548a42SCédric Le Goater 10562b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10572b548a42SCédric Le Goater } 10582b548a42SCédric Le Goater 105985913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 106085913070SGreg Kurz Monitor *mon) 106185913070SGreg Kurz { 106285913070SGreg Kurz } 106385913070SGreg Kurz 106459b7c1c2SBalamuruhan S /* 106559b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1066397a79e7SCédric Le Goater * 1067397a79e7SCédric Le Goater * <EX0 reserved> 1068397a79e7SCédric Le Goater * EX1 - Venice only 1069397a79e7SCédric Le Goater * EX2 - Venice only 1070397a79e7SCédric Le Goater * EX3 - Venice only 1071397a79e7SCédric Le Goater * EX4 1072397a79e7SCédric Le Goater * EX5 1073397a79e7SCédric Le Goater * EX6 1074397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1075397a79e7SCédric Le Goater * EX9 - Venice only 1076397a79e7SCédric Le Goater * EX10 - Venice only 1077397a79e7SCédric Le Goater * EX11 - Venice only 1078397a79e7SCédric Le Goater * EX12 1079397a79e7SCédric Le Goater * EX13 1080397a79e7SCédric Le Goater * EX14 1081397a79e7SCédric Le Goater * <EX15 reserved> 1082397a79e7SCédric Le Goater */ 1083397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1084397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1085397a79e7SCédric Le Goater 1086397a79e7SCédric Le Goater /* 108709279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1088397a79e7SCédric Le Goater */ 108909279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1090397a79e7SCédric Le Goater 10912b548a42SCédric Le Goater 10922b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 10932b548a42SCédric Le Goater 109477864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 109577864267SCédric Le Goater { 10969ae1329eSCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 109777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 10989ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 10999ae1329eSCédric Le Goater int i; 110077864267SCédric Le Goater 1101245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1102245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1103245cdb7fSCédric Le Goater object_property_allow_set_link, 1104d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1105245cdb7fSCédric Le Goater 11069fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 110777864267SCédric Le Goater 11089fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 110977864267SCédric Le Goater 11109fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 11113887d241SBalamuruhan S 11129fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 11139ae1329eSCédric Le Goater 11149ae1329eSCédric Le Goater for (i = 0; i < pcc->num_phbs; i++) { 11159fc7fc4dSMarkus Armbruster object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); 11169ae1329eSCédric Le Goater } 11179ae1329eSCédric Le Goater 11189ae1329eSCédric Le Goater /* 11199ae1329eSCédric Le Goater * Number of PHBs is the chip default 11209ae1329eSCédric Le Goater */ 11219ae1329eSCédric Le Goater chip->num_phbs = pcc->num_phbs; 112277864267SCédric Le Goater } 112377864267SCédric Le Goater 112477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 112577864267SCédric Le Goater { 112677864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 112777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 112877864267SCédric Le Goater int i, j; 112977864267SCédric Le Goater char *name; 113077864267SCédric Le Goater 113177864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 113277864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 113377864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 113477864267SCédric Le Goater g_free(name); 113577864267SCédric Le Goater 113677864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 113777864267SCédric Le Goater 113877864267SCédric Le Goater /* Map the ICP registers for each thread */ 113977864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 11404fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 114177864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 114277864267SCédric Le Goater 114377864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 114477864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1145245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 114677864267SCédric Le Goater 114777864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 114877864267SCédric Le Goater &icp->mmio); 114977864267SCédric Le Goater } 115077864267SCédric Le Goater } 115177864267SCédric Le Goater } 115277864267SCédric Le Goater 115377864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 115477864267SCédric Le Goater { 115577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 115677864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 115777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1158ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 115977864267SCédric Le Goater Error *local_err = NULL; 11609ae1329eSCédric Le Goater int i; 116177864267SCédric Le Goater 1162245cdb7fSCédric Le Goater assert(chip8->xics); 1163245cdb7fSCédric Le Goater 1164709044fdSCédric Le Goater /* XSCOM bridge is first */ 1165709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1166709044fdSCédric Le Goater if (local_err) { 1167709044fdSCédric Le Goater error_propagate(errp, local_err); 1168709044fdSCédric Le Goater return; 1169709044fdSCédric Le Goater } 1170709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1171709044fdSCédric Le Goater 117277864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 117377864267SCédric Le Goater if (local_err) { 117477864267SCédric Le Goater error_propagate(errp, local_err); 117577864267SCédric Le Goater return; 117677864267SCédric Le Goater } 117777864267SCédric Le Goater 117877864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 11795325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), 11805325cc34SMarkus Armbruster &error_fatal); 11815325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, 11825325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort); 1183668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { 118477864267SCédric Le Goater return; 118577864267SCédric Le Goater } 1186ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1187ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 118877864267SCédric Le Goater 118977864267SCédric Le Goater /* Create LPC controller */ 11905325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi), 1191b63f3893SGreg Kurz &error_abort); 1192ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 119377864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 119477864267SCédric Le Goater 1195032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw; 119664d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 119764d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 119864d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 119964d011d5SCédric Le Goater 120059b7c1c2SBalamuruhan S /* 120159b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 120259b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 120359b7c1c2SBalamuruhan S */ 120477864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 120577864267SCédric Le Goater if (local_err) { 120677864267SCédric Le Goater error_propagate(errp, local_err); 120777864267SCédric Le Goater return; 120877864267SCédric Le Goater } 120977864267SCédric Le Goater 121077864267SCédric Le Goater /* Create the simplified OCC model */ 12115325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi), 1212ee3d2713SGreg Kurz &error_abort); 1213668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { 121477864267SCédric Le Goater return; 121577864267SCédric Le Goater } 121677864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1217f3db8266SBalamuruhan S 1218f3db8266SBalamuruhan S /* OCC SRAM model */ 12193a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1220f3db8266SBalamuruhan S &chip8->occ.sram_regs); 12213887d241SBalamuruhan S 12223887d241SBalamuruhan S /* HOMER */ 12235325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), 1224f2582acfSGreg Kurz &error_abort); 1225668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { 12263887d241SBalamuruhan S return; 12273887d241SBalamuruhan S } 12288f092316SCédric Le Goater /* Homer Xscom region */ 12298f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 12308f092316SCédric Le Goater 12318f092316SCédric Le Goater /* Homer mmio region */ 12323887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 12333887d241SBalamuruhan S &chip8->homer.regs); 12349ae1329eSCédric Le Goater 12359ae1329eSCédric Le Goater /* PHB3 controllers */ 12369ae1329eSCédric Le Goater for (i = 0; i < chip->num_phbs; i++) { 12379ae1329eSCédric Le Goater PnvPHB3 *phb = &chip8->phbs[i]; 12389ae1329eSCédric Le Goater 12395325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal); 12405325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, 12419ae1329eSCédric Le Goater &error_fatal); 12422c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip), 12432c4d3a50SCédric Le Goater &error_fatal); 1244668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { 12459ae1329eSCédric Le Goater return; 12469ae1329eSCédric Le Goater } 12479ae1329eSCédric Le Goater } 124877864267SCédric Le Goater } 124977864267SCédric Le Goater 125070c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 125170c059e9SGreg Kurz { 125270c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 125370c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 125470c059e9SGreg Kurz } 125570c059e9SGreg Kurz 1256e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1257e997040eSCédric Le Goater { 1258e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1259e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1260e997040eSCédric Le Goater 1261e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1262397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 12639ae1329eSCédric Le Goater k->num_phbs = 3; 1264631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1265d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1266d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12670990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 126885913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 126904026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1270eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1271d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1272c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 127370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1274e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 127577864267SCédric Le Goater 127677864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 127777864267SCédric Le Goater &k->parent_realize); 1278e997040eSCédric Le Goater } 1279e997040eSCédric Le Goater 1280e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1281e997040eSCédric Le Goater { 1282e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1283e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1284e997040eSCédric Le Goater 1285e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1286397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 12879ae1329eSCédric Le Goater k->num_phbs = 3; 1288631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1289d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1290d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12910990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 129285913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 129304026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1294eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1295d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1296c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 129770c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1298e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 129977864267SCédric Le Goater 130077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 130177864267SCédric Le Goater &k->parent_realize); 1302e997040eSCédric Le Goater } 1303e997040eSCédric Le Goater 1304e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1305e997040eSCédric Le Goater { 1306e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1307e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1308e997040eSCédric Le Goater 1309e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1310397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 13119ae1329eSCédric Le Goater k->num_phbs = 3; 1312631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1313d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1314d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13150990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 131685913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 131704026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1318eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1319d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1320c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 132170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1322e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 132377864267SCédric Le Goater 132477864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 132577864267SCédric Le Goater &k->parent_realize); 132677864267SCédric Le Goater } 132777864267SCédric Le Goater 132877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 132977864267SCédric Le Goater { 13304f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 13312dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 13324f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 13334f9924c4SBenjamin Herrenschmidt int i; 13342dfa91a2SCédric Le Goater 1335db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1336d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1337d2623129SMarkus Armbruster "xive-fabric"); 1338c38536bcSCédric Le Goater 13399fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 134015376c66SCédric Le Goater 13419fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 13426598a70dSCédric Le Goater 13439fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 13443887d241SBalamuruhan S 13459fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 13464f9924c4SBenjamin Herrenschmidt 1347422fd92eSCédric Le Goater /* Number of PECs is the chip default */ 1348422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs; 1349422fd92eSCédric Le Goater 1350422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 13514f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 13529fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 13534f9924c4SBenjamin Herrenschmidt } 135477864267SCédric Le Goater } 135577864267SCédric Le Goater 13565dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 13575dad902cSCédric Le Goater { 13585dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 13595dad902cSCédric Le Goater int i; 13605dad902cSCédric Le Goater 13615dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 13625dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 13635dad902cSCédric Le Goater 13645dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 13655dad902cSCédric Le Goater char eq_name[32]; 13665dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 13674fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 13685dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 13695dad902cSCédric Le Goater 13705dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 13719fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 13729fc7fc4dSMarkus Armbruster sizeof(*eq), TYPE_PNV_QUAD, 13739fc7fc4dSMarkus Armbruster &error_fatal, NULL); 13745dad902cSCédric Le Goater 137592612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); 1376ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 13775dad902cSCédric Le Goater 137892612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), 13795dad902cSCédric Le Goater &eq->xscom_regs); 13805dad902cSCédric Le Goater } 13815dad902cSCédric Le Goater } 13825dad902cSCédric Le Goater 13834f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp) 13844f9924c4SBenjamin Herrenschmidt { 13854f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 13864f9924c4SBenjamin Herrenschmidt int i, j; 13874f9924c4SBenjamin Herrenschmidt int phb_id = 0; 13884f9924c4SBenjamin Herrenschmidt 1389422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 13904f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 13914f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 13924f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 13934f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 13944f9924c4SBenjamin Herrenschmidt 13955325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 13964f9924c4SBenjamin Herrenschmidt /* 13974f9924c4SBenjamin Herrenschmidt * PEC0 -> 1 stack 13984f9924c4SBenjamin Herrenschmidt * PEC1 -> 2 stacks 13994f9924c4SBenjamin Herrenschmidt * PEC2 -> 3 stacks 14004f9924c4SBenjamin Herrenschmidt */ 14015325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "num-stacks", i + 1, 14024f9924c4SBenjamin Herrenschmidt &error_fatal); 14035325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 14044f9924c4SBenjamin Herrenschmidt &error_fatal); 1405*6f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 1406*6f43d255SCédric Le Goater &error_fatal); 14075325cc34SMarkus Armbruster object_property_set_link(OBJECT(pec), "system-memory", 14085325cc34SMarkus Armbruster OBJECT(get_system_memory()), &error_abort); 1409668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) { 14104f9924c4SBenjamin Herrenschmidt return; 14114f9924c4SBenjamin Herrenschmidt } 14124f9924c4SBenjamin Herrenschmidt 14134f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 14144f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 14154f9924c4SBenjamin Herrenschmidt 14164f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 14174f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 14184f9924c4SBenjamin Herrenschmidt 1419422fd92eSCédric Le Goater for (j = 0; j < pec->num_stacks; j++, phb_id++) { 14204f9924c4SBenjamin Herrenschmidt PnvPhb4PecStack *stack = &pec->stacks[j]; 14214f9924c4SBenjamin Herrenschmidt Object *obj = OBJECT(&stack->phb); 14224f9924c4SBenjamin Herrenschmidt 14235325cc34SMarkus Armbruster object_property_set_int(obj, "index", phb_id, &error_fatal); 14245325cc34SMarkus Armbruster object_property_set_int(obj, "chip-id", chip->chip_id, 14254f9924c4SBenjamin Herrenschmidt &error_fatal); 142612060cbdSCédric Le Goater object_property_set_int(obj, "version", pecc->version, 14274f9924c4SBenjamin Herrenschmidt &error_fatal); 142812060cbdSCédric Le Goater object_property_set_int(obj, "device-id", pecc->device_id, 14294f9924c4SBenjamin Herrenschmidt &error_fatal); 14305325cc34SMarkus Armbruster object_property_set_link(obj, "stack", OBJECT(stack), 14315325cc34SMarkus Armbruster &error_abort); 1432668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) { 14334f9924c4SBenjamin Herrenschmidt return; 14344f9924c4SBenjamin Herrenschmidt } 14354f9924c4SBenjamin Herrenschmidt 14364f9924c4SBenjamin Herrenschmidt /* Populate the XSCOM address space. */ 14374f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14384f9924c4SBenjamin Herrenschmidt pec_nest_base + 0x40 * (stack->stack_no + 1), 14394f9924c4SBenjamin Herrenschmidt &stack->nest_regs_mr); 14404f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14414f9924c4SBenjamin Herrenschmidt pec_pci_base + 0x40 * (stack->stack_no + 1), 14424f9924c4SBenjamin Herrenschmidt &stack->pci_regs_mr); 14434f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14444f9924c4SBenjamin Herrenschmidt pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + 14454f9924c4SBenjamin Herrenschmidt 0x40 * stack->stack_no, 14464f9924c4SBenjamin Herrenschmidt &stack->phb_regs_mr); 14474f9924c4SBenjamin Herrenschmidt } 14484f9924c4SBenjamin Herrenschmidt } 14494f9924c4SBenjamin Herrenschmidt } 14504f9924c4SBenjamin Herrenschmidt 145177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 145277864267SCédric Le Goater { 145377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 14542dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 14552dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1456c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 145777864267SCédric Le Goater Error *local_err = NULL; 145877864267SCédric Le Goater 1459709044fdSCédric Le Goater /* XSCOM bridge is first */ 1460709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1461709044fdSCédric Le Goater if (local_err) { 1462709044fdSCédric Le Goater error_propagate(errp, local_err); 1463709044fdSCédric Le Goater return; 1464709044fdSCédric Le Goater } 1465709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1466709044fdSCédric Le Goater 146777864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 146877864267SCédric Le Goater if (local_err) { 146977864267SCédric Le Goater error_propagate(errp, local_err); 147077864267SCédric Le Goater return; 147177864267SCédric Le Goater } 14722dfa91a2SCédric Le Goater 14735dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 14745dad902cSCédric Le Goater if (local_err) { 14755dad902cSCédric Le Goater error_propagate(errp, local_err); 14765dad902cSCédric Le Goater return; 14775dad902cSCédric Le Goater } 14785dad902cSCédric Le Goater 14792dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 14805325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar", 14815325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal); 14825325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar", 14835325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal); 14845325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar", 14855325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal); 14865325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar", 14875325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal); 14885325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), 14897ae54cc3SGreg Kurz &error_abort); 1490668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { 14912dfa91a2SCédric Le Goater return; 14922dfa91a2SCédric Le Goater } 14932dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 14942dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1495c38536bcSCédric Le Goater 1496c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 14975325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), 14985325cc34SMarkus Armbruster &error_fatal); 1499668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { 1500c38536bcSCédric Le Goater return; 1501c38536bcSCédric Le Goater } 1502c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1503c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 150415376c66SCédric Le Goater 150515376c66SCédric Le Goater /* LPC */ 15065325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi), 1507b63f3893SGreg Kurz &error_abort); 1508668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { 150915376c66SCédric Le Goater return; 151015376c66SCédric Le Goater } 151115376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 151215376c66SCédric Le Goater &chip9->lpc.xscom_regs); 151315376c66SCédric Le Goater 1514032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw; 151515376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 151615376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 15176598a70dSCédric Le Goater 15186598a70dSCédric Le Goater /* Create the simplified OCC model */ 15195325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi), 1520ee3d2713SGreg Kurz &error_abort); 1521668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { 15226598a70dSCédric Le Goater return; 15236598a70dSCédric Le Goater } 15246598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1525f3db8266SBalamuruhan S 1526f3db8266SBalamuruhan S /* OCC SRAM model */ 15273a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1528f3db8266SBalamuruhan S &chip9->occ.sram_regs); 15293887d241SBalamuruhan S 15303887d241SBalamuruhan S /* HOMER */ 15315325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), 1532f2582acfSGreg Kurz &error_abort); 1533668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { 15343887d241SBalamuruhan S return; 15353887d241SBalamuruhan S } 15368f092316SCédric Le Goater /* Homer Xscom region */ 15378f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 15388f092316SCédric Le Goater 15398f092316SCédric Le Goater /* Homer mmio region */ 15403887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 15413887d241SBalamuruhan S &chip9->homer.regs); 15424f9924c4SBenjamin Herrenschmidt 15434f9924c4SBenjamin Herrenschmidt /* PHBs */ 15444f9924c4SBenjamin Herrenschmidt pnv_chip_power9_phb_realize(chip, &local_err); 15454f9924c4SBenjamin Herrenschmidt if (local_err) { 15464f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 15474f9924c4SBenjamin Herrenschmidt return; 15484f9924c4SBenjamin Herrenschmidt } 1549e997040eSCédric Le Goater } 1550e997040eSCédric Le Goater 155170c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 155270c059e9SGreg Kurz { 155370c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 155470c059e9SGreg Kurz return addr >> 3; 155570c059e9SGreg Kurz } 155670c059e9SGreg Kurz 1557e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1558e997040eSCédric Le Goater { 1559e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1560e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1561e997040eSCédric Le Goater 156283028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1563397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1564631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1565d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1566d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 15670990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 156885913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 156904026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1570eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1571d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1572c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 157370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1574e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 1575422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC; 157677864267SCédric Le Goater 157777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 157877864267SCédric Le Goater &k->parent_realize); 1579e997040eSCédric Le Goater } 1580e997040eSCédric Le Goater 15812b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 15822b548a42SCédric Le Goater { 15838b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 15848b50ce85SCédric Le Goater 15859fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 15869fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 15872b548a42SCédric Le Goater } 15882b548a42SCédric Le Goater 15892b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 15902b548a42SCédric Le Goater { 15912b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 15922b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 15938b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 15942b548a42SCédric Le Goater Error *local_err = NULL; 15952b548a42SCédric Le Goater 15962b548a42SCédric Le Goater /* XSCOM bridge is first */ 15972b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 15982b548a42SCédric Le Goater if (local_err) { 15992b548a42SCédric Le Goater error_propagate(errp, local_err); 16002b548a42SCédric Le Goater return; 16012b548a42SCédric Le Goater } 16022b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 16032b548a42SCédric Le Goater 16042b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 16052b548a42SCédric Le Goater if (local_err) { 16062b548a42SCédric Le Goater error_propagate(errp, local_err); 16072b548a42SCédric Le Goater return; 16082b548a42SCédric Le Goater } 16098b50ce85SCédric Le Goater 16108b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 16115325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar", 16125325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal); 1613668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { 16148b50ce85SCédric Le Goater return; 16158b50ce85SCédric Le Goater } 16168b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 16178b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 16182661f6abSCédric Le Goater 16192661f6abSCédric Le Goater /* LPC */ 16205325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip10->lpc), "psi", 16215325cc34SMarkus Armbruster OBJECT(&chip10->psi), &error_abort); 1622668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { 16232661f6abSCédric Le Goater return; 16242661f6abSCédric Le Goater } 16252661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 16262661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 16272661f6abSCédric Le Goater 1628032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw; 16292661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 16302661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 16312b548a42SCédric Le Goater } 16322b548a42SCédric Le Goater 163370c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 163470c059e9SGreg Kurz { 163570c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 163670c059e9SGreg Kurz return addr >> 3; 163770c059e9SGreg Kurz } 163870c059e9SGreg Kurz 16392b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 16402b548a42SCédric Le Goater { 16412b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 16422b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 16432b548a42SCédric Le Goater 16442b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 16452b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 16462b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 16472b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 16482b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 16492b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 165085913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 16512b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 16522b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 16532b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1654c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 165570c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 16562b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 16572b548a42SCédric Le Goater 16582b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 16592b548a42SCédric Le Goater &k->parent_realize); 16602b548a42SCédric Le Goater } 16612b548a42SCédric Le Goater 1662397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1663397a79e7SCédric Le Goater { 1664397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1665397a79e7SCédric Le Goater int cores_max; 1666397a79e7SCédric Le Goater 1667397a79e7SCédric Le Goater /* 1668397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1669397a79e7SCédric Le Goater * the chip class 1670397a79e7SCédric Le Goater */ 1671397a79e7SCédric Le Goater if (!chip->cores_mask) { 1672397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1673397a79e7SCédric Le Goater } 1674397a79e7SCédric Le Goater 1675397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1676397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1677397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1678397a79e7SCédric Le Goater chip->cores_mask); 1679397a79e7SCédric Le Goater return; 1680397a79e7SCédric Le Goater } 1681397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1682397a79e7SCédric Le Goater 1683397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 168427d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1685397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1686397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1687397a79e7SCédric Le Goater cores_max); 1688397a79e7SCédric Le Goater return; 1689397a79e7SCédric Le Goater } 1690397a79e7SCédric Le Goater } 1691397a79e7SCédric Le Goater 169251c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1693e997040eSCédric Le Goater { 1694397a79e7SCédric Le Goater Error *error = NULL; 1695d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 169640abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1697d2fd9612SCédric Le Goater int i, core_hwid; 169808c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1699397a79e7SCédric Le Goater 1700d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1701d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1702d2fd9612SCédric Le Goater return; 1703d2fd9612SCédric Le Goater } 1704d2fd9612SCédric Le Goater 1705d2fd9612SCédric Le Goater /* Cores */ 1706397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1707397a79e7SCédric Le Goater if (error) { 1708397a79e7SCédric Le Goater error_propagate(errp, error); 1709397a79e7SCédric Le Goater return; 1710397a79e7SCédric Le Goater } 1711d2fd9612SCédric Le Goater 17124fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1713d2fd9612SCédric Le Goater 1714d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1715d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1716d2fd9612SCédric Le Goater char core_name[32]; 17174fa28f23SGreg Kurz PnvCore *pnv_core; 1718c035851aSCédric Le Goater uint64_t xscom_core_base; 1719d2fd9612SCédric Le Goater 1720d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1721d2fd9612SCédric Le Goater continue; 1722d2fd9612SCédric Le Goater } 1723d2fd9612SCédric Le Goater 17244fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 17254fa28f23SGreg Kurz 1726d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1727d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 17284fa28f23SGreg Kurz chip->cores[i] = pnv_core; 17295325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads", 17305325cc34SMarkus Armbruster chip->nr_threads, &error_fatal); 17315325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, 17325325cc34SMarkus Armbruster core_hwid, &error_fatal); 17335325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "pir", 17345325cc34SMarkus Armbruster pcc->core_pir(chip, core_hwid), &error_fatal); 17355325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, 17365325cc34SMarkus Armbruster &error_fatal); 17375325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), 1738158e17a6SGreg Kurz &error_abort); 1739ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 174024ece072SCédric Le Goater 174124ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1742c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1743c035851aSCédric Le Goater 1744c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 17454fa28f23SGreg Kurz &pnv_core->xscom_regs); 1746d2fd9612SCédric Le Goater i++; 1747d2fd9612SCédric Le Goater } 174851c04728SCédric Le Goater } 174951c04728SCédric Le Goater 175051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 175151c04728SCédric Le Goater { 175251c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 175351c04728SCédric Le Goater Error *error = NULL; 175451c04728SCédric Le Goater 175551c04728SCédric Le Goater /* Cores */ 175651c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 175751c04728SCédric Le Goater if (error) { 175851c04728SCédric Le Goater error_propagate(errp, error); 175951c04728SCédric Le Goater return; 176051c04728SCédric Le Goater } 1761e997040eSCédric Le Goater } 1762e997040eSCédric Le Goater 1763e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1764e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1765e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1766e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1767397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1768397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1769764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 1770e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1771e997040eSCédric Le Goater }; 1772e997040eSCédric Le Goater 1773e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1774e997040eSCédric Le Goater { 1775e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1776e997040eSCédric Le Goater 17779d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1778e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 17794f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 1780e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1781e997040eSCédric Le Goater } 1782e997040eSCédric Le Goater 1783119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1784119eaa9dSCédric Le Goater { 1785119eaa9dSCédric Le Goater int i, j; 1786119eaa9dSCédric Le Goater 1787119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1788119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1789119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1790119eaa9dSCédric Le Goater 1791119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1792119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1793119eaa9dSCédric Le Goater return pc->threads[j]; 1794119eaa9dSCédric Le Goater } 1795119eaa9dSCédric Le Goater } 1796119eaa9dSCédric Le Goater } 1797119eaa9dSCédric Le Goater return NULL; 1798119eaa9dSCédric Le Goater } 1799119eaa9dSCédric Le Goater 18002ff73ddaSCédric Le Goater typedef struct ForeachPhb3Args { 18012ff73ddaSCédric Le Goater int irq; 18022ff73ddaSCédric Le Goater ICSState *ics; 18032ff73ddaSCédric Le Goater } ForeachPhb3Args; 18042ff73ddaSCédric Le Goater 18052ff73ddaSCédric Le Goater static int pnv_ics_get_child(Object *child, void *opaque) 18062ff73ddaSCédric Le Goater { 18072ff73ddaSCédric Le Goater ForeachPhb3Args *args = opaque; 18082ff73ddaSCédric Le Goater PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3); 18092ff73ddaSCédric Le Goater 18102ff73ddaSCédric Le Goater if (phb3) { 18112ff73ddaSCédric Le Goater if (ics_valid_irq(&phb3->lsis, args->irq)) { 18122ff73ddaSCédric Le Goater args->ics = &phb3->lsis; 18132ff73ddaSCédric Le Goater } 18142ff73ddaSCédric Le Goater if (ics_valid_irq(ICS(&phb3->msis), args->irq)) { 18152ff73ddaSCédric Le Goater args->ics = ICS(&phb3->msis); 18162ff73ddaSCédric Le Goater } 18172ff73ddaSCédric Le Goater } 18182ff73ddaSCédric Le Goater return args->ics ? 1 : 0; 18192ff73ddaSCédric Le Goater } 18202ff73ddaSCédric Le Goater 182154f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 182254f59d78SCédric Le Goater { 1823b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 18242ff73ddaSCédric Le Goater ForeachPhb3Args args = { irq, NULL }; 18252ff73ddaSCédric Le Goater int i; 182654f59d78SCédric Le Goater 182754f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 18289ae1329eSCédric Le Goater PnvChip *chip = pnv->chips[i]; 182977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 183077864267SCédric Le Goater 183177864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 183277864267SCédric Le Goater return &chip8->psi.ics; 183354f59d78SCédric Le Goater } 18342ff73ddaSCédric Le Goater 18352ff73ddaSCédric Le Goater object_child_foreach(OBJECT(chip), pnv_ics_get_child, &args); 18362ff73ddaSCédric Le Goater if (args.ics) { 18372ff73ddaSCédric Le Goater return args.ics; 18389ae1329eSCédric Le Goater } 183954f59d78SCédric Le Goater } 184054f59d78SCédric Le Goater return NULL; 184154f59d78SCédric Le Goater } 184254f59d78SCédric Le Goater 18432ff73ddaSCédric Le Goater static int pnv_ics_resend_child(Object *child, void *opaque) 18442ff73ddaSCédric Le Goater { 18452ff73ddaSCédric Le Goater PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3); 18462ff73ddaSCédric Le Goater 18472ff73ddaSCédric Le Goater if (phb3) { 18482ff73ddaSCédric Le Goater ics_resend(&phb3->lsis); 18492ff73ddaSCédric Le Goater ics_resend(ICS(&phb3->msis)); 18502ff73ddaSCédric Le Goater } 18512ff73ddaSCédric Le Goater return 0; 18522ff73ddaSCédric Le Goater } 18532ff73ddaSCédric Le Goater 185454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 185554f59d78SCédric Le Goater { 1856b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 18572ff73ddaSCédric Le Goater int i; 185854f59d78SCédric Le Goater 185954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 18609ae1329eSCédric Le Goater PnvChip *chip = pnv->chips[i]; 186177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 18629ae1329eSCédric Le Goater 186377864267SCédric Le Goater ics_resend(&chip8->psi.ics); 18642ff73ddaSCédric Le Goater object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL); 186554f59d78SCédric Le Goater } 186654f59d78SCédric Le Goater } 186754f59d78SCédric Le Goater 186836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 186936fc6f08SCédric Le Goater { 187036fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 187136fc6f08SCédric Le Goater 1872956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 187336fc6f08SCédric Le Goater } 187436fc6f08SCédric Le Goater 187547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 187647fea43aSCédric Le Goater Monitor *mon) 187747fea43aSCédric Le Goater { 1878b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 187954f59d78SCédric Le Goater int i; 188047fea43aSCédric Le Goater CPUState *cs; 188147fea43aSCédric Le Goater 188247fea43aSCédric Le Goater CPU_FOREACH(cs) { 188347fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 188447fea43aSCédric Le Goater 188585913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 188685913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 188785913070SGreg Kurz mon); 1888d8e4aad5SCédric Le Goater } 188954f59d78SCédric Le Goater 189054f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1891d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 189254f59d78SCédric Le Goater } 189347fea43aSCédric Le Goater } 189447fea43aSCédric Le Goater 1895c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1896c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1897c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1898c722579eSCédric Le Goater uint32_t logic_serv, 1899c722579eSCédric Le Goater XiveTCTXMatch *match) 1900c722579eSCédric Le Goater { 1901c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1902c722579eSCédric Le Goater int total_count = 0; 1903c722579eSCédric Le Goater int i; 1904c722579eSCédric Le Goater 1905c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1906c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1907c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1908c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1909c722579eSCédric Le Goater int count; 1910c722579eSCédric Le Goater 1911c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1912c722579eSCédric Le Goater priority, logic_serv, match); 1913c722579eSCédric Le Goater 1914c722579eSCédric Le Goater if (count < 0) { 1915c722579eSCédric Le Goater return count; 1916c722579eSCédric Le Goater } 1917c722579eSCédric Le Goater 1918c722579eSCédric Le Goater total_count += count; 1919c722579eSCédric Le Goater } 1920c722579eSCédric Le Goater 1921c722579eSCédric Le Goater return total_count; 1922c722579eSCédric Le Goater } 1923c722579eSCédric Le Goater 1924f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 19259e933f4aSBenjamin Herrenschmidt { 19269e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 192736fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1928d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1929d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 1930f30c843cSCédric Le Goater 1931f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1932f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1933f30c843cSCédric Le Goater 1934f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1935f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1936f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1937d76f2da7SGreg Kurz 1938d76f2da7SGreg Kurz pmc->compat = compat; 1939d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 1940f30c843cSCédric Le Goater } 1941f30c843cSCédric Le Goater 1942f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1943f30c843cSCédric Le Goater { 1944f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1945c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1946d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1947d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 1948f30c843cSCédric Le Goater 1949f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1950f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1951c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1952f30c843cSCédric Le Goater 1953f30c843cSCédric Le Goater mc->alias = "powernv"; 1954d76f2da7SGreg Kurz 1955d76f2da7SGreg Kurz pmc->compat = compat; 1956d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 19577a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 1958f30c843cSCédric Le Goater } 1959f30c843cSCédric Le Goater 19602b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 19612b548a42SCédric Le Goater { 19622b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1963d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1964d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 19652b548a42SCédric Le Goater 19662b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 19676bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); 1968d76f2da7SGreg Kurz 1969d76f2da7SGreg Kurz pmc->compat = compat; 1970d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 19717a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 19722b548a42SCédric Le Goater } 19732b548a42SCédric Le Goater 197408c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 197508c3f3a7SCédric Le Goater { 197608c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 197708c3f3a7SCédric Le Goater 197808c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 197908c3f3a7SCédric Le Goater } 198008c3f3a7SCédric Le Goater 198108c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 198208c3f3a7SCédric Le Goater { 198308c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 198408c3f3a7SCédric Le Goater 198508c3f3a7SCédric Le Goater if (value) { 198608c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 198708c3f3a7SCédric Le Goater } 198808c3f3a7SCédric Le Goater } 198908c3f3a7SCédric Le Goater 199001b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 199101b552b0SNicholas Piggin { 199201b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 199301b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 199401b552b0SNicholas Piggin 199501b552b0SNicholas Piggin cpu_synchronize_state(cs); 199601b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 19970911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 199801b552b0SNicholas Piggin /* 1999fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 2000fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 2001fe837714SNicholas Piggin * (PPC_BIT(43)). 200201b552b0SNicholas Piggin */ 20030911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 2004fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 20050911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 200601b552b0SNicholas Piggin } 2007fe837714SNicholas Piggin } else { 2008fe837714SNicholas Piggin /* 2009fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 2010fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 2011fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 2012fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 2013fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 2014fe837714SNicholas Piggin */ 20150911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 2016fe837714SNicholas Piggin } 2017fe837714SNicholas Piggin } 201801b552b0SNicholas Piggin 201901b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 202001b552b0SNicholas Piggin { 202101b552b0SNicholas Piggin CPUState *cs; 202201b552b0SNicholas Piggin 202301b552b0SNicholas Piggin CPU_FOREACH(cs) { 202401b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 202501b552b0SNicholas Piggin } 202601b552b0SNicholas Piggin } 202701b552b0SNicholas Piggin 2028f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 2029f30c843cSCédric Le Goater { 2030f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 203147fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 203201b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 20339e933f4aSBenjamin Herrenschmidt 20349e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 2035b168a138SCédric Le Goater mc->init = pnv_init; 2036b168a138SCédric Le Goater mc->reset = pnv_reset; 20379e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 203859b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 203959b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 20409e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 20419e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 2042f1d18b0aSJoel Stanley /* 2043f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 2044f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 2045f1d18b0aSJoel Stanley */ 2046dd7ef911SCédric Le Goater mc->default_ram_size = 1 * GiB; 2047173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 204847fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 204901b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 205008c3f3a7SCédric Le Goater 205108c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 2052d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 205308c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 20547eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 20559e933f4aSBenjamin Herrenschmidt } 20569e933f4aSBenjamin Herrenschmidt 205777864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2058beba5c0fSIgor Mammedov { \ 2059beba5c0fSIgor Mammedov .name = type, \ 2060beba5c0fSIgor Mammedov .class_init = class_initfn, \ 206177864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 206277864267SCédric Le Goater } 206377864267SCédric Le Goater 206477864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 206577864267SCédric Le Goater { \ 206677864267SCédric Le Goater .name = type, \ 206777864267SCédric Le Goater .class_init = class_initfn, \ 206877864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2069beba5c0fSIgor Mammedov } 2070beba5c0fSIgor Mammedov 20712b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 20722b548a42SCédric Le Goater { \ 20732b548a42SCédric Le Goater .name = type, \ 20742b548a42SCédric Le Goater .class_init = class_initfn, \ 20752b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 20762b548a42SCédric Le Goater } 20772b548a42SCédric Le Goater 2078beba5c0fSIgor Mammedov static const TypeInfo types[] = { 20791aba8716SCédric Le Goater { 20802b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 20812b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20822b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 20832b548a42SCédric Le Goater }, 20842b548a42SCédric Le Goater { 20851aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 20861aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20871aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2088c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2089c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2090c722579eSCédric Le Goater { }, 2091c722579eSCédric Le Goater }, 20921aba8716SCédric Le Goater }, 20931aba8716SCédric Le Goater { 20941aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 20951aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20961aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 20971aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 20981aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 20991aba8716SCédric Le Goater { }, 21001aba8716SCédric Le Goater }, 21011aba8716SCédric Le Goater }, 2102beba5c0fSIgor Mammedov { 2103b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 21049e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2105f30c843cSCédric Le Goater .abstract = true, 21069e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2107b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2108d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 210936fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 211047fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 211101b552b0SNicholas Piggin { TYPE_NMI }, 211236fc6f08SCédric Le Goater { }, 211336fc6f08SCédric Le Goater }, 2114beba5c0fSIgor Mammedov }, 2115beba5c0fSIgor Mammedov { 2116beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2117beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2118beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2119beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2120beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2121beba5c0fSIgor Mammedov .abstract = true, 2122beba5c0fSIgor Mammedov }, 212377864267SCédric Le Goater 212477864267SCédric Le Goater /* 21252b548a42SCédric Le Goater * P10 chip and variants 21262b548a42SCédric Le Goater */ 21272b548a42SCédric Le Goater { 21282b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 21292b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 21302b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 21312b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 21322b548a42SCédric Le Goater }, 21332b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 21342b548a42SCédric Le Goater 21352b548a42SCédric Le Goater /* 213677864267SCédric Le Goater * P9 chip and variants 213777864267SCédric Le Goater */ 213877864267SCédric Le Goater { 213977864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 214077864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 214177864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 214277864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 214377864267SCédric Le Goater }, 214477864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 214577864267SCédric Le Goater 214677864267SCédric Le Goater /* 214777864267SCédric Le Goater * P8 chip and variants 214877864267SCédric Le Goater */ 214977864267SCédric Le Goater { 215077864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 215177864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 215277864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 215377864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 215477864267SCédric Le Goater }, 215577864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 215677864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 215777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2158beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 21599e933f4aSBenjamin Herrenschmidt }; 21609e933f4aSBenjamin Herrenschmidt 2161beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2162