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" 469e933f4aSBenjamin Herrenschmidt 4736fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 48a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 49967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 5035dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 51967b7523SCédric Le Goater 523495b6b6SCédric Le Goater #include "hw/isa/isa.h" 533495b6b6SCédric Le Goater #include "hw/char/serial.h" 54bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 553495b6b6SCédric Le Goater 569e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 579e933f4aSBenjamin Herrenschmidt 58b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 599e933f4aSBenjamin Herrenschmidt 609e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 619e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 6283fa6e2aSCédric Le Goater #define FW_MAX_SIZE (16 * MiB) 639e933f4aSBenjamin Herrenschmidt 649e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 6505ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE (128 * MiB) 6605ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR 0x28000000 6705ce9b73SCédric Le Goater #define INITRD_MAX_SIZE (128 * MiB) 689e933f4aSBenjamin Herrenschmidt 6940abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 7040abf43fSIgor Mammedov { 7140abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7240abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7340abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7440abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7540abf43fSIgor Mammedov g_free(s); 7640abf43fSIgor Mammedov return core_type; 7740abf43fSIgor Mammedov } 7840abf43fSIgor Mammedov 799e933f4aSBenjamin Herrenschmidt /* 809e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 819e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 829e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 839e933f4aSBenjamin Herrenschmidt */ 849e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 859e933f4aSBenjamin Herrenschmidt 869e933f4aSBenjamin Herrenschmidt /* 879e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 889e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 899e933f4aSBenjamin Herrenschmidt * per chip. 909e933f4aSBenjamin Herrenschmidt */ 91b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 929e933f4aSBenjamin Herrenschmidt { 939e933f4aSBenjamin Herrenschmidt char *mem_name; 949e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 959e933f4aSBenjamin Herrenschmidt int off; 969e933f4aSBenjamin Herrenschmidt 979e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 989e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 999e933f4aSBenjamin Herrenschmidt 1009e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 1019e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1029e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1039e933f4aSBenjamin Herrenschmidt 1049e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1059e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1069e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1079e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1089e933f4aSBenjamin Herrenschmidt } 1099e933f4aSBenjamin Herrenschmidt 110d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 111d2fd9612SCédric Le Goater { 112d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 113d2fd9612SCédric Le Goater 114d2fd9612SCédric Le Goater if (cpus_offset < 0) { 115a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 116d2fd9612SCédric Le Goater if (cpus_offset) { 117d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 118d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 119d2fd9612SCédric Le Goater } 120d2fd9612SCédric Le Goater } 121d2fd9612SCédric Le Goater _FDT(cpus_offset); 122d2fd9612SCédric Le Goater return cpus_offset; 123d2fd9612SCédric Le Goater } 124d2fd9612SCédric Le Goater 125d2fd9612SCédric Le Goater /* 126d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 127d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 128d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 129d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 130d2fd9612SCédric Le Goater * servers. 131d2fd9612SCédric Le Goater */ 132b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 133d2fd9612SCédric Le Goater { 13408304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13508304a86SDavid Gibson CPUState *cs = CPU(cpu); 136d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1378bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 138d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 139d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 140d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 141d2fd9612SCédric Le Goater int i; 142d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 143d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 144d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 145d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 146d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 147d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 148d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 149d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 150d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 151d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 152d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 153d2fd9612SCédric Le Goater int offset; 154d2fd9612SCédric Le Goater char *nodename; 155d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 156d2fd9612SCédric Le Goater 157d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 158d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 159d2fd9612SCédric Le Goater _FDT(offset); 160d2fd9612SCédric Le Goater g_free(nodename); 161d2fd9612SCédric Le Goater 162d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 163d2fd9612SCédric Le Goater 164d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 167d2fd9612SCédric Le Goater 168d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 170d2fd9612SCédric Le Goater env->dcache_line_size))); 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 172d2fd9612SCédric Le Goater env->dcache_line_size))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 174d2fd9612SCédric Le Goater env->icache_line_size))); 175d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 176d2fd9612SCédric Le Goater env->icache_line_size))); 177d2fd9612SCédric Le Goater 178d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 179d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 180d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 181d2fd9612SCédric Le Goater } else { 1823dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 183d2fd9612SCédric Le Goater } 184d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 185d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 186d2fd9612SCédric Le Goater pcc->l1_icache_size))); 187d2fd9612SCédric Le Goater } else { 1883dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 189d2fd9612SCédric Le Goater } 190d2fd9612SCédric Le Goater 191d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 192d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19359b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19459b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 195d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 196d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 197d2fd9612SCédric Le Goater 19803282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) { 199d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 200d2fd9612SCédric Le Goater } 201d2fd9612SCédric Le Goater 20258969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 203d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 204d2fd9612SCédric Le Goater segs, sizeof(segs)))); 205d2fd9612SCédric Le Goater } 206d2fd9612SCédric Le Goater 20759b7c1c2SBalamuruhan S /* 20859b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 209d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 210d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 21159b7c1c2SBalamuruhan S * 2 == VSX available 21259b7c1c2SBalamuruhan S */ 213d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 214d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 215d2fd9612SCédric Le Goater 216d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 217d2fd9612SCédric Le Goater } 218d2fd9612SCédric Le Goater 21959b7c1c2SBalamuruhan S /* 22059b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 221d2fd9612SCédric Le Goater * 0 / no property == no DFP 22259b7c1c2SBalamuruhan S * 1 == DFP available 22359b7c1c2SBalamuruhan S */ 224d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 225d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 226d2fd9612SCédric Le Goater } 227d2fd9612SCédric Le Goater 228644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 229d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 230d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 231d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 232d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 233d2fd9612SCédric Le Goater } 234d2fd9612SCédric Le Goater 235d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 236d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 237d2fd9612SCédric Le Goater 238d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 239d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 240d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 241d2fd9612SCédric Le Goater } 242d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 243d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 244d2fd9612SCédric Le Goater } 245d2fd9612SCédric Le Goater 246b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 247bf5615e7SCédric Le Goater uint32_t nr_threads) 248bf5615e7SCédric Le Goater { 249bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 250bf5615e7SCédric Le Goater char *name; 251bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 252bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 253bf5615e7SCédric Le Goater uint64_t *reg; 254bf5615e7SCédric Le Goater int offset; 255bf5615e7SCédric Le Goater 256bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 257bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 258bf5615e7SCédric Le Goater 259bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 260bf5615e7SCédric Le Goater reg = g_malloc(rsize); 261bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 262bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 263bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 264bf5615e7SCédric Le Goater } 265bf5615e7SCédric Le Goater 266bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 267bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 268bf5615e7SCédric Le Goater _FDT(offset); 269bf5615e7SCédric Le Goater g_free(name); 270bf5615e7SCédric Le Goater 271bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 272bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 273bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 274bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 275bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 277bf5615e7SCédric Le Goater irange, sizeof(irange)))); 278bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 279bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 280bf5615e7SCédric Le Goater g_free(reg); 281bf5615e7SCédric Le Goater } 282bf5615e7SCédric Le Goater 283eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 284e997040eSCédric Le Goater { 285c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; 286d2fd9612SCédric Le Goater int i; 287d2fd9612SCédric Le Goater 2883f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 2893f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 290c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE), 291c396c58aSGreg Kurz compat, sizeof(compat)); 292967b7523SCédric Le Goater 293d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2944fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 295d2fd9612SCédric Le Goater 296b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 297bf5615e7SCédric Le Goater 298bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 299b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 300d2fd9612SCédric Le Goater } 301d2fd9612SCédric Le Goater 302e997040eSCédric Le Goater if (chip->ram_size) { 303b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 304e997040eSCédric Le Goater } 305e997040eSCédric Le Goater } 306e997040eSCédric Le Goater 307eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 308eb859a27SCédric Le Goater { 309c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom"; 310eb859a27SCédric Le Goater int i; 311eb859a27SCédric Le Goater 3123f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3133f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 314c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE), 315c396c58aSGreg Kurz compat, sizeof(compat)); 316eb859a27SCédric Le Goater 317eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3184fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 319eb859a27SCédric Le Goater 320eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 321eb859a27SCédric Le Goater } 322eb859a27SCédric Le Goater 323eb859a27SCédric Le Goater if (chip->ram_size) { 324eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 325eb859a27SCédric Le Goater } 32615376c66SCédric Le Goater 3272661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 328eb859a27SCédric Le Goater } 329eb859a27SCédric Le Goater 3302b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3312b548a42SCédric Le Goater { 332c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom"; 3332b548a42SCédric Le Goater int i; 3342b548a42SCédric Le Goater 3353f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3363f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 337c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE), 338c396c58aSGreg Kurz compat, sizeof(compat)); 3392b548a42SCédric Le Goater 3402b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3412b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3422b548a42SCédric Le Goater 3432b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3442b548a42SCédric Le Goater } 3452b548a42SCédric Le Goater 3462b548a42SCédric Le Goater if (chip->ram_size) { 3472b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3482b548a42SCédric Le Goater } 3492661f6abSCédric Le Goater 3502661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 3512b548a42SCédric Le Goater } 3522b548a42SCédric Le Goater 353b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 354c5ffdcaeSCédric Le Goater { 355c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 356c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 357c5ffdcaeSCédric Le Goater cpu_to_be32(1), 358c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 359c5ffdcaeSCédric Le Goater cpu_to_be32(2) 360c5ffdcaeSCédric Le Goater }; 361c5ffdcaeSCédric Le Goater char *name; 362c5ffdcaeSCédric Le Goater int node; 363c5ffdcaeSCédric Le Goater 364c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 365c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 366c5ffdcaeSCédric Le Goater _FDT(node); 367c5ffdcaeSCédric Le Goater g_free(name); 368c5ffdcaeSCédric Le Goater 369c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 370c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 371c5ffdcaeSCédric Le Goater } 372c5ffdcaeSCédric Le Goater 373b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 374cb228f5aSCédric Le Goater { 375cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 376cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 377cb228f5aSCédric Le Goater uint32_t io_regs[] = { 378cb228f5aSCédric Le Goater cpu_to_be32(1), 379cb228f5aSCédric Le Goater cpu_to_be32(io_base), 380cb228f5aSCédric Le Goater cpu_to_be32(8) 381cb228f5aSCédric Le Goater }; 382632fc0b3SBernhard Beschow uint32_t irq; 383cb228f5aSCédric Le Goater char *name; 384cb228f5aSCédric Le Goater int node; 385cb228f5aSCédric Le Goater 386632fc0b3SBernhard Beschow irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal); 387632fc0b3SBernhard Beschow 388cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 389cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 390cb228f5aSCédric Le Goater _FDT(node); 391cb228f5aSCédric Le Goater g_free(name); 392cb228f5aSCédric Le Goater 393cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 394cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 395cb228f5aSCédric Le Goater sizeof(compatible)))); 396cb228f5aSCédric Le Goater 397cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 398cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 399632fc0b3SBernhard Beschow _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 400cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 401cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 402cb228f5aSCédric Le Goater 403cb228f5aSCédric Le Goater /* This is needed by Linux */ 404cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 405cb228f5aSCédric Le Goater } 406cb228f5aSCédric Le Goater 407b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 40804f6c8b2SCédric Le Goater { 40904f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 41004f6c8b2SCédric Le Goater uint32_t io_base; 41104f6c8b2SCédric Le Goater uint32_t io_regs[] = { 41204f6c8b2SCédric Le Goater cpu_to_be32(1), 41304f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 41404f6c8b2SCédric Le Goater cpu_to_be32(3) 41504f6c8b2SCédric Le Goater }; 41604f6c8b2SCédric Le Goater uint32_t irq; 41704f6c8b2SCédric Le Goater char *name; 41804f6c8b2SCédric Le Goater int node; 41904f6c8b2SCédric Le Goater 42004f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 42104f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 42204f6c8b2SCédric Le Goater 42304f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 42404f6c8b2SCédric Le Goater 42504f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 42604f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 42704f6c8b2SCédric Le Goater _FDT(node); 42804f6c8b2SCédric Le Goater g_free(name); 42904f6c8b2SCédric Le Goater 4307032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4317032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4327032d92aSCédric Le Goater sizeof(compatible)))); 43304f6c8b2SCédric Le Goater 43404f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 43504f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 43604f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 43704f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 43804f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 43904f6c8b2SCédric Le Goater } 44004f6c8b2SCédric Le Goater 441e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 442e7a3fee3SCédric Le Goater void *fdt; 443e7a3fee3SCédric Le Goater int offset; 444e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 445e7a3fee3SCédric Le Goater 446b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 447e7a3fee3SCédric Le Goater { 448c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 449c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 450c5ffdcaeSCédric Le Goater 451c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 452b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 453cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 454b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 45504f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 456b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 457c5ffdcaeSCédric Le Goater } else { 458c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 459c5ffdcaeSCédric Le Goater d->ioport_id); 460c5ffdcaeSCédric Le Goater } 461c5ffdcaeSCédric Le Goater 462e7a3fee3SCédric Le Goater return 0; 463e7a3fee3SCédric Le Goater } 464e7a3fee3SCédric Le Goater 46559b7c1c2SBalamuruhan S /* 46659b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 467bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 468bb7ab95cSCédric Le Goater */ 469bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 470bb7ab95cSCédric Le Goater { 47164d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 472e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 473e7a3fee3SCédric Le Goater .fdt = fdt, 474bb7ab95cSCédric Le Goater .offset = isa_offset, 475e7a3fee3SCédric Le Goater }; 476f47a08d1SCédric Le Goater uint32_t phandle; 477e7a3fee3SCédric Le Goater 478bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 479bb7ab95cSCédric Le Goater 480f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 481f47a08d1SCédric Le Goater assert(phandle > 0); 482f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 483f47a08d1SCédric Le Goater 48459b7c1c2SBalamuruhan S /* 48559b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 48659b7c1c2SBalamuruhan S * can not use object_child_foreach() 48759b7c1c2SBalamuruhan S */ 488bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 489bb7ab95cSCédric Le Goater &args); 490e7a3fee3SCédric Le Goater } 491e7a3fee3SCédric Le Goater 4927a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 493e5694793SCédric Le Goater { 494e5694793SCédric Le Goater int off; 495e5694793SCédric Le Goater 496e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 497e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 498e5694793SCédric Le Goater 499e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 500e5694793SCédric Le Goater } 501e5694793SCédric Le Goater 502b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 5039e933f4aSBenjamin Herrenschmidt { 504d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 505b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5069e933f4aSBenjamin Herrenschmidt void *fdt; 5079e933f4aSBenjamin Herrenschmidt char *buf; 5089e933f4aSBenjamin Herrenschmidt int off; 509e997040eSCédric Le Goater int i; 5109e933f4aSBenjamin Herrenschmidt 5119e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5129e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5139e933f4aSBenjamin Herrenschmidt 514ccb099b3SCédric Le Goater /* /qemu node */ 515ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 516ccb099b3SCédric Le Goater 5179e933f4aSBenjamin Herrenschmidt /* Root node */ 5189e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5199e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5209e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5219e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 522d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5239e933f4aSBenjamin Herrenschmidt 5249e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5259e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5269e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 527bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "system-id", buf))); 5289e933f4aSBenjamin Herrenschmidt } 5299e933f4aSBenjamin Herrenschmidt g_free(buf); 5309e933f4aSBenjamin Herrenschmidt 5319e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5329e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5339e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5349e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5359e933f4aSBenjamin Herrenschmidt } 5369e933f4aSBenjamin Herrenschmidt 5379e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5389e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5399e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5409e933f4aSBenjamin Herrenschmidt 5419e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5429e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5439e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5449e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5459e933f4aSBenjamin Herrenschmidt } 5469e933f4aSBenjamin Herrenschmidt 547e997040eSCédric Le Goater /* Populate device tree for each chip */ 548e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 549eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 550e997040eSCédric Le Goater } 551e7a3fee3SCédric Le Goater 552e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 553bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 554aeaef83dSCédric Le Goater 555aeaef83dSCédric Le Goater if (pnv->bmc) { 556b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 557aeaef83dSCédric Le Goater } 558aeaef83dSCédric Le Goater 5597a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5607a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5617a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 562e5694793SCédric Le Goater } 563e5694793SCédric Le Goater 5649e933f4aSBenjamin Herrenschmidt return fdt; 5659e933f4aSBenjamin Herrenschmidt } 5669e933f4aSBenjamin Herrenschmidt 567bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 568bce0b691SCédric Le Goater { 5698f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 570bce0b691SCédric Le Goater 571bce0b691SCédric Le Goater if (pnv->bmc) { 572bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 573bce0b691SCédric Le Goater } 574bce0b691SCédric Le Goater } 575bce0b691SCédric Le Goater 576a0628599SLike Xu static void pnv_reset(MachineState *machine) 5779e933f4aSBenjamin Herrenschmidt { 57825f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 57925f3170bSCédric Le Goater IPMIBmc *bmc; 5809e933f4aSBenjamin Herrenschmidt void *fdt; 5819e933f4aSBenjamin Herrenschmidt 5829e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5839e933f4aSBenjamin Herrenschmidt 58425f3170bSCédric Le Goater /* 58525f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator. 58625f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command 58725f3170bSCédric Le Goater * line. 58825f3170bSCédric Le Goater */ 58925f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal); 59025f3170bSCédric Le Goater if (!pnv->bmc) { 59125f3170bSCédric Le Goater if (!bmc) { 59238d2448aSGreg Kurz if (!qtest_enabled()) { 59325f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 59425f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 59525f3170bSCédric Le Goater "to define one"); 59638d2448aSGreg Kurz } 59725f3170bSCédric Le Goater } else { 59825f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 59925f3170bSCédric Le Goater pnv->bmc = bmc; 60025f3170bSCédric Le Goater } 60125f3170bSCédric Le Goater } 60225f3170bSCédric Le Goater 603b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6049e933f4aSBenjamin Herrenschmidt 6059e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6069e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6079e933f4aSBenjamin Herrenschmidt 6088d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6099e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 610b2fb7a43SPan Nengyuan 611b2fb7a43SPan Nengyuan g_free(fdt); 6129e933f4aSBenjamin Herrenschmidt } 6139e933f4aSBenjamin Herrenschmidt 61404026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6153495b6b6SCédric Le Goater { 61677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 617c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL); 618c05aa140SCédric Le Goater 619c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 62077864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 62104026890SCédric Le Goater } 6223495b6b6SCédric Le Goater 62304026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 62404026890SCédric Le Goater { 62577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 626c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C); 627c05aa140SCédric Le Goater 628c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 62977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 63004026890SCédric Le Goater } 6313495b6b6SCédric Le Goater 63204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 63304026890SCédric Le Goater { 63415376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 635c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC); 636c05aa140SCédric Le Goater 637c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq); 63815376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 63904026890SCédric Le Goater } 6403495b6b6SCédric Le Goater 6412b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6422b548a42SCédric Le Goater { 6432661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 644c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC); 645c05aa140SCédric Le Goater 646c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq); 6472661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6482b548a42SCédric Le Goater } 6492b548a42SCédric Le Goater 65004026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 65104026890SCédric Le Goater { 65204026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6533495b6b6SCédric Le Goater } 6543495b6b6SCédric Le Goater 655d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 656d8e4aad5SCédric Le Goater { 657d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 6588a69bca7SDaniel Henrique Barboza int i; 659d8e4aad5SCédric Le Goater 660d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 6618a69bca7SDaniel Henrique Barboza 6628a69bca7SDaniel Henrique Barboza for (i = 0; i < chip8->num_phbs; i++) { 6638a69bca7SDaniel Henrique Barboza PnvPHB3 *phb3 = &chip8->phbs[i]; 6648a69bca7SDaniel Henrique Barboza 6658a69bca7SDaniel Henrique Barboza pnv_phb3_msi_pic_print_info(&phb3->msis, mon); 6668a69bca7SDaniel Henrique Barboza ics_pic_print_info(&phb3->lsis, mon); 6678a69bca7SDaniel Henrique Barboza } 668d8e4aad5SCédric Le Goater } 669d8e4aad5SCédric Le Goater 6700e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque) 6710e6232bcSCédric Le Goater { 6720e6232bcSCédric Le Goater Monitor *mon = opaque; 6730e6232bcSCédric Le Goater PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4); 6740e6232bcSCédric Le Goater 6750e6232bcSCédric Le Goater if (phb4) { 6760e6232bcSCédric Le Goater pnv_phb4_pic_print_info(phb4, mon); 6770e6232bcSCédric Le Goater } 6780e6232bcSCédric Le Goater return 0; 6790e6232bcSCédric Le Goater } 6800e6232bcSCédric Le Goater 681d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 682d8e4aad5SCédric Le Goater { 683d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 684d8e4aad5SCédric Le Goater 685d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 686c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 6874f9924c4SBenjamin Herrenschmidt 6880e6232bcSCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 6890e6232bcSCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 690d8e4aad5SCédric Le Goater } 691d8e4aad5SCédric Le Goater 692c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 693c4b2c40cSGreg Kurz uint32_t core_id) 694c4b2c40cSGreg Kurz { 695c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 696c4b2c40cSGreg Kurz } 697c4b2c40cSGreg Kurz 698c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 699c4b2c40cSGreg Kurz uint32_t core_id) 700c4b2c40cSGreg Kurz { 701c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 702c4b2c40cSGreg Kurz } 703c4b2c40cSGreg Kurz 704c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 705c4b2c40cSGreg Kurz uint32_t core_id) 706c4b2c40cSGreg Kurz { 707c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 708c4b2c40cSGreg Kurz } 709c4b2c40cSGreg Kurz 710f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 711f30c843cSCédric Le Goater { 712f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 713f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 714f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 715f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 716f30c843cSCédric Le Goater 717f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 718f30c843cSCédric Le Goater } 719f30c843cSCédric Le Goater 720e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 721e2392d43SCédric Le Goater { 722c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 723e2392d43SCédric Le Goater 7245325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); 7255325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); 726c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 727e2392d43SCédric Le Goater } 728e2392d43SCédric Le Goater 7292b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 7302b548a42SCédric Le Goater { 7318b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 7328b50ce85SCédric Le Goater 733da71b7e3SCédric Le Goater pnv_xive2_pic_print_info(&chip10->xive, mon); 7348b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 735623575e1SCédric Le Goater 736623575e1SCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 737623575e1SCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 7382b548a42SCédric Le Goater } 7392b548a42SCédric Le Goater 740458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */ 741458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id) 742458c6f01SCédric Le Goater { 743458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv); 744458c6f01SCédric Le Goater uint64_t ram_per_chip; 745458c6f01SCédric Le Goater 746458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB); 747458c6f01SCédric Le Goater 748458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips; 749458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) { 750458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 751458c6f01SCédric Le Goater } 752458c6f01SCédric Le Goater 753f640afecSCédric Le Goater assert(pnv->num_chips > 1); 754f640afecSCédric Le Goater 755458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1); 756458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 757458c6f01SCédric Le Goater } 758458c6f01SCédric Le Goater 759b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 7609e933f4aSBenjamin Herrenschmidt { 761cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME; 762b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 763f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 7649e933f4aSBenjamin Herrenschmidt char *fw_filename; 7659e933f4aSBenjamin Herrenschmidt long fw_size; 766458c6f01SCédric Le Goater uint64_t chip_ram_start = 0; 767e997040eSCédric Le Goater int i; 768e997040eSCédric Le Goater char *chip_typename; 76935dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 77035dde576SCédric Le Goater DeviceState *dev; 7719e933f4aSBenjamin Herrenschmidt 772ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) { 773ebe6c3faSDaniel Henrique Barboza error_report("The powernv machine does not work with KVM acceleration"); 774ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE); 775ebe6c3faSDaniel Henrique Barboza } 776ebe6c3faSDaniel Henrique Barboza 7779e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 778dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) { 779dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size); 780dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz); 781dd7ef911SCédric Le Goater g_free(sz); 782dd7ef911SCédric Le Goater exit(EXIT_FAILURE); 7839e933f4aSBenjamin Herrenschmidt } 784173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 7859e933f4aSBenjamin Herrenschmidt 78635dde576SCédric Le Goater /* 78735dde576SCédric Le Goater * Create our simple PNOR device 78835dde576SCédric Le Goater */ 7893e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 79035dde576SCédric Le Goater if (pnor) { 791934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 79235dde576SCédric Le Goater } 7933c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 79435dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 79535dde576SCédric Le Goater 7969e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 7979e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 79815fcedb2SCédric Le Goater if (!fw_filename) { 79915fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 80015fcedb2SCédric Le Goater exit(1); 80115fcedb2SCédric Le Goater } 8029e933f4aSBenjamin Herrenschmidt 80308c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 8049e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 80515fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 8069e933f4aSBenjamin Herrenschmidt exit(1); 8079e933f4aSBenjamin Herrenschmidt } 8089e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 8099e933f4aSBenjamin Herrenschmidt 8109e933f4aSBenjamin Herrenschmidt /* load kernel */ 8119e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 8129e933f4aSBenjamin Herrenschmidt long kernel_size; 8139e933f4aSBenjamin Herrenschmidt 8149e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 815b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 8169e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 817802fc7abSThomas Huth error_report("Could not load kernel '%s'", 8189e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 8199e933f4aSBenjamin Herrenschmidt exit(1); 8209e933f4aSBenjamin Herrenschmidt } 8219e933f4aSBenjamin Herrenschmidt } 8229e933f4aSBenjamin Herrenschmidt 8239e933f4aSBenjamin Herrenschmidt /* load initrd */ 8249e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 8259e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 8269e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 827584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 8289e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 829802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 8309e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 8319e933f4aSBenjamin Herrenschmidt exit(1); 8329e933f4aSBenjamin Herrenschmidt } 8339e933f4aSBenjamin Herrenschmidt } 834e997040eSCédric Le Goater 8354f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 8364f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 8374f9924c4SBenjamin Herrenschmidt 838f30c843cSCédric Le Goater /* 839f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 840f30c843cSCédric Le Goater * default. 841f30c843cSCédric Le Goater */ 842f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 843f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 844f30c843cSCédric Le Goater machine->cpu_type, mc->name); 845f30c843cSCédric Le Goater exit(1); 846f30c843cSCédric Le Goater } 847f30c843cSCédric Le Goater 848e997040eSCédric Le Goater /* Create the processor chips */ 8494a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 8507fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 8514a12c699SIgor Mammedov i, machine->cpu_type); 852e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 853f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 854f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 855e997040eSCédric Le Goater exit(1); 856e997040eSCédric Le Goater } 857e997040eSCédric Le Goater 858e44acde2SGreg Kurz pnv->num_chips = 859e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 860e44acde2SGreg Kurz /* 861e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 862e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 863e44acde2SGreg Kurz */ 864ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) { 865e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 866ab17a3feSCédric Le Goater error_printf( 867ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n"); 868e44acde2SGreg Kurz exit(1); 869e44acde2SGreg Kurz } 870e44acde2SGreg Kurz 871e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 872e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 873e997040eSCédric Le Goater char chip_name[32]; 874df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 8750e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i); 876e997040eSCédric Le Goater 877e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 878e997040eSCédric Le Goater 879458c6f01SCédric Le Goater /* Distribute RAM among the chips */ 880458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start, 881e997040eSCédric Le Goater &error_fatal); 882458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size, 883458c6f01SCédric Le Goater &error_fatal); 884458c6f01SCédric Le Goater chip_ram_start += chip_ram_size; 885e997040eSCédric Le Goater 8860e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i); 887d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 8880e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal); 8895325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores, 8905325cc34SMarkus Armbruster &error_fatal); 8915325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads, 8925325cc34SMarkus Armbruster &error_fatal); 893245cdb7fSCédric Le Goater /* 894245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 895245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 896245cdb7fSCédric Le Goater */ 897245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 8985325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); 899245cdb7fSCédric Le Goater } 900d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 9015325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv), 902d1214b81SGreg Kurz &error_abort); 903d1214b81SGreg Kurz } 9043c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 905e997040eSCédric Le Goater } 906e997040eSCédric Le Goater g_free(chip_typename); 9073495b6b6SCédric Le Goater 9083495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 90904026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 9103495b6b6SCédric Le Goater 9113495b6b6SCédric Le Goater /* Create serial port */ 912def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 9133495b6b6SCédric Le Goater 9143495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 9156c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 916bce0b691SCédric Le Goater 91725f3170bSCédric Le Goater /* 91825f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 91925f3170bSCédric Le Goater * communication with the BMC 92025f3170bSCédric Le Goater */ 92125f3170bSCédric Le Goater if (defaults_enabled()) { 92225f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 923e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 92425f3170bSCédric Le Goater } 925e2392d43SCédric Le Goater 92659b7c1c2SBalamuruhan S /* 927032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC. 928032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops, 929032c226bSCédric Le Goater * map it always for now. 930032c226bSCédric Le Goater */ 931032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, 932032c226bSCédric Le Goater &pnv->pnor->mmio); 933032c226bSCédric Le Goater 934032c226bSCédric Le Goater /* 93559b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 93659b7c1c2SBalamuruhan S * host to powerdown 93759b7c1c2SBalamuruhan S */ 938bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 939bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 940e997040eSCédric Le Goater } 941e997040eSCédric Le Goater 942631adaffSCédric Le Goater /* 943631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 944631adaffSCédric Le Goater * 22:24 Chip ID 945631adaffSCédric Le Goater * 25:28 Core number 946631adaffSCédric Le Goater * 29:31 Thread ID 947631adaffSCédric Le Goater */ 948631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 949631adaffSCédric Le Goater { 950631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 951631adaffSCédric Le Goater } 952631adaffSCédric Le Goater 9538fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 954d35aefa9SCédric Le Goater Error **errp) 955d35aefa9SCédric Le Goater { 956245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 9578fa1f4efSCédric Le Goater Error *local_err = NULL; 9588fa1f4efSCédric Le Goater Object *obj; 9598907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9608fa1f4efSCédric Le Goater 961245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 9628fa1f4efSCédric Le Goater if (local_err) { 9638fa1f4efSCédric Le Goater error_propagate(errp, local_err); 9648fa1f4efSCédric Le Goater return; 9658fa1f4efSCédric Le Goater } 9668fa1f4efSCédric Le Goater 967956b8f46SCédric Le Goater pnv_cpu->intc = obj; 968d35aefa9SCédric Le Goater } 969d35aefa9SCédric Le Goater 9700990ce6aSGreg Kurz 971d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 972d49e8a9bSCédric Le Goater { 973d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 974d49e8a9bSCédric Le Goater 975d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 976d49e8a9bSCédric Le Goater } 977d49e8a9bSCédric Le Goater 9780990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9790990ce6aSGreg Kurz { 9800990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9810990ce6aSGreg Kurz 9820990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 9830990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9840990ce6aSGreg Kurz } 9850990ce6aSGreg Kurz 98685913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 98785913070SGreg Kurz Monitor *mon) 98885913070SGreg Kurz { 98985913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 99085913070SGreg Kurz } 99185913070SGreg Kurz 992631adaffSCédric Le Goater /* 993631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 994631adaffSCédric Le Goater * 49:52 Node ID 995631adaffSCédric Le Goater * 53:55 Chip ID 996631adaffSCédric Le Goater * 56 Reserved - Read as zero 997631adaffSCédric Le Goater * 57:61 Core number 998631adaffSCédric Le Goater * 62:63 Thread ID 999631adaffSCédric Le Goater * 1000631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 1001631adaffSCédric Le Goater */ 1002631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 1003631adaffSCédric Le Goater { 1004631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 1005631adaffSCédric Le Goater } 1006631adaffSCédric Le Goater 10072b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 10082b548a42SCédric Le Goater { 10092b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 10102b548a42SCédric Le Goater } 10112b548a42SCédric Le Goater 10128fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 1013d35aefa9SCédric Le Goater Error **errp) 1014d35aefa9SCédric Le Goater { 10152dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 10162dfa91a2SCédric Le Goater Error *local_err = NULL; 10172dfa91a2SCédric Le Goater Object *obj; 10182dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10192dfa91a2SCédric Le Goater 10202dfa91a2SCédric Le Goater /* 10212dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 10222dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 10232dfa91a2SCédric Le Goater * only used at runtime. 10242dfa91a2SCédric Le Goater */ 102547950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 102647950946SCédric Le Goater &local_err); 10272dfa91a2SCédric Le Goater if (local_err) { 10282dfa91a2SCédric Le Goater error_propagate(errp, local_err); 10298fa1f4efSCédric Le Goater return; 1030d35aefa9SCédric Le Goater } 1031d35aefa9SCédric Le Goater 10322dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 10332dfa91a2SCédric Le Goater } 10342dfa91a2SCédric Le Goater 1035d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1036d49e8a9bSCédric Le Goater { 1037d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1038d49e8a9bSCédric Le Goater 1039d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 1040d49e8a9bSCédric Le Goater } 1041d49e8a9bSCédric Le Goater 10420990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10430990ce6aSGreg Kurz { 10440990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10450990ce6aSGreg Kurz 10460990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 10470990ce6aSGreg Kurz pnv_cpu->intc = NULL; 10480990ce6aSGreg Kurz } 10490990ce6aSGreg Kurz 105085913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 105185913070SGreg Kurz Monitor *mon) 105285913070SGreg Kurz { 105385913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 105485913070SGreg Kurz } 105585913070SGreg Kurz 10562b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 10572b548a42SCédric Le Goater Error **errp) 10582b548a42SCédric Le Goater { 1059da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1060da71b7e3SCédric Le Goater Error *local_err = NULL; 1061da71b7e3SCédric Le Goater Object *obj; 10622b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10632b548a42SCédric Le Goater 1064da71b7e3SCédric Le Goater /* 1065da71b7e3SCédric Le Goater * The core creates its interrupt presenter but the XIVE2 interrupt 1066da71b7e3SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 1067da71b7e3SCédric Le Goater * only used at runtime. 1068da71b7e3SCédric Le Goater */ 1069da71b7e3SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive), 1070da71b7e3SCédric Le Goater &local_err); 1071da71b7e3SCédric Le Goater if (local_err) { 1072da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1073da71b7e3SCédric Le Goater return; 1074da71b7e3SCédric Le Goater } 1075da71b7e3SCédric Le Goater 1076da71b7e3SCédric Le Goater pnv_cpu->intc = obj; 10772b548a42SCédric Le Goater } 10782b548a42SCédric Le Goater 10792b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 10802b548a42SCédric Le Goater { 1081da71b7e3SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1082da71b7e3SCédric Le Goater 1083da71b7e3SCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 10842b548a42SCédric Le Goater } 10852b548a42SCédric Le Goater 10862b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10872b548a42SCédric Le Goater { 10882b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10892b548a42SCédric Le Goater 1090da71b7e3SCédric Le Goater xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 10912b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10922b548a42SCédric Le Goater } 10932b548a42SCédric Le Goater 109485913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 109585913070SGreg Kurz Monitor *mon) 109685913070SGreg Kurz { 1097da71b7e3SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 109885913070SGreg Kurz } 109985913070SGreg Kurz 110059b7c1c2SBalamuruhan S /* 110159b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1102397a79e7SCédric Le Goater * 1103397a79e7SCédric Le Goater * <EX0 reserved> 1104397a79e7SCédric Le Goater * EX1 - Venice only 1105397a79e7SCédric Le Goater * EX2 - Venice only 1106397a79e7SCédric Le Goater * EX3 - Venice only 1107397a79e7SCédric Le Goater * EX4 1108397a79e7SCédric Le Goater * EX5 1109397a79e7SCédric Le Goater * EX6 1110397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1111397a79e7SCédric Le Goater * EX9 - Venice only 1112397a79e7SCédric Le Goater * EX10 - Venice only 1113397a79e7SCédric Le Goater * EX11 - Venice only 1114397a79e7SCédric Le Goater * EX12 1115397a79e7SCédric Le Goater * EX13 1116397a79e7SCédric Le Goater * EX14 1117397a79e7SCédric Le Goater * <EX15 reserved> 1118397a79e7SCédric Le Goater */ 1119397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1120397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1121397a79e7SCédric Le Goater 1122397a79e7SCédric Le Goater /* 112309279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1124397a79e7SCédric Le Goater */ 112509279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1126397a79e7SCédric Le Goater 11272b548a42SCédric Le Goater 11282b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 11292b548a42SCédric Le Goater 113077864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 113177864267SCédric Le Goater { 113277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 11339ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 11349ae1329eSCédric Le Goater int i; 113577864267SCédric Le Goater 1136245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1137245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1138245cdb7fSCédric Le Goater object_property_allow_set_link, 1139d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1140245cdb7fSCédric Le Goater 11419fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 114277864267SCédric Le Goater 11439fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 114477864267SCédric Le Goater 11459fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 11463887d241SBalamuruhan S 11479fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 11489ae1329eSCédric Le Goater 1149eb93c828SCédric Le Goater chip8->num_phbs = pcc->num_phbs; 11501f6a88ffSCédric Le Goater 1151eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 11529fc7fc4dSMarkus Armbruster object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); 11539ae1329eSCédric Le Goater } 11549ae1329eSCédric Le Goater 115577864267SCédric Le Goater } 115677864267SCédric Le Goater 115777864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 115877864267SCédric Le Goater { 115977864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 116077864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 116177864267SCédric Le Goater int i, j; 116277864267SCédric Le Goater char *name; 116377864267SCédric Le Goater 116477864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 116577864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 116677864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 116777864267SCédric Le Goater g_free(name); 116877864267SCédric Le Goater 116977864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 117077864267SCédric Le Goater 117177864267SCédric Le Goater /* Map the ICP registers for each thread */ 117277864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 11734fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 117477864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 117577864267SCédric Le Goater 117677864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 117777864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1178245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 117977864267SCédric Le Goater 118077864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 118177864267SCédric Le Goater &icp->mmio); 118277864267SCédric Le Goater } 118377864267SCédric Le Goater } 118477864267SCédric Le Goater } 118577864267SCédric Le Goater 1186792e8bb6SDaniel Henrique Barboza /* 1187792e8bb6SDaniel Henrique Barboza * Attach a root port device. 1188792e8bb6SDaniel Henrique Barboza * 1189792e8bb6SDaniel Henrique Barboza * 'index' will be used both as a PCIE slot value and to calculate 1190792e8bb6SDaniel Henrique Barboza * QOM id. 'chip_id' is going to be used as PCIE chassis for the 1191792e8bb6SDaniel Henrique Barboza * root port. 1192792e8bb6SDaniel Henrique Barboza */ 1193792e8bb6SDaniel Henrique Barboza void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, 1194792e8bb6SDaniel Henrique Barboza int index, int chip_id) 1195a71cd51eSCédric Le Goater { 1196a71cd51eSCédric Le Goater PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name); 11978625164aSDaniel Henrique Barboza g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index); 11988625164aSDaniel Henrique Barboza const char *dev_id = DEVICE(root)->id; 11998625164aSDaniel Henrique Barboza 12008625164aSDaniel Henrique Barboza object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, 12018625164aSDaniel Henrique Barboza OBJECT(root)); 1202a71cd51eSCédric Le Goater 1203792e8bb6SDaniel Henrique Barboza /* Set unique chassis/slot values for the root port */ 1204792e8bb6SDaniel Henrique Barboza qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); 1205792e8bb6SDaniel Henrique Barboza qdev_prop_set_uint16(DEVICE(root), "slot", index); 1206792e8bb6SDaniel Henrique Barboza 1207a71cd51eSCédric Le Goater pci_realize_and_unref(root, pci->bus, &error_fatal); 1208a71cd51eSCédric Le Goater } 1209a71cd51eSCédric Le Goater 121077864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 121177864267SCédric Le Goater { 121277864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 121377864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 121477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1215ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 121677864267SCédric Le Goater Error *local_err = NULL; 12179ae1329eSCédric Le Goater int i; 121877864267SCédric Le Goater 1219245cdb7fSCédric Le Goater assert(chip8->xics); 1220245cdb7fSCédric Le Goater 1221709044fdSCédric Le Goater /* XSCOM bridge is first */ 1222709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1223709044fdSCédric Le Goater if (local_err) { 1224709044fdSCédric Le Goater error_propagate(errp, local_err); 1225709044fdSCédric Le Goater return; 1226709044fdSCédric Le Goater } 1227709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1228709044fdSCédric Le Goater 122977864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 123077864267SCédric Le Goater if (local_err) { 123177864267SCédric Le Goater error_propagate(errp, local_err); 123277864267SCédric Le Goater return; 123377864267SCédric Le Goater } 123477864267SCédric Le Goater 123577864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 12365325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), 12375325cc34SMarkus Armbruster &error_fatal); 12385325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, 12395325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort); 1240668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { 124177864267SCédric Le Goater return; 124277864267SCédric Le Goater } 1243ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1244ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 124577864267SCédric Le Goater 124677864267SCédric Le Goater /* Create LPC controller */ 1247ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 124877864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 124977864267SCédric Le Goater 1250032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw; 125164d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 125264d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 125364d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 125464d011d5SCédric Le Goater 125559b7c1c2SBalamuruhan S /* 125659b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 125759b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 125859b7c1c2SBalamuruhan S */ 125977864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 126077864267SCédric Le Goater if (local_err) { 126177864267SCédric Le Goater error_propagate(errp, local_err); 126277864267SCédric Le Goater return; 126377864267SCédric Le Goater } 126477864267SCédric Le Goater 126577864267SCédric Le Goater /* Create the simplified OCC model */ 1266668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { 126777864267SCédric Le Goater return; 126877864267SCédric Le Goater } 126977864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1270b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->occ), 0, 1271b0ae5c69SCédric Le Goater qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC)); 1272f3db8266SBalamuruhan S 1273f3db8266SBalamuruhan S /* OCC SRAM model */ 12743a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1275f3db8266SBalamuruhan S &chip8->occ.sram_regs); 12763887d241SBalamuruhan S 12773887d241SBalamuruhan S /* HOMER */ 12785325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), 1279f2582acfSGreg Kurz &error_abort); 1280668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { 12813887d241SBalamuruhan S return; 12823887d241SBalamuruhan S } 12838f092316SCédric Le Goater /* Homer Xscom region */ 12848f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 12858f092316SCédric Le Goater 12868f092316SCédric Le Goater /* Homer mmio region */ 12873887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 12883887d241SBalamuruhan S &chip8->homer.regs); 12899ae1329eSCédric Le Goater 12909ae1329eSCédric Le Goater /* PHB3 controllers */ 1291eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 12929ae1329eSCédric Le Goater PnvPHB3 *phb = &chip8->phbs[i]; 12939ae1329eSCédric Le Goater 12945325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal); 12955325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, 12969ae1329eSCédric Le Goater &error_fatal); 12972c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip), 12982c4d3a50SCédric Le Goater &error_fatal); 1299668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { 13009ae1329eSCédric Le Goater return; 13019ae1329eSCédric Le Goater } 13029ae1329eSCédric Le Goater } 130377864267SCédric Le Goater } 130477864267SCédric Le Goater 130570c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 130670c059e9SGreg Kurz { 130770c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 130870c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 130970c059e9SGreg Kurz } 131070c059e9SGreg Kurz 1311e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1312e997040eSCédric Le Goater { 1313e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1314e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1315e997040eSCédric Le Goater 1316e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1317397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 13189ae1329eSCédric Le Goater k->num_phbs = 3; 1319631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1320d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1321d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13220990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 132385913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 132404026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1325eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1326d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1327c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 132870c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1329e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 133077864267SCédric Le Goater 133177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 133277864267SCédric Le Goater &k->parent_realize); 1333e997040eSCédric Le Goater } 1334e997040eSCédric Le Goater 1335e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1336e997040eSCédric Le Goater { 1337e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1338e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1339e997040eSCédric Le Goater 1340e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1341397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 13429ae1329eSCédric Le Goater k->num_phbs = 3; 1343631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1344d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1345d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13460990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 134785913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 134804026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1349eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1350d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1351c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 135270c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1353e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 135477864267SCédric Le Goater 135577864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 135677864267SCédric Le Goater &k->parent_realize); 1357e997040eSCédric Le Goater } 1358e997040eSCédric Le Goater 1359e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1360e997040eSCédric Le Goater { 1361e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1362e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1363e997040eSCédric Le Goater 1364e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1365397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1366316717feSCédric Le Goater k->num_phbs = 4; 1367631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1368d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1369d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13700990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 137185913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 137204026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1373eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1374d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1375c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 137670c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1377e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 137877864267SCédric Le Goater 137977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 138077864267SCédric Le Goater &k->parent_realize); 138177864267SCédric Le Goater } 138277864267SCédric Le Goater 138377864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 138477864267SCédric Le Goater { 13854f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 13862dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 13874f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 13884f9924c4SBenjamin Herrenschmidt int i; 13892dfa91a2SCédric Le Goater 1390db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1391d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1392d2623129SMarkus Armbruster "xive-fabric"); 1393c38536bcSCédric Le Goater 13949fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 139515376c66SCédric Le Goater 13969fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 13976598a70dSCédric Le Goater 13989fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 13993887d241SBalamuruhan S 14009fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 14014f9924c4SBenjamin Herrenschmidt 1402422fd92eSCédric Le Goater /* Number of PECs is the chip default */ 1403422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs; 1404422fd92eSCédric Le Goater 1405422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14064f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 14079fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 14084f9924c4SBenjamin Herrenschmidt } 140977864267SCédric Le Goater } 141077864267SCédric Le Goater 1411ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, 1412ae4c68e3SCédric Le Goater PnvCore *pnv_core) 14135dad902cSCédric Le Goater { 14145dad902cSCédric Le Goater char eq_name[32]; 14155dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 14165dad902cSCédric Le Goater 14175dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 14189fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 14199fc7fc4dSMarkus Armbruster sizeof(*eq), TYPE_PNV_QUAD, 14209fc7fc4dSMarkus Armbruster &error_fatal, NULL); 14215dad902cSCédric Le Goater 142292612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); 1423ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 1424ae4c68e3SCédric Le Goater } 1425ae4c68e3SCédric Le Goater 1426ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 1427ae4c68e3SCédric Le Goater { 1428ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 1429ae4c68e3SCédric Le Goater int i; 1430ae4c68e3SCédric Le Goater 1431ae4c68e3SCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1432ae4c68e3SCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 1433ae4c68e3SCédric Le Goater 1434ae4c68e3SCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 1435ae4c68e3SCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 1436ae4c68e3SCédric Le Goater 1437ae4c68e3SCédric Le Goater pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); 14385dad902cSCédric Le Goater 143992612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), 14405dad902cSCédric Le Goater &eq->xscom_regs); 14415dad902cSCédric Le Goater } 14425dad902cSCédric Le Goater } 14435dad902cSCédric Le Goater 144413480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp) 14454f9924c4SBenjamin Herrenschmidt { 14464f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 144713480fc5SCédric Le Goater int i; 14484f9924c4SBenjamin Herrenschmidt 1449422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14504f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 14514f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 14524f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 14534f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 14544f9924c4SBenjamin Herrenschmidt 14555325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 14565325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 14574f9924c4SBenjamin Herrenschmidt &error_fatal); 14586f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 14596f43d255SCédric Le Goater &error_fatal); 1460668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) { 14614f9924c4SBenjamin Herrenschmidt return; 14624f9924c4SBenjamin Herrenschmidt } 14634f9924c4SBenjamin Herrenschmidt 14644f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 14654f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 14664f9924c4SBenjamin Herrenschmidt 14674f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 14684f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 14694f9924c4SBenjamin Herrenschmidt } 14704f9924c4SBenjamin Herrenschmidt } 14714f9924c4SBenjamin Herrenschmidt 147277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 147377864267SCédric Le Goater { 147477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 14752dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 14762dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1477c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 147877864267SCédric Le Goater Error *local_err = NULL; 147977864267SCédric Le Goater 1480709044fdSCédric Le Goater /* XSCOM bridge is first */ 1481709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1482709044fdSCédric Le Goater if (local_err) { 1483709044fdSCédric Le Goater error_propagate(errp, local_err); 1484709044fdSCédric Le Goater return; 1485709044fdSCédric Le Goater } 1486709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1487709044fdSCédric Le Goater 148877864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 148977864267SCédric Le Goater if (local_err) { 149077864267SCédric Le Goater error_propagate(errp, local_err); 149177864267SCédric Le Goater return; 149277864267SCédric Le Goater } 14932dfa91a2SCédric Le Goater 14945dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 14955dad902cSCédric Le Goater if (local_err) { 14965dad902cSCédric Le Goater error_propagate(errp, local_err); 14975dad902cSCédric Le Goater return; 14985dad902cSCédric Le Goater } 14995dad902cSCédric Le Goater 15002dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 15015325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar", 15025325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal); 15035325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar", 15045325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal); 15055325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar", 15065325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal); 15075325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar", 15085325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal); 15095325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), 15107ae54cc3SGreg Kurz &error_abort); 1511668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { 15122dfa91a2SCédric Le Goater return; 15132dfa91a2SCédric Le Goater } 15142dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 15152dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1516c38536bcSCédric Le Goater 1517c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 15185325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), 15195325cc34SMarkus Armbruster &error_fatal); 152024c8fa96SCédric Le Goater /* This is the only device with 4k ESB pages */ 152124c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K, 152224c8fa96SCédric Le Goater &error_fatal); 1523668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { 1524c38536bcSCédric Le Goater return; 1525c38536bcSCédric Le Goater } 1526c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1527c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 152815376c66SCédric Le Goater 152915376c66SCédric Le Goater /* LPC */ 1530668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { 153115376c66SCédric Le Goater return; 153215376c66SCédric Le Goater } 153315376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 153415376c66SCédric Le Goater &chip9->lpc.xscom_regs); 153515376c66SCédric Le Goater 1536032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw; 153715376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 153815376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 15396598a70dSCédric Le Goater 15406598a70dSCédric Le Goater /* Create the simplified OCC model */ 1541668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { 15426598a70dSCédric Le Goater return; 15436598a70dSCédric Le Goater } 15446598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1545b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in( 1546b0ae5c69SCédric Le Goater DEVICE(&chip9->psi), PSIHB9_IRQ_OCC)); 1547f3db8266SBalamuruhan S 1548f3db8266SBalamuruhan S /* OCC SRAM model */ 15493a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1550f3db8266SBalamuruhan S &chip9->occ.sram_regs); 15513887d241SBalamuruhan S 15523887d241SBalamuruhan S /* HOMER */ 15535325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), 1554f2582acfSGreg Kurz &error_abort); 1555668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { 15563887d241SBalamuruhan S return; 15573887d241SBalamuruhan S } 15588f092316SCédric Le Goater /* Homer Xscom region */ 15598f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 15608f092316SCédric Le Goater 15618f092316SCédric Le Goater /* Homer mmio region */ 15623887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 15633887d241SBalamuruhan S &chip9->homer.regs); 15644f9924c4SBenjamin Herrenschmidt 156513480fc5SCédric Le Goater /* PEC PHBs */ 156613480fc5SCédric Le Goater pnv_chip_power9_pec_realize(chip, &local_err); 15674f9924c4SBenjamin Herrenschmidt if (local_err) { 15684f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 15694f9924c4SBenjamin Herrenschmidt return; 15704f9924c4SBenjamin Herrenschmidt } 1571e997040eSCédric Le Goater } 1572e997040eSCédric Le Goater 157370c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 157470c059e9SGreg Kurz { 157570c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 157670c059e9SGreg Kurz return addr >> 3; 157770c059e9SGreg Kurz } 157870c059e9SGreg Kurz 1579e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1580e997040eSCédric Le Goater { 1581e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1582e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1583e997040eSCédric Le Goater 158483028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1585397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1586631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1587d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1588d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 15890990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 159085913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 159104026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1592eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1593d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1594c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 159570c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1596e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 1597422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC; 159877864267SCédric Le Goater 159977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 160077864267SCédric Le Goater &k->parent_realize); 1601e997040eSCédric Le Goater } 1602e997040eSCédric Le Goater 16032b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 16042b548a42SCédric Le Goater { 1605623575e1SCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 16068b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 1607623575e1SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 1608623575e1SCédric Le Goater int i; 16098b50ce85SCédric Le Goater 1610da71b7e3SCédric Le Goater object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); 1611da71b7e3SCédric Le Goater object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), 1612da71b7e3SCédric Le Goater "xive-fabric"); 16139fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 16149fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 16158bf682a3SCédric Le Goater object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); 161692499676SCédric Le Goater object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); 1617623575e1SCédric Le Goater 1618623575e1SCédric Le Goater chip->num_pecs = pcc->num_pecs; 1619623575e1SCédric Le Goater 1620623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1621623575e1SCédric Le Goater object_initialize_child(obj, "pec[*]", &chip10->pecs[i], 1622623575e1SCédric Le Goater TYPE_PNV_PHB5_PEC); 1623623575e1SCédric Le Goater } 16242b548a42SCédric Le Goater } 16252b548a42SCédric Le Goater 1626ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) 1627ae4c68e3SCédric Le Goater { 1628ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip10); 1629ae4c68e3SCédric Le Goater int i; 1630ae4c68e3SCédric Le Goater 1631ae4c68e3SCédric Le Goater chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1632ae4c68e3SCédric Le Goater chip10->quads = g_new0(PnvQuad, chip10->nr_quads); 1633ae4c68e3SCédric Le Goater 1634ae4c68e3SCédric Le Goater for (i = 0; i < chip10->nr_quads; i++) { 1635ae4c68e3SCédric Le Goater PnvQuad *eq = &chip10->quads[i]; 1636ae4c68e3SCédric Le Goater 1637ae4c68e3SCédric Le Goater pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); 1638ae4c68e3SCédric Le Goater 1639ae4c68e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), 1640ae4c68e3SCédric Le Goater &eq->xscom_regs); 1641ae4c68e3SCédric Le Goater } 1642ae4c68e3SCédric Le Goater } 1643ae4c68e3SCédric Le Goater 1644623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) 1645623575e1SCédric Le Goater { 1646623575e1SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1647623575e1SCédric Le Goater int i; 1648623575e1SCédric Le Goater 1649623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1650623575e1SCédric Le Goater PnvPhb4PecState *pec = &chip10->pecs[i]; 1651623575e1SCédric Le Goater PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 1652623575e1SCédric Le Goater uint32_t pec_nest_base; 1653623575e1SCédric Le Goater uint32_t pec_pci_base; 1654623575e1SCédric Le Goater 1655623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 1656623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 1657623575e1SCédric Le Goater &error_fatal); 1658623575e1SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 1659623575e1SCédric Le Goater &error_fatal); 1660623575e1SCédric Le Goater if (!qdev_realize(DEVICE(pec), NULL, errp)) { 1661623575e1SCédric Le Goater return; 1662623575e1SCédric Le Goater } 1663623575e1SCédric Le Goater 1664623575e1SCédric Le Goater pec_nest_base = pecc->xscom_nest_base(pec); 1665623575e1SCédric Le Goater pec_pci_base = pecc->xscom_pci_base(pec); 1666623575e1SCédric Le Goater 1667623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 1668623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 1669623575e1SCédric Le Goater } 1670623575e1SCédric Le Goater } 1671623575e1SCédric Le Goater 16722b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 16732b548a42SCédric Le Goater { 16742b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 16752b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 16768b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 16772b548a42SCédric Le Goater Error *local_err = NULL; 16782b548a42SCédric Le Goater 16792b548a42SCédric Le Goater /* XSCOM bridge is first */ 16802b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 16812b548a42SCédric Le Goater if (local_err) { 16822b548a42SCédric Le Goater error_propagate(errp, local_err); 16832b548a42SCédric Le Goater return; 16842b548a42SCédric Le Goater } 16852b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 16862b548a42SCédric Le Goater 16872b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 16882b548a42SCédric Le Goater if (local_err) { 16892b548a42SCédric Le Goater error_propagate(errp, local_err); 16902b548a42SCédric Le Goater return; 16912b548a42SCédric Le Goater } 16928b50ce85SCédric Le Goater 1693ae4c68e3SCédric Le Goater pnv_chip_power10_quad_realize(chip10, &local_err); 1694ae4c68e3SCédric Le Goater if (local_err) { 1695ae4c68e3SCédric Le Goater error_propagate(errp, local_err); 1696ae4c68e3SCédric Le Goater return; 1697ae4c68e3SCédric Le Goater } 1698ae4c68e3SCédric Le Goater 1699da71b7e3SCédric Le Goater /* XIVE2 interrupt controller (POWER10) */ 1700da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "ic-bar", 1701da71b7e3SCédric Le Goater PNV10_XIVE2_IC_BASE(chip), &error_fatal); 1702da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "esb-bar", 1703da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_BASE(chip), &error_fatal); 1704da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "end-bar", 1705da71b7e3SCédric Le Goater PNV10_XIVE2_END_BASE(chip), &error_fatal); 1706da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar", 1707da71b7e3SCédric Le Goater PNV10_XIVE2_NVPG_BASE(chip), &error_fatal); 1708da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvc-bar", 1709da71b7e3SCédric Le Goater PNV10_XIVE2_NVC_BASE(chip), &error_fatal); 1710da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "tm-bar", 1711da71b7e3SCédric Le Goater PNV10_XIVE2_TM_BASE(chip), &error_fatal); 1712da71b7e3SCédric Le Goater object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip), 1713da71b7e3SCédric Le Goater &error_abort); 1714da71b7e3SCédric Le Goater if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) { 1715da71b7e3SCédric Le Goater return; 1716da71b7e3SCédric Le Goater } 1717da71b7e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE, 1718da71b7e3SCédric Le Goater &chip10->xive.xscom_regs); 1719da71b7e3SCédric Le Goater 17208b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 17215325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar", 17225325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal); 172324c8fa96SCédric Le Goater /* PSI can now be configured to use 64k ESB pages on POWER10 */ 172424c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K, 172524c8fa96SCédric Le Goater &error_fatal); 1726668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { 17278b50ce85SCédric Le Goater return; 17288b50ce85SCédric Le Goater } 17298b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 17308b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 17312661f6abSCédric Le Goater 17322661f6abSCédric Le Goater /* LPC */ 1733668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { 17342661f6abSCédric Le Goater return; 17352661f6abSCédric Le Goater } 17362661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 17372661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 17382661f6abSCédric Le Goater 1739032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw; 17402661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 17412661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 17428bf682a3SCédric Le Goater 17438bf682a3SCédric Le Goater /* Create the simplified OCC model */ 17448bf682a3SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) { 17458bf682a3SCédric Le Goater return; 17468bf682a3SCédric Le Goater } 17478bf682a3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE, 17488bf682a3SCédric Le Goater &chip10->occ.xscom_regs); 1749b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in( 1750b0ae5c69SCédric Le Goater DEVICE(&chip10->psi), PSIHB9_IRQ_OCC)); 1751623575e1SCédric Le Goater 175292499676SCédric Le Goater /* OCC SRAM model */ 175392499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), 175492499676SCédric Le Goater PNV10_OCC_SENSOR_BASE(chip), 175592499676SCédric Le Goater &chip10->occ.sram_regs); 175692499676SCédric Le Goater 175792499676SCédric Le Goater /* HOMER */ 175892499676SCédric Le Goater object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip), 175992499676SCédric Le Goater &error_abort); 176092499676SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) { 176192499676SCédric Le Goater return; 176292499676SCédric Le Goater } 176392499676SCédric Le Goater /* Homer Xscom region */ 176492499676SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE, 176592499676SCédric Le Goater &chip10->homer.pba_regs); 176692499676SCédric Le Goater 176792499676SCédric Le Goater /* Homer mmio region */ 176892499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip), 176992499676SCédric Le Goater &chip10->homer.regs); 177092499676SCédric Le Goater 1771623575e1SCédric Le Goater /* PHBs */ 1772623575e1SCédric Le Goater pnv_chip_power10_phb_realize(chip, &local_err); 1773623575e1SCédric Le Goater if (local_err) { 1774623575e1SCédric Le Goater error_propagate(errp, local_err); 1775623575e1SCédric Le Goater return; 1776623575e1SCédric Le Goater } 17772b548a42SCédric Le Goater } 17782b548a42SCédric Le Goater 177970c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 178070c059e9SGreg Kurz { 178170c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 178270c059e9SGreg Kurz return addr >> 3; 178370c059e9SGreg Kurz } 178470c059e9SGreg Kurz 17852b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 17862b548a42SCédric Le Goater { 17872b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 17882b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 17892b548a42SCédric Le Goater 17902b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 17912b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 17922b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 17932b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 17942b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 17952b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 179685913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 17972b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 17982b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 17992b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1800c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 180170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 18022b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 1803623575e1SCédric Le Goater k->num_pecs = PNV10_CHIP_MAX_PEC; 18042b548a42SCédric Le Goater 18052b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 18062b548a42SCédric Le Goater &k->parent_realize); 18072b548a42SCédric Le Goater } 18082b548a42SCédric Le Goater 1809397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1810397a79e7SCédric Le Goater { 1811397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1812397a79e7SCédric Le Goater int cores_max; 1813397a79e7SCédric Le Goater 1814397a79e7SCédric Le Goater /* 1815397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1816397a79e7SCédric Le Goater * the chip class 1817397a79e7SCédric Le Goater */ 1818397a79e7SCédric Le Goater if (!chip->cores_mask) { 1819397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1820397a79e7SCédric Le Goater } 1821397a79e7SCédric Le Goater 1822397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1823397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1824397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1825397a79e7SCédric Le Goater chip->cores_mask); 1826397a79e7SCédric Le Goater return; 1827397a79e7SCédric Le Goater } 1828397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1829397a79e7SCédric Le Goater 1830397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 183127d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1832397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1833397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1834397a79e7SCédric Le Goater cores_max); 1835397a79e7SCédric Le Goater return; 1836397a79e7SCédric Le Goater } 1837397a79e7SCédric Le Goater } 1838397a79e7SCédric Le Goater 183951c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1840e997040eSCédric Le Goater { 1841397a79e7SCédric Le Goater Error *error = NULL; 1842d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 184340abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1844d2fd9612SCédric Le Goater int i, core_hwid; 184508c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1846397a79e7SCédric Le Goater 1847d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1848d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1849d2fd9612SCédric Le Goater return; 1850d2fd9612SCédric Le Goater } 1851d2fd9612SCédric Le Goater 1852d2fd9612SCédric Le Goater /* Cores */ 1853397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1854397a79e7SCédric Le Goater if (error) { 1855397a79e7SCédric Le Goater error_propagate(errp, error); 1856397a79e7SCédric Le Goater return; 1857397a79e7SCédric Le Goater } 1858d2fd9612SCédric Le Goater 18594fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1860d2fd9612SCédric Le Goater 1861d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1862d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1863d2fd9612SCédric Le Goater char core_name[32]; 18644fa28f23SGreg Kurz PnvCore *pnv_core; 1865c035851aSCédric Le Goater uint64_t xscom_core_base; 1866d2fd9612SCédric Le Goater 1867d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1868d2fd9612SCédric Le Goater continue; 1869d2fd9612SCédric Le Goater } 1870d2fd9612SCédric Le Goater 18714fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 18724fa28f23SGreg Kurz 1873d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1874d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 18754fa28f23SGreg Kurz chip->cores[i] = pnv_core; 18765325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads", 18775325cc34SMarkus Armbruster chip->nr_threads, &error_fatal); 18785325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, 18795325cc34SMarkus Armbruster core_hwid, &error_fatal); 18805325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "pir", 18815325cc34SMarkus Armbruster pcc->core_pir(chip, core_hwid), &error_fatal); 18825325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, 18835325cc34SMarkus Armbruster &error_fatal); 18845325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), 1885158e17a6SGreg Kurz &error_abort); 1886ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 188724ece072SCédric Le Goater 188824ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1889c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1890c035851aSCédric Le Goater 1891c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 18924fa28f23SGreg Kurz &pnv_core->xscom_regs); 1893d2fd9612SCédric Le Goater i++; 1894d2fd9612SCédric Le Goater } 189551c04728SCédric Le Goater } 189651c04728SCédric Le Goater 189751c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 189851c04728SCédric Le Goater { 189951c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 190051c04728SCédric Le Goater Error *error = NULL; 190151c04728SCédric Le Goater 190251c04728SCédric Le Goater /* Cores */ 190351c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 190451c04728SCédric Le Goater if (error) { 190551c04728SCédric Le Goater error_propagate(errp, error); 190651c04728SCédric Le Goater return; 190751c04728SCédric Le Goater } 1908e997040eSCédric Le Goater } 1909e997040eSCédric Le Goater 1910e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1911e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1912e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1913e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1914397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1915397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1916764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 1917e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1918e997040eSCédric Le Goater }; 1919e997040eSCédric Le Goater 1920e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1921e997040eSCédric Le Goater { 1922e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1923e997040eSCédric Le Goater 19249d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1925e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 19264f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 1927e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1928e997040eSCédric Le Goater } 1929e997040eSCédric Le Goater 1930119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1931119eaa9dSCédric Le Goater { 1932119eaa9dSCédric Le Goater int i, j; 1933119eaa9dSCédric Le Goater 1934119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1935119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1936119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1937119eaa9dSCédric Le Goater 1938119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1939119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1940119eaa9dSCédric Le Goater return pc->threads[j]; 1941119eaa9dSCédric Le Goater } 1942119eaa9dSCédric Le Goater } 1943119eaa9dSCédric Le Goater } 1944119eaa9dSCédric Le Goater return NULL; 1945119eaa9dSCédric Le Goater } 1946119eaa9dSCédric Le Goater 194754f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 194854f59d78SCédric Le Goater { 1949b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 1950da6be501SDaniel Henrique Barboza int i, j; 195154f59d78SCédric Le Goater 195254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 195377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 195477864267SCédric Le Goater 195577864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 195677864267SCédric Le Goater return &chip8->psi.ics; 195754f59d78SCédric Le Goater } 19582ff73ddaSCédric Le Goater 1959da6be501SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 1960da6be501SDaniel Henrique Barboza PnvPHB3 *phb3 = &chip8->phbs[j]; 1961da6be501SDaniel Henrique Barboza 1962da6be501SDaniel Henrique Barboza if (ics_valid_irq(&phb3->lsis, irq)) { 1963da6be501SDaniel Henrique Barboza return &phb3->lsis; 1964da6be501SDaniel Henrique Barboza } 1965da6be501SDaniel Henrique Barboza 1966da6be501SDaniel Henrique Barboza if (ics_valid_irq(ICS(&phb3->msis), irq)) { 1967da6be501SDaniel Henrique Barboza return ICS(&phb3->msis); 1968da6be501SDaniel Henrique Barboza } 19699ae1329eSCédric Le Goater } 197054f59d78SCédric Le Goater } 197154f59d78SCédric Le Goater return NULL; 197254f59d78SCédric Le Goater } 197354f59d78SCédric Le Goater 19741f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id) 19751f6a88ffSCédric Le Goater { 19761f6a88ffSCédric Le Goater int i; 19771f6a88ffSCédric Le Goater 19781f6a88ffSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 19791f6a88ffSCédric Le Goater PnvChip *chip = pnv->chips[i]; 19801f6a88ffSCédric Le Goater if (chip->chip_id == chip_id) { 19811f6a88ffSCédric Le Goater return chip; 19821f6a88ffSCédric Le Goater } 19831f6a88ffSCédric Le Goater } 19841f6a88ffSCédric Le Goater return NULL; 19851f6a88ffSCédric Le Goater } 19861f6a88ffSCédric Le Goater 198754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 198854f59d78SCédric Le Goater { 1989b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 1990ca459489SDaniel Henrique Barboza int i, j; 199154f59d78SCédric Le Goater 199254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 199377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 19949ae1329eSCédric Le Goater 199577864267SCédric Le Goater ics_resend(&chip8->psi.ics); 1996ca459489SDaniel Henrique Barboza 1997ca459489SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 1998ca459489SDaniel Henrique Barboza PnvPHB3 *phb3 = &chip8->phbs[j]; 1999ca459489SDaniel Henrique Barboza 2000ca459489SDaniel Henrique Barboza ics_resend(&phb3->lsis); 2001ca459489SDaniel Henrique Barboza ics_resend(ICS(&phb3->msis)); 2002ca459489SDaniel Henrique Barboza } 200354f59d78SCédric Le Goater } 200454f59d78SCédric Le Goater } 200554f59d78SCédric Le Goater 200636fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 200736fc6f08SCédric Le Goater { 200836fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 200936fc6f08SCédric Le Goater 2010956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 201136fc6f08SCédric Le Goater } 201236fc6f08SCédric Le Goater 201347fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 201447fea43aSCédric Le Goater Monitor *mon) 201547fea43aSCédric Le Goater { 2016b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 201754f59d78SCédric Le Goater int i; 201847fea43aSCédric Le Goater CPUState *cs; 201947fea43aSCédric Le Goater 202047fea43aSCédric Le Goater CPU_FOREACH(cs) { 202147fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 202247fea43aSCédric Le Goater 202385913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 202485913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 202585913070SGreg Kurz mon); 2026d8e4aad5SCédric Le Goater } 202754f59d78SCédric Le Goater 202854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2029d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 203054f59d78SCédric Le Goater } 203147fea43aSCédric Le Goater } 203247fea43aSCédric Le Goater 2033c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 2034c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2035c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 2036c722579eSCédric Le Goater uint32_t logic_serv, 2037c722579eSCédric Le Goater XiveTCTXMatch *match) 2038c722579eSCédric Le Goater { 2039c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2040c722579eSCédric Le Goater int total_count = 0; 2041c722579eSCédric Le Goater int i; 2042c722579eSCédric Le Goater 2043c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2044c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 2045c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 2046c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2047c722579eSCédric Le Goater int count; 2048c722579eSCédric Le Goater 2049c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2050c722579eSCédric Le Goater priority, logic_serv, match); 2051c722579eSCédric Le Goater 2052c722579eSCédric Le Goater if (count < 0) { 2053c722579eSCédric Le Goater return count; 2054c722579eSCédric Le Goater } 2055c722579eSCédric Le Goater 2056c722579eSCédric Le Goater total_count += count; 2057c722579eSCédric Le Goater } 2058c722579eSCédric Le Goater 2059c722579eSCédric Le Goater return total_count; 2060c722579eSCédric Le Goater } 2061c722579eSCédric Le Goater 2062da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format, 2063da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2064da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority, 2065da71b7e3SCédric Le Goater uint32_t logic_serv, 2066da71b7e3SCédric Le Goater XiveTCTXMatch *match) 2067da71b7e3SCédric Le Goater { 2068da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2069da71b7e3SCédric Le Goater int total_count = 0; 2070da71b7e3SCédric Le Goater int i; 2071da71b7e3SCédric Le Goater 2072da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2073da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); 2074da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive); 2075da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2076da71b7e3SCédric Le Goater int count; 2077da71b7e3SCédric Le Goater 2078da71b7e3SCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2079da71b7e3SCédric Le Goater priority, logic_serv, match); 2080da71b7e3SCédric Le Goater 2081da71b7e3SCédric Le Goater if (count < 0) { 2082da71b7e3SCédric Le Goater return count; 2083da71b7e3SCédric Le Goater } 2084da71b7e3SCédric Le Goater 2085da71b7e3SCédric Le Goater total_count += count; 2086da71b7e3SCédric Le Goater } 2087da71b7e3SCédric Le Goater 2088da71b7e3SCédric Le Goater return total_count; 2089da71b7e3SCédric Le Goater } 2090da71b7e3SCédric Le Goater 2091f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 20929e933f4aSBenjamin Herrenschmidt { 20939e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 209436fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 2095d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2096d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 2097f30c843cSCédric Le Goater 2098f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 2099f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 2100f30c843cSCédric Le Goater 2101f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 2102f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 2103f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 2104d76f2da7SGreg Kurz 2105d76f2da7SGreg Kurz pmc->compat = compat; 2106d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 2107f30c843cSCédric Le Goater } 2108f30c843cSCédric Le Goater 2109f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 2110f30c843cSCédric Le Goater { 2111f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2112c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2113d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2114d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 2115f30c843cSCédric Le Goater 2116f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 2117f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 2118c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 2119f30c843cSCédric Le Goater 2120f30c843cSCédric Le Goater mc->alias = "powernv"; 2121d76f2da7SGreg Kurz 2122d76f2da7SGreg Kurz pmc->compat = compat; 2123d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 21247a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2125f30c843cSCédric Le Goater } 2126f30c843cSCédric Le Goater 21272b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 21282b548a42SCédric Le Goater { 21292b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2130d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2131da71b7e3SCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2132d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 21332b548a42SCédric Le Goater 21342b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 21356bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); 2136d76f2da7SGreg Kurz 2137d76f2da7SGreg Kurz pmc->compat = compat; 2138d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 21397a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2140da71b7e3SCédric Le Goater 2141da71b7e3SCédric Le Goater xfc->match_nvt = pnv10_xive_match_nvt; 21422b548a42SCédric Le Goater } 21432b548a42SCédric Le Goater 214408c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 214508c3f3a7SCédric Le Goater { 214608c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 214708c3f3a7SCédric Le Goater 214808c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 214908c3f3a7SCédric Le Goater } 215008c3f3a7SCédric Le Goater 215108c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 215208c3f3a7SCédric Le Goater { 215308c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 215408c3f3a7SCédric Le Goater 215508c3f3a7SCédric Le Goater if (value) { 215608c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 215708c3f3a7SCédric Le Goater } 215808c3f3a7SCédric Le Goater } 215908c3f3a7SCédric Le Goater 216001b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 216101b552b0SNicholas Piggin { 216201b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 216301b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 216401b552b0SNicholas Piggin 216501b552b0SNicholas Piggin cpu_synchronize_state(cs); 216601b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 21670911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 216801b552b0SNicholas Piggin /* 2169fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 2170fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 2171fe837714SNicholas Piggin * (PPC_BIT(43)). 217201b552b0SNicholas Piggin */ 21730911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 2174fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 21750911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 217601b552b0SNicholas Piggin } 2177fe837714SNicholas Piggin } else { 2178fe837714SNicholas Piggin /* 2179fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 2180fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 2181fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 2182fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 2183fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 2184fe837714SNicholas Piggin */ 21850911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 2186fe837714SNicholas Piggin } 2187fe837714SNicholas Piggin } 218801b552b0SNicholas Piggin 218901b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 219001b552b0SNicholas Piggin { 219101b552b0SNicholas Piggin CPUState *cs; 219201b552b0SNicholas Piggin 219301b552b0SNicholas Piggin CPU_FOREACH(cs) { 219401b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 219501b552b0SNicholas Piggin } 219601b552b0SNicholas Piggin } 219701b552b0SNicholas Piggin 2198f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 2199f30c843cSCédric Le Goater { 2200f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 220147fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 220201b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 22039e933f4aSBenjamin Herrenschmidt 22049e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 2205b168a138SCédric Le Goater mc->init = pnv_init; 2206b168a138SCédric Le Goater mc->reset = pnv_reset; 22079e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 220859b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 220959b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 22109e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 22119e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 2212f1d18b0aSJoel Stanley /* 2213f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 2214f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 2215f1d18b0aSJoel Stanley */ 2216dd7ef911SCédric Le Goater mc->default_ram_size = 1 * GiB; 2217173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 221847fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 221901b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 222008c3f3a7SCédric Le Goater 222108c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 2222d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 222308c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 22247eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 22259e933f4aSBenjamin Herrenschmidt } 22269e933f4aSBenjamin Herrenschmidt 222777864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2228beba5c0fSIgor Mammedov { \ 2229beba5c0fSIgor Mammedov .name = type, \ 2230beba5c0fSIgor Mammedov .class_init = class_initfn, \ 223177864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 223277864267SCédric Le Goater } 223377864267SCédric Le Goater 223477864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 223577864267SCédric Le Goater { \ 223677864267SCédric Le Goater .name = type, \ 223777864267SCédric Le Goater .class_init = class_initfn, \ 223877864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2239beba5c0fSIgor Mammedov } 2240beba5c0fSIgor Mammedov 22412b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 22422b548a42SCédric Le Goater { \ 22432b548a42SCédric Le Goater .name = type, \ 22442b548a42SCédric Le Goater .class_init = class_initfn, \ 22452b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 22462b548a42SCédric Le Goater } 22472b548a42SCédric Le Goater 2248beba5c0fSIgor Mammedov static const TypeInfo types[] = { 22491aba8716SCédric Le Goater { 22502b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 22512b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 22522b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 2253da71b7e3SCédric Le Goater .interfaces = (InterfaceInfo[]) { 2254da71b7e3SCédric Le Goater { TYPE_XIVE_FABRIC }, 2255da71b7e3SCédric Le Goater { }, 2256da71b7e3SCédric Le Goater }, 22572b548a42SCédric Le Goater }, 22582b548a42SCédric Le Goater { 22591aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 22601aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 22611aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2262c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2263c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2264c722579eSCédric Le Goater { }, 2265c722579eSCédric Le Goater }, 22661aba8716SCédric Le Goater }, 22671aba8716SCédric Le Goater { 22681aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 22691aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 22701aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 22711aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 22721aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 22731aba8716SCédric Le Goater { }, 22741aba8716SCédric Le Goater }, 22751aba8716SCédric Le Goater }, 2276beba5c0fSIgor Mammedov { 2277b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 22789e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2279f30c843cSCédric Le Goater .abstract = true, 22809e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2281b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2282d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 228336fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 228447fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 228501b552b0SNicholas Piggin { TYPE_NMI }, 228636fc6f08SCédric Le Goater { }, 228736fc6f08SCédric Le Goater }, 2288beba5c0fSIgor Mammedov }, 2289beba5c0fSIgor Mammedov { 2290beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2291beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2292beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2293beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2294beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2295beba5c0fSIgor Mammedov .abstract = true, 2296beba5c0fSIgor Mammedov }, 229777864267SCédric Le Goater 229877864267SCédric Le Goater /* 22992b548a42SCédric Le Goater * P10 chip and variants 23002b548a42SCédric Le Goater */ 23012b548a42SCédric Le Goater { 23022b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 23032b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 23042b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 23052b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 23062b548a42SCédric Le Goater }, 23072b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 23082b548a42SCédric Le Goater 23092b548a42SCédric Le Goater /* 231077864267SCédric Le Goater * P9 chip and variants 231177864267SCédric Le Goater */ 231277864267SCédric Le Goater { 231377864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 231477864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 231577864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 231677864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 231777864267SCédric Le Goater }, 231877864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 231977864267SCédric Le Goater 232077864267SCédric Le Goater /* 232177864267SCédric Le Goater * P8 chip and variants 232277864267SCédric Le Goater */ 232377864267SCédric Le Goater { 232477864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 232577864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 232677864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 232777864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 232877864267SCédric Le Goater }, 232977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 233077864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 233177864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2332beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 23339e933f4aSBenjamin Herrenschmidt }; 23349e933f4aSBenjamin Herrenschmidt 2335beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2336