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" 212c65db5eSPaolo Bonzini #include "qemu/datadir.h" 22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 23dd7ef911SCédric Le Goater #include "qemu/cutils.h" 249e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 2538d2448aSGreg Kurz #include "sysemu/qtest.h" 269e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 279e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2871e8a915SMarkus Armbruster #include "sysemu/reset.h" 2954d31236SMarkus Armbruster #include "sysemu/runstate.h" 30d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 318d409261SCédric Le Goater #include "sysemu/device_tree.h" 3201b552b0SNicholas Piggin #include "sysemu/hw_accel.h" 33fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 3901b552b0SNicholas Piggin #include "hw/nmi.h" 40e997040eSCédric Le Goater #include "qapi/visitor.h" 4147fea43aSCédric Le Goater #include "monitor/monitor.h" 4247fea43aSCédric Le Goater #include "hw/intc/intc.h" 43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h" 461f5d6b2aSDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.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 }; 383632fc0b3SBernhard Beschow uint32_t irq; 384cb228f5aSCédric Le Goater char *name; 385cb228f5aSCédric Le Goater int node; 386cb228f5aSCédric Le Goater 387632fc0b3SBernhard Beschow irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal); 388632fc0b3SBernhard Beschow 389cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 390cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 391cb228f5aSCédric Le Goater _FDT(node); 392cb228f5aSCédric Le Goater g_free(name); 393cb228f5aSCédric Le Goater 394cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 395cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 396cb228f5aSCédric Le Goater sizeof(compatible)))); 397cb228f5aSCédric Le Goater 398cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 399cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 400632fc0b3SBernhard Beschow _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 401cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 402cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 403cb228f5aSCédric Le Goater 404cb228f5aSCédric Le Goater /* This is needed by Linux */ 405cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 406cb228f5aSCédric Le Goater } 407cb228f5aSCédric Le Goater 408b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 40904f6c8b2SCédric Le Goater { 41004f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 41104f6c8b2SCédric Le Goater uint32_t io_base; 41204f6c8b2SCédric Le Goater uint32_t io_regs[] = { 41304f6c8b2SCédric Le Goater cpu_to_be32(1), 41404f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 41504f6c8b2SCédric Le Goater cpu_to_be32(3) 41604f6c8b2SCédric Le Goater }; 41704f6c8b2SCédric Le Goater uint32_t irq; 41804f6c8b2SCédric Le Goater char *name; 41904f6c8b2SCédric Le Goater int node; 42004f6c8b2SCédric Le Goater 42104f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 42204f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 42304f6c8b2SCédric Le Goater 42404f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 42504f6c8b2SCédric Le Goater 42604f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 42704f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 42804f6c8b2SCédric Le Goater _FDT(node); 42904f6c8b2SCédric Le Goater g_free(name); 43004f6c8b2SCédric Le Goater 4317032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4327032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4337032d92aSCédric Le Goater sizeof(compatible)))); 43404f6c8b2SCédric Le Goater 43504f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 43604f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 43704f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 43804f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 43904f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 44004f6c8b2SCédric Le Goater } 44104f6c8b2SCédric Le Goater 442e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 443e7a3fee3SCédric Le Goater void *fdt; 444e7a3fee3SCédric Le Goater int offset; 445e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 446e7a3fee3SCédric Le Goater 447b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 448e7a3fee3SCédric Le Goater { 449c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 450c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 451c5ffdcaeSCédric Le Goater 452c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 453b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 454cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 455b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 45604f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 457b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 458c5ffdcaeSCédric Le Goater } else { 459c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 460c5ffdcaeSCédric Le Goater d->ioport_id); 461c5ffdcaeSCédric Le Goater } 462c5ffdcaeSCédric Le Goater 463e7a3fee3SCédric Le Goater return 0; 464e7a3fee3SCédric Le Goater } 465e7a3fee3SCédric Le Goater 46659b7c1c2SBalamuruhan S /* 46759b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 468bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 469bb7ab95cSCédric Le Goater */ 470bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 471bb7ab95cSCédric Le Goater { 47264d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 473e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 474e7a3fee3SCédric Le Goater .fdt = fdt, 475bb7ab95cSCédric Le Goater .offset = isa_offset, 476e7a3fee3SCédric Le Goater }; 477f47a08d1SCédric Le Goater uint32_t phandle; 478e7a3fee3SCédric Le Goater 479bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 480bb7ab95cSCédric Le Goater 481f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 482f47a08d1SCédric Le Goater assert(phandle > 0); 483f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 484f47a08d1SCédric Le Goater 48559b7c1c2SBalamuruhan S /* 48659b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 48759b7c1c2SBalamuruhan S * can not use object_child_foreach() 48859b7c1c2SBalamuruhan S */ 489bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 490bb7ab95cSCédric Le Goater &args); 491e7a3fee3SCédric Le Goater } 492e7a3fee3SCédric Le Goater 4937a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 494e5694793SCédric Le Goater { 495e5694793SCédric Le Goater int off; 496e5694793SCédric Le Goater 497e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 498e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 499e5694793SCédric Le Goater 500e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 501e5694793SCédric Le Goater } 502e5694793SCédric Le Goater 503b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 5049e933f4aSBenjamin Herrenschmidt { 505d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 506b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5079e933f4aSBenjamin Herrenschmidt void *fdt; 5089e933f4aSBenjamin Herrenschmidt char *buf; 5099e933f4aSBenjamin Herrenschmidt int off; 510e997040eSCédric Le Goater int i; 5119e933f4aSBenjamin Herrenschmidt 5129e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5139e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5149e933f4aSBenjamin Herrenschmidt 515ccb099b3SCédric Le Goater /* /qemu node */ 516ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 517ccb099b3SCédric Le Goater 5189e933f4aSBenjamin Herrenschmidt /* Root node */ 5199e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5209e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5219e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5229e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 523d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5249e933f4aSBenjamin Herrenschmidt 5259e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5269e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5279e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 528bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "system-id", buf))); 5299e933f4aSBenjamin Herrenschmidt } 5309e933f4aSBenjamin Herrenschmidt g_free(buf); 5319e933f4aSBenjamin Herrenschmidt 5329e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5339e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5349e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5359e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5369e933f4aSBenjamin Herrenschmidt } 5379e933f4aSBenjamin Herrenschmidt 5389e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5399e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5409e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5419e933f4aSBenjamin Herrenschmidt 5429e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5439e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5449e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5459e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5469e933f4aSBenjamin Herrenschmidt } 5479e933f4aSBenjamin Herrenschmidt 548e997040eSCédric Le Goater /* Populate device tree for each chip */ 549e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 550eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 551e997040eSCédric Le Goater } 552e7a3fee3SCédric Le Goater 553e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 554bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 555aeaef83dSCédric Le Goater 556aeaef83dSCédric Le Goater if (pnv->bmc) { 557b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 558aeaef83dSCédric Le Goater } 559aeaef83dSCédric Le Goater 5607a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5617a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5627a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 563e5694793SCédric Le Goater } 564e5694793SCédric Le Goater 5659e933f4aSBenjamin Herrenschmidt return fdt; 5669e933f4aSBenjamin Herrenschmidt } 5679e933f4aSBenjamin Herrenschmidt 568bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 569bce0b691SCédric Le Goater { 5708f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 571bce0b691SCédric Le Goater 572bce0b691SCédric Le Goater if (pnv->bmc) { 573bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 574bce0b691SCédric Le Goater } 575bce0b691SCédric Le Goater } 576bce0b691SCédric Le Goater 577a0628599SLike Xu static void pnv_reset(MachineState *machine) 5789e933f4aSBenjamin Herrenschmidt { 57925f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 58025f3170bSCédric Le Goater IPMIBmc *bmc; 5819e933f4aSBenjamin Herrenschmidt void *fdt; 5829e933f4aSBenjamin Herrenschmidt 5839e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5849e933f4aSBenjamin Herrenschmidt 58525f3170bSCédric Le Goater /* 58625f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator. 58725f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command 58825f3170bSCédric Le Goater * line. 58925f3170bSCédric Le Goater */ 59025f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal); 59125f3170bSCédric Le Goater if (!pnv->bmc) { 59225f3170bSCédric Le Goater if (!bmc) { 59338d2448aSGreg Kurz if (!qtest_enabled()) { 59425f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 59525f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 59625f3170bSCédric Le Goater "to define one"); 59738d2448aSGreg Kurz } 59825f3170bSCédric Le Goater } else { 59925f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 60025f3170bSCédric Le Goater pnv->bmc = bmc; 60125f3170bSCédric Le Goater } 60225f3170bSCédric Le Goater } 60325f3170bSCédric Le Goater 604b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6059e933f4aSBenjamin Herrenschmidt 6069e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6079e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6089e933f4aSBenjamin Herrenschmidt 6098d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6109e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 611b2fb7a43SPan Nengyuan 612b2fb7a43SPan Nengyuan g_free(fdt); 6139e933f4aSBenjamin Herrenschmidt } 6149e933f4aSBenjamin Herrenschmidt 61504026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6163495b6b6SCédric Le Goater { 61777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 618c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL); 619c05aa140SCédric Le Goater 620c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 62177864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 62204026890SCédric Le Goater } 6233495b6b6SCédric Le Goater 62404026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 62504026890SCédric Le Goater { 62677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 627c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C); 628c05aa140SCédric Le Goater 629c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 63077864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 63104026890SCédric Le Goater } 6323495b6b6SCédric Le Goater 63304026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 63404026890SCédric Le Goater { 63515376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 636c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC); 637c05aa140SCédric Le Goater 638c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq); 63915376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 64004026890SCédric Le Goater } 6413495b6b6SCédric Le Goater 6422b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6432b548a42SCédric Le Goater { 6442661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 645c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC); 646c05aa140SCédric Le Goater 647c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq); 6482661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6492b548a42SCédric Le Goater } 6502b548a42SCédric Le Goater 65104026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 65204026890SCédric Le Goater { 65304026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6543495b6b6SCédric Le Goater } 6553495b6b6SCédric Le Goater 656d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 657d8e4aad5SCédric Le Goater { 658d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 6598a69bca7SDaniel Henrique Barboza int i; 660d8e4aad5SCédric Le Goater 661d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 6628a69bca7SDaniel Henrique Barboza 6638a69bca7SDaniel Henrique Barboza for (i = 0; i < chip8->num_phbs; i++) { 6641f5d6b2aSDaniel Henrique Barboza PnvPHB *phb = &chip8->phbs[i]; 6651f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 6668a69bca7SDaniel Henrique Barboza 6678a69bca7SDaniel Henrique Barboza pnv_phb3_msi_pic_print_info(&phb3->msis, mon); 6688a69bca7SDaniel Henrique Barboza ics_pic_print_info(&phb3->lsis, mon); 6698a69bca7SDaniel Henrique Barboza } 670d8e4aad5SCédric Le Goater } 671d8e4aad5SCédric Le Goater 6720e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque) 6730e6232bcSCédric Le Goater { 6740e6232bcSCédric Le Goater Monitor *mon = opaque; 675210aacb3SDaniel Henrique Barboza PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB); 6760e6232bcSCédric Le Goater 677210aacb3SDaniel Henrique Barboza if (!phb) { 678210aacb3SDaniel Henrique Barboza return 0; 6790e6232bcSCédric Le Goater } 680210aacb3SDaniel Henrique Barboza 681210aacb3SDaniel Henrique Barboza pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon); 682210aacb3SDaniel Henrique Barboza 6830e6232bcSCédric Le Goater return 0; 6840e6232bcSCédric Le Goater } 6850e6232bcSCédric Le Goater 686d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 687d8e4aad5SCédric Le Goater { 688d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 689d8e4aad5SCédric Le Goater 690d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 691c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 6924f9924c4SBenjamin Herrenschmidt 6930e6232bcSCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 6940e6232bcSCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 695d8e4aad5SCédric Le Goater } 696d8e4aad5SCédric Le Goater 697c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 698c4b2c40cSGreg Kurz uint32_t core_id) 699c4b2c40cSGreg Kurz { 700c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 701c4b2c40cSGreg Kurz } 702c4b2c40cSGreg Kurz 703c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 704c4b2c40cSGreg Kurz uint32_t core_id) 705c4b2c40cSGreg Kurz { 706c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 707c4b2c40cSGreg Kurz } 708c4b2c40cSGreg Kurz 709c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 710c4b2c40cSGreg Kurz uint32_t core_id) 711c4b2c40cSGreg Kurz { 712c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 713c4b2c40cSGreg Kurz } 714c4b2c40cSGreg Kurz 715f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 716f30c843cSCédric Le Goater { 717f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 718f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 719f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 720f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 721f30c843cSCédric Le Goater 72221d3a78eSNicholas Piggin return ppc_default->pvr_match(ppc_default, ppc->pvr, false); 723f30c843cSCédric Le Goater } 724f30c843cSCédric Le Goater 725e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 726e2392d43SCédric Le Goater { 727c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 728e2392d43SCédric Le Goater 7295325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); 7305325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); 731c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 732e2392d43SCédric Le Goater } 733e2392d43SCédric Le Goater 7342b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 7352b548a42SCédric Le Goater { 7368b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 7378b50ce85SCédric Le Goater 738da71b7e3SCédric Le Goater pnv_xive2_pic_print_info(&chip10->xive, mon); 7398b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 740623575e1SCédric Le Goater 741623575e1SCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 742623575e1SCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 7432b548a42SCédric Le Goater } 7442b548a42SCédric Le Goater 745458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */ 746458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id) 747458c6f01SCédric Le Goater { 748458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv); 749458c6f01SCédric Le Goater uint64_t ram_per_chip; 750458c6f01SCédric Le Goater 751458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB); 752458c6f01SCédric Le Goater 753458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips; 754458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) { 755458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 756458c6f01SCédric Le Goater } 757458c6f01SCédric Le Goater 758f640afecSCédric Le Goater assert(pnv->num_chips > 1); 759f640afecSCédric Le Goater 760458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1); 761458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 762458c6f01SCédric Le Goater } 763458c6f01SCédric Le Goater 764b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 7659e933f4aSBenjamin Herrenschmidt { 766cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME; 767b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 768f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 7699e933f4aSBenjamin Herrenschmidt char *fw_filename; 7709e933f4aSBenjamin Herrenschmidt long fw_size; 771458c6f01SCédric Le Goater uint64_t chip_ram_start = 0; 772e997040eSCédric Le Goater int i; 773e997040eSCédric Le Goater char *chip_typename; 77435dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 77535dde576SCédric Le Goater DeviceState *dev; 7769e933f4aSBenjamin Herrenschmidt 777ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) { 778ebe6c3faSDaniel Henrique Barboza error_report("The powernv machine does not work with KVM acceleration"); 779ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE); 780ebe6c3faSDaniel Henrique Barboza } 781ebe6c3faSDaniel Henrique Barboza 7829e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 783dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) { 784dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size); 785dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz); 786dd7ef911SCédric Le Goater g_free(sz); 787dd7ef911SCédric Le Goater exit(EXIT_FAILURE); 7889e933f4aSBenjamin Herrenschmidt } 789173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 7909e933f4aSBenjamin Herrenschmidt 79135dde576SCédric Le Goater /* 79235dde576SCédric Le Goater * Create our simple PNOR device 79335dde576SCédric Le Goater */ 7943e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 79535dde576SCédric Le Goater if (pnor) { 796934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 79735dde576SCédric Le Goater } 7983c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 79935dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 80035dde576SCédric Le Goater 8019e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 8029e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 80315fcedb2SCédric Le Goater if (!fw_filename) { 80415fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 80515fcedb2SCédric Le Goater exit(1); 80615fcedb2SCédric Le Goater } 8079e933f4aSBenjamin Herrenschmidt 80808c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 8099e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 81015fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 8119e933f4aSBenjamin Herrenschmidt exit(1); 8129e933f4aSBenjamin Herrenschmidt } 8139e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 8149e933f4aSBenjamin Herrenschmidt 8159e933f4aSBenjamin Herrenschmidt /* load kernel */ 8169e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 8179e933f4aSBenjamin Herrenschmidt long kernel_size; 8189e933f4aSBenjamin Herrenschmidt 8199e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 820b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 8219e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 822802fc7abSThomas Huth error_report("Could not load kernel '%s'", 8239e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 8249e933f4aSBenjamin Herrenschmidt exit(1); 8259e933f4aSBenjamin Herrenschmidt } 8269e933f4aSBenjamin Herrenschmidt } 8279e933f4aSBenjamin Herrenschmidt 8289e933f4aSBenjamin Herrenschmidt /* load initrd */ 8299e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 8309e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 8319e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 832584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 8339e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 834802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 8359e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 8369e933f4aSBenjamin Herrenschmidt exit(1); 8379e933f4aSBenjamin Herrenschmidt } 8389e933f4aSBenjamin Herrenschmidt } 839e997040eSCédric Le Goater 8404f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 8414f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 8424f9924c4SBenjamin Herrenschmidt 843f30c843cSCédric Le Goater /* 844f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 845f30c843cSCédric Le Goater * default. 846f30c843cSCédric Le Goater */ 847f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 848f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 849f30c843cSCédric Le Goater machine->cpu_type, mc->name); 850f30c843cSCédric Le Goater exit(1); 851f30c843cSCédric Le Goater } 852f30c843cSCédric Le Goater 853e997040eSCédric Le Goater /* Create the processor chips */ 8544a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 8557fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 8564a12c699SIgor Mammedov i, machine->cpu_type); 857e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 858f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 859f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 860e997040eSCédric Le Goater exit(1); 861e997040eSCédric Le Goater } 862e997040eSCédric Le Goater 863e44acde2SGreg Kurz pnv->num_chips = 864e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 865e44acde2SGreg Kurz /* 866e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 867e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 868e44acde2SGreg Kurz */ 869ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) { 870e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 871ab17a3feSCédric Le Goater error_printf( 872ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n"); 873e44acde2SGreg Kurz exit(1); 874e44acde2SGreg Kurz } 875e44acde2SGreg Kurz 876e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 877e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 878e997040eSCédric Le Goater char chip_name[32]; 879df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 8800e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i); 881e997040eSCédric Le Goater 882e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 883e997040eSCédric Le Goater 884458c6f01SCédric Le Goater /* Distribute RAM among the chips */ 885458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start, 886e997040eSCédric Le Goater &error_fatal); 887458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size, 888458c6f01SCédric Le Goater &error_fatal); 889458c6f01SCédric Le Goater chip_ram_start += chip_ram_size; 890e997040eSCédric Le Goater 8910e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i); 892d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 8930e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal); 8945325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores, 8955325cc34SMarkus Armbruster &error_fatal); 8965325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads, 8975325cc34SMarkus Armbruster &error_fatal); 898245cdb7fSCédric Le Goater /* 899245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 900245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 901245cdb7fSCédric Le Goater */ 902245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 9035325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); 904245cdb7fSCédric Le Goater } 905d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 9065325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv), 907d1214b81SGreg Kurz &error_abort); 908d1214b81SGreg Kurz } 9093c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 910e997040eSCédric Le Goater } 911e997040eSCédric Le Goater g_free(chip_typename); 9123495b6b6SCédric Le Goater 9133495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 91404026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 9153495b6b6SCédric Le Goater 9163495b6b6SCédric Le Goater /* Create serial port */ 917def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 9183495b6b6SCédric Le Goater 9193495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 9206c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 921bce0b691SCédric Le Goater 92225f3170bSCédric Le Goater /* 92325f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 92425f3170bSCédric Le Goater * communication with the BMC 92525f3170bSCédric Le Goater */ 92625f3170bSCédric Le Goater if (defaults_enabled()) { 92725f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 928e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 92925f3170bSCédric Le Goater } 930e2392d43SCédric Le Goater 93159b7c1c2SBalamuruhan S /* 932032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC. 933032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops, 934032c226bSCédric Le Goater * map it always for now. 935032c226bSCédric Le Goater */ 936032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, 937032c226bSCédric Le Goater &pnv->pnor->mmio); 938032c226bSCédric Le Goater 939032c226bSCédric Le Goater /* 94059b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 94159b7c1c2SBalamuruhan S * host to powerdown 94259b7c1c2SBalamuruhan S */ 943bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 944bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 945e997040eSCédric Le Goater } 946e997040eSCédric Le Goater 947631adaffSCédric Le Goater /* 948631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 949631adaffSCédric Le Goater * 22:24 Chip ID 950631adaffSCédric Le Goater * 25:28 Core number 951631adaffSCédric Le Goater * 29:31 Thread ID 952631adaffSCédric Le Goater */ 953631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 954631adaffSCédric Le Goater { 955631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 956631adaffSCédric Le Goater } 957631adaffSCédric Le Goater 9588fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 959d35aefa9SCédric Le Goater Error **errp) 960d35aefa9SCédric Le Goater { 961245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 9628fa1f4efSCédric Le Goater Error *local_err = NULL; 9638fa1f4efSCédric Le Goater Object *obj; 9648907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9658fa1f4efSCédric Le Goater 966245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 9678fa1f4efSCédric Le Goater if (local_err) { 9688fa1f4efSCédric Le Goater error_propagate(errp, local_err); 9698fa1f4efSCédric Le Goater return; 9708fa1f4efSCédric Le Goater } 9718fa1f4efSCédric Le Goater 972956b8f46SCédric Le Goater pnv_cpu->intc = obj; 973d35aefa9SCédric Le Goater } 974d35aefa9SCédric Le Goater 9750990ce6aSGreg Kurz 976d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 977d49e8a9bSCédric Le Goater { 978d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 979d49e8a9bSCédric Le Goater 980d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 981d49e8a9bSCédric Le Goater } 982d49e8a9bSCédric Le Goater 9830990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9840990ce6aSGreg Kurz { 9850990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9860990ce6aSGreg Kurz 9870990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 9880990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9890990ce6aSGreg Kurz } 9900990ce6aSGreg Kurz 99185913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 99285913070SGreg Kurz Monitor *mon) 99385913070SGreg Kurz { 99485913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 99585913070SGreg Kurz } 99685913070SGreg Kurz 997631adaffSCédric Le Goater /* 998631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 999631adaffSCédric Le Goater * 49:52 Node ID 1000631adaffSCédric Le Goater * 53:55 Chip ID 1001631adaffSCédric Le Goater * 56 Reserved - Read as zero 1002631adaffSCédric Le Goater * 57:61 Core number 1003631adaffSCédric Le Goater * 62:63 Thread ID 1004631adaffSCédric Le Goater * 1005631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 1006631adaffSCédric Le Goater */ 1007631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 1008631adaffSCédric Le Goater { 1009631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 1010631adaffSCédric Le Goater } 1011631adaffSCédric Le Goater 10122b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 10132b548a42SCédric Le Goater { 10142b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 10152b548a42SCédric Le Goater } 10162b548a42SCédric Le Goater 10178fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 1018d35aefa9SCédric Le Goater Error **errp) 1019d35aefa9SCédric Le Goater { 10202dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 10212dfa91a2SCédric Le Goater Error *local_err = NULL; 10222dfa91a2SCédric Le Goater Object *obj; 10232dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10242dfa91a2SCédric Le Goater 10252dfa91a2SCédric Le Goater /* 10262dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 10272dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 10282dfa91a2SCédric Le Goater * only used at runtime. 10292dfa91a2SCédric Le Goater */ 103047950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 103147950946SCédric Le Goater &local_err); 10322dfa91a2SCédric Le Goater if (local_err) { 10332dfa91a2SCédric Le Goater error_propagate(errp, local_err); 10348fa1f4efSCédric Le Goater return; 1035d35aefa9SCédric Le Goater } 1036d35aefa9SCédric Le Goater 10372dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 10382dfa91a2SCédric Le Goater } 10392dfa91a2SCédric Le Goater 1040d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1041d49e8a9bSCédric Le Goater { 1042d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1043d49e8a9bSCédric Le Goater 1044d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 1045d49e8a9bSCédric Le Goater } 1046d49e8a9bSCédric Le Goater 10470990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10480990ce6aSGreg Kurz { 10490990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10500990ce6aSGreg Kurz 10510990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 10520990ce6aSGreg Kurz pnv_cpu->intc = NULL; 10530990ce6aSGreg Kurz } 10540990ce6aSGreg Kurz 105585913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 105685913070SGreg Kurz Monitor *mon) 105785913070SGreg Kurz { 105885913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 105985913070SGreg Kurz } 106085913070SGreg Kurz 10612b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 10622b548a42SCédric Le Goater Error **errp) 10632b548a42SCédric Le Goater { 1064da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1065da71b7e3SCédric Le Goater Error *local_err = NULL; 1066da71b7e3SCédric Le Goater Object *obj; 10672b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10682b548a42SCédric Le Goater 1069da71b7e3SCédric Le Goater /* 1070da71b7e3SCédric Le Goater * The core creates its interrupt presenter but the XIVE2 interrupt 1071da71b7e3SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 1072da71b7e3SCédric Le Goater * only used at runtime. 1073da71b7e3SCédric Le Goater */ 1074da71b7e3SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive), 1075da71b7e3SCédric Le Goater &local_err); 1076da71b7e3SCédric Le Goater if (local_err) { 1077da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1078da71b7e3SCédric Le Goater return; 1079da71b7e3SCédric Le Goater } 1080da71b7e3SCédric Le Goater 1081da71b7e3SCédric Le Goater pnv_cpu->intc = obj; 10822b548a42SCédric Le Goater } 10832b548a42SCédric Le Goater 10842b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 10852b548a42SCédric Le Goater { 1086da71b7e3SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1087da71b7e3SCédric Le Goater 1088da71b7e3SCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 10892b548a42SCédric Le Goater } 10902b548a42SCédric Le Goater 10912b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10922b548a42SCédric Le Goater { 10932b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10942b548a42SCédric Le Goater 1095da71b7e3SCédric Le Goater xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 10962b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10972b548a42SCédric Le Goater } 10982b548a42SCédric Le Goater 109985913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 110085913070SGreg Kurz Monitor *mon) 110185913070SGreg Kurz { 1102da71b7e3SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 110385913070SGreg Kurz } 110485913070SGreg Kurz 110559b7c1c2SBalamuruhan S /* 110659b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1107397a79e7SCédric Le Goater * 1108397a79e7SCédric Le Goater * <EX0 reserved> 1109397a79e7SCédric Le Goater * EX1 - Venice only 1110397a79e7SCédric Le Goater * EX2 - Venice only 1111397a79e7SCédric Le Goater * EX3 - Venice only 1112397a79e7SCédric Le Goater * EX4 1113397a79e7SCédric Le Goater * EX5 1114397a79e7SCédric Le Goater * EX6 1115397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1116397a79e7SCédric Le Goater * EX9 - Venice only 1117397a79e7SCédric Le Goater * EX10 - Venice only 1118397a79e7SCédric Le Goater * EX11 - Venice only 1119397a79e7SCédric Le Goater * EX12 1120397a79e7SCédric Le Goater * EX13 1121397a79e7SCédric Le Goater * EX14 1122397a79e7SCédric Le Goater * <EX15 reserved> 1123397a79e7SCédric Le Goater */ 1124397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1125397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1126397a79e7SCédric Le Goater 1127397a79e7SCédric Le Goater /* 112809279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1129397a79e7SCédric Le Goater */ 113009279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1131397a79e7SCédric Le Goater 11322b548a42SCédric Le Goater 11332b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 11342b548a42SCédric Le Goater 113577864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 113677864267SCédric Le Goater { 113777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 11389ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 11399ae1329eSCédric Le Goater int i; 114077864267SCédric Le Goater 1141245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1142245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1143245cdb7fSCédric Le Goater object_property_allow_set_link, 1144d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1145245cdb7fSCédric Le Goater 11469fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 114777864267SCédric Le Goater 11489fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 114977864267SCédric Le Goater 11509fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 11513887d241SBalamuruhan S 11529fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 11539ae1329eSCédric Le Goater 1154eb93c828SCédric Le Goater chip8->num_phbs = pcc->num_phbs; 11551f6a88ffSCédric Le Goater 1156eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 11571f5d6b2aSDaniel Henrique Barboza object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB); 11589ae1329eSCédric Le Goater } 11599ae1329eSCédric Le Goater 116077864267SCédric Le Goater } 116177864267SCédric Le Goater 116277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 116377864267SCédric Le Goater { 116477864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 116577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 116677864267SCédric Le Goater int i, j; 116777864267SCédric Le Goater char *name; 116877864267SCédric Le Goater 116977864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 117077864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 117177864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 117277864267SCédric Le Goater g_free(name); 117377864267SCédric Le Goater 117477864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 117577864267SCédric Le Goater 117677864267SCédric Le Goater /* Map the ICP registers for each thread */ 117777864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 11784fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 117977864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 118077864267SCédric Le Goater 118177864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 118277864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1183245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 118477864267SCédric Le Goater 118577864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 118677864267SCédric Le Goater &icp->mmio); 118777864267SCédric Le Goater } 118877864267SCédric Le Goater } 118977864267SCédric Le Goater } 119077864267SCédric Le Goater 1191792e8bb6SDaniel Henrique Barboza /* 1192792e8bb6SDaniel Henrique Barboza * Attach a root port device. 1193792e8bb6SDaniel Henrique Barboza * 1194792e8bb6SDaniel Henrique Barboza * 'index' will be used both as a PCIE slot value and to calculate 1195792e8bb6SDaniel Henrique Barboza * QOM id. 'chip_id' is going to be used as PCIE chassis for the 1196792e8bb6SDaniel Henrique Barboza * root port. 1197792e8bb6SDaniel Henrique Barboza */ 1198792e8bb6SDaniel Henrique Barboza void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, 1199792e8bb6SDaniel Henrique Barboza int index, int chip_id) 1200a71cd51eSCédric Le Goater { 1201a71cd51eSCédric Le Goater PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name); 12028625164aSDaniel Henrique Barboza g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index); 12038625164aSDaniel Henrique Barboza const char *dev_id = DEVICE(root)->id; 12048625164aSDaniel Henrique Barboza 12058625164aSDaniel Henrique Barboza object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, 12068625164aSDaniel Henrique Barboza OBJECT(root)); 1207a71cd51eSCédric Le Goater 1208792e8bb6SDaniel Henrique Barboza /* Set unique chassis/slot values for the root port */ 1209792e8bb6SDaniel Henrique Barboza qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); 1210792e8bb6SDaniel Henrique Barboza qdev_prop_set_uint16(DEVICE(root), "slot", index); 1211792e8bb6SDaniel Henrique Barboza 1212a71cd51eSCédric Le Goater pci_realize_and_unref(root, pci->bus, &error_fatal); 1213a71cd51eSCédric Le Goater } 1214a71cd51eSCédric Le Goater 121577864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 121677864267SCédric Le Goater { 121777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 121877864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 121977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1220ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 122177864267SCédric Le Goater Error *local_err = NULL; 12229ae1329eSCédric Le Goater int i; 122377864267SCédric Le Goater 1224245cdb7fSCédric Le Goater assert(chip8->xics); 1225245cdb7fSCédric Le Goater 1226709044fdSCédric Le Goater /* XSCOM bridge is first */ 1227709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1228709044fdSCédric Le Goater if (local_err) { 1229709044fdSCédric Le Goater error_propagate(errp, local_err); 1230709044fdSCédric Le Goater return; 1231709044fdSCédric Le Goater } 1232709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1233709044fdSCédric Le Goater 123477864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 123577864267SCédric Le Goater if (local_err) { 123677864267SCédric Le Goater error_propagate(errp, local_err); 123777864267SCédric Le Goater return; 123877864267SCédric Le Goater } 123977864267SCédric Le Goater 124077864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 12415325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), 12425325cc34SMarkus Armbruster &error_fatal); 12435325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, 12445325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort); 1245668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { 124677864267SCédric Le Goater return; 124777864267SCédric Le Goater } 1248ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1249ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 125077864267SCédric Le Goater 125177864267SCédric Le Goater /* Create LPC controller */ 1252ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 125377864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 125477864267SCédric Le Goater 1255032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw; 125664d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 125764d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 125864d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 125964d011d5SCédric Le Goater 126059b7c1c2SBalamuruhan S /* 126159b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 126259b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 126359b7c1c2SBalamuruhan S */ 126477864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 126577864267SCédric Le Goater if (local_err) { 126677864267SCédric Le Goater error_propagate(errp, local_err); 126777864267SCédric Le Goater return; 126877864267SCédric Le Goater } 126977864267SCédric Le Goater 127077864267SCédric Le Goater /* Create the simplified OCC model */ 1271668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { 127277864267SCédric Le Goater return; 127377864267SCédric Le Goater } 127477864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1275b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->occ), 0, 1276b0ae5c69SCédric Le Goater qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC)); 1277f3db8266SBalamuruhan S 1278f3db8266SBalamuruhan S /* OCC SRAM model */ 12793a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1280f3db8266SBalamuruhan S &chip8->occ.sram_regs); 12813887d241SBalamuruhan S 12823887d241SBalamuruhan S /* HOMER */ 12835325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), 1284f2582acfSGreg Kurz &error_abort); 1285668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { 12863887d241SBalamuruhan S return; 12873887d241SBalamuruhan S } 12888f092316SCédric Le Goater /* Homer Xscom region */ 12898f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 12908f092316SCédric Le Goater 12918f092316SCédric Le Goater /* Homer mmio region */ 12923887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 12933887d241SBalamuruhan S &chip8->homer.regs); 12949ae1329eSCédric Le Goater 12951f5d6b2aSDaniel Henrique Barboza /* PHB controllers */ 1296eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 12971f5d6b2aSDaniel Henrique Barboza PnvPHB *phb = &chip8->phbs[i]; 12989ae1329eSCédric Le Goater 12995325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal); 13005325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, 13019ae1329eSCédric Le Goater &error_fatal); 13022c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip), 13032c4d3a50SCédric Le Goater &error_fatal); 1304668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { 13059ae1329eSCédric Le Goater return; 13069ae1329eSCédric Le Goater } 13079ae1329eSCédric Le Goater } 130877864267SCédric Le Goater } 130977864267SCédric Le Goater 131070c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 131170c059e9SGreg Kurz { 131270c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 131370c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 131470c059e9SGreg Kurz } 131570c059e9SGreg Kurz 1316e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1317e997040eSCédric Le Goater { 1318e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1319e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1320e997040eSCédric Le Goater 1321e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1322397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 13239ae1329eSCédric Le Goater k->num_phbs = 3; 1324631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1325d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1326d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13270990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 132885913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 132904026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1330eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1331d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1332c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 133370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1334e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 133577864267SCédric Le Goater 133677864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 133777864267SCédric Le Goater &k->parent_realize); 1338e997040eSCédric Le Goater } 1339e997040eSCédric Le Goater 1340e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1341e997040eSCédric Le Goater { 1342e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1343e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1344e997040eSCédric Le Goater 1345e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1346397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 13479ae1329eSCédric Le Goater k->num_phbs = 3; 1348631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1349d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1350d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13510990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 135285913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 135304026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1354eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1355d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1356c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 135770c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1358e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 135977864267SCédric Le Goater 136077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 136177864267SCédric Le Goater &k->parent_realize); 1362e997040eSCédric Le Goater } 1363e997040eSCédric Le Goater 1364e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1365e997040eSCédric Le Goater { 1366e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1367e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1368e997040eSCédric Le Goater 1369e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1370397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1371316717feSCédric Le Goater k->num_phbs = 4; 1372631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1373d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1374d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13750990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 137685913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 137704026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1378eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1379d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1380c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 138170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1382e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 138377864267SCédric Le Goater 138477864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 138577864267SCédric Le Goater &k->parent_realize); 138677864267SCédric Le Goater } 138777864267SCédric Le Goater 138877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 138977864267SCédric Le Goater { 13904f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 13912dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 13924f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 13934f9924c4SBenjamin Herrenschmidt int i; 13942dfa91a2SCédric Le Goater 1395db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1396d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1397d2623129SMarkus Armbruster "xive-fabric"); 1398c38536bcSCédric Le Goater 13999fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 140015376c66SCédric Le Goater 14019fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 14026598a70dSCédric Le Goater 14039fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 14043887d241SBalamuruhan S 14050bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE); 14060bf4d77eSNicholas Piggin 14079fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 14084f9924c4SBenjamin Herrenschmidt 1409422fd92eSCédric Le Goater /* Number of PECs is the chip default */ 1410422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs; 1411422fd92eSCédric Le Goater 1412422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14134f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 14149fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 14154f9924c4SBenjamin Herrenschmidt } 141677864267SCédric Le Goater } 141777864267SCédric Le Goater 1418ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, 1419ae4c68e3SCédric Le Goater PnvCore *pnv_core) 14205dad902cSCédric Le Goater { 14215dad902cSCédric Le Goater char eq_name[32]; 14225dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 14235dad902cSCédric Le Goater 14245dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 14259fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 14269fc7fc4dSMarkus Armbruster sizeof(*eq), TYPE_PNV_QUAD, 14279fc7fc4dSMarkus Armbruster &error_fatal, NULL); 14285dad902cSCédric Le Goater 142992612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); 1430ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 1431ae4c68e3SCédric Le Goater } 1432ae4c68e3SCédric Le Goater 1433ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 1434ae4c68e3SCédric Le Goater { 1435ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 1436ae4c68e3SCédric Le Goater int i; 1437ae4c68e3SCédric Le Goater 1438ae4c68e3SCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1439ae4c68e3SCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 1440ae4c68e3SCédric Le Goater 1441ae4c68e3SCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 1442ae4c68e3SCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 1443ae4c68e3SCédric Le Goater 1444ae4c68e3SCédric Le Goater pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); 14455dad902cSCédric Le Goater 144692612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), 14475dad902cSCédric Le Goater &eq->xscom_regs); 14485dad902cSCédric Le Goater } 14495dad902cSCédric Le Goater } 14505dad902cSCédric Le Goater 145113480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp) 14524f9924c4SBenjamin Herrenschmidt { 14534f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 145413480fc5SCédric Le Goater int i; 14554f9924c4SBenjamin Herrenschmidt 1456422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14574f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 14584f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 14594f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 14604f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 14614f9924c4SBenjamin Herrenschmidt 14625325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 14635325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 14644f9924c4SBenjamin Herrenschmidt &error_fatal); 14656f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 14666f43d255SCédric Le Goater &error_fatal); 1467668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) { 14684f9924c4SBenjamin Herrenschmidt return; 14694f9924c4SBenjamin Herrenschmidt } 14704f9924c4SBenjamin Herrenschmidt 14714f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 14724f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 14734f9924c4SBenjamin Herrenschmidt 14744f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 14754f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 14764f9924c4SBenjamin Herrenschmidt } 14774f9924c4SBenjamin Herrenschmidt } 14784f9924c4SBenjamin Herrenschmidt 147977864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 148077864267SCédric Le Goater { 148177864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 14822dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 14832dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1484c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 148577864267SCédric Le Goater Error *local_err = NULL; 148677864267SCédric Le Goater 1487709044fdSCédric Le Goater /* XSCOM bridge is first */ 1488709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1489709044fdSCédric Le Goater if (local_err) { 1490709044fdSCédric Le Goater error_propagate(errp, local_err); 1491709044fdSCédric Le Goater return; 1492709044fdSCédric Le Goater } 1493709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1494709044fdSCédric Le Goater 149577864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 149677864267SCédric Le Goater if (local_err) { 149777864267SCédric Le Goater error_propagate(errp, local_err); 149877864267SCédric Le Goater return; 149977864267SCédric Le Goater } 15002dfa91a2SCédric Le Goater 15015dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 15025dad902cSCédric Le Goater if (local_err) { 15035dad902cSCédric Le Goater error_propagate(errp, local_err); 15045dad902cSCédric Le Goater return; 15055dad902cSCédric Le Goater } 15065dad902cSCédric Le Goater 15072dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 15085325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar", 15095325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal); 15105325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar", 15115325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal); 15125325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar", 15135325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal); 15145325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar", 15155325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal); 15165325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), 15177ae54cc3SGreg Kurz &error_abort); 1518668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { 15192dfa91a2SCédric Le Goater return; 15202dfa91a2SCédric Le Goater } 15212dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 15222dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1523c38536bcSCédric Le Goater 1524c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 15255325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), 15265325cc34SMarkus Armbruster &error_fatal); 152724c8fa96SCédric Le Goater /* This is the only device with 4k ESB pages */ 152824c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K, 152924c8fa96SCédric Le Goater &error_fatal); 1530668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { 1531c38536bcSCédric Le Goater return; 1532c38536bcSCédric Le Goater } 1533c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1534c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 153515376c66SCédric Le Goater 153615376c66SCédric Le Goater /* LPC */ 1537668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { 153815376c66SCédric Le Goater return; 153915376c66SCédric Le Goater } 154015376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 154115376c66SCédric Le Goater &chip9->lpc.xscom_regs); 154215376c66SCédric Le Goater 1543032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw; 154415376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 154515376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 15466598a70dSCédric Le Goater 15476598a70dSCédric Le Goater /* Create the simplified OCC model */ 1548668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { 15496598a70dSCédric Le Goater return; 15506598a70dSCédric Le Goater } 15516598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1552b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in( 1553b0ae5c69SCédric Le Goater DEVICE(&chip9->psi), PSIHB9_IRQ_OCC)); 1554f3db8266SBalamuruhan S 1555f3db8266SBalamuruhan S /* OCC SRAM model */ 15563a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1557f3db8266SBalamuruhan S &chip9->occ.sram_regs); 15583887d241SBalamuruhan S 15590bf4d77eSNicholas Piggin /* SBE */ 15600bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) { 15610bf4d77eSNicholas Piggin return; 15620bf4d77eSNicholas Piggin } 15630bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE, 15640bf4d77eSNicholas Piggin &chip9->sbe.xscom_ctrl_regs); 15650bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE, 15660bf4d77eSNicholas Piggin &chip9->sbe.xscom_mbox_regs); 15670bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in( 15680bf4d77eSNicholas Piggin DEVICE(&chip9->psi), PSIHB9_IRQ_PSU)); 15690bf4d77eSNicholas Piggin 15703887d241SBalamuruhan S /* HOMER */ 15715325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), 1572f2582acfSGreg Kurz &error_abort); 1573668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { 15743887d241SBalamuruhan S return; 15753887d241SBalamuruhan S } 15768f092316SCédric Le Goater /* Homer Xscom region */ 15778f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 15788f092316SCédric Le Goater 15798f092316SCédric Le Goater /* Homer mmio region */ 15803887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 15813887d241SBalamuruhan S &chip9->homer.regs); 15824f9924c4SBenjamin Herrenschmidt 158313480fc5SCédric Le Goater /* PEC PHBs */ 158413480fc5SCédric Le Goater pnv_chip_power9_pec_realize(chip, &local_err); 15854f9924c4SBenjamin Herrenschmidt if (local_err) { 15864f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 15874f9924c4SBenjamin Herrenschmidt return; 15884f9924c4SBenjamin Herrenschmidt } 1589e997040eSCédric Le Goater } 1590e997040eSCédric Le Goater 159170c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 159270c059e9SGreg Kurz { 159370c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 159470c059e9SGreg Kurz return addr >> 3; 159570c059e9SGreg Kurz } 159670c059e9SGreg Kurz 1597e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1598e997040eSCédric Le Goater { 1599e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1600e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1601e997040eSCédric Le Goater 160283028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1603397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1604631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1605d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1606d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 16070990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 160885913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 160904026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1610eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1611d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1612c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 161370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1614e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 1615422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC; 161677864267SCédric Le Goater 161777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 161877864267SCédric Le Goater &k->parent_realize); 1619e997040eSCédric Le Goater } 1620e997040eSCédric Le Goater 16212b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 16222b548a42SCédric Le Goater { 1623623575e1SCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 16248b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 1625623575e1SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 1626623575e1SCédric Le Goater int i; 16278b50ce85SCédric Le Goater 1628da71b7e3SCédric Le Goater object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); 1629da71b7e3SCédric Le Goater object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), 1630da71b7e3SCédric Le Goater "xive-fabric"); 16319fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 16329fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 16338bf682a3SCédric Le Goater object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); 16340bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE); 163592499676SCédric Le Goater object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); 1636623575e1SCédric Le Goater 1637623575e1SCédric Le Goater chip->num_pecs = pcc->num_pecs; 1638623575e1SCédric Le Goater 1639623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1640623575e1SCédric Le Goater object_initialize_child(obj, "pec[*]", &chip10->pecs[i], 1641623575e1SCédric Le Goater TYPE_PNV_PHB5_PEC); 1642623575e1SCédric Le Goater } 16432b548a42SCédric Le Goater } 16442b548a42SCédric Le Goater 1645ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) 1646ae4c68e3SCédric Le Goater { 1647ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip10); 1648ae4c68e3SCédric Le Goater int i; 1649ae4c68e3SCédric Le Goater 1650ae4c68e3SCédric Le Goater chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1651ae4c68e3SCédric Le Goater chip10->quads = g_new0(PnvQuad, chip10->nr_quads); 1652ae4c68e3SCédric Le Goater 1653ae4c68e3SCédric Le Goater for (i = 0; i < chip10->nr_quads; i++) { 1654ae4c68e3SCédric Le Goater PnvQuad *eq = &chip10->quads[i]; 1655ae4c68e3SCédric Le Goater 1656ae4c68e3SCédric Le Goater pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); 1657ae4c68e3SCédric Le Goater 1658ae4c68e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), 1659ae4c68e3SCédric Le Goater &eq->xscom_regs); 1660ae4c68e3SCédric Le Goater } 1661ae4c68e3SCédric Le Goater } 1662ae4c68e3SCédric Le Goater 1663623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) 1664623575e1SCédric Le Goater { 1665623575e1SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1666623575e1SCédric Le Goater int i; 1667623575e1SCédric Le Goater 1668623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1669623575e1SCédric Le Goater PnvPhb4PecState *pec = &chip10->pecs[i]; 1670623575e1SCédric Le Goater PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 1671623575e1SCédric Le Goater uint32_t pec_nest_base; 1672623575e1SCédric Le Goater uint32_t pec_pci_base; 1673623575e1SCédric Le Goater 1674623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 1675623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 1676623575e1SCédric Le Goater &error_fatal); 1677623575e1SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 1678623575e1SCédric Le Goater &error_fatal); 1679623575e1SCédric Le Goater if (!qdev_realize(DEVICE(pec), NULL, errp)) { 1680623575e1SCédric Le Goater return; 1681623575e1SCédric Le Goater } 1682623575e1SCédric Le Goater 1683623575e1SCédric Le Goater pec_nest_base = pecc->xscom_nest_base(pec); 1684623575e1SCédric Le Goater pec_pci_base = pecc->xscom_pci_base(pec); 1685623575e1SCédric Le Goater 1686623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 1687623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 1688623575e1SCédric Le Goater } 1689623575e1SCédric Le Goater } 1690623575e1SCédric Le Goater 16912b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 16922b548a42SCédric Le Goater { 16932b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 16942b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 16958b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 16962b548a42SCédric Le Goater Error *local_err = NULL; 16972b548a42SCédric Le Goater 16982b548a42SCédric Le Goater /* XSCOM bridge is first */ 16992b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 17002b548a42SCédric Le Goater if (local_err) { 17012b548a42SCédric Le Goater error_propagate(errp, local_err); 17022b548a42SCédric Le Goater return; 17032b548a42SCédric Le Goater } 17042b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 17052b548a42SCédric Le Goater 17062b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 17072b548a42SCédric Le Goater if (local_err) { 17082b548a42SCédric Le Goater error_propagate(errp, local_err); 17092b548a42SCédric Le Goater return; 17102b548a42SCédric Le Goater } 17118b50ce85SCédric Le Goater 1712ae4c68e3SCédric Le Goater pnv_chip_power10_quad_realize(chip10, &local_err); 1713ae4c68e3SCédric Le Goater if (local_err) { 1714ae4c68e3SCédric Le Goater error_propagate(errp, local_err); 1715ae4c68e3SCédric Le Goater return; 1716ae4c68e3SCédric Le Goater } 1717ae4c68e3SCédric Le Goater 1718da71b7e3SCédric Le Goater /* XIVE2 interrupt controller (POWER10) */ 1719da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "ic-bar", 1720da71b7e3SCédric Le Goater PNV10_XIVE2_IC_BASE(chip), &error_fatal); 1721da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "esb-bar", 1722da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_BASE(chip), &error_fatal); 1723da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "end-bar", 1724da71b7e3SCédric Le Goater PNV10_XIVE2_END_BASE(chip), &error_fatal); 1725da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar", 1726da71b7e3SCédric Le Goater PNV10_XIVE2_NVPG_BASE(chip), &error_fatal); 1727da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvc-bar", 1728da71b7e3SCédric Le Goater PNV10_XIVE2_NVC_BASE(chip), &error_fatal); 1729da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "tm-bar", 1730da71b7e3SCédric Le Goater PNV10_XIVE2_TM_BASE(chip), &error_fatal); 1731da71b7e3SCédric Le Goater object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip), 1732da71b7e3SCédric Le Goater &error_abort); 1733da71b7e3SCédric Le Goater if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) { 1734da71b7e3SCédric Le Goater return; 1735da71b7e3SCédric Le Goater } 1736da71b7e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE, 1737da71b7e3SCédric Le Goater &chip10->xive.xscom_regs); 1738da71b7e3SCédric Le Goater 17398b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 17405325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar", 17415325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal); 174224c8fa96SCédric Le Goater /* PSI can now be configured to use 64k ESB pages on POWER10 */ 174324c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K, 174424c8fa96SCédric Le Goater &error_fatal); 1745668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { 17468b50ce85SCédric Le Goater return; 17478b50ce85SCédric Le Goater } 17488b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 17498b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 17502661f6abSCédric Le Goater 17512661f6abSCédric Le Goater /* LPC */ 1752668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { 17532661f6abSCédric Le Goater return; 17542661f6abSCédric Le Goater } 17552661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 17562661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 17572661f6abSCédric Le Goater 1758032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw; 17592661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 17602661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 17618bf682a3SCédric Le Goater 17628bf682a3SCédric Le Goater /* Create the simplified OCC model */ 17638bf682a3SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) { 17648bf682a3SCédric Le Goater return; 17658bf682a3SCédric Le Goater } 17668bf682a3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE, 17678bf682a3SCédric Le Goater &chip10->occ.xscom_regs); 1768b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in( 1769b0ae5c69SCédric Le Goater DEVICE(&chip10->psi), PSIHB9_IRQ_OCC)); 1770623575e1SCédric Le Goater 177192499676SCédric Le Goater /* OCC SRAM model */ 177292499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), 177392499676SCédric Le Goater PNV10_OCC_SENSOR_BASE(chip), 177492499676SCédric Le Goater &chip10->occ.sram_regs); 177592499676SCédric Le Goater 17760bf4d77eSNicholas Piggin /* SBE */ 17770bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) { 17780bf4d77eSNicholas Piggin return; 17790bf4d77eSNicholas Piggin } 17800bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE, 17810bf4d77eSNicholas Piggin &chip10->sbe.xscom_ctrl_regs); 17820bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE, 17830bf4d77eSNicholas Piggin &chip10->sbe.xscom_mbox_regs); 17840bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in( 17850bf4d77eSNicholas Piggin DEVICE(&chip10->psi), PSIHB9_IRQ_PSU)); 17860bf4d77eSNicholas Piggin 178792499676SCédric Le Goater /* HOMER */ 178892499676SCédric Le Goater object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip), 178992499676SCédric Le Goater &error_abort); 179092499676SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) { 179192499676SCédric Le Goater return; 179292499676SCédric Le Goater } 179392499676SCédric Le Goater /* Homer Xscom region */ 179492499676SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE, 179592499676SCédric Le Goater &chip10->homer.pba_regs); 179692499676SCédric Le Goater 179792499676SCédric Le Goater /* Homer mmio region */ 179892499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip), 179992499676SCédric Le Goater &chip10->homer.regs); 180092499676SCédric Le Goater 1801623575e1SCédric Le Goater /* PHBs */ 1802623575e1SCédric Le Goater pnv_chip_power10_phb_realize(chip, &local_err); 1803623575e1SCédric Le Goater if (local_err) { 1804623575e1SCédric Le Goater error_propagate(errp, local_err); 1805623575e1SCédric Le Goater return; 1806623575e1SCédric Le Goater } 18072b548a42SCédric Le Goater } 18082b548a42SCédric Le Goater 180970c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 181070c059e9SGreg Kurz { 181170c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 181270c059e9SGreg Kurz return addr >> 3; 181370c059e9SGreg Kurz } 181470c059e9SGreg Kurz 18152b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 18162b548a42SCédric Le Goater { 18172b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 18182b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 18192b548a42SCédric Le Goater 18202b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 18212b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 18222b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 18232b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 18242b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 18252b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 182685913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 18272b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 18282b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 18292b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1830c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 183170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 18322b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 1833623575e1SCédric Le Goater k->num_pecs = PNV10_CHIP_MAX_PEC; 18342b548a42SCédric Le Goater 18352b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 18362b548a42SCédric Le Goater &k->parent_realize); 18372b548a42SCédric Le Goater } 18382b548a42SCédric Le Goater 1839397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1840397a79e7SCédric Le Goater { 1841397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1842397a79e7SCédric Le Goater int cores_max; 1843397a79e7SCédric Le Goater 1844397a79e7SCédric Le Goater /* 1845397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1846397a79e7SCédric Le Goater * the chip class 1847397a79e7SCédric Le Goater */ 1848397a79e7SCédric Le Goater if (!chip->cores_mask) { 1849397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1850397a79e7SCédric Le Goater } 1851397a79e7SCédric Le Goater 1852397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1853397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1854397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1855397a79e7SCédric Le Goater chip->cores_mask); 1856397a79e7SCédric Le Goater return; 1857397a79e7SCédric Le Goater } 1858397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1859397a79e7SCédric Le Goater 1860397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 186127d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1862397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1863397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1864397a79e7SCédric Le Goater cores_max); 1865397a79e7SCédric Le Goater return; 1866397a79e7SCédric Le Goater } 1867397a79e7SCédric Le Goater } 1868397a79e7SCédric Le Goater 186951c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1870e997040eSCédric Le Goater { 1871397a79e7SCédric Le Goater Error *error = NULL; 1872d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 187340abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1874d2fd9612SCédric Le Goater int i, core_hwid; 187508c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1876397a79e7SCédric Le Goater 1877d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1878d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1879d2fd9612SCédric Le Goater return; 1880d2fd9612SCédric Le Goater } 1881d2fd9612SCédric Le Goater 1882d2fd9612SCédric Le Goater /* Cores */ 1883397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1884397a79e7SCédric Le Goater if (error) { 1885397a79e7SCédric Le Goater error_propagate(errp, error); 1886397a79e7SCédric Le Goater return; 1887397a79e7SCédric Le Goater } 1888d2fd9612SCédric Le Goater 18894fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1890d2fd9612SCédric Le Goater 1891d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1892d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1893d2fd9612SCédric Le Goater char core_name[32]; 18944fa28f23SGreg Kurz PnvCore *pnv_core; 1895c035851aSCédric Le Goater uint64_t xscom_core_base; 1896d2fd9612SCédric Le Goater 1897d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1898d2fd9612SCédric Le Goater continue; 1899d2fd9612SCédric Le Goater } 1900d2fd9612SCédric Le Goater 19014fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 19024fa28f23SGreg Kurz 1903d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1904d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 19054fa28f23SGreg Kurz chip->cores[i] = pnv_core; 19065325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads", 19075325cc34SMarkus Armbruster chip->nr_threads, &error_fatal); 19085325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, 19095325cc34SMarkus Armbruster core_hwid, &error_fatal); 19105325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "pir", 19115325cc34SMarkus Armbruster pcc->core_pir(chip, core_hwid), &error_fatal); 19125325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, 19135325cc34SMarkus Armbruster &error_fatal); 19145325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), 1915158e17a6SGreg Kurz &error_abort); 1916ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 191724ece072SCédric Le Goater 191824ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1919c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1920c035851aSCédric Le Goater 1921c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 19224fa28f23SGreg Kurz &pnv_core->xscom_regs); 1923d2fd9612SCédric Le Goater i++; 1924d2fd9612SCédric Le Goater } 192551c04728SCédric Le Goater } 192651c04728SCédric Le Goater 192751c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 192851c04728SCédric Le Goater { 192951c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 193051c04728SCédric Le Goater Error *error = NULL; 193151c04728SCédric Le Goater 193251c04728SCédric Le Goater /* Cores */ 193351c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 193451c04728SCédric Le Goater if (error) { 193551c04728SCédric Le Goater error_propagate(errp, error); 193651c04728SCédric Le Goater return; 193751c04728SCédric Le Goater } 1938e997040eSCédric Le Goater } 1939e997040eSCédric Le Goater 1940e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1941e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1942e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1943e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1944397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1945397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1946764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 1947e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1948e997040eSCédric Le Goater }; 1949e997040eSCédric Le Goater 1950e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1951e997040eSCédric Le Goater { 1952e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1953e997040eSCédric Le Goater 19549d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1955e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 19564f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 1957e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1958e997040eSCédric Le Goater } 1959e997040eSCédric Le Goater 1960119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1961119eaa9dSCédric Le Goater { 1962119eaa9dSCédric Le Goater int i, j; 1963119eaa9dSCédric Le Goater 1964119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1965119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1966119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1967119eaa9dSCédric Le Goater 1968119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1969119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1970119eaa9dSCédric Le Goater return pc->threads[j]; 1971119eaa9dSCédric Le Goater } 1972119eaa9dSCédric Le Goater } 1973119eaa9dSCédric Le Goater } 1974119eaa9dSCédric Le Goater return NULL; 1975119eaa9dSCédric Le Goater } 1976119eaa9dSCédric Le Goater 197754f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 197854f59d78SCédric Le Goater { 1979b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 1980da6be501SDaniel Henrique Barboza int i, j; 198154f59d78SCédric Le Goater 198254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 198377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 198477864267SCédric Le Goater 198577864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 198677864267SCédric Le Goater return &chip8->psi.ics; 198754f59d78SCédric Le Goater } 19882ff73ddaSCédric Le Goater 1989da6be501SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 19901f5d6b2aSDaniel Henrique Barboza PnvPHB *phb = &chip8->phbs[j]; 19911f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 1992da6be501SDaniel Henrique Barboza 1993da6be501SDaniel Henrique Barboza if (ics_valid_irq(&phb3->lsis, irq)) { 1994da6be501SDaniel Henrique Barboza return &phb3->lsis; 1995da6be501SDaniel Henrique Barboza } 1996da6be501SDaniel Henrique Barboza 1997da6be501SDaniel Henrique Barboza if (ics_valid_irq(ICS(&phb3->msis), irq)) { 1998da6be501SDaniel Henrique Barboza return ICS(&phb3->msis); 1999da6be501SDaniel Henrique Barboza } 20009ae1329eSCédric Le Goater } 200154f59d78SCédric Le Goater } 200254f59d78SCédric Le Goater return NULL; 200354f59d78SCédric Le Goater } 200454f59d78SCédric Le Goater 20051f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id) 20061f6a88ffSCédric Le Goater { 20071f6a88ffSCédric Le Goater int i; 20081f6a88ffSCédric Le Goater 20091f6a88ffSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 20101f6a88ffSCédric Le Goater PnvChip *chip = pnv->chips[i]; 20111f6a88ffSCédric Le Goater if (chip->chip_id == chip_id) { 20121f6a88ffSCédric Le Goater return chip; 20131f6a88ffSCédric Le Goater } 20141f6a88ffSCédric Le Goater } 20151f6a88ffSCédric Le Goater return NULL; 20161f6a88ffSCédric Le Goater } 20171f6a88ffSCédric Le Goater 201854f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 201954f59d78SCédric Le Goater { 2020b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 2021ca459489SDaniel Henrique Barboza int i, j; 202254f59d78SCédric Le Goater 202354f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 202477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 20259ae1329eSCédric Le Goater 202677864267SCédric Le Goater ics_resend(&chip8->psi.ics); 2027ca459489SDaniel Henrique Barboza 2028ca459489SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 20291f5d6b2aSDaniel Henrique Barboza PnvPHB *phb = &chip8->phbs[j]; 20301f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 2031ca459489SDaniel Henrique Barboza 2032ca459489SDaniel Henrique Barboza ics_resend(&phb3->lsis); 2033ca459489SDaniel Henrique Barboza ics_resend(ICS(&phb3->msis)); 2034ca459489SDaniel Henrique Barboza } 203554f59d78SCédric Le Goater } 203654f59d78SCédric Le Goater } 203754f59d78SCédric Le Goater 203836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 203936fc6f08SCédric Le Goater { 204036fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 204136fc6f08SCédric Le Goater 2042956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 204336fc6f08SCédric Le Goater } 204436fc6f08SCédric Le Goater 204547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 204647fea43aSCédric Le Goater Monitor *mon) 204747fea43aSCédric Le Goater { 2048b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 204954f59d78SCédric Le Goater int i; 205047fea43aSCédric Le Goater CPUState *cs; 205147fea43aSCédric Le Goater 205247fea43aSCédric Le Goater CPU_FOREACH(cs) { 205347fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 205447fea43aSCédric Le Goater 205585913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 205685913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 205785913070SGreg Kurz mon); 2058d8e4aad5SCédric Le Goater } 205954f59d78SCédric Le Goater 206054f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2061d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 206254f59d78SCédric Le Goater } 206347fea43aSCédric Le Goater } 206447fea43aSCédric Le Goater 2065c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 2066c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2067c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 2068c722579eSCédric Le Goater uint32_t logic_serv, 2069c722579eSCédric Le Goater XiveTCTXMatch *match) 2070c722579eSCédric Le Goater { 2071c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2072c722579eSCédric Le Goater int total_count = 0; 2073c722579eSCédric Le Goater int i; 2074c722579eSCédric Le Goater 2075c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2076c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 2077c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 2078c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2079c722579eSCédric Le Goater int count; 2080c722579eSCédric Le Goater 2081c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2082c722579eSCédric Le Goater priority, logic_serv, match); 2083c722579eSCédric Le Goater 2084c722579eSCédric Le Goater if (count < 0) { 2085c722579eSCédric Le Goater return count; 2086c722579eSCédric Le Goater } 2087c722579eSCédric Le Goater 2088c722579eSCédric Le Goater total_count += count; 2089c722579eSCédric Le Goater } 2090c722579eSCédric Le Goater 2091c722579eSCédric Le Goater return total_count; 2092c722579eSCédric Le Goater } 2093c722579eSCédric Le Goater 2094da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format, 2095da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2096da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority, 2097da71b7e3SCédric Le Goater uint32_t logic_serv, 2098da71b7e3SCédric Le Goater XiveTCTXMatch *match) 2099da71b7e3SCédric Le Goater { 2100da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2101da71b7e3SCédric Le Goater int total_count = 0; 2102da71b7e3SCédric Le Goater int i; 2103da71b7e3SCédric Le Goater 2104da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2105da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); 2106da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive); 2107da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2108da71b7e3SCédric Le Goater int count; 2109da71b7e3SCédric Le Goater 2110da71b7e3SCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2111da71b7e3SCédric Le Goater priority, logic_serv, match); 2112da71b7e3SCédric Le Goater 2113da71b7e3SCédric Le Goater if (count < 0) { 2114da71b7e3SCédric Le Goater return count; 2115da71b7e3SCédric Le Goater } 2116da71b7e3SCédric Le Goater 2117da71b7e3SCédric Le Goater total_count += count; 2118da71b7e3SCédric Le Goater } 2119da71b7e3SCédric Le Goater 2120da71b7e3SCédric Le Goater return total_count; 2121da71b7e3SCédric Le Goater } 2122da71b7e3SCédric Le Goater 2123f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 21249e933f4aSBenjamin Herrenschmidt { 21259e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 212636fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 2127d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2128d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 2129f30c843cSCédric Le Goater 21301f5d6b2aSDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 21311f5d6b2aSDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "3" }, 21321f5d6b2aSDaniel Henrique Barboza }; 21331f5d6b2aSDaniel Henrique Barboza 2134f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 2135f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 21361f5d6b2aSDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2137f30c843cSCédric Le Goater 2138f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 2139f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 2140f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 2141d76f2da7SGreg Kurz 2142d76f2da7SGreg Kurz pmc->compat = compat; 2143d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 2144f30c843cSCédric Le Goater } 2145f30c843cSCédric Le Goater 2146f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 2147f30c843cSCédric Le Goater { 2148f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2149c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2150d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2151d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 2152f30c843cSCédric Le Goater 2153210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 2154210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "4" }, 2155210aacb3SDaniel Henrique Barboza }; 2156210aacb3SDaniel Henrique Barboza 2157f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 2158f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 2159210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2160210aacb3SDaniel Henrique Barboza 2161c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 2162f30c843cSCédric Le Goater 2163f30c843cSCédric Le Goater mc->alias = "powernv"; 2164d76f2da7SGreg Kurz 2165d76f2da7SGreg Kurz pmc->compat = compat; 2166d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 21677a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2168f30c843cSCédric Le Goater } 2169f30c843cSCédric Le Goater 21702b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 21712b548a42SCédric Le Goater { 21722b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2173d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2174da71b7e3SCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2175d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 21762b548a42SCédric Le Goater 2177210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 2178210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "5" }, 2179210aacb3SDaniel Henrique Barboza }; 2180210aacb3SDaniel Henrique Barboza 21812b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 21826bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); 2183210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2184d76f2da7SGreg Kurz 2185d76f2da7SGreg Kurz pmc->compat = compat; 2186d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 21877a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2188da71b7e3SCédric Le Goater 2189da71b7e3SCédric Le Goater xfc->match_nvt = pnv10_xive_match_nvt; 21902b548a42SCédric Le Goater } 21912b548a42SCédric Le Goater 219208c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 219308c3f3a7SCédric Le Goater { 219408c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 219508c3f3a7SCédric Le Goater 219608c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 219708c3f3a7SCédric Le Goater } 219808c3f3a7SCédric Le Goater 219908c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 220008c3f3a7SCédric Le Goater { 220108c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 220208c3f3a7SCédric Le Goater 220308c3f3a7SCédric Le Goater if (value) { 220408c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 220508c3f3a7SCédric Le Goater } 220608c3f3a7SCédric Le Goater } 220708c3f3a7SCédric Le Goater 220801b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 220901b552b0SNicholas Piggin { 221001b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 221101b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 221201b552b0SNicholas Piggin 221301b552b0SNicholas Piggin cpu_synchronize_state(cs); 221401b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 22150911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 221601b552b0SNicholas Piggin /* 2217fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 2218fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 2219fe837714SNicholas Piggin * (PPC_BIT(43)). 222001b552b0SNicholas Piggin */ 22210911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 2222fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 22230911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 222401b552b0SNicholas Piggin } 2225fe837714SNicholas Piggin } else { 2226fe837714SNicholas Piggin /* 2227fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 2228fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 2229fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 2230fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 2231fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 2232fe837714SNicholas Piggin */ 22330911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 2234fe837714SNicholas Piggin } 2235fe837714SNicholas Piggin } 223601b552b0SNicholas Piggin 223701b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 223801b552b0SNicholas Piggin { 223901b552b0SNicholas Piggin CPUState *cs; 224001b552b0SNicholas Piggin 224101b552b0SNicholas Piggin CPU_FOREACH(cs) { 224201b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 224301b552b0SNicholas Piggin } 224401b552b0SNicholas Piggin } 224501b552b0SNicholas Piggin 2246f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 2247f30c843cSCédric Le Goater { 2248f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 224947fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 225001b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 22519e933f4aSBenjamin Herrenschmidt 22529e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 2253b168a138SCédric Le Goater mc->init = pnv_init; 2254b168a138SCédric Le Goater mc->reset = pnv_reset; 22559e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 225659b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 225759b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 22589e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 22599e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 2260f1d18b0aSJoel Stanley /* 2261f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 2262f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 2263f1d18b0aSJoel Stanley */ 2264dd7ef911SCédric Le Goater mc->default_ram_size = 1 * GiB; 2265173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 226647fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 226701b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 226808c3f3a7SCédric Le Goater 226908c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 2270d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 227108c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 22727eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 22739e933f4aSBenjamin Herrenschmidt } 22749e933f4aSBenjamin Herrenschmidt 227577864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2276beba5c0fSIgor Mammedov { \ 2277beba5c0fSIgor Mammedov .name = type, \ 2278beba5c0fSIgor Mammedov .class_init = class_initfn, \ 227977864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 228077864267SCédric Le Goater } 228177864267SCédric Le Goater 228277864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 228377864267SCédric Le Goater { \ 228477864267SCédric Le Goater .name = type, \ 228577864267SCédric Le Goater .class_init = class_initfn, \ 228677864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2287beba5c0fSIgor Mammedov } 2288beba5c0fSIgor Mammedov 22892b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 22902b548a42SCédric Le Goater { \ 22912b548a42SCédric Le Goater .name = type, \ 22922b548a42SCédric Le Goater .class_init = class_initfn, \ 22932b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 22942b548a42SCédric Le Goater } 22952b548a42SCédric Le Goater 2296beba5c0fSIgor Mammedov static const TypeInfo types[] = { 22971aba8716SCédric Le Goater { 22982b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 22992b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23002b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 2301da71b7e3SCédric Le Goater .interfaces = (InterfaceInfo[]) { 2302da71b7e3SCédric Le Goater { TYPE_XIVE_FABRIC }, 2303da71b7e3SCédric Le Goater { }, 2304da71b7e3SCédric Le Goater }, 23052b548a42SCédric Le Goater }, 23062b548a42SCédric Le Goater { 23071aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 23081aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23091aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2310c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2311c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2312c722579eSCédric Le Goater { }, 2313c722579eSCédric Le Goater }, 23141aba8716SCédric Le Goater }, 23151aba8716SCédric Le Goater { 23161aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 23171aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23181aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 23191aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 23201aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 23211aba8716SCédric Le Goater { }, 23221aba8716SCédric Le Goater }, 23231aba8716SCédric Le Goater }, 2324beba5c0fSIgor Mammedov { 2325b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 23269e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2327f30c843cSCédric Le Goater .abstract = true, 23289e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2329b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2330d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 233136fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 233247fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 233301b552b0SNicholas Piggin { TYPE_NMI }, 233436fc6f08SCédric Le Goater { }, 233536fc6f08SCédric Le Goater }, 2336beba5c0fSIgor Mammedov }, 2337beba5c0fSIgor Mammedov { 2338beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2339beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2340beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2341beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2342beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2343beba5c0fSIgor Mammedov .abstract = true, 2344beba5c0fSIgor Mammedov }, 234577864267SCédric Le Goater 234677864267SCédric Le Goater /* 23472b548a42SCédric Le Goater * P10 chip and variants 23482b548a42SCédric Le Goater */ 23492b548a42SCédric Le Goater { 23502b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 23512b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 23522b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 23532b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 23542b548a42SCédric Le Goater }, 23552b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 23562b548a42SCédric Le Goater 23572b548a42SCédric Le Goater /* 235877864267SCédric Le Goater * P9 chip and variants 235977864267SCédric Le Goater */ 236077864267SCédric Le Goater { 236177864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 236277864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 236377864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 236477864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 236577864267SCédric Le Goater }, 236677864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 236777864267SCédric Le Goater 236877864267SCédric Le Goater /* 236977864267SCédric Le Goater * P8 chip and variants 237077864267SCédric Le Goater */ 237177864267SCédric Le Goater { 237277864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 237377864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 237477864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 237577864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 237677864267SCédric Le Goater }, 237777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 237877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 237977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2380beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 23819e933f4aSBenjamin Herrenschmidt }; 23829e933f4aSBenjamin Herrenschmidt 2383beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2384