19e933f4aSBenjamin Herrenschmidt /* 29e933f4aSBenjamin Herrenschmidt * QEMU PowerPC PowerNV machine model 39e933f4aSBenjamin Herrenschmidt * 49e933f4aSBenjamin Herrenschmidt * Copyright (c) 2016, IBM Corporation. 59e933f4aSBenjamin Herrenschmidt * 69e933f4aSBenjamin Herrenschmidt * This library is free software; you can redistribute it and/or 79e933f4aSBenjamin Herrenschmidt * modify it under the terms of the GNU Lesser General Public 89e933f4aSBenjamin Herrenschmidt * License as published by the Free Software Foundation; either 99e933f4aSBenjamin Herrenschmidt * version 2 of the License, or (at your option) any later version. 109e933f4aSBenjamin Herrenschmidt * 119e933f4aSBenjamin Herrenschmidt * This library is distributed in the hope that it will be useful, 129e933f4aSBenjamin Herrenschmidt * but WITHOUT ANY WARRANTY; without even the implied warranty of 139e933f4aSBenjamin Herrenschmidt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 149e933f4aSBenjamin Herrenschmidt * Lesser General Public License for more details. 159e933f4aSBenjamin Herrenschmidt * 169e933f4aSBenjamin Herrenschmidt * You should have received a copy of the GNU Lesser General Public 179e933f4aSBenjamin Herrenschmidt * License along with this library; if not, see <http://www.gnu.org/licenses/>. 189e933f4aSBenjamin Herrenschmidt */ 199e933f4aSBenjamin Herrenschmidt 209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h" 21a8d25326SMarkus Armbruster #include "qemu-common.h" 22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 2438d2448aSGreg Kurz #include "sysemu/qtest.h" 259e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 269e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2771e8a915SMarkus Armbruster #include "sysemu/reset.h" 2854d31236SMarkus Armbruster #include "sysemu/runstate.h" 29d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 308d409261SCédric Le Goater #include "sysemu/device_tree.h" 3101b552b0SNicholas Piggin #include "sysemu/hw_accel.h" 32fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 339e933f4aSBenjamin Herrenschmidt #include "qemu/log.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" 409e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 41e997040eSCédric Le Goater #include "qapi/visitor.h" 4247fea43aSCédric Le Goater #include "monitor/monitor.h" 4347fea43aSCédric Le Goater #include "hw/intc/intc.h" 44aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4558969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 464f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h" 479e933f4aSBenjamin Herrenschmidt 4836fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 49a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 50967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 5135dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 52967b7523SCédric Le Goater 533495b6b6SCédric Le Goater #include "hw/isa/isa.h" 5412e9493dSMarkus Armbruster #include "hw/boards.h" 553495b6b6SCédric Le Goater #include "hw/char/serial.h" 56bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 573495b6b6SCédric Le Goater 589e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 599e933f4aSBenjamin Herrenschmidt 60b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 619e933f4aSBenjamin Herrenschmidt 629e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 639e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 64*83fa6e2aSCédric Le Goater #define FW_MAX_SIZE (16 * MiB) 659e933f4aSBenjamin Herrenschmidt 669e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 67b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 68fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 69584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 709e933f4aSBenjamin Herrenschmidt 7140abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 7240abf43fSIgor Mammedov { 7340abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7440abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7540abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7640abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7740abf43fSIgor Mammedov g_free(s); 7840abf43fSIgor Mammedov return core_type; 7940abf43fSIgor Mammedov } 8040abf43fSIgor Mammedov 819e933f4aSBenjamin Herrenschmidt /* 829e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 839e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 849e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 859e933f4aSBenjamin Herrenschmidt */ 869e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 879e933f4aSBenjamin Herrenschmidt 889e933f4aSBenjamin Herrenschmidt /* 899e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 909e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 919e933f4aSBenjamin Herrenschmidt * per chip. 929e933f4aSBenjamin Herrenschmidt */ 93b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 949e933f4aSBenjamin Herrenschmidt { 959e933f4aSBenjamin Herrenschmidt char *mem_name; 969e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 979e933f4aSBenjamin Herrenschmidt int off; 989e933f4aSBenjamin Herrenschmidt 999e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 1009e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 1019e933f4aSBenjamin Herrenschmidt 1029e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 1039e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1049e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1059e933f4aSBenjamin Herrenschmidt 1069e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1079e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1089e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1099e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1109e933f4aSBenjamin Herrenschmidt } 1119e933f4aSBenjamin Herrenschmidt 112d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 113d2fd9612SCédric Le Goater { 114d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 115d2fd9612SCédric Le Goater 116d2fd9612SCédric Le Goater if (cpus_offset < 0) { 117a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 118d2fd9612SCédric Le Goater if (cpus_offset) { 119d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 120d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 121d2fd9612SCédric Le Goater } 122d2fd9612SCédric Le Goater } 123d2fd9612SCédric Le Goater _FDT(cpus_offset); 124d2fd9612SCédric Le Goater return cpus_offset; 125d2fd9612SCédric Le Goater } 126d2fd9612SCédric Le Goater 127d2fd9612SCédric Le Goater /* 128d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 129d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 130d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 131d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 132d2fd9612SCédric Le Goater * servers. 133d2fd9612SCédric Le Goater */ 134b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 135d2fd9612SCédric Le Goater { 13608304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13708304a86SDavid Gibson CPUState *cs = CPU(cpu); 138d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1398bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 140d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 141d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 142d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 143d2fd9612SCédric Le Goater int i; 144d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 145d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 146d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 147d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 148d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 149d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 150d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 151d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 152d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 153d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 154d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 155d2fd9612SCédric Le Goater int offset; 156d2fd9612SCédric Le Goater char *nodename; 157d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 158d2fd9612SCédric Le Goater 159d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 160d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 161d2fd9612SCédric Le Goater _FDT(offset); 162d2fd9612SCédric Le Goater g_free(nodename); 163d2fd9612SCédric Le Goater 164d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 165d2fd9612SCédric Le Goater 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 168d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 169d2fd9612SCédric Le Goater 170d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 172d2fd9612SCédric Le Goater env->dcache_line_size))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 174d2fd9612SCédric Le Goater env->dcache_line_size))); 175d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 176d2fd9612SCédric Le Goater env->icache_line_size))); 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 178d2fd9612SCédric Le Goater env->icache_line_size))); 179d2fd9612SCédric Le Goater 180d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 181d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 182d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 183d2fd9612SCédric Le Goater } else { 1843dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 185d2fd9612SCédric Le Goater } 186d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 187d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 188d2fd9612SCédric Le Goater pcc->l1_icache_size))); 189d2fd9612SCédric Le Goater } else { 1903dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 191d2fd9612SCédric Le Goater } 192d2fd9612SCédric Le Goater 193d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 194d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19559b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19659b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 197d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 198d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 199d2fd9612SCédric Le Goater 200d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 201d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 202d2fd9612SCédric Le Goater } 203d2fd9612SCédric Le Goater 20458969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 205d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 206d2fd9612SCédric Le Goater segs, sizeof(segs)))); 207d2fd9612SCédric Le Goater } 208d2fd9612SCédric Le Goater 20959b7c1c2SBalamuruhan S /* 21059b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 211d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 212d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 21359b7c1c2SBalamuruhan S * 2 == VSX available 21459b7c1c2SBalamuruhan S */ 215d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 216d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 217d2fd9612SCédric Le Goater 218d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 219d2fd9612SCédric Le Goater } 220d2fd9612SCédric Le Goater 22159b7c1c2SBalamuruhan S /* 22259b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 223d2fd9612SCédric Le Goater * 0 / no property == no DFP 22459b7c1c2SBalamuruhan S * 1 == DFP available 22559b7c1c2SBalamuruhan S */ 226d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 227d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 228d2fd9612SCédric Le Goater } 229d2fd9612SCédric Le Goater 230644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 231d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 232d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 233d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 234d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 235d2fd9612SCédric Le Goater } 236d2fd9612SCédric Le Goater 237d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 238d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 239d2fd9612SCédric Le Goater 240d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 241d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 242d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 243d2fd9612SCédric Le Goater } 244d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 245d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 246d2fd9612SCédric Le Goater } 247d2fd9612SCédric Le Goater 248b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 249bf5615e7SCédric Le Goater uint32_t nr_threads) 250bf5615e7SCédric Le Goater { 251bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 252bf5615e7SCédric Le Goater char *name; 253bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 254bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 255bf5615e7SCédric Le Goater uint64_t *reg; 256bf5615e7SCédric Le Goater int offset; 257bf5615e7SCédric Le Goater 258bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 259bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 260bf5615e7SCédric Le Goater 261bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 262bf5615e7SCédric Le Goater reg = g_malloc(rsize); 263bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 264bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 265bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 266bf5615e7SCédric Le Goater } 267bf5615e7SCédric Le Goater 268bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 269bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 270bf5615e7SCédric Le Goater _FDT(offset); 271bf5615e7SCédric Le Goater g_free(name); 272bf5615e7SCédric Le Goater 273bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 274bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 275bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 276bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 278bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 279bf5615e7SCédric Le Goater irange, sizeof(irange)))); 280bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 281bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 282bf5615e7SCédric Le Goater g_free(reg); 283bf5615e7SCédric Le Goater } 284bf5615e7SCédric Le Goater 285eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 286e997040eSCédric Le Goater { 287c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; 288d2fd9612SCédric Le Goater int i; 289d2fd9612SCédric Le Goater 2903f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 2913f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 292c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE), 293c396c58aSGreg Kurz compat, sizeof(compat)); 294967b7523SCédric Le Goater 295d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2964fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 297d2fd9612SCédric Le Goater 298b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 299bf5615e7SCédric Le Goater 300bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 301b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 302d2fd9612SCédric Le Goater } 303d2fd9612SCédric Le Goater 304e997040eSCédric Le Goater if (chip->ram_size) { 305b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 306e997040eSCédric Le Goater } 307e997040eSCédric Le Goater } 308e997040eSCédric Le Goater 309eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 310eb859a27SCédric Le Goater { 311c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom"; 312eb859a27SCédric Le Goater int i; 313eb859a27SCédric Le Goater 3143f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3153f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 316c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE), 317c396c58aSGreg Kurz compat, sizeof(compat)); 318eb859a27SCédric Le Goater 319eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3204fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 321eb859a27SCédric Le Goater 322eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 323eb859a27SCédric Le Goater } 324eb859a27SCédric Le Goater 325eb859a27SCédric Le Goater if (chip->ram_size) { 326eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 327eb859a27SCédric Le Goater } 32815376c66SCédric Le Goater 3292661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 330eb859a27SCédric Le Goater } 331eb859a27SCédric Le Goater 3322b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3332b548a42SCédric Le Goater { 334c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom"; 3352b548a42SCédric Le Goater int i; 3362b548a42SCédric Le Goater 3373f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3383f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 339c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE), 340c396c58aSGreg Kurz compat, sizeof(compat)); 3412b548a42SCédric Le Goater 3422b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3432b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3442b548a42SCédric Le Goater 3452b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3462b548a42SCédric Le Goater } 3472b548a42SCédric Le Goater 3482b548a42SCédric Le Goater if (chip->ram_size) { 3492b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3502b548a42SCédric Le Goater } 3512661f6abSCédric Le Goater 3522661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 3532b548a42SCédric Le Goater } 3542b548a42SCédric Le Goater 355b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 356c5ffdcaeSCédric Le Goater { 357c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 358c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 359c5ffdcaeSCédric Le Goater cpu_to_be32(1), 360c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 361c5ffdcaeSCédric Le Goater cpu_to_be32(2) 362c5ffdcaeSCédric Le Goater }; 363c5ffdcaeSCédric Le Goater char *name; 364c5ffdcaeSCédric Le Goater int node; 365c5ffdcaeSCédric Le Goater 366c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 367c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 368c5ffdcaeSCédric Le Goater _FDT(node); 369c5ffdcaeSCédric Le Goater g_free(name); 370c5ffdcaeSCédric Le Goater 371c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 372c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 373c5ffdcaeSCédric Le Goater } 374c5ffdcaeSCédric Le Goater 375b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 376cb228f5aSCédric Le Goater { 377cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 378cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 379cb228f5aSCédric Le Goater uint32_t io_regs[] = { 380cb228f5aSCédric Le Goater cpu_to_be32(1), 381cb228f5aSCédric Le Goater cpu_to_be32(io_base), 382cb228f5aSCédric Le Goater cpu_to_be32(8) 383cb228f5aSCédric Le Goater }; 384cb228f5aSCédric Le Goater char *name; 385cb228f5aSCédric Le Goater int node; 386cb228f5aSCédric Le Goater 387cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 388cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 389cb228f5aSCédric Le Goater _FDT(node); 390cb228f5aSCédric Le Goater g_free(name); 391cb228f5aSCédric Le Goater 392cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 393cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 394cb228f5aSCédric Le Goater sizeof(compatible)))); 395cb228f5aSCédric Le Goater 396cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 397cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 398cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 399cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 400cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 401cb228f5aSCédric Le Goater 402cb228f5aSCédric Le Goater /* This is needed by Linux */ 403cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 404cb228f5aSCédric Le Goater } 405cb228f5aSCédric Le Goater 406b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 40704f6c8b2SCédric Le Goater { 40804f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 40904f6c8b2SCédric Le Goater uint32_t io_base; 41004f6c8b2SCédric Le Goater uint32_t io_regs[] = { 41104f6c8b2SCédric Le Goater cpu_to_be32(1), 41204f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 41304f6c8b2SCédric Le Goater cpu_to_be32(3) 41404f6c8b2SCédric Le Goater }; 41504f6c8b2SCédric Le Goater uint32_t irq; 41604f6c8b2SCédric Le Goater char *name; 41704f6c8b2SCédric Le Goater int node; 41804f6c8b2SCédric Le Goater 41904f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 42004f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 42104f6c8b2SCédric Le Goater 42204f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 42304f6c8b2SCédric Le Goater 42404f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 42504f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 42604f6c8b2SCédric Le Goater _FDT(node); 42704f6c8b2SCédric Le Goater g_free(name); 42804f6c8b2SCédric Le Goater 4297032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4307032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4317032d92aSCédric Le Goater sizeof(compatible)))); 43204f6c8b2SCédric Le Goater 43304f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 43404f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 43504f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 43604f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 43704f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 43804f6c8b2SCédric Le Goater } 43904f6c8b2SCédric Le Goater 440e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 441e7a3fee3SCédric Le Goater void *fdt; 442e7a3fee3SCédric Le Goater int offset; 443e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 444e7a3fee3SCédric Le Goater 445b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 446e7a3fee3SCédric Le Goater { 447c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 448c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 449c5ffdcaeSCédric Le Goater 450c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 451b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 452cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 453b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 45404f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 455b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 456c5ffdcaeSCédric Le Goater } else { 457c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 458c5ffdcaeSCédric Le Goater d->ioport_id); 459c5ffdcaeSCédric Le Goater } 460c5ffdcaeSCédric Le Goater 461e7a3fee3SCédric Le Goater return 0; 462e7a3fee3SCédric Le Goater } 463e7a3fee3SCédric Le Goater 46459b7c1c2SBalamuruhan S /* 46559b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 466bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 467bb7ab95cSCédric Le Goater */ 468bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 469bb7ab95cSCédric Le Goater { 47064d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 471e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 472e7a3fee3SCédric Le Goater .fdt = fdt, 473bb7ab95cSCédric Le Goater .offset = isa_offset, 474e7a3fee3SCédric Le Goater }; 475f47a08d1SCédric Le Goater uint32_t phandle; 476e7a3fee3SCédric Le Goater 477bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 478bb7ab95cSCédric Le Goater 479f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 480f47a08d1SCédric Le Goater assert(phandle > 0); 481f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 482f47a08d1SCédric Le Goater 48359b7c1c2SBalamuruhan S /* 48459b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 48559b7c1c2SBalamuruhan S * can not use object_child_foreach() 48659b7c1c2SBalamuruhan S */ 487bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 488bb7ab95cSCédric Le Goater &args); 489e7a3fee3SCédric Le Goater } 490e7a3fee3SCédric Le Goater 4917a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 492e5694793SCédric Le Goater { 493e5694793SCédric Le Goater int off; 494e5694793SCédric Le Goater 495e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 496e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 497e5694793SCédric Le Goater 498e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 499e5694793SCédric Le Goater } 500e5694793SCédric Le Goater 501b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 5029e933f4aSBenjamin Herrenschmidt { 503d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 504b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5059e933f4aSBenjamin Herrenschmidt void *fdt; 5069e933f4aSBenjamin Herrenschmidt char *buf; 5079e933f4aSBenjamin Herrenschmidt int off; 508e997040eSCédric Le Goater int i; 5099e933f4aSBenjamin Herrenschmidt 5109e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5119e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5129e933f4aSBenjamin Herrenschmidt 513ccb099b3SCédric Le Goater /* /qemu node */ 514ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 515ccb099b3SCédric Le Goater 5169e933f4aSBenjamin Herrenschmidt /* Root node */ 5179e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5189e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5199e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5209e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 521d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5229e933f4aSBenjamin Herrenschmidt 5239e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5249e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5259e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 5269e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5279e933f4aSBenjamin Herrenschmidt } 5289e933f4aSBenjamin Herrenschmidt g_free(buf); 5299e933f4aSBenjamin Herrenschmidt 5309e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5319e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5329e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5339e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5349e933f4aSBenjamin Herrenschmidt } 5359e933f4aSBenjamin Herrenschmidt 5369e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5379e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5389e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5399e933f4aSBenjamin Herrenschmidt 5409e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5419e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5429e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5439e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5449e933f4aSBenjamin Herrenschmidt } 5459e933f4aSBenjamin Herrenschmidt 546e997040eSCédric Le Goater /* Populate device tree for each chip */ 547e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 548eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 549e997040eSCédric Le Goater } 550e7a3fee3SCédric Le Goater 551e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 552bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 553aeaef83dSCédric Le Goater 554aeaef83dSCédric Le Goater if (pnv->bmc) { 555b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 556aeaef83dSCédric Le Goater } 557aeaef83dSCédric Le Goater 5587a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5597a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5607a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 561e5694793SCédric Le Goater } 562e5694793SCédric Le Goater 5639e933f4aSBenjamin Herrenschmidt return fdt; 5649e933f4aSBenjamin Herrenschmidt } 5659e933f4aSBenjamin Herrenschmidt 566bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 567bce0b691SCédric Le Goater { 5688f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 569bce0b691SCédric Le Goater 570bce0b691SCédric Le Goater if (pnv->bmc) { 571bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 572bce0b691SCédric Le Goater } 573bce0b691SCédric Le Goater } 574bce0b691SCédric Le Goater 575a0628599SLike Xu static void pnv_reset(MachineState *machine) 5769e933f4aSBenjamin Herrenschmidt { 57725f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 57825f3170bSCédric Le Goater IPMIBmc *bmc; 5799e933f4aSBenjamin Herrenschmidt void *fdt; 5809e933f4aSBenjamin Herrenschmidt 5819e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5829e933f4aSBenjamin Herrenschmidt 58325f3170bSCédric Le Goater /* 58425f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator. 58525f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command 58625f3170bSCédric Le Goater * line. 58725f3170bSCédric Le Goater */ 58825f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal); 58925f3170bSCédric Le Goater if (!pnv->bmc) { 59025f3170bSCédric Le Goater if (!bmc) { 59138d2448aSGreg Kurz if (!qtest_enabled()) { 59225f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 59325f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 59425f3170bSCédric Le Goater "to define one"); 59538d2448aSGreg Kurz } 59625f3170bSCédric Le Goater } else { 59725f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 59825f3170bSCédric Le Goater pnv->bmc = bmc; 59925f3170bSCédric Le Goater } 60025f3170bSCédric Le Goater } 60125f3170bSCédric Le Goater 602b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6039e933f4aSBenjamin Herrenschmidt 6049e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6059e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6069e933f4aSBenjamin Herrenschmidt 6078d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6089e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 609b2fb7a43SPan Nengyuan 610b2fb7a43SPan Nengyuan g_free(fdt); 6119e933f4aSBenjamin Herrenschmidt } 6129e933f4aSBenjamin Herrenschmidt 61304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6143495b6b6SCédric Le Goater { 61577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 61677864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 61704026890SCédric Le Goater } 6183495b6b6SCédric Le Goater 61904026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 62004026890SCédric Le Goater { 62177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 62277864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 62304026890SCédric Le Goater } 6243495b6b6SCédric Le Goater 62504026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 62604026890SCédric Le Goater { 62715376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 62815376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 62904026890SCédric Le Goater } 6303495b6b6SCédric Le Goater 6312b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6322b548a42SCédric Le Goater { 6332661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6342661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6352b548a42SCédric Le Goater } 6362b548a42SCédric Le Goater 63704026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 63804026890SCédric Le Goater { 63904026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6403495b6b6SCédric Le Goater } 6413495b6b6SCédric Le Goater 642d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 643d8e4aad5SCédric Le Goater { 644d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 6459ae1329eSCédric Le Goater int i; 646d8e4aad5SCédric Le Goater 647d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 6489ae1329eSCédric Le Goater for (i = 0; i < chip->num_phbs; i++) { 6499ae1329eSCédric Le Goater pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon); 6509ae1329eSCédric Le Goater ics_pic_print_info(&chip8->phbs[i].lsis, mon); 6519ae1329eSCédric Le Goater } 652d8e4aad5SCédric Le Goater } 653d8e4aad5SCédric Le Goater 654d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 655d8e4aad5SCédric Le Goater { 656d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 6574f9924c4SBenjamin Herrenschmidt int i, j; 658d8e4aad5SCédric Le Goater 659d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 660c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 6614f9924c4SBenjamin Herrenschmidt 6624f9924c4SBenjamin Herrenschmidt for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { 6634f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 6644f9924c4SBenjamin Herrenschmidt for (j = 0; j < pec->num_stacks; j++) { 6654f9924c4SBenjamin Herrenschmidt pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon); 6664f9924c4SBenjamin Herrenschmidt } 6674f9924c4SBenjamin Herrenschmidt } 668d8e4aad5SCédric Le Goater } 669d8e4aad5SCédric Le Goater 670c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 671c4b2c40cSGreg Kurz uint32_t core_id) 672c4b2c40cSGreg Kurz { 673c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 674c4b2c40cSGreg Kurz } 675c4b2c40cSGreg Kurz 676c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 677c4b2c40cSGreg Kurz uint32_t core_id) 678c4b2c40cSGreg Kurz { 679c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 680c4b2c40cSGreg Kurz } 681c4b2c40cSGreg Kurz 682c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 683c4b2c40cSGreg Kurz uint32_t core_id) 684c4b2c40cSGreg Kurz { 685c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 686c4b2c40cSGreg Kurz } 687c4b2c40cSGreg Kurz 688f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 689f30c843cSCédric Le Goater { 690f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 691f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 692f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 693f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 694f30c843cSCédric Le Goater 695f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 696f30c843cSCédric Le Goater } 697f30c843cSCédric Le Goater 698e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 699e2392d43SCédric Le Goater { 700c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 701e2392d43SCédric Le Goater 7025325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); 7035325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); 704c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 705e2392d43SCédric Le Goater } 706e2392d43SCédric Le Goater 7072b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 7082b548a42SCédric Le Goater { 7098b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 7108b50ce85SCédric Le Goater 7118b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 7122b548a42SCédric Le Goater } 7132b548a42SCédric Le Goater 714b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 7159e933f4aSBenjamin Herrenschmidt { 716b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 717f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 7189e933f4aSBenjamin Herrenschmidt char *fw_filename; 7199e933f4aSBenjamin Herrenschmidt long fw_size; 720e997040eSCédric Le Goater int i; 721e997040eSCédric Le Goater char *chip_typename; 72235dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 72335dde576SCédric Le Goater DeviceState *dev; 7249e933f4aSBenjamin Herrenschmidt 7259e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 726d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 7273dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 7289e933f4aSBenjamin Herrenschmidt } 729173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 7309e933f4aSBenjamin Herrenschmidt 73135dde576SCédric Le Goater /* 73235dde576SCédric Le Goater * Create our simple PNOR device 73335dde576SCédric Le Goater */ 7343e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 73535dde576SCédric Le Goater if (pnor) { 736934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 73735dde576SCédric Le Goater } 7383c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 73935dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 74035dde576SCédric Le Goater 7419e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 7429e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 7439e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 7449e933f4aSBenjamin Herrenschmidt } 7459e933f4aSBenjamin Herrenschmidt 7469e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 74715fcedb2SCédric Le Goater if (!fw_filename) { 74815fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 74915fcedb2SCédric Le Goater exit(1); 75015fcedb2SCédric Le Goater } 7519e933f4aSBenjamin Herrenschmidt 75208c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 7539e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 75415fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 7559e933f4aSBenjamin Herrenschmidt exit(1); 7569e933f4aSBenjamin Herrenschmidt } 7579e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 7589e933f4aSBenjamin Herrenschmidt 7599e933f4aSBenjamin Herrenschmidt /* load kernel */ 7609e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 7619e933f4aSBenjamin Herrenschmidt long kernel_size; 7629e933f4aSBenjamin Herrenschmidt 7639e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 764b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 7659e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 766802fc7abSThomas Huth error_report("Could not load kernel '%s'", 7679e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 7689e933f4aSBenjamin Herrenschmidt exit(1); 7699e933f4aSBenjamin Herrenschmidt } 7709e933f4aSBenjamin Herrenschmidt } 7719e933f4aSBenjamin Herrenschmidt 7729e933f4aSBenjamin Herrenschmidt /* load initrd */ 7739e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 7749e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 7759e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 776584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 7779e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 778802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 7799e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 7809e933f4aSBenjamin Herrenschmidt exit(1); 7819e933f4aSBenjamin Herrenschmidt } 7829e933f4aSBenjamin Herrenschmidt } 783e997040eSCédric Le Goater 7844f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 7854f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 7864f9924c4SBenjamin Herrenschmidt 787f30c843cSCédric Le Goater /* 788f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 789f30c843cSCédric Le Goater * default. 790f30c843cSCédric Le Goater */ 791f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 792f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 793f30c843cSCédric Le Goater machine->cpu_type, mc->name); 794f30c843cSCédric Le Goater exit(1); 795f30c843cSCédric Le Goater } 796f30c843cSCédric Le Goater 797e997040eSCédric Le Goater /* Create the processor chips */ 7984a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7997fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 8004a12c699SIgor Mammedov i, machine->cpu_type); 801e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 802f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 803f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 804e997040eSCédric Le Goater exit(1); 805e997040eSCédric Le Goater } 806e997040eSCédric Le Goater 807e44acde2SGreg Kurz pnv->num_chips = 808e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 809e44acde2SGreg Kurz /* 810e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 811e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 812e44acde2SGreg Kurz */ 813e44acde2SGreg Kurz if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 4) { 814e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 815e44acde2SGreg Kurz error_printf("Try '-smp sockets=N'. Valid values are : 1, 2 or 4.\n"); 816e44acde2SGreg Kurz exit(1); 817e44acde2SGreg Kurz } 818e44acde2SGreg Kurz 819e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 820e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 821e997040eSCédric Le Goater char chip_name[32]; 822df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 823e997040eSCédric Le Goater 824e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 825e997040eSCédric Le Goater 82659b7c1c2SBalamuruhan S /* 82759b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 828e997040eSCédric Le Goater * way to specify different ranges for each chip 829e997040eSCédric Le Goater */ 830e997040eSCédric Le Goater if (i == 0) { 8315325cc34SMarkus Armbruster object_property_set_int(chip, "ram-size", machine->ram_size, 832e997040eSCédric Le Goater &error_fatal); 833e997040eSCédric Le Goater } 834e997040eSCédric Le Goater 835e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 836d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 8375325cc34SMarkus Armbruster object_property_set_int(chip, "chip-id", PNV_CHIP_HWID(i), 838e997040eSCédric Le Goater &error_fatal); 8395325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores, 8405325cc34SMarkus Armbruster &error_fatal); 8415325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads, 8425325cc34SMarkus Armbruster &error_fatal); 843245cdb7fSCédric Le Goater /* 844245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 845245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 846245cdb7fSCédric Le Goater */ 847245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 8485325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); 849245cdb7fSCédric Le Goater } 850d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 8515325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv), 852d1214b81SGreg Kurz &error_abort); 853d1214b81SGreg Kurz } 8543c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 855e997040eSCédric Le Goater } 856e997040eSCédric Le Goater g_free(chip_typename); 8573495b6b6SCédric Le Goater 8583495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 85904026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 8603495b6b6SCédric Le Goater 8613495b6b6SCédric Le Goater /* Create serial port */ 862def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 8633495b6b6SCédric Le Goater 8643495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 8656c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 866bce0b691SCédric Le Goater 86725f3170bSCédric Le Goater /* 86825f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 86925f3170bSCédric Le Goater * communication with the BMC 87025f3170bSCédric Le Goater */ 87125f3170bSCédric Le Goater if (defaults_enabled()) { 87225f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 873e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 87425f3170bSCédric Le Goater } 875e2392d43SCédric Le Goater 87659b7c1c2SBalamuruhan S /* 87759b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 87859b7c1c2SBalamuruhan S * host to powerdown 87959b7c1c2SBalamuruhan S */ 880bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 881bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 882e997040eSCédric Le Goater } 883e997040eSCédric Le Goater 884631adaffSCédric Le Goater /* 885631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 886631adaffSCédric Le Goater * 22:24 Chip ID 887631adaffSCédric Le Goater * 25:28 Core number 888631adaffSCédric Le Goater * 29:31 Thread ID 889631adaffSCédric Le Goater */ 890631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 891631adaffSCédric Le Goater { 892631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 893631adaffSCédric Le Goater } 894631adaffSCédric Le Goater 8958fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 896d35aefa9SCédric Le Goater Error **errp) 897d35aefa9SCédric Le Goater { 898245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 8998fa1f4efSCédric Le Goater Error *local_err = NULL; 9008fa1f4efSCédric Le Goater Object *obj; 9018907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9028fa1f4efSCédric Le Goater 903245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 9048fa1f4efSCédric Le Goater if (local_err) { 9058fa1f4efSCédric Le Goater error_propagate(errp, local_err); 9068fa1f4efSCédric Le Goater return; 9078fa1f4efSCédric Le Goater } 9088fa1f4efSCédric Le Goater 909956b8f46SCédric Le Goater pnv_cpu->intc = obj; 910d35aefa9SCédric Le Goater } 911d35aefa9SCédric Le Goater 9120990ce6aSGreg Kurz 913d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 914d49e8a9bSCédric Le Goater { 915d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 916d49e8a9bSCédric Le Goater 917d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 918d49e8a9bSCédric Le Goater } 919d49e8a9bSCédric Le Goater 9200990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9210990ce6aSGreg Kurz { 9220990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9230990ce6aSGreg Kurz 9240990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 9250990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9260990ce6aSGreg Kurz } 9270990ce6aSGreg Kurz 92885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 92985913070SGreg Kurz Monitor *mon) 93085913070SGreg Kurz { 93185913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 93285913070SGreg Kurz } 93385913070SGreg Kurz 934631adaffSCédric Le Goater /* 935631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 936631adaffSCédric Le Goater * 49:52 Node ID 937631adaffSCédric Le Goater * 53:55 Chip ID 938631adaffSCédric Le Goater * 56 Reserved - Read as zero 939631adaffSCédric Le Goater * 57:61 Core number 940631adaffSCédric Le Goater * 62:63 Thread ID 941631adaffSCédric Le Goater * 942631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 943631adaffSCédric Le Goater */ 944631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 945631adaffSCédric Le Goater { 946631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 947631adaffSCédric Le Goater } 948631adaffSCédric Le Goater 9492b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 9502b548a42SCédric Le Goater { 9512b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 9522b548a42SCédric Le Goater } 9532b548a42SCédric Le Goater 9548fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 955d35aefa9SCédric Le Goater Error **errp) 956d35aefa9SCédric Le Goater { 9572dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 9582dfa91a2SCédric Le Goater Error *local_err = NULL; 9592dfa91a2SCédric Le Goater Object *obj; 9602dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9612dfa91a2SCédric Le Goater 9622dfa91a2SCédric Le Goater /* 9632dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 9642dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 9652dfa91a2SCédric Le Goater * only used at runtime. 9662dfa91a2SCédric Le Goater */ 96747950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 96847950946SCédric Le Goater &local_err); 9692dfa91a2SCédric Le Goater if (local_err) { 9702dfa91a2SCédric Le Goater error_propagate(errp, local_err); 9718fa1f4efSCédric Le Goater return; 972d35aefa9SCédric Le Goater } 973d35aefa9SCédric Le Goater 9742dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 9752dfa91a2SCédric Le Goater } 9762dfa91a2SCédric Le Goater 977d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 978d49e8a9bSCédric Le Goater { 979d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 980d49e8a9bSCédric Le Goater 981d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 982d49e8a9bSCédric Le Goater } 983d49e8a9bSCédric Le Goater 9840990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9850990ce6aSGreg Kurz { 9860990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9870990ce6aSGreg Kurz 9880990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 9890990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9900990ce6aSGreg Kurz } 9910990ce6aSGreg Kurz 99285913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 99385913070SGreg Kurz Monitor *mon) 99485913070SGreg Kurz { 99585913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 99685913070SGreg Kurz } 99785913070SGreg Kurz 9982b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 9992b548a42SCédric Le Goater Error **errp) 10002b548a42SCédric Le Goater { 10012b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10022b548a42SCédric Le Goater 10032b548a42SCédric Le Goater /* Will be defined when the interrupt controller is */ 10042b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10052b548a42SCédric Le Goater } 10062b548a42SCédric Le Goater 10072b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 10082b548a42SCédric Le Goater { 10092b548a42SCédric Le Goater ; 10102b548a42SCédric Le Goater } 10112b548a42SCédric Le Goater 10122b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10132b548a42SCédric Le Goater { 10142b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10152b548a42SCédric Le Goater 10162b548a42SCédric Le Goater pnv_cpu->intc = NULL; 10172b548a42SCédric Le Goater } 10182b548a42SCédric Le Goater 101985913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 102085913070SGreg Kurz Monitor *mon) 102185913070SGreg Kurz { 102285913070SGreg Kurz } 102385913070SGreg Kurz 102459b7c1c2SBalamuruhan S /* 102559b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1026397a79e7SCédric Le Goater * 1027397a79e7SCédric Le Goater * <EX0 reserved> 1028397a79e7SCédric Le Goater * EX1 - Venice only 1029397a79e7SCédric Le Goater * EX2 - Venice only 1030397a79e7SCédric Le Goater * EX3 - Venice only 1031397a79e7SCédric Le Goater * EX4 1032397a79e7SCédric Le Goater * EX5 1033397a79e7SCédric Le Goater * EX6 1034397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1035397a79e7SCédric Le Goater * EX9 - Venice only 1036397a79e7SCédric Le Goater * EX10 - Venice only 1037397a79e7SCédric Le Goater * EX11 - Venice only 1038397a79e7SCédric Le Goater * EX12 1039397a79e7SCédric Le Goater * EX13 1040397a79e7SCédric Le Goater * EX14 1041397a79e7SCédric Le Goater * <EX15 reserved> 1042397a79e7SCédric Le Goater */ 1043397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1044397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1045397a79e7SCédric Le Goater 1046397a79e7SCédric Le Goater /* 104709279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1048397a79e7SCédric Le Goater */ 104909279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1050397a79e7SCédric Le Goater 10512b548a42SCédric Le Goater 10522b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 10532b548a42SCédric Le Goater 105477864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 105577864267SCédric Le Goater { 10569ae1329eSCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 105777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 10589ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 10599ae1329eSCédric Le Goater int i; 106077864267SCédric Le Goater 1061245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1062245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1063245cdb7fSCédric Le Goater object_property_allow_set_link, 1064d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1065245cdb7fSCédric Le Goater 10669fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 106777864267SCédric Le Goater 10689fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 106977864267SCédric Le Goater 10709fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 10713887d241SBalamuruhan S 10729fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 10739ae1329eSCédric Le Goater 10749ae1329eSCédric Le Goater for (i = 0; i < pcc->num_phbs; i++) { 10759fc7fc4dSMarkus Armbruster object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); 10769ae1329eSCédric Le Goater } 10779ae1329eSCédric Le Goater 10789ae1329eSCédric Le Goater /* 10799ae1329eSCédric Le Goater * Number of PHBs is the chip default 10809ae1329eSCédric Le Goater */ 10819ae1329eSCédric Le Goater chip->num_phbs = pcc->num_phbs; 108277864267SCédric Le Goater } 108377864267SCédric Le Goater 108477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 108577864267SCédric Le Goater { 108677864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 108777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 108877864267SCédric Le Goater int i, j; 108977864267SCédric Le Goater char *name; 109077864267SCédric Le Goater 109177864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 109277864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 109377864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 109477864267SCédric Le Goater g_free(name); 109577864267SCédric Le Goater 109677864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 109777864267SCédric Le Goater 109877864267SCédric Le Goater /* Map the ICP registers for each thread */ 109977864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 11004fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 110177864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 110277864267SCédric Le Goater 110377864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 110477864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1105245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 110677864267SCédric Le Goater 110777864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 110877864267SCédric Le Goater &icp->mmio); 110977864267SCédric Le Goater } 111077864267SCédric Le Goater } 111177864267SCédric Le Goater } 111277864267SCédric Le Goater 111377864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 111477864267SCédric Le Goater { 111577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 111677864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 111777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1118ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 111977864267SCédric Le Goater Error *local_err = NULL; 11209ae1329eSCédric Le Goater int i; 112177864267SCédric Le Goater 1122245cdb7fSCédric Le Goater assert(chip8->xics); 1123245cdb7fSCédric Le Goater 1124709044fdSCédric Le Goater /* XSCOM bridge is first */ 1125709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1126709044fdSCédric Le Goater if (local_err) { 1127709044fdSCédric Le Goater error_propagate(errp, local_err); 1128709044fdSCédric Le Goater return; 1129709044fdSCédric Le Goater } 1130709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1131709044fdSCédric Le Goater 113277864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 113377864267SCédric Le Goater if (local_err) { 113477864267SCédric Le Goater error_propagate(errp, local_err); 113577864267SCédric Le Goater return; 113677864267SCédric Le Goater } 113777864267SCédric Le Goater 113877864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 11395325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), 11405325cc34SMarkus Armbruster &error_fatal); 11415325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, 11425325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort); 1143668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { 114477864267SCédric Le Goater return; 114577864267SCédric Le Goater } 1146ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1147ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 114877864267SCédric Le Goater 114977864267SCédric Le Goater /* Create LPC controller */ 11505325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi), 1151b63f3893SGreg Kurz &error_abort); 1152ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 115377864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 115477864267SCédric Le Goater 115564d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 115664d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 115764d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 115864d011d5SCédric Le Goater 115959b7c1c2SBalamuruhan S /* 116059b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 116159b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 116259b7c1c2SBalamuruhan S */ 116377864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 116477864267SCédric Le Goater if (local_err) { 116577864267SCédric Le Goater error_propagate(errp, local_err); 116677864267SCédric Le Goater return; 116777864267SCédric Le Goater } 116877864267SCédric Le Goater 116977864267SCédric Le Goater /* Create the simplified OCC model */ 11705325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi), 1171ee3d2713SGreg Kurz &error_abort); 1172668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { 117377864267SCédric Le Goater return; 117477864267SCédric Le Goater } 117577864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1176f3db8266SBalamuruhan S 1177f3db8266SBalamuruhan S /* OCC SRAM model */ 11783a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1179f3db8266SBalamuruhan S &chip8->occ.sram_regs); 11803887d241SBalamuruhan S 11813887d241SBalamuruhan S /* HOMER */ 11825325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), 1183f2582acfSGreg Kurz &error_abort); 1184668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { 11853887d241SBalamuruhan S return; 11863887d241SBalamuruhan S } 11878f092316SCédric Le Goater /* Homer Xscom region */ 11888f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 11898f092316SCédric Le Goater 11908f092316SCédric Le Goater /* Homer mmio region */ 11913887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 11923887d241SBalamuruhan S &chip8->homer.regs); 11939ae1329eSCédric Le Goater 11949ae1329eSCédric Le Goater /* PHB3 controllers */ 11959ae1329eSCédric Le Goater for (i = 0; i < chip->num_phbs; i++) { 11969ae1329eSCédric Le Goater PnvPHB3 *phb = &chip8->phbs[i]; 11979ae1329eSCédric Le Goater PnvPBCQState *pbcq = &phb->pbcq; 11989ae1329eSCédric Le Goater 11995325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal); 12005325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, 12019ae1329eSCédric Le Goater &error_fatal); 1202668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { 12039ae1329eSCédric Le Goater return; 12049ae1329eSCédric Le Goater } 12059ae1329eSCédric Le Goater 12069ae1329eSCédric Le Goater /* Populate the XSCOM address space. */ 12079ae1329eSCédric Le Goater pnv_xscom_add_subregion(chip, 12089ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id, 12099ae1329eSCédric Le Goater &pbcq->xscom_nest_regs); 12109ae1329eSCédric Le Goater pnv_xscom_add_subregion(chip, 12119ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id, 12129ae1329eSCédric Le Goater &pbcq->xscom_pci_regs); 12139ae1329eSCédric Le Goater pnv_xscom_add_subregion(chip, 12149ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id, 12159ae1329eSCédric Le Goater &pbcq->xscom_spci_regs); 12169ae1329eSCédric Le Goater } 121777864267SCédric Le Goater } 121877864267SCédric Le Goater 121970c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 122070c059e9SGreg Kurz { 122170c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 122270c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 122370c059e9SGreg Kurz } 122470c059e9SGreg Kurz 1225e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1226e997040eSCédric Le Goater { 1227e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1228e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1229e997040eSCédric Le Goater 1230e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1231397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 12329ae1329eSCédric Le Goater k->num_phbs = 3; 1233631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1234d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1235d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12360990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 123785913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 123804026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1239eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1240d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1241c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 124270c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1243e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 124477864267SCédric Le Goater 124577864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 124677864267SCédric Le Goater &k->parent_realize); 1247e997040eSCédric Le Goater } 1248e997040eSCédric Le Goater 1249e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1250e997040eSCédric Le Goater { 1251e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1252e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1253e997040eSCédric Le Goater 1254e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1255397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 12569ae1329eSCédric Le Goater k->num_phbs = 3; 1257631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1258d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1259d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12600990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 126185913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 126204026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1263eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1264d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1265c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 126670c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1267e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 126877864267SCédric Le Goater 126977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 127077864267SCédric Le Goater &k->parent_realize); 1271e997040eSCédric Le Goater } 1272e997040eSCédric Le Goater 1273e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1274e997040eSCédric Le Goater { 1275e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1276e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1277e997040eSCédric Le Goater 1278e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1279397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 12809ae1329eSCédric Le Goater k->num_phbs = 3; 1281631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1282d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1283d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 12840990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 128585913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 128604026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1287eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1288d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1289c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 129070c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1291e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 129277864267SCédric Le Goater 129377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 129477864267SCédric Le Goater &k->parent_realize); 129577864267SCédric Le Goater } 129677864267SCédric Le Goater 129777864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 129877864267SCédric Le Goater { 12994f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 13002dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 13014f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 13024f9924c4SBenjamin Herrenschmidt int i; 13032dfa91a2SCédric Le Goater 1304db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1305d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1306d2623129SMarkus Armbruster "xive-fabric"); 1307c38536bcSCédric Le Goater 13089fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 130915376c66SCédric Le Goater 13109fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 13116598a70dSCédric Le Goater 13129fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 13133887d241SBalamuruhan S 13149fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 13154f9924c4SBenjamin Herrenschmidt 13164f9924c4SBenjamin Herrenschmidt for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { 13174f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 13189fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 13194f9924c4SBenjamin Herrenschmidt } 13204f9924c4SBenjamin Herrenschmidt 13214f9924c4SBenjamin Herrenschmidt /* 13224f9924c4SBenjamin Herrenschmidt * Number of PHBs is the chip default 13234f9924c4SBenjamin Herrenschmidt */ 13244f9924c4SBenjamin Herrenschmidt chip->num_phbs = pcc->num_phbs; 132577864267SCédric Le Goater } 132677864267SCédric Le Goater 13275dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 13285dad902cSCédric Le Goater { 13295dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 13305dad902cSCédric Le Goater int i; 13315dad902cSCédric Le Goater 13325dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 13335dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 13345dad902cSCédric Le Goater 13355dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 13365dad902cSCédric Le Goater char eq_name[32]; 13375dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 13384fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 13395dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 13405dad902cSCédric Le Goater 13415dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 13429fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 13439fc7fc4dSMarkus Armbruster sizeof(*eq), TYPE_PNV_QUAD, 13449fc7fc4dSMarkus Armbruster &error_fatal, NULL); 13455dad902cSCédric Le Goater 13465325cc34SMarkus Armbruster object_property_set_int(OBJECT(eq), "id", core_id, &error_fatal); 1347ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 13485dad902cSCédric Le Goater 13495dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 13505dad902cSCédric Le Goater &eq->xscom_regs); 13515dad902cSCédric Le Goater } 13525dad902cSCédric Le Goater } 13535dad902cSCédric Le Goater 13544f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp) 13554f9924c4SBenjamin Herrenschmidt { 13564f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 13574f9924c4SBenjamin Herrenschmidt int i, j; 13584f9924c4SBenjamin Herrenschmidt int phb_id = 0; 13594f9924c4SBenjamin Herrenschmidt 13604f9924c4SBenjamin Herrenschmidt for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) { 13614f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 13624f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 13634f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 13644f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 13654f9924c4SBenjamin Herrenschmidt 13665325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 13674f9924c4SBenjamin Herrenschmidt /* 13684f9924c4SBenjamin Herrenschmidt * PEC0 -> 1 stack 13694f9924c4SBenjamin Herrenschmidt * PEC1 -> 2 stacks 13704f9924c4SBenjamin Herrenschmidt * PEC2 -> 3 stacks 13714f9924c4SBenjamin Herrenschmidt */ 13725325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "num-stacks", i + 1, 13734f9924c4SBenjamin Herrenschmidt &error_fatal); 13745325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 13754f9924c4SBenjamin Herrenschmidt &error_fatal); 13765325cc34SMarkus Armbruster object_property_set_link(OBJECT(pec), "system-memory", 13775325cc34SMarkus Armbruster OBJECT(get_system_memory()), &error_abort); 1378668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) { 13794f9924c4SBenjamin Herrenschmidt return; 13804f9924c4SBenjamin Herrenschmidt } 13814f9924c4SBenjamin Herrenschmidt 13824f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 13834f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 13844f9924c4SBenjamin Herrenschmidt 13854f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 13864f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 13874f9924c4SBenjamin Herrenschmidt 13884f9924c4SBenjamin Herrenschmidt for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs; 13894f9924c4SBenjamin Herrenschmidt j++, phb_id++) { 13904f9924c4SBenjamin Herrenschmidt PnvPhb4PecStack *stack = &pec->stacks[j]; 13914f9924c4SBenjamin Herrenschmidt Object *obj = OBJECT(&stack->phb); 13924f9924c4SBenjamin Herrenschmidt 13935325cc34SMarkus Armbruster object_property_set_int(obj, "index", phb_id, &error_fatal); 13945325cc34SMarkus Armbruster object_property_set_int(obj, "chip-id", chip->chip_id, 13954f9924c4SBenjamin Herrenschmidt &error_fatal); 13965325cc34SMarkus Armbruster object_property_set_int(obj, "version", PNV_PHB4_VERSION, 13974f9924c4SBenjamin Herrenschmidt &error_fatal); 13985325cc34SMarkus Armbruster object_property_set_int(obj, "device-id", PNV_PHB4_DEVICE_ID, 13994f9924c4SBenjamin Herrenschmidt &error_fatal); 14005325cc34SMarkus Armbruster object_property_set_link(obj, "stack", OBJECT(stack), 14015325cc34SMarkus Armbruster &error_abort); 1402668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) { 14034f9924c4SBenjamin Herrenschmidt return; 14044f9924c4SBenjamin Herrenschmidt } 14054f9924c4SBenjamin Herrenschmidt 14064f9924c4SBenjamin Herrenschmidt /* Populate the XSCOM address space. */ 14074f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14084f9924c4SBenjamin Herrenschmidt pec_nest_base + 0x40 * (stack->stack_no + 1), 14094f9924c4SBenjamin Herrenschmidt &stack->nest_regs_mr); 14104f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14114f9924c4SBenjamin Herrenschmidt pec_pci_base + 0x40 * (stack->stack_no + 1), 14124f9924c4SBenjamin Herrenschmidt &stack->pci_regs_mr); 14134f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, 14144f9924c4SBenjamin Herrenschmidt pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + 14154f9924c4SBenjamin Herrenschmidt 0x40 * stack->stack_no, 14164f9924c4SBenjamin Herrenschmidt &stack->phb_regs_mr); 14174f9924c4SBenjamin Herrenschmidt } 14184f9924c4SBenjamin Herrenschmidt } 14194f9924c4SBenjamin Herrenschmidt } 14204f9924c4SBenjamin Herrenschmidt 142177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 142277864267SCédric Le Goater { 142377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 14242dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 14252dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1426c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 142777864267SCédric Le Goater Error *local_err = NULL; 142877864267SCédric Le Goater 1429709044fdSCédric Le Goater /* XSCOM bridge is first */ 1430709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1431709044fdSCédric Le Goater if (local_err) { 1432709044fdSCédric Le Goater error_propagate(errp, local_err); 1433709044fdSCédric Le Goater return; 1434709044fdSCédric Le Goater } 1435709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1436709044fdSCédric Le Goater 143777864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 143877864267SCédric Le Goater if (local_err) { 143977864267SCédric Le Goater error_propagate(errp, local_err); 144077864267SCédric Le Goater return; 144177864267SCédric Le Goater } 14422dfa91a2SCédric Le Goater 14435dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 14445dad902cSCédric Le Goater if (local_err) { 14455dad902cSCédric Le Goater error_propagate(errp, local_err); 14465dad902cSCédric Le Goater return; 14475dad902cSCédric Le Goater } 14485dad902cSCédric Le Goater 14492dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 14505325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar", 14515325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal); 14525325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar", 14535325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal); 14545325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar", 14555325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal); 14565325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar", 14575325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal); 14585325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), 14597ae54cc3SGreg Kurz &error_abort); 1460668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { 14612dfa91a2SCédric Le Goater return; 14622dfa91a2SCédric Le Goater } 14632dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 14642dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1465c38536bcSCédric Le Goater 1466c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 14675325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), 14685325cc34SMarkus Armbruster &error_fatal); 1469668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { 1470c38536bcSCédric Le Goater return; 1471c38536bcSCédric Le Goater } 1472c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1473c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 147415376c66SCédric Le Goater 147515376c66SCédric Le Goater /* LPC */ 14765325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi), 1477b63f3893SGreg Kurz &error_abort); 1478668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { 147915376c66SCédric Le Goater return; 148015376c66SCédric Le Goater } 148115376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 148215376c66SCédric Le Goater &chip9->lpc.xscom_regs); 148315376c66SCédric Le Goater 148415376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 148515376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 14866598a70dSCédric Le Goater 14876598a70dSCédric Le Goater /* Create the simplified OCC model */ 14885325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi), 1489ee3d2713SGreg Kurz &error_abort); 1490668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { 14916598a70dSCédric Le Goater return; 14926598a70dSCédric Le Goater } 14936598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1494f3db8266SBalamuruhan S 1495f3db8266SBalamuruhan S /* OCC SRAM model */ 14963a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1497f3db8266SBalamuruhan S &chip9->occ.sram_regs); 14983887d241SBalamuruhan S 14993887d241SBalamuruhan S /* HOMER */ 15005325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), 1501f2582acfSGreg Kurz &error_abort); 1502668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { 15033887d241SBalamuruhan S return; 15043887d241SBalamuruhan S } 15058f092316SCédric Le Goater /* Homer Xscom region */ 15068f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 15078f092316SCédric Le Goater 15088f092316SCédric Le Goater /* Homer mmio region */ 15093887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 15103887d241SBalamuruhan S &chip9->homer.regs); 15114f9924c4SBenjamin Herrenschmidt 15124f9924c4SBenjamin Herrenschmidt /* PHBs */ 15134f9924c4SBenjamin Herrenschmidt pnv_chip_power9_phb_realize(chip, &local_err); 15144f9924c4SBenjamin Herrenschmidt if (local_err) { 15154f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 15164f9924c4SBenjamin Herrenschmidt return; 15174f9924c4SBenjamin Herrenschmidt } 1518e997040eSCédric Le Goater } 1519e997040eSCédric Le Goater 152070c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 152170c059e9SGreg Kurz { 152270c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 152370c059e9SGreg Kurz return addr >> 3; 152470c059e9SGreg Kurz } 152570c059e9SGreg Kurz 1526e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1527e997040eSCédric Le Goater { 1528e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1529e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1530e997040eSCédric Le Goater 153183028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1532397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1533631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1534d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1535d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 15360990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 153785913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 153804026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1539eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1540d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1541c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 154270c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1543e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 15444f9924c4SBenjamin Herrenschmidt k->num_phbs = 6; 154577864267SCédric Le Goater 154677864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 154777864267SCédric Le Goater &k->parent_realize); 1548e997040eSCédric Le Goater } 1549e997040eSCédric Le Goater 15502b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 15512b548a42SCédric Le Goater { 15528b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 15538b50ce85SCédric Le Goater 15549fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 15559fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 15562b548a42SCédric Le Goater } 15572b548a42SCédric Le Goater 15582b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 15592b548a42SCédric Le Goater { 15602b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 15612b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 15628b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 15632b548a42SCédric Le Goater Error *local_err = NULL; 15642b548a42SCédric Le Goater 15652b548a42SCédric Le Goater /* XSCOM bridge is first */ 15662b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 15672b548a42SCédric Le Goater if (local_err) { 15682b548a42SCédric Le Goater error_propagate(errp, local_err); 15692b548a42SCédric Le Goater return; 15702b548a42SCédric Le Goater } 15712b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 15722b548a42SCédric Le Goater 15732b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 15742b548a42SCédric Le Goater if (local_err) { 15752b548a42SCédric Le Goater error_propagate(errp, local_err); 15762b548a42SCédric Le Goater return; 15772b548a42SCédric Le Goater } 15788b50ce85SCédric Le Goater 15798b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 15805325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar", 15815325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal); 1582668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { 15838b50ce85SCédric Le Goater return; 15848b50ce85SCédric Le Goater } 15858b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 15868b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 15872661f6abSCédric Le Goater 15882661f6abSCédric Le Goater /* LPC */ 15895325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip10->lpc), "psi", 15905325cc34SMarkus Armbruster OBJECT(&chip10->psi), &error_abort); 1591668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { 15922661f6abSCédric Le Goater return; 15932661f6abSCédric Le Goater } 15942661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 15952661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 15962661f6abSCédric Le Goater 15972661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 15982661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 15992b548a42SCédric Le Goater } 16002b548a42SCédric Le Goater 160170c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 160270c059e9SGreg Kurz { 160370c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 160470c059e9SGreg Kurz return addr >> 3; 160570c059e9SGreg Kurz } 160670c059e9SGreg Kurz 16072b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 16082b548a42SCédric Le Goater { 16092b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 16102b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 16112b548a42SCédric Le Goater 16122b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 16132b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 16142b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 16152b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 16162b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 16172b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 161885913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 16192b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 16202b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 16212b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1622c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 162370c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 16242b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 16252b548a42SCédric Le Goater 16262b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 16272b548a42SCédric Le Goater &k->parent_realize); 16282b548a42SCédric Le Goater } 16292b548a42SCédric Le Goater 1630397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1631397a79e7SCédric Le Goater { 1632397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1633397a79e7SCédric Le Goater int cores_max; 1634397a79e7SCédric Le Goater 1635397a79e7SCédric Le Goater /* 1636397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1637397a79e7SCédric Le Goater * the chip class 1638397a79e7SCédric Le Goater */ 1639397a79e7SCédric Le Goater if (!chip->cores_mask) { 1640397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1641397a79e7SCédric Le Goater } 1642397a79e7SCédric Le Goater 1643397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1644397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1645397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1646397a79e7SCédric Le Goater chip->cores_mask); 1647397a79e7SCédric Le Goater return; 1648397a79e7SCédric Le Goater } 1649397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1650397a79e7SCédric Le Goater 1651397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 165227d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1653397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1654397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1655397a79e7SCédric Le Goater cores_max); 1656397a79e7SCédric Le Goater return; 1657397a79e7SCédric Le Goater } 1658397a79e7SCédric Le Goater } 1659397a79e7SCédric Le Goater 166051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1661e997040eSCédric Le Goater { 1662397a79e7SCédric Le Goater Error *error = NULL; 1663d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 166440abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1665d2fd9612SCédric Le Goater int i, core_hwid; 166608c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1667397a79e7SCédric Le Goater 1668d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1669d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1670d2fd9612SCédric Le Goater return; 1671d2fd9612SCédric Le Goater } 1672d2fd9612SCédric Le Goater 1673d2fd9612SCédric Le Goater /* Cores */ 1674397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1675397a79e7SCédric Le Goater if (error) { 1676397a79e7SCédric Le Goater error_propagate(errp, error); 1677397a79e7SCédric Le Goater return; 1678397a79e7SCédric Le Goater } 1679d2fd9612SCédric Le Goater 16804fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1681d2fd9612SCédric Le Goater 1682d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1683d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1684d2fd9612SCédric Le Goater char core_name[32]; 16854fa28f23SGreg Kurz PnvCore *pnv_core; 1686c035851aSCédric Le Goater uint64_t xscom_core_base; 1687d2fd9612SCédric Le Goater 1688d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1689d2fd9612SCédric Le Goater continue; 1690d2fd9612SCédric Le Goater } 1691d2fd9612SCédric Le Goater 16924fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 16934fa28f23SGreg Kurz 1694d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1695d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 16964fa28f23SGreg Kurz chip->cores[i] = pnv_core; 16975325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads", 16985325cc34SMarkus Armbruster chip->nr_threads, &error_fatal); 16995325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, 17005325cc34SMarkus Armbruster core_hwid, &error_fatal); 17015325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "pir", 17025325cc34SMarkus Armbruster pcc->core_pir(chip, core_hwid), &error_fatal); 17035325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, 17045325cc34SMarkus Armbruster &error_fatal); 17055325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), 1706158e17a6SGreg Kurz &error_abort); 1707ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 170824ece072SCédric Le Goater 170924ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1710c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1711c035851aSCédric Le Goater 1712c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 17134fa28f23SGreg Kurz &pnv_core->xscom_regs); 1714d2fd9612SCédric Le Goater i++; 1715d2fd9612SCédric Le Goater } 171651c04728SCédric Le Goater } 171751c04728SCédric Le Goater 171851c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 171951c04728SCédric Le Goater { 172051c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 172151c04728SCédric Le Goater Error *error = NULL; 172251c04728SCédric Le Goater 172351c04728SCédric Le Goater /* Cores */ 172451c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 172551c04728SCédric Le Goater if (error) { 172651c04728SCédric Le Goater error_propagate(errp, error); 172751c04728SCédric Le Goater return; 172851c04728SCédric Le Goater } 1729e997040eSCédric Le Goater } 1730e997040eSCédric Le Goater 1731e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1732e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1733e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1734e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1735397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1736397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1737764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 17384f9924c4SBenjamin Herrenschmidt DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0), 1739e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1740e997040eSCédric Le Goater }; 1741e997040eSCédric Le Goater 1742e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1743e997040eSCédric Le Goater { 1744e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1745e997040eSCédric Le Goater 17469d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1747e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 17484f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 1749e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1750e997040eSCédric Le Goater } 1751e997040eSCédric Le Goater 1752119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1753119eaa9dSCédric Le Goater { 1754119eaa9dSCédric Le Goater int i, j; 1755119eaa9dSCédric Le Goater 1756119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1757119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1758119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1759119eaa9dSCédric Le Goater 1760119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1761119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1762119eaa9dSCédric Le Goater return pc->threads[j]; 1763119eaa9dSCédric Le Goater } 1764119eaa9dSCédric Le Goater } 1765119eaa9dSCédric Le Goater } 1766119eaa9dSCédric Le Goater return NULL; 1767119eaa9dSCédric Le Goater } 1768119eaa9dSCédric Le Goater 176954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 177054f59d78SCédric Le Goater { 1771b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 17729ae1329eSCédric Le Goater int i, j; 177354f59d78SCédric Le Goater 177454f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 17759ae1329eSCédric Le Goater PnvChip *chip = pnv->chips[i]; 177677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 177777864267SCédric Le Goater 177877864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 177977864267SCédric Le Goater return &chip8->psi.ics; 178054f59d78SCédric Le Goater } 17819ae1329eSCédric Le Goater for (j = 0; j < chip->num_phbs; j++) { 17829ae1329eSCédric Le Goater if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) { 17839ae1329eSCédric Le Goater return &chip8->phbs[j].lsis; 17849ae1329eSCédric Le Goater } 17859ae1329eSCédric Le Goater if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) { 17869ae1329eSCédric Le Goater return ICS(&chip8->phbs[j].msis); 17879ae1329eSCédric Le Goater } 17889ae1329eSCédric Le Goater } 178954f59d78SCédric Le Goater } 179054f59d78SCédric Le Goater return NULL; 179154f59d78SCédric Le Goater } 179254f59d78SCédric Le Goater 179354f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 179454f59d78SCédric Le Goater { 1795b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 17969ae1329eSCédric Le Goater int i, j; 179754f59d78SCédric Le Goater 179854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 17999ae1329eSCédric Le Goater PnvChip *chip = pnv->chips[i]; 180077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 18019ae1329eSCédric Le Goater 180277864267SCédric Le Goater ics_resend(&chip8->psi.ics); 18039ae1329eSCédric Le Goater for (j = 0; j < chip->num_phbs; j++) { 18049ae1329eSCédric Le Goater ics_resend(&chip8->phbs[j].lsis); 18059ae1329eSCédric Le Goater ics_resend(ICS(&chip8->phbs[j].msis)); 18069ae1329eSCédric Le Goater } 180754f59d78SCédric Le Goater } 180854f59d78SCédric Le Goater } 180954f59d78SCédric Le Goater 181036fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 181136fc6f08SCédric Le Goater { 181236fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 181336fc6f08SCédric Le Goater 1814956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 181536fc6f08SCédric Le Goater } 181636fc6f08SCédric Le Goater 181747fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 181847fea43aSCédric Le Goater Monitor *mon) 181947fea43aSCédric Le Goater { 1820b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 182154f59d78SCédric Le Goater int i; 182247fea43aSCédric Le Goater CPUState *cs; 182347fea43aSCédric Le Goater 182447fea43aSCédric Le Goater CPU_FOREACH(cs) { 182547fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 182647fea43aSCédric Le Goater 182785913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 182885913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 182985913070SGreg Kurz mon); 1830d8e4aad5SCédric Le Goater } 183154f59d78SCédric Le Goater 183254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1833d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 183454f59d78SCédric Le Goater } 183547fea43aSCédric Le Goater } 183647fea43aSCédric Le Goater 1837c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1838c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1839c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1840c722579eSCédric Le Goater uint32_t logic_serv, 1841c722579eSCédric Le Goater XiveTCTXMatch *match) 1842c722579eSCédric Le Goater { 1843c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1844c722579eSCédric Le Goater int total_count = 0; 1845c722579eSCédric Le Goater int i; 1846c722579eSCédric Le Goater 1847c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1848c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1849c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1850c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1851c722579eSCédric Le Goater int count; 1852c722579eSCédric Le Goater 1853c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1854c722579eSCédric Le Goater priority, logic_serv, match); 1855c722579eSCédric Le Goater 1856c722579eSCédric Le Goater if (count < 0) { 1857c722579eSCédric Le Goater return count; 1858c722579eSCédric Le Goater } 1859c722579eSCédric Le Goater 1860c722579eSCédric Le Goater total_count += count; 1861c722579eSCédric Le Goater } 1862c722579eSCédric Le Goater 1863c722579eSCédric Le Goater return total_count; 1864c722579eSCédric Le Goater } 1865c722579eSCédric Le Goater 1866f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 18679e933f4aSBenjamin Herrenschmidt { 18689e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 186936fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1870d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1871d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 1872f30c843cSCédric Le Goater 1873f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1874f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1875f30c843cSCédric Le Goater 1876f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1877f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1878f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1879d76f2da7SGreg Kurz 1880d76f2da7SGreg Kurz pmc->compat = compat; 1881d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 1882f30c843cSCédric Le Goater } 1883f30c843cSCédric Le Goater 1884f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1885f30c843cSCédric Le Goater { 1886f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1887c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1888d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1889d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 1890f30c843cSCédric Le Goater 1891f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1892f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1893c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1894f30c843cSCédric Le Goater 1895f30c843cSCédric Le Goater mc->alias = "powernv"; 1896d76f2da7SGreg Kurz 1897d76f2da7SGreg Kurz pmc->compat = compat; 1898d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 18997a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 1900f30c843cSCédric Le Goater } 1901f30c843cSCédric Le Goater 19022b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 19032b548a42SCédric Le Goater { 19042b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1905d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1906d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 19072b548a42SCédric Le Goater 19082b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 19092b548a42SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); 1910d76f2da7SGreg Kurz 1911d76f2da7SGreg Kurz pmc->compat = compat; 1912d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 19137a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 19142b548a42SCédric Le Goater } 19152b548a42SCédric Le Goater 191608c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 191708c3f3a7SCédric Le Goater { 191808c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 191908c3f3a7SCédric Le Goater 192008c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 192108c3f3a7SCédric Le Goater } 192208c3f3a7SCédric Le Goater 192308c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 192408c3f3a7SCédric Le Goater { 192508c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 192608c3f3a7SCédric Le Goater 192708c3f3a7SCédric Le Goater if (value) { 192808c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 192908c3f3a7SCédric Le Goater } 193008c3f3a7SCédric Le Goater } 193108c3f3a7SCédric Le Goater 193201b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 193301b552b0SNicholas Piggin { 193401b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 193501b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 193601b552b0SNicholas Piggin 193701b552b0SNicholas Piggin cpu_synchronize_state(cs); 193801b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 19390911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 194001b552b0SNicholas Piggin /* 1941fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 1942fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 1943fe837714SNicholas Piggin * (PPC_BIT(43)). 194401b552b0SNicholas Piggin */ 19450911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 1946fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 19470911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 194801b552b0SNicholas Piggin } 1949fe837714SNicholas Piggin } else { 1950fe837714SNicholas Piggin /* 1951fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 1952fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 1953fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 1954fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 1955fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 1956fe837714SNicholas Piggin */ 19570911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 1958fe837714SNicholas Piggin } 1959fe837714SNicholas Piggin } 196001b552b0SNicholas Piggin 196101b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 196201b552b0SNicholas Piggin { 196301b552b0SNicholas Piggin CPUState *cs; 196401b552b0SNicholas Piggin 196501b552b0SNicholas Piggin CPU_FOREACH(cs) { 196601b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 196701b552b0SNicholas Piggin } 196801b552b0SNicholas Piggin } 196901b552b0SNicholas Piggin 1970f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1971f30c843cSCédric Le Goater { 1972f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 197347fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 197401b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 19759e933f4aSBenjamin Herrenschmidt 19769e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1977b168a138SCédric Le Goater mc->init = pnv_init; 1978b168a138SCédric Le Goater mc->reset = pnv_reset; 19799e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 198059b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 198159b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 19829e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 19839e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1984f1d18b0aSJoel Stanley /* 1985f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1986f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1987f1d18b0aSJoel Stanley */ 1988f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 1989173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 199047fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 199101b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 199208c3f3a7SCédric Le Goater 199308c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 1994d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 199508c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 19967eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 19979e933f4aSBenjamin Herrenschmidt } 19989e933f4aSBenjamin Herrenschmidt 199977864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2000beba5c0fSIgor Mammedov { \ 2001beba5c0fSIgor Mammedov .name = type, \ 2002beba5c0fSIgor Mammedov .class_init = class_initfn, \ 200377864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 200477864267SCédric Le Goater } 200577864267SCédric Le Goater 200677864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 200777864267SCédric Le Goater { \ 200877864267SCédric Le Goater .name = type, \ 200977864267SCédric Le Goater .class_init = class_initfn, \ 201077864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2011beba5c0fSIgor Mammedov } 2012beba5c0fSIgor Mammedov 20132b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 20142b548a42SCédric Le Goater { \ 20152b548a42SCédric Le Goater .name = type, \ 20162b548a42SCédric Le Goater .class_init = class_initfn, \ 20172b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 20182b548a42SCédric Le Goater } 20192b548a42SCédric Le Goater 2020beba5c0fSIgor Mammedov static const TypeInfo types[] = { 20211aba8716SCédric Le Goater { 20222b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 20232b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20242b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 20252b548a42SCédric Le Goater }, 20262b548a42SCédric Le Goater { 20271aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 20281aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20291aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2030c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2031c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2032c722579eSCédric Le Goater { }, 2033c722579eSCédric Le Goater }, 20341aba8716SCédric Le Goater }, 20351aba8716SCédric Le Goater { 20361aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 20371aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 20381aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 20391aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 20401aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 20411aba8716SCédric Le Goater { }, 20421aba8716SCédric Le Goater }, 20431aba8716SCédric Le Goater }, 2044beba5c0fSIgor Mammedov { 2045b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 20469e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2047f30c843cSCédric Le Goater .abstract = true, 20489e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2049b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2050d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 205136fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 205247fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 205301b552b0SNicholas Piggin { TYPE_NMI }, 205436fc6f08SCédric Le Goater { }, 205536fc6f08SCédric Le Goater }, 2056beba5c0fSIgor Mammedov }, 2057beba5c0fSIgor Mammedov { 2058beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2059beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2060beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2061beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2062beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2063beba5c0fSIgor Mammedov .abstract = true, 2064beba5c0fSIgor Mammedov }, 206577864267SCédric Le Goater 206677864267SCédric Le Goater /* 20672b548a42SCédric Le Goater * P10 chip and variants 20682b548a42SCédric Le Goater */ 20692b548a42SCédric Le Goater { 20702b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 20712b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 20722b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 20732b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 20742b548a42SCédric Le Goater }, 20752b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 20762b548a42SCédric Le Goater 20772b548a42SCédric Le Goater /* 207877864267SCédric Le Goater * P9 chip and variants 207977864267SCédric Le Goater */ 208077864267SCédric Le Goater { 208177864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 208277864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 208377864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 208477864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 208577864267SCédric Le Goater }, 208677864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 208777864267SCédric Le Goater 208877864267SCédric Le Goater /* 208977864267SCédric Le Goater * P8 chip and variants 209077864267SCédric Le Goater */ 209177864267SCédric Le Goater { 209277864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 209377864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 209477864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 209577864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 209677864267SCédric Le Goater }, 209777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 209877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 209977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2100beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 21019e933f4aSBenjamin Herrenschmidt }; 21029e933f4aSBenjamin Herrenschmidt 2103beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2104