19e933f4aSBenjamin Herrenschmidt /* 29e933f4aSBenjamin Herrenschmidt * QEMU PowerPC PowerNV machine model 39e933f4aSBenjamin Herrenschmidt * 49e933f4aSBenjamin Herrenschmidt * Copyright (c) 2016, IBM Corporation. 59e933f4aSBenjamin Herrenschmidt * 69e933f4aSBenjamin Herrenschmidt * This library is free software; you can redistribute it and/or 79e933f4aSBenjamin Herrenschmidt * modify it under the terms of the GNU Lesser General Public 89e933f4aSBenjamin Herrenschmidt * License as published by the Free Software Foundation; either 9f70c5966SChetan Pant * version 2.1 of the License, or (at your option) any later version. 109e933f4aSBenjamin Herrenschmidt * 119e933f4aSBenjamin Herrenschmidt * This library is distributed in the hope that it will be useful, 129e933f4aSBenjamin Herrenschmidt * but WITHOUT ANY WARRANTY; without even the implied warranty of 139e933f4aSBenjamin Herrenschmidt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 149e933f4aSBenjamin Herrenschmidt * Lesser General Public License for more details. 159e933f4aSBenjamin Herrenschmidt * 169e933f4aSBenjamin Herrenschmidt * You should have received a copy of the GNU Lesser General Public 179e933f4aSBenjamin Herrenschmidt * License along with this library; if not, see <http://www.gnu.org/licenses/>. 189e933f4aSBenjamin Herrenschmidt */ 199e933f4aSBenjamin Herrenschmidt 209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h" 212c65db5eSPaolo Bonzini #include "qemu/datadir.h" 22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 23dd7ef911SCédric Le Goater #include "qemu/cutils.h" 249e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 2538d2448aSGreg Kurz #include "sysemu/qtest.h" 269e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 279e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2871e8a915SMarkus Armbruster #include "sysemu/reset.h" 2954d31236SMarkus Armbruster #include "sysemu/runstate.h" 30d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 318d409261SCédric Le Goater #include "sysemu/device_tree.h" 3201b552b0SNicholas Piggin #include "sysemu/hw_accel.h" 33fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 3901b552b0SNicholas Piggin #include "hw/nmi.h" 40e997040eSCédric Le Goater #include "qapi/visitor.h" 4147fea43aSCédric Le Goater #include "monitor/monitor.h" 4247fea43aSCédric Le Goater #include "hw/intc/intc.h" 43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h" 461f5d6b2aSDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h" 472c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb3.h" 482c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb4.h" 499e933f4aSBenjamin Herrenschmidt 5036fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 51a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 522c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h" 53967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 5435dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 55967b7523SCédric Le Goater 563495b6b6SCédric Le Goater #include "hw/isa/isa.h" 573495b6b6SCédric Le Goater #include "hw/char/serial.h" 58bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 593495b6b6SCédric Le Goater 609e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 619e933f4aSBenjamin Herrenschmidt 62b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 639e933f4aSBenjamin Herrenschmidt 649e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 659e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 6683fa6e2aSCédric Le Goater #define FW_MAX_SIZE (16 * MiB) 679e933f4aSBenjamin Herrenschmidt 689e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 6905ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE (128 * MiB) 7005ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR 0x28000000 7105ce9b73SCédric Le Goater #define INITRD_MAX_SIZE (128 * MiB) 729e933f4aSBenjamin Herrenschmidt 7340abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 7440abf43fSIgor Mammedov { 7540abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7640abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7740abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7840abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7940abf43fSIgor Mammedov g_free(s); 8040abf43fSIgor Mammedov return core_type; 8140abf43fSIgor Mammedov } 8240abf43fSIgor Mammedov 839e933f4aSBenjamin Herrenschmidt /* 849e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 859e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 869e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 879e933f4aSBenjamin Herrenschmidt */ 889e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 899e933f4aSBenjamin Herrenschmidt 909e933f4aSBenjamin Herrenschmidt /* 919e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 929e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 939e933f4aSBenjamin Herrenschmidt * per chip. 949e933f4aSBenjamin Herrenschmidt */ 95b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 969e933f4aSBenjamin Herrenschmidt { 979e933f4aSBenjamin Herrenschmidt char *mem_name; 989e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 999e933f4aSBenjamin Herrenschmidt int off; 1009e933f4aSBenjamin Herrenschmidt 1019e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 1029e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 1039e933f4aSBenjamin Herrenschmidt 1049e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 1059e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1069e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1079e933f4aSBenjamin Herrenschmidt 1089e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1099e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1109e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1119e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1129e933f4aSBenjamin Herrenschmidt } 1139e933f4aSBenjamin Herrenschmidt 114d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 115d2fd9612SCédric Le Goater { 116d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 117d2fd9612SCédric Le Goater 118d2fd9612SCédric Le Goater if (cpus_offset < 0) { 119a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 120d2fd9612SCédric Le Goater if (cpus_offset) { 121d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 122d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 123d2fd9612SCédric Le Goater } 124d2fd9612SCédric Le Goater } 125d2fd9612SCédric Le Goater _FDT(cpus_offset); 126d2fd9612SCédric Le Goater return cpus_offset; 127d2fd9612SCédric Le Goater } 128d2fd9612SCédric Le Goater 129d2fd9612SCédric Le Goater /* 130d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 131d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 132d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 133d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 134d2fd9612SCédric Le Goater * servers. 135d2fd9612SCédric Le Goater */ 136b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 137d2fd9612SCédric Le Goater { 13808304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13908304a86SDavid Gibson CPUState *cs = CPU(cpu); 140d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1418bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 142d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 143d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 144a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); 145d2fd9612SCédric Le Goater int i; 146d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 147d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 148d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 149d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 150d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 151d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 152d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 153d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 154d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 155d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 156d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 157d2fd9612SCédric Le Goater int offset; 158d2fd9612SCédric Le Goater char *nodename; 159d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 160d2fd9612SCédric Le Goater 161d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 162d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 163d2fd9612SCédric Le Goater _FDT(offset); 164d2fd9612SCédric Le Goater g_free(nodename); 165d2fd9612SCédric Le Goater 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 167d2fd9612SCédric Le Goater 168d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 170d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 171d2fd9612SCédric Le Goater 172d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 174d2fd9612SCédric Le Goater env->dcache_line_size))); 175d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 176d2fd9612SCédric Le Goater env->dcache_line_size))); 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 178d2fd9612SCédric Le Goater env->icache_line_size))); 179d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 180d2fd9612SCédric Le Goater env->icache_line_size))); 181d2fd9612SCédric Le Goater 182d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 183d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 184d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 185d2fd9612SCédric Le Goater } else { 1863dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 187d2fd9612SCédric Le Goater } 188d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 189d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 190d2fd9612SCédric Le Goater pcc->l1_icache_size))); 191d2fd9612SCédric Le Goater } else { 1923dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 193d2fd9612SCédric Le Goater } 194d2fd9612SCédric Le Goater 195d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 196d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19759b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19859b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 199d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 200d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 201d2fd9612SCédric Le Goater 20203282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) { 203d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 204d2fd9612SCédric Le Goater } 205d2fd9612SCédric Le Goater 20658969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 207d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 208d2fd9612SCédric Le Goater segs, sizeof(segs)))); 209d2fd9612SCédric Le Goater } 210d2fd9612SCédric Le Goater 21159b7c1c2SBalamuruhan S /* 21259b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 213d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 214d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 21559b7c1c2SBalamuruhan S * 2 == VSX available 21659b7c1c2SBalamuruhan S */ 217d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 218d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 219d2fd9612SCédric Le Goater 220d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 221d2fd9612SCédric Le Goater } 222d2fd9612SCédric Le Goater 22359b7c1c2SBalamuruhan S /* 22459b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 225d2fd9612SCédric Le Goater * 0 / no property == no DFP 22659b7c1c2SBalamuruhan S * 1 == DFP available 22759b7c1c2SBalamuruhan S */ 228d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 229d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 230d2fd9612SCédric Le Goater } 231d2fd9612SCédric Le Goater 232644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 233d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 234d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 235d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 236d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 237d2fd9612SCédric Le Goater } 238d2fd9612SCédric Le Goater 239d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 240d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 241d2fd9612SCédric Le Goater 242d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 243d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 244d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 245d2fd9612SCédric Le Goater } 246d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 247a580fdcdSPhilippe Mathieu-Daudé servers_prop, sizeof(*servers_prop) * smt_threads))); 248d2fd9612SCédric Le Goater } 249d2fd9612SCédric Le Goater 250b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 251bf5615e7SCédric Le Goater uint32_t nr_threads) 252bf5615e7SCédric Le Goater { 253bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 254bf5615e7SCédric Le Goater char *name; 255bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 256bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 257bf5615e7SCédric Le Goater uint64_t *reg; 258bf5615e7SCédric Le Goater int offset; 259bf5615e7SCédric Le Goater 260bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 261bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 262bf5615e7SCédric Le Goater 263bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 264bf5615e7SCédric Le Goater reg = g_malloc(rsize); 265bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 266bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 267bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 268bf5615e7SCédric Le Goater } 269bf5615e7SCédric Le Goater 270bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 271bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 272bf5615e7SCédric Le Goater _FDT(offset); 273bf5615e7SCédric Le Goater g_free(name); 274bf5615e7SCédric Le Goater 275bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 278bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 279bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 280bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 281bf5615e7SCédric Le Goater irange, sizeof(irange)))); 282bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 283bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 284bf5615e7SCédric Le Goater g_free(reg); 285bf5615e7SCédric Le Goater } 286bf5615e7SCédric Le Goater 287c1471772SDaniel Henrique Barboza static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb, 288c1471772SDaniel Henrique Barboza Error **errp) 289c1471772SDaniel Henrique Barboza { 290607e9316SDaniel Henrique Barboza PnvPHB *phb_base = phb->phb_base; 291607e9316SDaniel Henrique Barboza PnvPhb4PecState *pecs = NULL; 292c1471772SDaniel Henrique Barboza int chip_id = phb->chip_id; 293c1471772SDaniel Henrique Barboza int index = phb->phb_id; 294c1471772SDaniel Henrique Barboza int i, j; 295c1471772SDaniel Henrique Barboza 296607e9316SDaniel Henrique Barboza if (phb_base->version == 4) { 297607e9316SDaniel Henrique Barboza Pnv9Chip *chip9 = PNV9_CHIP(chip); 298607e9316SDaniel Henrique Barboza 299607e9316SDaniel Henrique Barboza pecs = chip9->pecs; 300607e9316SDaniel Henrique Barboza } else if (phb_base->version == 5) { 301607e9316SDaniel Henrique Barboza Pnv10Chip *chip10 = PNV10_CHIP(chip); 302607e9316SDaniel Henrique Barboza 303607e9316SDaniel Henrique Barboza pecs = chip10->pecs; 304607e9316SDaniel Henrique Barboza } else { 305607e9316SDaniel Henrique Barboza g_assert_not_reached(); 306607e9316SDaniel Henrique Barboza } 307607e9316SDaniel Henrique Barboza 308c1471772SDaniel Henrique Barboza for (i = 0; i < chip->num_pecs; i++) { 309c1471772SDaniel Henrique Barboza /* 310c1471772SDaniel Henrique Barboza * For each PEC, check the amount of phbs it supports 311c1471772SDaniel Henrique Barboza * and see if the given phb4 index matches an index. 312c1471772SDaniel Henrique Barboza */ 313607e9316SDaniel Henrique Barboza PnvPhb4PecState *pec = &pecs[i]; 314c1471772SDaniel Henrique Barboza 315c1471772SDaniel Henrique Barboza for (j = 0; j < pec->num_phbs; j++) { 316c1471772SDaniel Henrique Barboza if (index == pnv_phb4_pec_get_phb_id(pec, j)) { 317c1471772SDaniel Henrique Barboza return pec; 318c1471772SDaniel Henrique Barboza } 319c1471772SDaniel Henrique Barboza } 320c1471772SDaniel Henrique Barboza } 321c1471772SDaniel Henrique Barboza error_setg(errp, 322c1471772SDaniel Henrique Barboza "pnv-phb4 chip-id %d index %d didn't match any existing PEC", 323c1471772SDaniel Henrique Barboza chip_id, index); 324c1471772SDaniel Henrique Barboza 325c1471772SDaniel Henrique Barboza return NULL; 326c1471772SDaniel Henrique Barboza } 327c1471772SDaniel Henrique Barboza 328ba47c3a4SDaniel Henrique Barboza /* 329ba47c3a4SDaniel Henrique Barboza * Adds a PnvPHB to the chip. Returns the parent obj of the 330ba47c3a4SDaniel Henrique Barboza * PHB which varies with each version (phb version 3 is parented 331ba47c3a4SDaniel Henrique Barboza * by the chip, version 4 and 5 are parented by the PEC 332ba47c3a4SDaniel Henrique Barboza * device). 333ba47c3a4SDaniel Henrique Barboza * 334ba47c3a4SDaniel Henrique Barboza * TODO: for version 3 we're still parenting the PHB with the 335ba47c3a4SDaniel Henrique Barboza * chip. We should parent with a (so far not implemented) 336ba47c3a4SDaniel Henrique Barboza * PHB3 PEC device. 337ba47c3a4SDaniel Henrique Barboza */ 338ba47c3a4SDaniel Henrique Barboza Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp) 339ba47c3a4SDaniel Henrique Barboza { 340ba47c3a4SDaniel Henrique Barboza if (phb->version == 3) { 3410d512c71SDaniel Henrique Barboza Pnv8Chip *chip8 = PNV8_CHIP(chip); 3420d512c71SDaniel Henrique Barboza 3430d512c71SDaniel Henrique Barboza phb->chip = chip; 3440d512c71SDaniel Henrique Barboza 3450d512c71SDaniel Henrique Barboza chip8->phbs[chip8->num_phbs] = phb; 3460d512c71SDaniel Henrique Barboza chip8->num_phbs++; 3470d512c71SDaniel Henrique Barboza 348ba47c3a4SDaniel Henrique Barboza return OBJECT(chip); 349ba47c3a4SDaniel Henrique Barboza } 350c1471772SDaniel Henrique Barboza 351c1471772SDaniel Henrique Barboza phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp); 352c1471772SDaniel Henrique Barboza 353c1471772SDaniel Henrique Barboza return OBJECT(phb->pec); 354ba47c3a4SDaniel Henrique Barboza } 355ba47c3a4SDaniel Henrique Barboza 356eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 357e997040eSCédric Le Goater { 358c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; 359d2fd9612SCédric Le Goater int i; 360d2fd9612SCédric Le Goater 3613f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3623f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 363c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE), 364c396c58aSGreg Kurz compat, sizeof(compat)); 365967b7523SCédric Le Goater 366d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3674fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 368d2fd9612SCédric Le Goater 369b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 370bf5615e7SCédric Le Goater 371bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 372b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 373d2fd9612SCédric Le Goater } 374d2fd9612SCédric Le Goater 375e997040eSCédric Le Goater if (chip->ram_size) { 376b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 377e997040eSCédric Le Goater } 378e997040eSCédric Le Goater } 379e997040eSCédric Le Goater 380eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 381eb859a27SCédric Le Goater { 382c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom"; 383eb859a27SCédric Le Goater int i; 384eb859a27SCédric Le Goater 3853f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3863f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 387c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE), 388c396c58aSGreg Kurz compat, sizeof(compat)); 389eb859a27SCédric Le Goater 390eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3914fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 392eb859a27SCédric Le Goater 393eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 394eb859a27SCédric Le Goater } 395eb859a27SCédric Le Goater 396eb859a27SCédric Le Goater if (chip->ram_size) { 397eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 398eb859a27SCédric Le Goater } 39915376c66SCédric Le Goater 4002661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 401eb859a27SCédric Le Goater } 402eb859a27SCédric Le Goater 4032b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 4042b548a42SCédric Le Goater { 405c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom"; 4062b548a42SCédric Le Goater int i; 4072b548a42SCédric Le Goater 4083f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 4093f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 410c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE), 411c396c58aSGreg Kurz compat, sizeof(compat)); 4122b548a42SCédric Le Goater 4132b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 4142b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 4152b548a42SCédric Le Goater 4162b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 4172b548a42SCédric Le Goater } 4182b548a42SCédric Le Goater 4192b548a42SCédric Le Goater if (chip->ram_size) { 4202b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 4212b548a42SCédric Le Goater } 4222661f6abSCédric Le Goater 4232661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 4242b548a42SCédric Le Goater } 4252b548a42SCédric Le Goater 426b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 427c5ffdcaeSCédric Le Goater { 428c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 429c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 430c5ffdcaeSCédric Le Goater cpu_to_be32(1), 431c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 432c5ffdcaeSCédric Le Goater cpu_to_be32(2) 433c5ffdcaeSCédric Le Goater }; 434c5ffdcaeSCédric Le Goater char *name; 435c5ffdcaeSCédric Le Goater int node; 436c5ffdcaeSCédric Le Goater 437c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 438c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 439c5ffdcaeSCédric Le Goater _FDT(node); 440c5ffdcaeSCédric Le Goater g_free(name); 441c5ffdcaeSCédric Le Goater 442c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 443c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 444c5ffdcaeSCédric Le Goater } 445c5ffdcaeSCédric Le Goater 446b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 447cb228f5aSCédric Le Goater { 448cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 449cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 450cb228f5aSCédric Le Goater uint32_t io_regs[] = { 451cb228f5aSCédric Le Goater cpu_to_be32(1), 452cb228f5aSCédric Le Goater cpu_to_be32(io_base), 453cb228f5aSCédric Le Goater cpu_to_be32(8) 454cb228f5aSCédric Le Goater }; 455632fc0b3SBernhard Beschow uint32_t irq; 456cb228f5aSCédric Le Goater char *name; 457cb228f5aSCédric Le Goater int node; 458cb228f5aSCédric Le Goater 459632fc0b3SBernhard Beschow irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal); 460632fc0b3SBernhard Beschow 461cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 462cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 463cb228f5aSCédric Le Goater _FDT(node); 464cb228f5aSCédric Le Goater g_free(name); 465cb228f5aSCédric Le Goater 466cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 467cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 468cb228f5aSCédric Le Goater sizeof(compatible)))); 469cb228f5aSCédric Le Goater 470cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 471cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 472632fc0b3SBernhard Beschow _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 473cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 474cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 475cb228f5aSCédric Le Goater 476cb228f5aSCédric Le Goater /* This is needed by Linux */ 477cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 478cb228f5aSCédric Le Goater } 479cb228f5aSCédric Le Goater 480b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 48104f6c8b2SCédric Le Goater { 48204f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 48304f6c8b2SCédric Le Goater uint32_t io_base; 48404f6c8b2SCédric Le Goater uint32_t io_regs[] = { 48504f6c8b2SCédric Le Goater cpu_to_be32(1), 48604f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 48704f6c8b2SCédric Le Goater cpu_to_be32(3) 48804f6c8b2SCédric Le Goater }; 48904f6c8b2SCédric Le Goater uint32_t irq; 49004f6c8b2SCédric Le Goater char *name; 49104f6c8b2SCédric Le Goater int node; 49204f6c8b2SCédric Le Goater 49304f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 49404f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 49504f6c8b2SCédric Le Goater 49604f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 49704f6c8b2SCédric Le Goater 49804f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 49904f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 50004f6c8b2SCédric Le Goater _FDT(node); 50104f6c8b2SCédric Le Goater g_free(name); 50204f6c8b2SCédric Le Goater 5037032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 5047032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 5057032d92aSCédric Le Goater sizeof(compatible)))); 50604f6c8b2SCédric Le Goater 50704f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 50804f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 50904f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 51004f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 51104f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 51204f6c8b2SCédric Le Goater } 51304f6c8b2SCédric Le Goater 514e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 515e7a3fee3SCédric Le Goater void *fdt; 516e7a3fee3SCédric Le Goater int offset; 517e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 518e7a3fee3SCédric Le Goater 519b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 520e7a3fee3SCédric Le Goater { 521c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 522c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 523c5ffdcaeSCédric Le Goater 524c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 525b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 526cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 527b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 52804f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 529b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 530c5ffdcaeSCédric Le Goater } else { 531c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 532c5ffdcaeSCédric Le Goater d->ioport_id); 533c5ffdcaeSCédric Le Goater } 534c5ffdcaeSCédric Le Goater 535e7a3fee3SCédric Le Goater return 0; 536e7a3fee3SCédric Le Goater } 537e7a3fee3SCédric Le Goater 53859b7c1c2SBalamuruhan S /* 53959b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 540bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 541bb7ab95cSCédric Le Goater */ 542bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 543bb7ab95cSCédric Le Goater { 54464d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 545e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 546e7a3fee3SCédric Le Goater .fdt = fdt, 547bb7ab95cSCédric Le Goater .offset = isa_offset, 548e7a3fee3SCédric Le Goater }; 549f47a08d1SCédric Le Goater uint32_t phandle; 550e7a3fee3SCédric Le Goater 551bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 552bb7ab95cSCédric Le Goater 553f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 554f47a08d1SCédric Le Goater assert(phandle > 0); 555f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 556f47a08d1SCédric Le Goater 55759b7c1c2SBalamuruhan S /* 55859b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 55959b7c1c2SBalamuruhan S * can not use object_child_foreach() 56059b7c1c2SBalamuruhan S */ 561bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 562bb7ab95cSCédric Le Goater &args); 563e7a3fee3SCédric Le Goater } 564e7a3fee3SCédric Le Goater 5657a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 566e5694793SCédric Le Goater { 567e5694793SCédric Le Goater int off; 568e5694793SCédric Le Goater 569e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 570e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 571e5694793SCédric Le Goater 572e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 573e5694793SCédric Le Goater } 574e5694793SCédric Le Goater 575b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 5769e933f4aSBenjamin Herrenschmidt { 577d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 578b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5799e933f4aSBenjamin Herrenschmidt void *fdt; 5809e933f4aSBenjamin Herrenschmidt char *buf; 5819e933f4aSBenjamin Herrenschmidt int off; 582e997040eSCédric Le Goater int i; 5839e933f4aSBenjamin Herrenschmidt 5849e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5859e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5869e933f4aSBenjamin Herrenschmidt 587ccb099b3SCédric Le Goater /* /qemu node */ 588ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 589ccb099b3SCédric Le Goater 5909e933f4aSBenjamin Herrenschmidt /* Root node */ 5919e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5929e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5939e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5949e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 595d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5969e933f4aSBenjamin Herrenschmidt 5979e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5989e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5999e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 600bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "system-id", buf))); 6019e933f4aSBenjamin Herrenschmidt } 6029e933f4aSBenjamin Herrenschmidt g_free(buf); 6039e933f4aSBenjamin Herrenschmidt 6049e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 6059e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 6069e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 6079e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 6089e933f4aSBenjamin Herrenschmidt } 6099e933f4aSBenjamin Herrenschmidt 6109e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 6119e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 6129e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 6139e933f4aSBenjamin Herrenschmidt 6149e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 6159e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 6169e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 6179e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 6189e933f4aSBenjamin Herrenschmidt } 6199e933f4aSBenjamin Herrenschmidt 620e997040eSCédric Le Goater /* Populate device tree for each chip */ 621e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 622eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 623e997040eSCédric Le Goater } 624e7a3fee3SCédric Le Goater 625e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 626bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 627aeaef83dSCédric Le Goater 628aeaef83dSCédric Le Goater if (pnv->bmc) { 629b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 630aeaef83dSCédric Le Goater } 631aeaef83dSCédric Le Goater 6327a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 6337a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 6347a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 635e5694793SCédric Le Goater } 636e5694793SCédric Le Goater 6379e933f4aSBenjamin Herrenschmidt return fdt; 6389e933f4aSBenjamin Herrenschmidt } 6399e933f4aSBenjamin Herrenschmidt 640bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 641bce0b691SCédric Le Goater { 6428f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 643bce0b691SCédric Le Goater 644bce0b691SCédric Le Goater if (pnv->bmc) { 645bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 646bce0b691SCédric Le Goater } 647bce0b691SCédric Le Goater } 648bce0b691SCédric Le Goater 6497966d70fSJason A. Donenfeld static void pnv_reset(MachineState *machine, ShutdownCause reason) 6509e933f4aSBenjamin Herrenschmidt { 65125f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 65225f3170bSCédric Le Goater IPMIBmc *bmc; 6539e933f4aSBenjamin Herrenschmidt void *fdt; 6549e933f4aSBenjamin Herrenschmidt 6557966d70fSJason A. Donenfeld qemu_devices_reset(reason); 6569e933f4aSBenjamin Herrenschmidt 65725f3170bSCédric Le Goater /* 65825f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator. 65925f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command 66025f3170bSCédric Le Goater * line. 66125f3170bSCédric Le Goater */ 66225f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal); 66325f3170bSCédric Le Goater if (!pnv->bmc) { 66425f3170bSCédric Le Goater if (!bmc) { 66538d2448aSGreg Kurz if (!qtest_enabled()) { 66625f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 66725f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 66825f3170bSCédric Le Goater "to define one"); 66938d2448aSGreg Kurz } 67025f3170bSCédric Le Goater } else { 67125f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 67225f3170bSCédric Le Goater pnv->bmc = bmc; 67325f3170bSCédric Le Goater } 67425f3170bSCédric Le Goater } 67525f3170bSCédric Le Goater 676b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6779e933f4aSBenjamin Herrenschmidt 6789e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6799e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6809e933f4aSBenjamin Herrenschmidt 6818d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6829e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 683b2fb7a43SPan Nengyuan 684adb77996SDaniel Henrique Barboza /* 685adb77996SDaniel Henrique Barboza * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free 686adb77996SDaniel Henrique Barboza * the existing machine->fdt to avoid leaking it during 687adb77996SDaniel Henrique Barboza * a reset. 688adb77996SDaniel Henrique Barboza */ 689adb77996SDaniel Henrique Barboza g_free(machine->fdt); 690adb77996SDaniel Henrique Barboza machine->fdt = fdt; 6919e933f4aSBenjamin Herrenschmidt } 6929e933f4aSBenjamin Herrenschmidt 69304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6943495b6b6SCédric Le Goater { 69577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 696c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL); 697c05aa140SCédric Le Goater 698c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 69977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 70004026890SCédric Le Goater } 7013495b6b6SCédric Le Goater 70204026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 70304026890SCédric Le Goater { 70477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 705c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C); 706c05aa140SCédric Le Goater 707c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 70877864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 70904026890SCédric Le Goater } 7103495b6b6SCédric Le Goater 71104026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 71204026890SCédric Le Goater { 71315376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 714c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC); 715c05aa140SCédric Le Goater 716c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq); 71715376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 71804026890SCédric Le Goater } 7193495b6b6SCédric Le Goater 7202b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 7212b548a42SCédric Le Goater { 7222661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 723c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC); 724c05aa140SCédric Le Goater 725c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq); 7262661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 7272b548a42SCédric Le Goater } 7282b548a42SCédric Le Goater 72904026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 73004026890SCédric Le Goater { 73104026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 7323495b6b6SCédric Le Goater } 7333495b6b6SCédric Le Goater 734d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 735d8e4aad5SCédric Le Goater { 736d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 7378a69bca7SDaniel Henrique Barboza int i; 738d8e4aad5SCédric Le Goater 739d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 7408a69bca7SDaniel Henrique Barboza 7418a69bca7SDaniel Henrique Barboza for (i = 0; i < chip8->num_phbs; i++) { 7420d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i]; 7431f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 7448a69bca7SDaniel Henrique Barboza 7458a69bca7SDaniel Henrique Barboza pnv_phb3_msi_pic_print_info(&phb3->msis, mon); 7468a69bca7SDaniel Henrique Barboza ics_pic_print_info(&phb3->lsis, mon); 7478a69bca7SDaniel Henrique Barboza } 748d8e4aad5SCédric Le Goater } 749d8e4aad5SCédric Le Goater 7500e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque) 7510e6232bcSCédric Le Goater { 7520e6232bcSCédric Le Goater Monitor *mon = opaque; 753210aacb3SDaniel Henrique Barboza PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB); 7540e6232bcSCédric Le Goater 755210aacb3SDaniel Henrique Barboza if (!phb) { 756210aacb3SDaniel Henrique Barboza return 0; 7570e6232bcSCédric Le Goater } 758210aacb3SDaniel Henrique Barboza 759210aacb3SDaniel Henrique Barboza pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon); 760210aacb3SDaniel Henrique Barboza 7610e6232bcSCédric Le Goater return 0; 7620e6232bcSCédric Le Goater } 7630e6232bcSCédric Le Goater 764d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 765d8e4aad5SCédric Le Goater { 766d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 767d8e4aad5SCédric Le Goater 768d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 769c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 7704f9924c4SBenjamin Herrenschmidt 7710e6232bcSCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 7720e6232bcSCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 773d8e4aad5SCédric Le Goater } 774d8e4aad5SCédric Le Goater 775c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 776c4b2c40cSGreg Kurz uint32_t core_id) 777c4b2c40cSGreg Kurz { 778c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 779c4b2c40cSGreg Kurz } 780c4b2c40cSGreg Kurz 781c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 782c4b2c40cSGreg Kurz uint32_t core_id) 783c4b2c40cSGreg Kurz { 784c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 785c4b2c40cSGreg Kurz } 786c4b2c40cSGreg Kurz 787c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 788c4b2c40cSGreg Kurz uint32_t core_id) 789c4b2c40cSGreg Kurz { 790c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 791c4b2c40cSGreg Kurz } 792c4b2c40cSGreg Kurz 793f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 794f30c843cSCédric Le Goater { 795f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 796f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 797f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 798f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 799f30c843cSCédric Le Goater 80021d3a78eSNicholas Piggin return ppc_default->pvr_match(ppc_default, ppc->pvr, false); 801f30c843cSCédric Le Goater } 802f30c843cSCédric Le Goater 803e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 804e2392d43SCédric Le Goater { 805c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 806e2392d43SCédric Le Goater 8075325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); 8085325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); 809c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 810e2392d43SCédric Le Goater } 811e2392d43SCédric Le Goater 8122b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 8132b548a42SCédric Le Goater { 8148b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 8158b50ce85SCédric Le Goater 816da71b7e3SCédric Le Goater pnv_xive2_pic_print_info(&chip10->xive, mon); 8178b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 818623575e1SCédric Le Goater 819623575e1SCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 820623575e1SCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 8212b548a42SCédric Le Goater } 8222b548a42SCédric Le Goater 823458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */ 824458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id) 825458c6f01SCédric Le Goater { 826458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv); 827458c6f01SCédric Le Goater uint64_t ram_per_chip; 828458c6f01SCédric Le Goater 829458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB); 830458c6f01SCédric Le Goater 831458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips; 832458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) { 833458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 834458c6f01SCédric Le Goater } 835458c6f01SCédric Le Goater 836f640afecSCédric Le Goater assert(pnv->num_chips > 1); 837f640afecSCédric Le Goater 838458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1); 839458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 840458c6f01SCédric Le Goater } 841458c6f01SCédric Le Goater 842b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 8439e933f4aSBenjamin Herrenschmidt { 844cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME; 845b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 846f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 8479e933f4aSBenjamin Herrenschmidt char *fw_filename; 8489e933f4aSBenjamin Herrenschmidt long fw_size; 849458c6f01SCédric Le Goater uint64_t chip_ram_start = 0; 850e997040eSCédric Le Goater int i; 851e997040eSCédric Le Goater char *chip_typename; 85235dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 85335dde576SCédric Le Goater DeviceState *dev; 8549e933f4aSBenjamin Herrenschmidt 855ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) { 856ebe6c3faSDaniel Henrique Barboza error_report("The powernv machine does not work with KVM acceleration"); 857ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE); 858ebe6c3faSDaniel Henrique Barboza } 859ebe6c3faSDaniel Henrique Barboza 8609e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 861dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) { 862dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size); 863dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz); 864dd7ef911SCédric Le Goater g_free(sz); 865dd7ef911SCédric Le Goater exit(EXIT_FAILURE); 8669e933f4aSBenjamin Herrenschmidt } 867173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 8689e933f4aSBenjamin Herrenschmidt 86935dde576SCédric Le Goater /* 87035dde576SCédric Le Goater * Create our simple PNOR device 87135dde576SCédric Le Goater */ 8723e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 87335dde576SCédric Le Goater if (pnor) { 874934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 87535dde576SCédric Le Goater } 8763c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 87735dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 87835dde576SCédric Le Goater 8799e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 8809e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 88115fcedb2SCédric Le Goater if (!fw_filename) { 88215fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 88315fcedb2SCédric Le Goater exit(1); 88415fcedb2SCédric Le Goater } 8859e933f4aSBenjamin Herrenschmidt 88608c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 8879e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 88815fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 8899e933f4aSBenjamin Herrenschmidt exit(1); 8909e933f4aSBenjamin Herrenschmidt } 8919e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 8929e933f4aSBenjamin Herrenschmidt 8939e933f4aSBenjamin Herrenschmidt /* load kernel */ 8949e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 8959e933f4aSBenjamin Herrenschmidt long kernel_size; 8969e933f4aSBenjamin Herrenschmidt 8979e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 898b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 8999e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 900802fc7abSThomas Huth error_report("Could not load kernel '%s'", 9019e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 9029e933f4aSBenjamin Herrenschmidt exit(1); 9039e933f4aSBenjamin Herrenschmidt } 9049e933f4aSBenjamin Herrenschmidt } 9059e933f4aSBenjamin Herrenschmidt 9069e933f4aSBenjamin Herrenschmidt /* load initrd */ 9079e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 9089e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 9099e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 910584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 9119e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 912802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 9139e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 9149e933f4aSBenjamin Herrenschmidt exit(1); 9159e933f4aSBenjamin Herrenschmidt } 9169e933f4aSBenjamin Herrenschmidt } 917e997040eSCédric Le Goater 9184f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 9194f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 9204f9924c4SBenjamin Herrenschmidt 921f30c843cSCédric Le Goater /* 922f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 923f30c843cSCédric Le Goater * default. 924f30c843cSCédric Le Goater */ 925f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 926f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 927f30c843cSCédric Le Goater machine->cpu_type, mc->name); 928f30c843cSCédric Le Goater exit(1); 929f30c843cSCédric Le Goater } 930f30c843cSCédric Le Goater 931e997040eSCédric Le Goater /* Create the processor chips */ 9324a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 9337fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 9344a12c699SIgor Mammedov i, machine->cpu_type); 935e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 936f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 937f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 938e997040eSCédric Le Goater exit(1); 939e997040eSCédric Le Goater } 940e997040eSCédric Le Goater 941e44acde2SGreg Kurz pnv->num_chips = 942e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 943e44acde2SGreg Kurz /* 944e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 945e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 946e44acde2SGreg Kurz */ 947ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) { 948e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 949ab17a3feSCédric Le Goater error_printf( 950ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n"); 951e44acde2SGreg Kurz exit(1); 952e44acde2SGreg Kurz } 953e44acde2SGreg Kurz 954e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 955e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 956e997040eSCédric Le Goater char chip_name[32]; 957df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 9580e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i); 959e997040eSCédric Le Goater 960e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 961e997040eSCédric Le Goater 962458c6f01SCédric Le Goater /* Distribute RAM among the chips */ 963458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start, 964e997040eSCédric Le Goater &error_fatal); 965458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size, 966458c6f01SCédric Le Goater &error_fatal); 967458c6f01SCédric Le Goater chip_ram_start += chip_ram_size; 968e997040eSCédric Le Goater 9690e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i); 970d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 9710e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal); 9725325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores, 9735325cc34SMarkus Armbruster &error_fatal); 9745325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads, 9755325cc34SMarkus Armbruster &error_fatal); 976245cdb7fSCédric Le Goater /* 977245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 978245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 979245cdb7fSCédric Le Goater */ 980245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 9815325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); 982245cdb7fSCédric Le Goater } 983d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 9845325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv), 985d1214b81SGreg Kurz &error_abort); 986d1214b81SGreg Kurz } 9873c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 988e997040eSCédric Le Goater } 989e997040eSCédric Le Goater g_free(chip_typename); 9903495b6b6SCédric Le Goater 9913495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 99204026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 9933495b6b6SCédric Le Goater 9943495b6b6SCédric Le Goater /* Create serial port */ 995def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 9963495b6b6SCédric Le Goater 9973495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 9986c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 999bce0b691SCédric Le Goater 100025f3170bSCédric Le Goater /* 100125f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 100225f3170bSCédric Le Goater * communication with the BMC 100325f3170bSCédric Le Goater */ 100425f3170bSCédric Le Goater if (defaults_enabled()) { 100525f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 1006e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 100725f3170bSCédric Le Goater } 1008e2392d43SCédric Le Goater 100959b7c1c2SBalamuruhan S /* 1010032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC. 1011032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops, 1012032c226bSCédric Le Goater * map it always for now. 1013032c226bSCédric Le Goater */ 1014032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, 1015032c226bSCédric Le Goater &pnv->pnor->mmio); 1016032c226bSCédric Le Goater 1017032c226bSCédric Le Goater /* 101859b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 101959b7c1c2SBalamuruhan S * host to powerdown 102059b7c1c2SBalamuruhan S */ 1021bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 1022bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 1023e997040eSCédric Le Goater } 1024e997040eSCédric Le Goater 1025631adaffSCédric Le Goater /* 1026631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 1027631adaffSCédric Le Goater * 22:24 Chip ID 1028631adaffSCédric Le Goater * 25:28 Core number 1029631adaffSCédric Le Goater * 29:31 Thread ID 1030631adaffSCédric Le Goater */ 1031631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 1032631adaffSCédric Le Goater { 1033631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 1034631adaffSCédric Le Goater } 1035631adaffSCédric Le Goater 10368fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 1037d35aefa9SCédric Le Goater Error **errp) 1038d35aefa9SCédric Le Goater { 1039245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 10408fa1f4efSCédric Le Goater Error *local_err = NULL; 10418fa1f4efSCédric Le Goater Object *obj; 10428907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10438fa1f4efSCédric Le Goater 1044245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 10458fa1f4efSCédric Le Goater if (local_err) { 10468fa1f4efSCédric Le Goater error_propagate(errp, local_err); 10478fa1f4efSCédric Le Goater return; 10488fa1f4efSCédric Le Goater } 10498fa1f4efSCédric Le Goater 1050956b8f46SCédric Le Goater pnv_cpu->intc = obj; 1051d35aefa9SCédric Le Goater } 1052d35aefa9SCédric Le Goater 10530990ce6aSGreg Kurz 1054d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1055d49e8a9bSCédric Le Goater { 1056d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1057d49e8a9bSCédric Le Goater 1058d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 1059d49e8a9bSCédric Le Goater } 1060d49e8a9bSCédric Le Goater 10610990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10620990ce6aSGreg Kurz { 10630990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10640990ce6aSGreg Kurz 10650990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 10660990ce6aSGreg Kurz pnv_cpu->intc = NULL; 10670990ce6aSGreg Kurz } 10680990ce6aSGreg Kurz 106985913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 107085913070SGreg Kurz Monitor *mon) 107185913070SGreg Kurz { 107285913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 107385913070SGreg Kurz } 107485913070SGreg Kurz 1075631adaffSCédric Le Goater /* 1076631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 1077631adaffSCédric Le Goater * 49:52 Node ID 1078631adaffSCédric Le Goater * 53:55 Chip ID 1079631adaffSCédric Le Goater * 56 Reserved - Read as zero 1080631adaffSCédric Le Goater * 57:61 Core number 1081631adaffSCédric Le Goater * 62:63 Thread ID 1082631adaffSCédric Le Goater * 1083631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 1084631adaffSCédric Le Goater */ 1085631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 1086631adaffSCédric Le Goater { 1087631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 1088631adaffSCédric Le Goater } 1089631adaffSCédric Le Goater 10902b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 10912b548a42SCédric Le Goater { 10922b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 10932b548a42SCédric Le Goater } 10942b548a42SCédric Le Goater 10958fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 1096d35aefa9SCédric Le Goater Error **errp) 1097d35aefa9SCédric Le Goater { 10982dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 10992dfa91a2SCédric Le Goater Error *local_err = NULL; 11002dfa91a2SCédric Le Goater Object *obj; 11012dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 11022dfa91a2SCédric Le Goater 11032dfa91a2SCédric Le Goater /* 11042dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 11052dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 11062dfa91a2SCédric Le Goater * only used at runtime. 11072dfa91a2SCédric Le Goater */ 110847950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 110947950946SCédric Le Goater &local_err); 11102dfa91a2SCédric Le Goater if (local_err) { 11112dfa91a2SCédric Le Goater error_propagate(errp, local_err); 11128fa1f4efSCédric Le Goater return; 1113d35aefa9SCédric Le Goater } 1114d35aefa9SCédric Le Goater 11152dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 11162dfa91a2SCédric Le Goater } 11172dfa91a2SCédric Le Goater 1118d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1119d49e8a9bSCédric Le Goater { 1120d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1121d49e8a9bSCédric Le Goater 1122d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 1123d49e8a9bSCédric Le Goater } 1124d49e8a9bSCédric Le Goater 11250990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 11260990ce6aSGreg Kurz { 11270990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 11280990ce6aSGreg Kurz 11290990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 11300990ce6aSGreg Kurz pnv_cpu->intc = NULL; 11310990ce6aSGreg Kurz } 11320990ce6aSGreg Kurz 113385913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 113485913070SGreg Kurz Monitor *mon) 113585913070SGreg Kurz { 113685913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 113785913070SGreg Kurz } 113885913070SGreg Kurz 11392b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 11402b548a42SCédric Le Goater Error **errp) 11412b548a42SCédric Le Goater { 1142da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1143da71b7e3SCédric Le Goater Error *local_err = NULL; 1144da71b7e3SCédric Le Goater Object *obj; 11452b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 11462b548a42SCédric Le Goater 1147da71b7e3SCédric Le Goater /* 1148da71b7e3SCédric Le Goater * The core creates its interrupt presenter but the XIVE2 interrupt 1149da71b7e3SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 1150da71b7e3SCédric Le Goater * only used at runtime. 1151da71b7e3SCédric Le Goater */ 1152da71b7e3SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive), 1153da71b7e3SCédric Le Goater &local_err); 1154da71b7e3SCédric Le Goater if (local_err) { 1155da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1156da71b7e3SCédric Le Goater return; 1157da71b7e3SCédric Le Goater } 1158da71b7e3SCédric Le Goater 1159da71b7e3SCédric Le Goater pnv_cpu->intc = obj; 11602b548a42SCédric Le Goater } 11612b548a42SCédric Le Goater 11622b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 11632b548a42SCédric Le Goater { 1164da71b7e3SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1165da71b7e3SCédric Le Goater 1166da71b7e3SCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 11672b548a42SCédric Le Goater } 11682b548a42SCédric Le Goater 11692b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 11702b548a42SCédric Le Goater { 11712b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 11722b548a42SCédric Le Goater 1173da71b7e3SCédric Le Goater xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 11742b548a42SCédric Le Goater pnv_cpu->intc = NULL; 11752b548a42SCédric Le Goater } 11762b548a42SCédric Le Goater 117785913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 117885913070SGreg Kurz Monitor *mon) 117985913070SGreg Kurz { 1180da71b7e3SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 118185913070SGreg Kurz } 118285913070SGreg Kurz 118359b7c1c2SBalamuruhan S /* 118459b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1185397a79e7SCédric Le Goater * 1186397a79e7SCédric Le Goater * <EX0 reserved> 1187397a79e7SCédric Le Goater * EX1 - Venice only 1188397a79e7SCédric Le Goater * EX2 - Venice only 1189397a79e7SCédric Le Goater * EX3 - Venice only 1190397a79e7SCédric Le Goater * EX4 1191397a79e7SCédric Le Goater * EX5 1192397a79e7SCédric Le Goater * EX6 1193397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1194397a79e7SCédric Le Goater * EX9 - Venice only 1195397a79e7SCédric Le Goater * EX10 - Venice only 1196397a79e7SCédric Le Goater * EX11 - Venice only 1197397a79e7SCédric Le Goater * EX12 1198397a79e7SCédric Le Goater * EX13 1199397a79e7SCédric Le Goater * EX14 1200397a79e7SCédric Le Goater * <EX15 reserved> 1201397a79e7SCédric Le Goater */ 1202397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1203397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1204397a79e7SCédric Le Goater 1205397a79e7SCédric Le Goater /* 120609279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1207397a79e7SCédric Le Goater */ 120809279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1209397a79e7SCédric Le Goater 12102b548a42SCédric Le Goater 12112b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 12122b548a42SCédric Le Goater 121377864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 121477864267SCédric Le Goater { 121577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 12169ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 12179ae1329eSCédric Le Goater int i; 121877864267SCédric Le Goater 1219245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1220245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1221245cdb7fSCédric Le Goater object_property_allow_set_link, 1222d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1223245cdb7fSCédric Le Goater 12249fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 122577864267SCédric Le Goater 12269fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 122777864267SCédric Le Goater 12289fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 12293887d241SBalamuruhan S 12309fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 12319ae1329eSCédric Le Goater 1232892c3ad0SDaniel Henrique Barboza if (defaults_enabled()) { 1233eb93c828SCédric Le Goater chip8->num_phbs = pcc->num_phbs; 12341f6a88ffSCédric Le Goater 1235eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 12360d512c71SDaniel Henrique Barboza Object *phb = object_new(TYPE_PNV_PHB); 12370d512c71SDaniel Henrique Barboza 12380d512c71SDaniel Henrique Barboza /* 12390d512c71SDaniel Henrique Barboza * We need the chip to parent the PHB to allow the DT 12400d512c71SDaniel Henrique Barboza * to build correctly (via pnv_xscom_dt()). 12410d512c71SDaniel Henrique Barboza * 12420d512c71SDaniel Henrique Barboza * TODO: the PHB should be parented by a PEC device that, at 12430d512c71SDaniel Henrique Barboza * this moment, is not modelled powernv8/phb3. 12440d512c71SDaniel Henrique Barboza */ 12450d512c71SDaniel Henrique Barboza object_property_add_child(obj, "phb[*]", phb); 12460d512c71SDaniel Henrique Barboza chip8->phbs[i] = PNV_PHB(phb); 12479ae1329eSCédric Le Goater } 1248892c3ad0SDaniel Henrique Barboza } 12499ae1329eSCédric Le Goater 125077864267SCédric Le Goater } 125177864267SCédric Le Goater 125277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 125377864267SCédric Le Goater { 125477864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 125577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 125677864267SCédric Le Goater int i, j; 125777864267SCédric Le Goater char *name; 125877864267SCédric Le Goater 125977864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 126077864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 126177864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 126277864267SCédric Le Goater g_free(name); 126377864267SCédric Le Goater 126477864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 126577864267SCédric Le Goater 126677864267SCédric Le Goater /* Map the ICP registers for each thread */ 126777864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 12684fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 126977864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 127077864267SCédric Le Goater 127177864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 127277864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1273245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 127477864267SCédric Le Goater 127577864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 127677864267SCédric Le Goater &icp->mmio); 127777864267SCédric Le Goater } 127877864267SCédric Le Goater } 127977864267SCédric Le Goater } 128077864267SCédric Le Goater 128177864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 128277864267SCédric Le Goater { 128377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 128477864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 128577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1286ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 128777864267SCédric Le Goater Error *local_err = NULL; 12889ae1329eSCédric Le Goater int i; 128977864267SCédric Le Goater 1290245cdb7fSCédric Le Goater assert(chip8->xics); 1291245cdb7fSCédric Le Goater 1292709044fdSCédric Le Goater /* XSCOM bridge is first */ 1293709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1294709044fdSCédric Le Goater if (local_err) { 1295709044fdSCédric Le Goater error_propagate(errp, local_err); 1296709044fdSCédric Le Goater return; 1297709044fdSCédric Le Goater } 1298709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1299709044fdSCédric Le Goater 130077864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 130177864267SCédric Le Goater if (local_err) { 130277864267SCédric Le Goater error_propagate(errp, local_err); 130377864267SCédric Le Goater return; 130477864267SCédric Le Goater } 130577864267SCédric Le Goater 130677864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 13075325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), 13085325cc34SMarkus Armbruster &error_fatal); 13095325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, 13105325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort); 1311668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { 131277864267SCédric Le Goater return; 131377864267SCédric Le Goater } 1314ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1315ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 131677864267SCédric Le Goater 131777864267SCédric Le Goater /* Create LPC controller */ 1318ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 131977864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 132077864267SCédric Le Goater 1321032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw; 132264d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 132364d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 132464d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 132564d011d5SCédric Le Goater 132659b7c1c2SBalamuruhan S /* 132759b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 132859b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 132959b7c1c2SBalamuruhan S */ 133077864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 133177864267SCédric Le Goater if (local_err) { 133277864267SCédric Le Goater error_propagate(errp, local_err); 133377864267SCédric Le Goater return; 133477864267SCédric Le Goater } 133577864267SCédric Le Goater 133677864267SCédric Le Goater /* Create the simplified OCC model */ 1337668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { 133877864267SCédric Le Goater return; 133977864267SCédric Le Goater } 134077864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1341b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->occ), 0, 1342b0ae5c69SCédric Le Goater qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC)); 1343f3db8266SBalamuruhan S 1344f3db8266SBalamuruhan S /* OCC SRAM model */ 13453a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1346f3db8266SBalamuruhan S &chip8->occ.sram_regs); 13473887d241SBalamuruhan S 13483887d241SBalamuruhan S /* HOMER */ 13495325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), 1350f2582acfSGreg Kurz &error_abort); 1351668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { 13523887d241SBalamuruhan S return; 13533887d241SBalamuruhan S } 13548f092316SCédric Le Goater /* Homer Xscom region */ 13558f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 13568f092316SCédric Le Goater 13578f092316SCédric Le Goater /* Homer mmio region */ 13583887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 13593887d241SBalamuruhan S &chip8->homer.regs); 13609ae1329eSCédric Le Goater 13611f5d6b2aSDaniel Henrique Barboza /* PHB controllers */ 1362eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 13630d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i]; 13649ae1329eSCédric Le Goater 13655325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal); 13665325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, 13679ae1329eSCédric Le Goater &error_fatal); 13682c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip), 13692c4d3a50SCédric Le Goater &error_fatal); 1370668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { 13719ae1329eSCédric Le Goater return; 13729ae1329eSCédric Le Goater } 13739ae1329eSCédric Le Goater } 137477864267SCédric Le Goater } 137577864267SCédric Le Goater 137670c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 137770c059e9SGreg Kurz { 137870c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 137970c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 138070c059e9SGreg Kurz } 138170c059e9SGreg Kurz 1382e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1383e997040eSCédric Le Goater { 1384e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1385e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1386e997040eSCédric Le Goater 1387e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1388397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 13899ae1329eSCédric Le Goater k->num_phbs = 3; 1390631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1391d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1392d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13930990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 139485913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 139504026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1396eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1397d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1398c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 139970c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1400e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 140177864267SCédric Le Goater 140277864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 140377864267SCédric Le Goater &k->parent_realize); 1404e997040eSCédric Le Goater } 1405e997040eSCédric Le Goater 1406e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1407e997040eSCédric Le Goater { 1408e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1409e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1410e997040eSCédric Le Goater 1411e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1412397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 14139ae1329eSCédric Le Goater k->num_phbs = 3; 1414631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1415d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1416d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 14170990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 141885913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 141904026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1420eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1421d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1422c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 142370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1424e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 142577864267SCédric Le Goater 142677864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 142777864267SCédric Le Goater &k->parent_realize); 1428e997040eSCédric Le Goater } 1429e997040eSCédric Le Goater 1430e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1431e997040eSCédric Le Goater { 1432e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1433e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1434e997040eSCédric Le Goater 1435e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1436397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1437316717feSCédric Le Goater k->num_phbs = 4; 1438631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1439d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1440d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 14410990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 144285913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 144304026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1444eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1445d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1446c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 144770c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1448e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 144977864267SCédric Le Goater 145077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 145177864267SCédric Le Goater &k->parent_realize); 145277864267SCédric Le Goater } 145377864267SCédric Le Goater 145477864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 145577864267SCédric Le Goater { 14564f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 14572dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 14584f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 14594f9924c4SBenjamin Herrenschmidt int i; 14602dfa91a2SCédric Le Goater 1461db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1462d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1463d2623129SMarkus Armbruster "xive-fabric"); 1464c38536bcSCédric Le Goater 14659fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 146615376c66SCédric Le Goater 14679fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 14686598a70dSCédric Le Goater 14699fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 14703887d241SBalamuruhan S 14710bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE); 14720bf4d77eSNicholas Piggin 14739fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 14744f9924c4SBenjamin Herrenschmidt 1475422fd92eSCédric Le Goater /* Number of PECs is the chip default */ 1476422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs; 1477422fd92eSCédric Le Goater 1478422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14794f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 14809fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 14814f9924c4SBenjamin Herrenschmidt } 148277864267SCédric Le Goater } 148377864267SCédric Le Goater 1484ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, 1485ae4c68e3SCédric Le Goater PnvCore *pnv_core) 14865dad902cSCédric Le Goater { 14875dad902cSCédric Le Goater char eq_name[32]; 14885dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 14895dad902cSCédric Le Goater 14905dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 14919fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 14929fc7fc4dSMarkus Armbruster sizeof(*eq), TYPE_PNV_QUAD, 14939fc7fc4dSMarkus Armbruster &error_fatal, NULL); 14945dad902cSCédric Le Goater 149592612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); 1496ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 1497ae4c68e3SCédric Le Goater } 1498ae4c68e3SCédric Le Goater 1499ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 1500ae4c68e3SCédric Le Goater { 1501ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 1502ae4c68e3SCédric Le Goater int i; 1503ae4c68e3SCédric Le Goater 1504ae4c68e3SCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1505ae4c68e3SCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 1506ae4c68e3SCédric Le Goater 1507ae4c68e3SCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 1508ae4c68e3SCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 1509ae4c68e3SCédric Le Goater 1510ae4c68e3SCédric Le Goater pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); 15115dad902cSCédric Le Goater 151292612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), 15135dad902cSCédric Le Goater &eq->xscom_regs); 15145dad902cSCédric Le Goater } 15155dad902cSCédric Le Goater } 15165dad902cSCédric Le Goater 151713480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp) 15184f9924c4SBenjamin Herrenschmidt { 15194f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 152013480fc5SCédric Le Goater int i; 15214f9924c4SBenjamin Herrenschmidt 1522422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 15234f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 15244f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 15254f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 15264f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 15274f9924c4SBenjamin Herrenschmidt 15285325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 15295325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 15304f9924c4SBenjamin Herrenschmidt &error_fatal); 15316f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 15326f43d255SCédric Le Goater &error_fatal); 1533668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) { 15344f9924c4SBenjamin Herrenschmidt return; 15354f9924c4SBenjamin Herrenschmidt } 15364f9924c4SBenjamin Herrenschmidt 15374f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 15384f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 15394f9924c4SBenjamin Herrenschmidt 15404f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 15414f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 15424f9924c4SBenjamin Herrenschmidt } 15434f9924c4SBenjamin Herrenschmidt } 15444f9924c4SBenjamin Herrenschmidt 154577864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 154677864267SCédric Le Goater { 154777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 15482dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 15492dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1550c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 155177864267SCédric Le Goater Error *local_err = NULL; 155277864267SCédric Le Goater 1553709044fdSCédric Le Goater /* XSCOM bridge is first */ 1554709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1555709044fdSCédric Le Goater if (local_err) { 1556709044fdSCédric Le Goater error_propagate(errp, local_err); 1557709044fdSCédric Le Goater return; 1558709044fdSCédric Le Goater } 1559709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1560709044fdSCédric Le Goater 156177864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 156277864267SCédric Le Goater if (local_err) { 156377864267SCédric Le Goater error_propagate(errp, local_err); 156477864267SCédric Le Goater return; 156577864267SCédric Le Goater } 15662dfa91a2SCédric Le Goater 15675dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 15685dad902cSCédric Le Goater if (local_err) { 15695dad902cSCédric Le Goater error_propagate(errp, local_err); 15705dad902cSCédric Le Goater return; 15715dad902cSCédric Le Goater } 15725dad902cSCédric Le Goater 15732dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 15745325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar", 15755325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal); 15765325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar", 15775325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal); 15785325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar", 15795325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal); 15805325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar", 15815325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal); 15825325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), 15837ae54cc3SGreg Kurz &error_abort); 1584668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { 15852dfa91a2SCédric Le Goater return; 15862dfa91a2SCédric Le Goater } 15872dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 15882dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1589c38536bcSCédric Le Goater 1590c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 15915325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), 15925325cc34SMarkus Armbruster &error_fatal); 159324c8fa96SCédric Le Goater /* This is the only device with 4k ESB pages */ 159424c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K, 159524c8fa96SCédric Le Goater &error_fatal); 1596668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { 1597c38536bcSCédric Le Goater return; 1598c38536bcSCédric Le Goater } 1599c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1600c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 160115376c66SCédric Le Goater 160215376c66SCédric Le Goater /* LPC */ 1603668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { 160415376c66SCédric Le Goater return; 160515376c66SCédric Le Goater } 160615376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 160715376c66SCédric Le Goater &chip9->lpc.xscom_regs); 160815376c66SCédric Le Goater 1609032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw; 161015376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 161115376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 16126598a70dSCédric Le Goater 16136598a70dSCédric Le Goater /* Create the simplified OCC model */ 1614668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { 16156598a70dSCédric Le Goater return; 16166598a70dSCédric Le Goater } 16176598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1618b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in( 1619b0ae5c69SCédric Le Goater DEVICE(&chip9->psi), PSIHB9_IRQ_OCC)); 1620f3db8266SBalamuruhan S 1621f3db8266SBalamuruhan S /* OCC SRAM model */ 16223a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1623f3db8266SBalamuruhan S &chip9->occ.sram_regs); 16243887d241SBalamuruhan S 16250bf4d77eSNicholas Piggin /* SBE */ 16260bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) { 16270bf4d77eSNicholas Piggin return; 16280bf4d77eSNicholas Piggin } 16290bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE, 16300bf4d77eSNicholas Piggin &chip9->sbe.xscom_ctrl_regs); 16310bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE, 16320bf4d77eSNicholas Piggin &chip9->sbe.xscom_mbox_regs); 16330bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in( 16340bf4d77eSNicholas Piggin DEVICE(&chip9->psi), PSIHB9_IRQ_PSU)); 16350bf4d77eSNicholas Piggin 16363887d241SBalamuruhan S /* HOMER */ 16375325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), 1638f2582acfSGreg Kurz &error_abort); 1639668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { 16403887d241SBalamuruhan S return; 16413887d241SBalamuruhan S } 16428f092316SCédric Le Goater /* Homer Xscom region */ 16438f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 16448f092316SCédric Le Goater 16458f092316SCédric Le Goater /* Homer mmio region */ 16463887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 16473887d241SBalamuruhan S &chip9->homer.regs); 16484f9924c4SBenjamin Herrenschmidt 164913480fc5SCédric Le Goater /* PEC PHBs */ 165013480fc5SCédric Le Goater pnv_chip_power9_pec_realize(chip, &local_err); 16514f9924c4SBenjamin Herrenschmidt if (local_err) { 16524f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 16534f9924c4SBenjamin Herrenschmidt return; 16544f9924c4SBenjamin Herrenschmidt } 1655e997040eSCédric Le Goater } 1656e997040eSCédric Le Goater 165770c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 165870c059e9SGreg Kurz { 165970c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 166070c059e9SGreg Kurz return addr >> 3; 166170c059e9SGreg Kurz } 166270c059e9SGreg Kurz 1663e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1664e997040eSCédric Le Goater { 1665e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1666e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1667e997040eSCédric Le Goater 166883028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1669397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1670631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1671d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1672d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 16730990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 167485913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 167504026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1676eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1677d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1678c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 167970c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1680e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 1681422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC; 168277864267SCédric Le Goater 168377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 168477864267SCédric Le Goater &k->parent_realize); 1685e997040eSCédric Le Goater } 1686e997040eSCédric Le Goater 16872b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 16882b548a42SCédric Le Goater { 1689623575e1SCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 16908b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 1691623575e1SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 1692623575e1SCédric Le Goater int i; 16938b50ce85SCédric Le Goater 1694da71b7e3SCédric Le Goater object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); 1695da71b7e3SCédric Le Goater object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), 1696da71b7e3SCédric Le Goater "xive-fabric"); 16979fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 16989fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 16998bf682a3SCédric Le Goater object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); 17000bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE); 170192499676SCédric Le Goater object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); 1702623575e1SCédric Le Goater 1703623575e1SCédric Le Goater chip->num_pecs = pcc->num_pecs; 1704623575e1SCédric Le Goater 1705623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1706623575e1SCédric Le Goater object_initialize_child(obj, "pec[*]", &chip10->pecs[i], 1707623575e1SCédric Le Goater TYPE_PNV_PHB5_PEC); 1708623575e1SCédric Le Goater } 17092b548a42SCédric Le Goater } 17102b548a42SCédric Le Goater 1711ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) 1712ae4c68e3SCédric Le Goater { 1713ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip10); 1714ae4c68e3SCédric Le Goater int i; 1715ae4c68e3SCédric Le Goater 1716ae4c68e3SCédric Le Goater chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1717ae4c68e3SCédric Le Goater chip10->quads = g_new0(PnvQuad, chip10->nr_quads); 1718ae4c68e3SCédric Le Goater 1719ae4c68e3SCédric Le Goater for (i = 0; i < chip10->nr_quads; i++) { 1720ae4c68e3SCédric Le Goater PnvQuad *eq = &chip10->quads[i]; 1721ae4c68e3SCédric Le Goater 1722ae4c68e3SCédric Le Goater pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]); 1723ae4c68e3SCédric Le Goater 1724ae4c68e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), 1725ae4c68e3SCédric Le Goater &eq->xscom_regs); 1726ae4c68e3SCédric Le Goater } 1727ae4c68e3SCédric Le Goater } 1728ae4c68e3SCédric Le Goater 1729623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) 1730623575e1SCédric Le Goater { 1731623575e1SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1732623575e1SCédric Le Goater int i; 1733623575e1SCédric Le Goater 1734623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1735623575e1SCédric Le Goater PnvPhb4PecState *pec = &chip10->pecs[i]; 1736623575e1SCédric Le Goater PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 1737623575e1SCédric Le Goater uint32_t pec_nest_base; 1738623575e1SCédric Le Goater uint32_t pec_pci_base; 1739623575e1SCédric Le Goater 1740623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 1741623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 1742623575e1SCédric Le Goater &error_fatal); 1743623575e1SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 1744623575e1SCédric Le Goater &error_fatal); 1745623575e1SCédric Le Goater if (!qdev_realize(DEVICE(pec), NULL, errp)) { 1746623575e1SCédric Le Goater return; 1747623575e1SCédric Le Goater } 1748623575e1SCédric Le Goater 1749623575e1SCédric Le Goater pec_nest_base = pecc->xscom_nest_base(pec); 1750623575e1SCédric Le Goater pec_pci_base = pecc->xscom_pci_base(pec); 1751623575e1SCédric Le Goater 1752623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 1753623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 1754623575e1SCédric Le Goater } 1755623575e1SCédric Le Goater } 1756623575e1SCédric Le Goater 17572b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 17582b548a42SCédric Le Goater { 17592b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 17602b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 17618b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 17622b548a42SCédric Le Goater Error *local_err = NULL; 17632b548a42SCédric Le Goater 17642b548a42SCédric Le Goater /* XSCOM bridge is first */ 17652b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 17662b548a42SCédric Le Goater if (local_err) { 17672b548a42SCédric Le Goater error_propagate(errp, local_err); 17682b548a42SCédric Le Goater return; 17692b548a42SCédric Le Goater } 17702b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 17712b548a42SCédric Le Goater 17722b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 17732b548a42SCédric Le Goater if (local_err) { 17742b548a42SCédric Le Goater error_propagate(errp, local_err); 17752b548a42SCédric Le Goater return; 17762b548a42SCédric Le Goater } 17778b50ce85SCédric Le Goater 1778ae4c68e3SCédric Le Goater pnv_chip_power10_quad_realize(chip10, &local_err); 1779ae4c68e3SCédric Le Goater if (local_err) { 1780ae4c68e3SCédric Le Goater error_propagate(errp, local_err); 1781ae4c68e3SCédric Le Goater return; 1782ae4c68e3SCédric Le Goater } 1783ae4c68e3SCédric Le Goater 1784da71b7e3SCédric Le Goater /* XIVE2 interrupt controller (POWER10) */ 1785da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "ic-bar", 1786da71b7e3SCédric Le Goater PNV10_XIVE2_IC_BASE(chip), &error_fatal); 1787da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "esb-bar", 1788da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_BASE(chip), &error_fatal); 1789da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "end-bar", 1790da71b7e3SCédric Le Goater PNV10_XIVE2_END_BASE(chip), &error_fatal); 1791da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar", 1792da71b7e3SCédric Le Goater PNV10_XIVE2_NVPG_BASE(chip), &error_fatal); 1793da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvc-bar", 1794da71b7e3SCédric Le Goater PNV10_XIVE2_NVC_BASE(chip), &error_fatal); 1795da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "tm-bar", 1796da71b7e3SCédric Le Goater PNV10_XIVE2_TM_BASE(chip), &error_fatal); 1797da71b7e3SCédric Le Goater object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip), 1798da71b7e3SCédric Le Goater &error_abort); 1799da71b7e3SCédric Le Goater if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) { 1800da71b7e3SCédric Le Goater return; 1801da71b7e3SCédric Le Goater } 1802da71b7e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE, 1803da71b7e3SCédric Le Goater &chip10->xive.xscom_regs); 1804da71b7e3SCédric Le Goater 18058b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 18065325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar", 18075325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal); 180824c8fa96SCédric Le Goater /* PSI can now be configured to use 64k ESB pages on POWER10 */ 180924c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K, 181024c8fa96SCédric Le Goater &error_fatal); 1811668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { 18128b50ce85SCédric Le Goater return; 18138b50ce85SCédric Le Goater } 18148b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 18158b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 18162661f6abSCédric Le Goater 18172661f6abSCédric Le Goater /* LPC */ 1818668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { 18192661f6abSCédric Le Goater return; 18202661f6abSCédric Le Goater } 18212661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 18222661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 18232661f6abSCédric Le Goater 1824032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw; 18252661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 18262661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 18278bf682a3SCédric Le Goater 18288bf682a3SCédric Le Goater /* Create the simplified OCC model */ 18298bf682a3SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) { 18308bf682a3SCédric Le Goater return; 18318bf682a3SCédric Le Goater } 18328bf682a3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE, 18338bf682a3SCédric Le Goater &chip10->occ.xscom_regs); 1834b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in( 1835b0ae5c69SCédric Le Goater DEVICE(&chip10->psi), PSIHB9_IRQ_OCC)); 1836623575e1SCédric Le Goater 183792499676SCédric Le Goater /* OCC SRAM model */ 183892499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), 183992499676SCédric Le Goater PNV10_OCC_SENSOR_BASE(chip), 184092499676SCédric Le Goater &chip10->occ.sram_regs); 184192499676SCédric Le Goater 18420bf4d77eSNicholas Piggin /* SBE */ 18430bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) { 18440bf4d77eSNicholas Piggin return; 18450bf4d77eSNicholas Piggin } 18460bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE, 18470bf4d77eSNicholas Piggin &chip10->sbe.xscom_ctrl_regs); 18480bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE, 18490bf4d77eSNicholas Piggin &chip10->sbe.xscom_mbox_regs); 18500bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in( 18510bf4d77eSNicholas Piggin DEVICE(&chip10->psi), PSIHB9_IRQ_PSU)); 18520bf4d77eSNicholas Piggin 185392499676SCédric Le Goater /* HOMER */ 185492499676SCédric Le Goater object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip), 185592499676SCédric Le Goater &error_abort); 185692499676SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) { 185792499676SCédric Le Goater return; 185892499676SCédric Le Goater } 185992499676SCédric Le Goater /* Homer Xscom region */ 186092499676SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE, 186192499676SCédric Le Goater &chip10->homer.pba_regs); 186292499676SCédric Le Goater 186392499676SCédric Le Goater /* Homer mmio region */ 186492499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip), 186592499676SCédric Le Goater &chip10->homer.regs); 186692499676SCédric Le Goater 1867623575e1SCédric Le Goater /* PHBs */ 1868623575e1SCédric Le Goater pnv_chip_power10_phb_realize(chip, &local_err); 1869623575e1SCédric Le Goater if (local_err) { 1870623575e1SCédric Le Goater error_propagate(errp, local_err); 1871623575e1SCédric Le Goater return; 1872623575e1SCédric Le Goater } 18732b548a42SCédric Le Goater } 18742b548a42SCédric Le Goater 187570c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 187670c059e9SGreg Kurz { 187770c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 187870c059e9SGreg Kurz return addr >> 3; 187970c059e9SGreg Kurz } 188070c059e9SGreg Kurz 18812b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 18822b548a42SCédric Le Goater { 18832b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 18842b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 18852b548a42SCédric Le Goater 18862b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 18872b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 18882b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 18892b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 18902b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 18912b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 189285913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 18932b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 18942b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 18952b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1896c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 189770c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 18982b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 1899623575e1SCédric Le Goater k->num_pecs = PNV10_CHIP_MAX_PEC; 19002b548a42SCédric Le Goater 19012b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 19022b548a42SCédric Le Goater &k->parent_realize); 19032b548a42SCédric Le Goater } 19042b548a42SCédric Le Goater 1905397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1906397a79e7SCédric Le Goater { 1907397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1908397a79e7SCédric Le Goater int cores_max; 1909397a79e7SCédric Le Goater 1910397a79e7SCédric Le Goater /* 1911397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1912397a79e7SCédric Le Goater * the chip class 1913397a79e7SCédric Le Goater */ 1914397a79e7SCédric Le Goater if (!chip->cores_mask) { 1915397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1916397a79e7SCédric Le Goater } 1917397a79e7SCédric Le Goater 1918397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1919397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1920397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1921397a79e7SCédric Le Goater chip->cores_mask); 1922397a79e7SCédric Le Goater return; 1923397a79e7SCédric Le Goater } 1924397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1925397a79e7SCédric Le Goater 1926397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 192727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1928397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1929397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1930397a79e7SCédric Le Goater cores_max); 1931397a79e7SCédric Le Goater return; 1932397a79e7SCédric Le Goater } 1933397a79e7SCédric Le Goater } 1934397a79e7SCédric Le Goater 193551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1936e997040eSCédric Le Goater { 1937397a79e7SCédric Le Goater Error *error = NULL; 1938d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 193940abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1940d2fd9612SCédric Le Goater int i, core_hwid; 194108c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1942397a79e7SCédric Le Goater 1943d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1944d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1945d2fd9612SCédric Le Goater return; 1946d2fd9612SCédric Le Goater } 1947d2fd9612SCédric Le Goater 1948d2fd9612SCédric Le Goater /* Cores */ 1949397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1950397a79e7SCédric Le Goater if (error) { 1951397a79e7SCédric Le Goater error_propagate(errp, error); 1952397a79e7SCédric Le Goater return; 1953397a79e7SCédric Le Goater } 1954d2fd9612SCédric Le Goater 19554fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1956d2fd9612SCédric Le Goater 1957d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1958d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1959d2fd9612SCédric Le Goater char core_name[32]; 19604fa28f23SGreg Kurz PnvCore *pnv_core; 1961c035851aSCédric Le Goater uint64_t xscom_core_base; 1962d2fd9612SCédric Le Goater 1963d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1964d2fd9612SCédric Le Goater continue; 1965d2fd9612SCédric Le Goater } 1966d2fd9612SCédric Le Goater 19674fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 19684fa28f23SGreg Kurz 1969d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1970d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 19714fa28f23SGreg Kurz chip->cores[i] = pnv_core; 19725325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads", 19735325cc34SMarkus Armbruster chip->nr_threads, &error_fatal); 19745325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, 19755325cc34SMarkus Armbruster core_hwid, &error_fatal); 19765325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "pir", 19775325cc34SMarkus Armbruster pcc->core_pir(chip, core_hwid), &error_fatal); 19785325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, 19795325cc34SMarkus Armbruster &error_fatal); 19805325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), 1981158e17a6SGreg Kurz &error_abort); 1982ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 198324ece072SCédric Le Goater 198424ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1985c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1986c035851aSCédric Le Goater 1987c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 19884fa28f23SGreg Kurz &pnv_core->xscom_regs); 1989d2fd9612SCédric Le Goater i++; 1990d2fd9612SCédric Le Goater } 199151c04728SCédric Le Goater } 199251c04728SCédric Le Goater 199351c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 199451c04728SCédric Le Goater { 199551c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 199651c04728SCédric Le Goater Error *error = NULL; 199751c04728SCédric Le Goater 199851c04728SCédric Le Goater /* Cores */ 199951c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 200051c04728SCédric Le Goater if (error) { 200151c04728SCédric Le Goater error_propagate(errp, error); 200251c04728SCédric Le Goater return; 200351c04728SCédric Le Goater } 2004e997040eSCédric Le Goater } 2005e997040eSCédric Le Goater 2006e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 2007e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 2008e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 2009e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 2010397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 2011397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 2012764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 2013e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 2014e997040eSCédric Le Goater }; 2015e997040eSCédric Le Goater 2016e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 2017e997040eSCédric Le Goater { 2018e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 2019e997040eSCédric Le Goater 20209d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 2021e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 20224f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 2023e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 2024e997040eSCédric Le Goater } 2025e997040eSCédric Le Goater 2026119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 2027119eaa9dSCédric Le Goater { 2028119eaa9dSCédric Le Goater int i, j; 2029119eaa9dSCédric Le Goater 2030119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2031119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 2032119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 2033119eaa9dSCédric Le Goater 2034119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 2035119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 2036119eaa9dSCédric Le Goater return pc->threads[j]; 2037119eaa9dSCédric Le Goater } 2038119eaa9dSCédric Le Goater } 2039119eaa9dSCédric Le Goater } 2040119eaa9dSCédric Le Goater return NULL; 2041119eaa9dSCédric Le Goater } 2042119eaa9dSCédric Le Goater 204354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 204454f59d78SCédric Le Goater { 2045b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 2046da6be501SDaniel Henrique Barboza int i, j; 204754f59d78SCédric Le Goater 204854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 204977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 205077864267SCédric Le Goater 205177864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 205277864267SCédric Le Goater return &chip8->psi.ics; 205354f59d78SCédric Le Goater } 20542ff73ddaSCédric Le Goater 2055da6be501SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 20560d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j]; 20571f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 2058da6be501SDaniel Henrique Barboza 2059da6be501SDaniel Henrique Barboza if (ics_valid_irq(&phb3->lsis, irq)) { 2060da6be501SDaniel Henrique Barboza return &phb3->lsis; 2061da6be501SDaniel Henrique Barboza } 2062da6be501SDaniel Henrique Barboza 2063da6be501SDaniel Henrique Barboza if (ics_valid_irq(ICS(&phb3->msis), irq)) { 2064da6be501SDaniel Henrique Barboza return ICS(&phb3->msis); 2065da6be501SDaniel Henrique Barboza } 20669ae1329eSCédric Le Goater } 206754f59d78SCédric Le Goater } 206854f59d78SCédric Le Goater return NULL; 206954f59d78SCédric Le Goater } 207054f59d78SCédric Le Goater 20711f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id) 20721f6a88ffSCédric Le Goater { 20731f6a88ffSCédric Le Goater int i; 20741f6a88ffSCédric Le Goater 20751f6a88ffSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 20761f6a88ffSCédric Le Goater PnvChip *chip = pnv->chips[i]; 20771f6a88ffSCédric Le Goater if (chip->chip_id == chip_id) { 20781f6a88ffSCédric Le Goater return chip; 20791f6a88ffSCédric Le Goater } 20801f6a88ffSCédric Le Goater } 20811f6a88ffSCédric Le Goater return NULL; 20821f6a88ffSCédric Le Goater } 20831f6a88ffSCédric Le Goater 208454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 208554f59d78SCédric Le Goater { 2086b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 2087ca459489SDaniel Henrique Barboza int i, j; 208854f59d78SCédric Le Goater 208954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 209077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 20919ae1329eSCédric Le Goater 209277864267SCédric Le Goater ics_resend(&chip8->psi.ics); 2093ca459489SDaniel Henrique Barboza 2094ca459489SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 20950d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j]; 20961f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 2097ca459489SDaniel Henrique Barboza 2098ca459489SDaniel Henrique Barboza ics_resend(&phb3->lsis); 2099ca459489SDaniel Henrique Barboza ics_resend(ICS(&phb3->msis)); 2100ca459489SDaniel Henrique Barboza } 210154f59d78SCédric Le Goater } 210254f59d78SCédric Le Goater } 210354f59d78SCédric Le Goater 210436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 210536fc6f08SCédric Le Goater { 210636fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 210736fc6f08SCédric Le Goater 2108956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 210936fc6f08SCédric Le Goater } 211036fc6f08SCédric Le Goater 211147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 211247fea43aSCédric Le Goater Monitor *mon) 211347fea43aSCédric Le Goater { 2114b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 211554f59d78SCédric Le Goater int i; 211647fea43aSCédric Le Goater CPUState *cs; 211747fea43aSCédric Le Goater 211847fea43aSCédric Le Goater CPU_FOREACH(cs) { 211947fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 212047fea43aSCédric Le Goater 212185913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 212285913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 212385913070SGreg Kurz mon); 2124d8e4aad5SCédric Le Goater } 212554f59d78SCédric Le Goater 212654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2127d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 212854f59d78SCédric Le Goater } 212947fea43aSCédric Le Goater } 213047fea43aSCédric Le Goater 2131c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 2132c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2133c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 2134c722579eSCédric Le Goater uint32_t logic_serv, 2135c722579eSCédric Le Goater XiveTCTXMatch *match) 2136c722579eSCédric Le Goater { 2137c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2138c722579eSCédric Le Goater int total_count = 0; 2139c722579eSCédric Le Goater int i; 2140c722579eSCédric Le Goater 2141c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2142c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 2143c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 2144c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2145c722579eSCédric Le Goater int count; 2146c722579eSCédric Le Goater 2147c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2148c722579eSCédric Le Goater priority, logic_serv, match); 2149c722579eSCédric Le Goater 2150c722579eSCédric Le Goater if (count < 0) { 2151c722579eSCédric Le Goater return count; 2152c722579eSCédric Le Goater } 2153c722579eSCédric Le Goater 2154c722579eSCédric Le Goater total_count += count; 2155c722579eSCédric Le Goater } 2156c722579eSCédric Le Goater 2157c722579eSCédric Le Goater return total_count; 2158c722579eSCédric Le Goater } 2159c722579eSCédric Le Goater 2160da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format, 2161da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2162da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority, 2163da71b7e3SCédric Le Goater uint32_t logic_serv, 2164da71b7e3SCédric Le Goater XiveTCTXMatch *match) 2165da71b7e3SCédric Le Goater { 2166da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2167da71b7e3SCédric Le Goater int total_count = 0; 2168da71b7e3SCédric Le Goater int i; 2169da71b7e3SCédric Le Goater 2170da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2171da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); 2172da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive); 2173da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2174da71b7e3SCédric Le Goater int count; 2175da71b7e3SCédric Le Goater 2176da71b7e3SCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2177da71b7e3SCédric Le Goater priority, logic_serv, match); 2178da71b7e3SCédric Le Goater 2179da71b7e3SCédric Le Goater if (count < 0) { 2180da71b7e3SCédric Le Goater return count; 2181da71b7e3SCédric Le Goater } 2182da71b7e3SCédric Le Goater 2183da71b7e3SCédric Le Goater total_count += count; 2184da71b7e3SCédric Le Goater } 2185da71b7e3SCédric Le Goater 2186da71b7e3SCédric Le Goater return total_count; 2187da71b7e3SCédric Le Goater } 2188da71b7e3SCédric Le Goater 2189f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 21909e933f4aSBenjamin Herrenschmidt { 21919e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 219236fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 2193d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2194d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 2195f30c843cSCédric Le Goater 21961f5d6b2aSDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 21971f5d6b2aSDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "3" }, 219880515061SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "3" }, 21991f5d6b2aSDaniel Henrique Barboza }; 22001f5d6b2aSDaniel Henrique Barboza 2201f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 2202f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 22031f5d6b2aSDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2204f30c843cSCédric Le Goater 2205f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 2206f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 2207f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 2208d76f2da7SGreg Kurz 2209d76f2da7SGreg Kurz pmc->compat = compat; 2210d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 2211892c3ad0SDaniel Henrique Barboza 2212892c3ad0SDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); 2213f30c843cSCédric Le Goater } 2214f30c843cSCédric Le Goater 2215f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 2216f30c843cSCédric Le Goater { 2217f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2218c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2219d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2220d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 2221f30c843cSCédric Le Goater 2222210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 2223210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "4" }, 2224c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "4" }, 2225210aacb3SDaniel Henrique Barboza }; 2226210aacb3SDaniel Henrique Barboza 2227f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 2228f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 2229210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2230210aacb3SDaniel Henrique Barboza 2231c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 2232f30c843cSCédric Le Goater 2233f30c843cSCédric Le Goater mc->alias = "powernv"; 2234d76f2da7SGreg Kurz 2235d76f2da7SGreg Kurz pmc->compat = compat; 2236d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 22377a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2238d786be3fSDaniel Henrique Barboza 2239d786be3fSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); 2240f30c843cSCédric Le Goater } 2241f30c843cSCédric Le Goater 22422b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 22432b548a42SCédric Le Goater { 22442b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2245d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2246da71b7e3SCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2247d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 22482b548a42SCédric Le Goater 2249210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 2250210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "5" }, 2251c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, 2252210aacb3SDaniel Henrique Barboza }; 2253210aacb3SDaniel Henrique Barboza 22542b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 22556bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); 2256210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2257d76f2da7SGreg Kurz 2258d76f2da7SGreg Kurz pmc->compat = compat; 2259d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 22607a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2261da71b7e3SCédric Le Goater 2262da71b7e3SCédric Le Goater xfc->match_nvt = pnv10_xive_match_nvt; 2263f1327fdeSDaniel Henrique Barboza 2264f1327fdeSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); 22652b548a42SCédric Le Goater } 22662b548a42SCédric Le Goater 226708c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 226808c3f3a7SCédric Le Goater { 226908c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 227008c3f3a7SCédric Le Goater 227108c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 227208c3f3a7SCédric Le Goater } 227308c3f3a7SCédric Le Goater 227408c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 227508c3f3a7SCédric Le Goater { 227608c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 227708c3f3a7SCédric Le Goater 227808c3f3a7SCédric Le Goater if (value) { 227908c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 228008c3f3a7SCédric Le Goater } 228108c3f3a7SCédric Le Goater } 228208c3f3a7SCédric Le Goater 228301b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 228401b552b0SNicholas Piggin { 228501b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 228601b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 228701b552b0SNicholas Piggin 228801b552b0SNicholas Piggin cpu_synchronize_state(cs); 228901b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 22900911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 229101b552b0SNicholas Piggin /* 2292fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 2293fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 2294fe837714SNicholas Piggin * (PPC_BIT(43)). 229501b552b0SNicholas Piggin */ 22960911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 2297fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 22980911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 229901b552b0SNicholas Piggin } 2300fe837714SNicholas Piggin } else { 2301fe837714SNicholas Piggin /* 2302fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 2303fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 2304fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 2305fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 2306fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 2307fe837714SNicholas Piggin */ 23080911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 2309fe837714SNicholas Piggin } 2310fe837714SNicholas Piggin } 231101b552b0SNicholas Piggin 231201b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 231301b552b0SNicholas Piggin { 231401b552b0SNicholas Piggin CPUState *cs; 231501b552b0SNicholas Piggin 231601b552b0SNicholas Piggin CPU_FOREACH(cs) { 231701b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 231801b552b0SNicholas Piggin } 231901b552b0SNicholas Piggin } 232001b552b0SNicholas Piggin 2321f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 2322f30c843cSCédric Le Goater { 2323f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 232447fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 232501b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 23269e933f4aSBenjamin Herrenschmidt 23279e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 2328b168a138SCédric Le Goater mc->init = pnv_init; 2329b168a138SCédric Le Goater mc->reset = pnv_reset; 23309e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 233159b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 233259b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 23339e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 23349e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 2335f1d18b0aSJoel Stanley /* 2336f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 2337f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 2338f1d18b0aSJoel Stanley */ 2339dd7ef911SCédric Le Goater mc->default_ram_size = 1 * GiB; 2340173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 234147fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 234201b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 234308c3f3a7SCédric Le Goater 234408c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 2345d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 234608c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 23477eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 23489e933f4aSBenjamin Herrenschmidt } 23499e933f4aSBenjamin Herrenschmidt 235077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2351beba5c0fSIgor Mammedov { \ 2352beba5c0fSIgor Mammedov .name = type, \ 2353beba5c0fSIgor Mammedov .class_init = class_initfn, \ 235477864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 235577864267SCédric Le Goater } 235677864267SCédric Le Goater 235777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 235877864267SCédric Le Goater { \ 235977864267SCédric Le Goater .name = type, \ 236077864267SCédric Le Goater .class_init = class_initfn, \ 236177864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2362beba5c0fSIgor Mammedov } 2363beba5c0fSIgor Mammedov 23642b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 23652b548a42SCédric Le Goater { \ 23662b548a42SCédric Le Goater .name = type, \ 23672b548a42SCédric Le Goater .class_init = class_initfn, \ 23682b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 23692b548a42SCédric Le Goater } 23702b548a42SCédric Le Goater 2371beba5c0fSIgor Mammedov static const TypeInfo types[] = { 23721aba8716SCédric Le Goater { 23732b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 23742b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23752b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 2376da71b7e3SCédric Le Goater .interfaces = (InterfaceInfo[]) { 2377da71b7e3SCédric Le Goater { TYPE_XIVE_FABRIC }, 2378da71b7e3SCédric Le Goater { }, 2379da71b7e3SCédric Le Goater }, 23802b548a42SCédric Le Goater }, 23812b548a42SCédric Le Goater { 23821aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 23831aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23841aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2385c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2386c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2387c722579eSCédric Le Goater { }, 2388c722579eSCédric Le Goater }, 23891aba8716SCédric Le Goater }, 23901aba8716SCédric Le Goater { 23911aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 23921aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23931aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 23941aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 23951aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 23961aba8716SCédric Le Goater { }, 23971aba8716SCédric Le Goater }, 23981aba8716SCédric Le Goater }, 2399beba5c0fSIgor Mammedov { 2400b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 24019e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2402f30c843cSCédric Le Goater .abstract = true, 24039e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2404b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2405d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 240636fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 240747fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 240801b552b0SNicholas Piggin { TYPE_NMI }, 240936fc6f08SCédric Le Goater { }, 241036fc6f08SCédric Le Goater }, 2411beba5c0fSIgor Mammedov }, 2412beba5c0fSIgor Mammedov { 2413beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2414beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2415beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2416beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2417beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2418beba5c0fSIgor Mammedov .abstract = true, 2419beba5c0fSIgor Mammedov }, 242077864267SCédric Le Goater 242177864267SCédric Le Goater /* 24222b548a42SCédric Le Goater * P10 chip and variants 24232b548a42SCédric Le Goater */ 24242b548a42SCédric Le Goater { 24252b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 24262b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 24272b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 24282b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 24292b548a42SCédric Le Goater }, 24302b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 24312b548a42SCédric Le Goater 24322b548a42SCédric Le Goater /* 243377864267SCédric Le Goater * P9 chip and variants 243477864267SCédric Le Goater */ 243577864267SCédric Le Goater { 243677864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 243777864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 243877864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 243977864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 244077864267SCédric Le Goater }, 244177864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 244277864267SCédric Le Goater 244377864267SCédric Le Goater /* 244477864267SCédric Le Goater * P8 chip and variants 244577864267SCédric Le Goater */ 244677864267SCédric Le Goater { 244777864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 244877864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 244977864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 245077864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 245177864267SCédric Le Goater }, 245277864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 245377864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 245477864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2455beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 24569e933f4aSBenjamin Herrenschmidt }; 24579e933f4aSBenjamin Herrenschmidt 2458beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2459