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" 249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2671e8a915SMarkus Armbruster #include "sysemu/reset.h" 2754d31236SMarkus Armbruster #include "sysemu/runstate.h" 28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 298d409261SCédric Le Goater #include "sysemu/device_tree.h" 30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 38e997040eSCédric Le Goater #include "qapi/visitor.h" 3947fea43aSCédric Le Goater #include "monitor/monitor.h" 4047fea43aSCédric Le Goater #include "hw/intc/intc.h" 41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 439e933f4aSBenjamin Herrenschmidt 4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 4735dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 48967b7523SCédric Le Goater 493495b6b6SCédric Le Goater #include "hw/isa/isa.h" 5012e9493dSMarkus Armbruster #include "hw/boards.h" 513495b6b6SCédric Le Goater #include "hw/char/serial.h" 52bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 533495b6b6SCédric Le Goater 549e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 559e933f4aSBenjamin Herrenschmidt 56b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 579e933f4aSBenjamin Herrenschmidt 589e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 599e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 60b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 619e933f4aSBenjamin Herrenschmidt 629e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 63b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 64fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 65584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 669e933f4aSBenjamin Herrenschmidt 6740abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 6840abf43fSIgor Mammedov { 6940abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7040abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7140abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7240abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7340abf43fSIgor Mammedov g_free(s); 7440abf43fSIgor Mammedov return core_type; 7540abf43fSIgor Mammedov } 7640abf43fSIgor Mammedov 779e933f4aSBenjamin Herrenschmidt /* 789e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 799e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 809e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 819e933f4aSBenjamin Herrenschmidt */ 829e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 839e933f4aSBenjamin Herrenschmidt 849e933f4aSBenjamin Herrenschmidt /* 859e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 869e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 879e933f4aSBenjamin Herrenschmidt * per chip. 889e933f4aSBenjamin Herrenschmidt */ 89b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 909e933f4aSBenjamin Herrenschmidt { 919e933f4aSBenjamin Herrenschmidt char *mem_name; 929e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 939e933f4aSBenjamin Herrenschmidt int off; 949e933f4aSBenjamin Herrenschmidt 959e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 969e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 979e933f4aSBenjamin Herrenschmidt 989e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 999e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1009e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1019e933f4aSBenjamin Herrenschmidt 1029e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1039e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1049e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1059e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1069e933f4aSBenjamin Herrenschmidt } 1079e933f4aSBenjamin Herrenschmidt 108d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 109d2fd9612SCédric Le Goater { 110d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 111d2fd9612SCédric Le Goater 112d2fd9612SCédric Le Goater if (cpus_offset < 0) { 113a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 114d2fd9612SCédric Le Goater if (cpus_offset) { 115d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 116d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 117d2fd9612SCédric Le Goater } 118d2fd9612SCédric Le Goater } 119d2fd9612SCédric Le Goater _FDT(cpus_offset); 120d2fd9612SCédric Le Goater return cpus_offset; 121d2fd9612SCédric Le Goater } 122d2fd9612SCédric Le Goater 123d2fd9612SCédric Le Goater /* 124d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 125d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 126d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 127d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 128d2fd9612SCédric Le Goater * servers. 129d2fd9612SCédric Le Goater */ 130b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 131d2fd9612SCédric Le Goater { 13208304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13308304a86SDavid Gibson CPUState *cs = CPU(cpu); 134d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1358bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 136d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 137d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 138d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 139d2fd9612SCédric Le Goater int i; 140d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 141d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 142d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 143d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 144d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 145d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 146d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 147d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 148d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 149d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 150d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 151d2fd9612SCédric Le Goater int offset; 152d2fd9612SCédric Le Goater char *nodename; 153d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 154d2fd9612SCédric Le Goater 155d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 156d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 157d2fd9612SCédric Le Goater _FDT(offset); 158d2fd9612SCédric Le Goater g_free(nodename); 159d2fd9612SCédric Le Goater 160d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 161d2fd9612SCédric Le Goater 162d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 164d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 165d2fd9612SCédric Le Goater 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 168d2fd9612SCédric Le Goater env->dcache_line_size))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 170d2fd9612SCédric Le Goater env->dcache_line_size))); 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 172d2fd9612SCédric Le Goater env->icache_line_size))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 174d2fd9612SCédric Le Goater env->icache_line_size))); 175d2fd9612SCédric Le Goater 176d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 178d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 179d2fd9612SCédric Le Goater } else { 1803dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 181d2fd9612SCédric Le Goater } 182d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 183d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 184d2fd9612SCédric Le Goater pcc->l1_icache_size))); 185d2fd9612SCédric Le Goater } else { 1863dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 187d2fd9612SCédric Le Goater } 188d2fd9612SCédric Le Goater 189d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 190d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19159b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19259b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 193d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 194d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 195d2fd9612SCédric Le Goater 196d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 197d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 198d2fd9612SCédric Le Goater } 199d2fd9612SCédric Le Goater 20058969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 201d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 202d2fd9612SCédric Le Goater segs, sizeof(segs)))); 203d2fd9612SCédric Le Goater } 204d2fd9612SCédric Le Goater 20559b7c1c2SBalamuruhan S /* 20659b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 207d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 208d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 20959b7c1c2SBalamuruhan S * 2 == VSX available 21059b7c1c2SBalamuruhan S */ 211d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 212d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 213d2fd9612SCédric Le Goater 214d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 215d2fd9612SCédric Le Goater } 216d2fd9612SCédric Le Goater 21759b7c1c2SBalamuruhan S /* 21859b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 219d2fd9612SCédric Le Goater * 0 / no property == no DFP 22059b7c1c2SBalamuruhan S * 1 == DFP available 22159b7c1c2SBalamuruhan S */ 222d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 223d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 224d2fd9612SCédric Le Goater } 225d2fd9612SCédric Le Goater 226644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 227d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 228d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 229d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 230d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 231d2fd9612SCédric Le Goater } 232d2fd9612SCédric Le Goater 233d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 234d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 235d2fd9612SCédric Le Goater 236d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 237d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 238d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 239d2fd9612SCédric Le Goater } 240d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 241d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 242d2fd9612SCédric Le Goater } 243d2fd9612SCédric Le Goater 244b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 245bf5615e7SCédric Le Goater uint32_t nr_threads) 246bf5615e7SCédric Le Goater { 247bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 248bf5615e7SCédric Le Goater char *name; 249bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 250bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 251bf5615e7SCédric Le Goater uint64_t *reg; 252bf5615e7SCédric Le Goater int offset; 253bf5615e7SCédric Le Goater 254bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 255bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 256bf5615e7SCédric Le Goater 257bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 258bf5615e7SCédric Le Goater reg = g_malloc(rsize); 259bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 260bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 261bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 262bf5615e7SCédric Le Goater } 263bf5615e7SCédric Le Goater 264bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 265bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 266bf5615e7SCédric Le Goater _FDT(offset); 267bf5615e7SCédric Le Goater g_free(name); 268bf5615e7SCédric Le Goater 269bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 270bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 271bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 272bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 273bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 274bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 275bf5615e7SCédric Le Goater irange, sizeof(irange)))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 278bf5615e7SCédric Le Goater g_free(reg); 279bf5615e7SCédric Le Goater } 280bf5615e7SCédric Le Goater 281eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 282e997040eSCédric Le Goater { 283d2fd9612SCédric Le Goater int i; 284d2fd9612SCédric Le Goater 285*3f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 286*3f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 287*3f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE)); 288967b7523SCédric Le Goater 289d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2904fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 291d2fd9612SCédric Le Goater 292b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 293bf5615e7SCédric Le Goater 294bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 295b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 296d2fd9612SCédric Le Goater } 297d2fd9612SCédric Le Goater 298e997040eSCédric Le Goater if (chip->ram_size) { 299b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 300e997040eSCédric Le Goater } 301e997040eSCédric Le Goater } 302e997040eSCédric Le Goater 303eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 304eb859a27SCédric Le Goater { 305eb859a27SCédric Le Goater int i; 306eb859a27SCédric Le Goater 307*3f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 308*3f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 309*3f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE)); 310eb859a27SCédric Le Goater 311eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3124fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 313eb859a27SCédric Le Goater 314eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 315eb859a27SCédric Le Goater } 316eb859a27SCédric Le Goater 317eb859a27SCédric Le Goater if (chip->ram_size) { 318eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 319eb859a27SCédric Le Goater } 32015376c66SCédric Le Goater 3212661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 322eb859a27SCédric Le Goater } 323eb859a27SCédric Le Goater 3242b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3252b548a42SCédric Le Goater { 3262b548a42SCédric Le Goater int i; 3272b548a42SCédric Le Goater 328*3f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 329*3f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 330*3f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE)); 3312b548a42SCédric Le Goater 3322b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3332b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3342b548a42SCédric Le Goater 3352b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3362b548a42SCédric Le Goater } 3372b548a42SCédric Le Goater 3382b548a42SCédric Le Goater if (chip->ram_size) { 3392b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3402b548a42SCédric Le Goater } 3412661f6abSCédric Le Goater 3422661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 3432b548a42SCédric Le Goater } 3442b548a42SCédric Le Goater 345b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 346c5ffdcaeSCédric Le Goater { 347c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 348c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 349c5ffdcaeSCédric Le Goater cpu_to_be32(1), 350c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 351c5ffdcaeSCédric Le Goater cpu_to_be32(2) 352c5ffdcaeSCédric Le Goater }; 353c5ffdcaeSCédric Le Goater char *name; 354c5ffdcaeSCédric Le Goater int node; 355c5ffdcaeSCédric Le Goater 356c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 357c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 358c5ffdcaeSCédric Le Goater _FDT(node); 359c5ffdcaeSCédric Le Goater g_free(name); 360c5ffdcaeSCédric Le Goater 361c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 362c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 363c5ffdcaeSCédric Le Goater } 364c5ffdcaeSCédric Le Goater 365b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 366cb228f5aSCédric Le Goater { 367cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 368cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 369cb228f5aSCédric Le Goater uint32_t io_regs[] = { 370cb228f5aSCédric Le Goater cpu_to_be32(1), 371cb228f5aSCédric Le Goater cpu_to_be32(io_base), 372cb228f5aSCédric Le Goater cpu_to_be32(8) 373cb228f5aSCédric Le Goater }; 374cb228f5aSCédric Le Goater char *name; 375cb228f5aSCédric Le Goater int node; 376cb228f5aSCédric Le Goater 377cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 378cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 379cb228f5aSCédric Le Goater _FDT(node); 380cb228f5aSCédric Le Goater g_free(name); 381cb228f5aSCédric Le Goater 382cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 383cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 384cb228f5aSCédric Le Goater sizeof(compatible)))); 385cb228f5aSCédric Le Goater 386cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 387cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 388cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 389cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 390cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 391cb228f5aSCédric Le Goater 392cb228f5aSCédric Le Goater /* This is needed by Linux */ 393cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 394cb228f5aSCédric Le Goater } 395cb228f5aSCédric Le Goater 396b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 39704f6c8b2SCédric Le Goater { 39804f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 39904f6c8b2SCédric Le Goater uint32_t io_base; 40004f6c8b2SCédric Le Goater uint32_t io_regs[] = { 40104f6c8b2SCédric Le Goater cpu_to_be32(1), 40204f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 40304f6c8b2SCédric Le Goater cpu_to_be32(3) 40404f6c8b2SCédric Le Goater }; 40504f6c8b2SCédric Le Goater uint32_t irq; 40604f6c8b2SCédric Le Goater char *name; 40704f6c8b2SCédric Le Goater int node; 40804f6c8b2SCédric Le Goater 40904f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 41004f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 41104f6c8b2SCédric Le Goater 41204f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 41304f6c8b2SCédric Le Goater 41404f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 41504f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 41604f6c8b2SCédric Le Goater _FDT(node); 41704f6c8b2SCédric Le Goater g_free(name); 41804f6c8b2SCédric Le Goater 4197032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4207032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4217032d92aSCédric Le Goater sizeof(compatible)))); 42204f6c8b2SCédric Le Goater 42304f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 42404f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 42504f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 42604f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 42704f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 42804f6c8b2SCédric Le Goater } 42904f6c8b2SCédric Le Goater 430e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 431e7a3fee3SCédric Le Goater void *fdt; 432e7a3fee3SCédric Le Goater int offset; 433e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 434e7a3fee3SCédric Le Goater 435b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 436e7a3fee3SCédric Le Goater { 437c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 438c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 439c5ffdcaeSCédric Le Goater 440c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 441b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 442cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 443b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 44404f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 445b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 446c5ffdcaeSCédric Le Goater } else { 447c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 448c5ffdcaeSCédric Le Goater d->ioport_id); 449c5ffdcaeSCédric Le Goater } 450c5ffdcaeSCédric Le Goater 451e7a3fee3SCédric Le Goater return 0; 452e7a3fee3SCédric Le Goater } 453e7a3fee3SCédric Le Goater 45459b7c1c2SBalamuruhan S /* 45559b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 456bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 457bb7ab95cSCédric Le Goater */ 458bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 459bb7ab95cSCédric Le Goater { 46064d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 461e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 462e7a3fee3SCédric Le Goater .fdt = fdt, 463bb7ab95cSCédric Le Goater .offset = isa_offset, 464e7a3fee3SCédric Le Goater }; 465f47a08d1SCédric Le Goater uint32_t phandle; 466e7a3fee3SCédric Le Goater 467bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 468bb7ab95cSCédric Le Goater 469f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 470f47a08d1SCédric Le Goater assert(phandle > 0); 471f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 472f47a08d1SCédric Le Goater 47359b7c1c2SBalamuruhan S /* 47459b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 47559b7c1c2SBalamuruhan S * can not use object_child_foreach() 47659b7c1c2SBalamuruhan S */ 477bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 478bb7ab95cSCédric Le Goater &args); 479e7a3fee3SCédric Le Goater } 480e7a3fee3SCédric Le Goater 4817a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 482e5694793SCédric Le Goater { 483e5694793SCédric Le Goater int off; 484e5694793SCédric Le Goater 485e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 486e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 487e5694793SCédric Le Goater 488e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 489e5694793SCédric Le Goater } 490e5694793SCédric Le Goater 491b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4929e933f4aSBenjamin Herrenschmidt { 493d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 494b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 4959e933f4aSBenjamin Herrenschmidt void *fdt; 4969e933f4aSBenjamin Herrenschmidt char *buf; 4979e933f4aSBenjamin Herrenschmidt int off; 498e997040eSCédric Le Goater int i; 4999e933f4aSBenjamin Herrenschmidt 5009e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5019e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5029e933f4aSBenjamin Herrenschmidt 503ccb099b3SCédric Le Goater /* /qemu node */ 504ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 505ccb099b3SCédric Le Goater 5069e933f4aSBenjamin Herrenschmidt /* Root node */ 5079e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5089e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5099e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5109e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 511d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5129e933f4aSBenjamin Herrenschmidt 5139e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5149e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5159e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 5169e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5179e933f4aSBenjamin Herrenschmidt } 5189e933f4aSBenjamin Herrenschmidt g_free(buf); 5199e933f4aSBenjamin Herrenschmidt 5209e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5219e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5229e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5239e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5249e933f4aSBenjamin Herrenschmidt } 5259e933f4aSBenjamin Herrenschmidt 5269e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5279e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5289e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5299e933f4aSBenjamin Herrenschmidt 5309e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5319e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5329e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5339e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5349e933f4aSBenjamin Herrenschmidt } 5359e933f4aSBenjamin Herrenschmidt 536e997040eSCédric Le Goater /* Populate device tree for each chip */ 537e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 538eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 539e997040eSCédric Le Goater } 540e7a3fee3SCédric Le Goater 541e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 542bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 543aeaef83dSCédric Le Goater 544aeaef83dSCédric Le Goater if (pnv->bmc) { 545b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 546aeaef83dSCédric Le Goater } 547aeaef83dSCédric Le Goater 5487a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5497a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5507a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 551e5694793SCédric Le Goater } 552e5694793SCédric Le Goater 5539e933f4aSBenjamin Herrenschmidt return fdt; 5549e933f4aSBenjamin Herrenschmidt } 5559e933f4aSBenjamin Herrenschmidt 556bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 557bce0b691SCédric Le Goater { 558b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 559bce0b691SCédric Le Goater 560bce0b691SCédric Le Goater if (pnv->bmc) { 561bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 562bce0b691SCédric Le Goater } 563bce0b691SCédric Le Goater } 564bce0b691SCédric Le Goater 565a0628599SLike Xu static void pnv_reset(MachineState *machine) 5669e933f4aSBenjamin Herrenschmidt { 5679e933f4aSBenjamin Herrenschmidt void *fdt; 5689e933f4aSBenjamin Herrenschmidt 5699e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5709e933f4aSBenjamin Herrenschmidt 571b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5729e933f4aSBenjamin Herrenschmidt 5739e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5749e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5759e933f4aSBenjamin Herrenschmidt 5768d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 5779e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5789e933f4aSBenjamin Herrenschmidt } 5799e933f4aSBenjamin Herrenschmidt 58004026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5813495b6b6SCédric Le Goater { 58277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58377864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 58404026890SCédric Le Goater } 5853495b6b6SCédric Le Goater 58604026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 58704026890SCédric Le Goater { 58877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 59004026890SCédric Le Goater } 5913495b6b6SCédric Le Goater 59204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 59304026890SCédric Le Goater { 59415376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 59515376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 59604026890SCédric Le Goater } 5973495b6b6SCédric Le Goater 5982b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 5992b548a42SCédric Le Goater { 6002661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6012661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6022b548a42SCédric Le Goater } 6032b548a42SCédric Le Goater 60404026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 60504026890SCédric Le Goater { 60604026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6073495b6b6SCédric Le Goater } 6083495b6b6SCédric Le Goater 609d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 610d8e4aad5SCédric Le Goater { 611d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 612d8e4aad5SCédric Le Goater 613d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 614d8e4aad5SCédric Le Goater } 615d8e4aad5SCédric Le Goater 616d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 617d8e4aad5SCédric Le Goater { 618d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 619d8e4aad5SCédric Le Goater 620d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 621c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 622d8e4aad5SCédric Le Goater } 623d8e4aad5SCédric Le Goater 624c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 625c4b2c40cSGreg Kurz uint32_t core_id) 626c4b2c40cSGreg Kurz { 627c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 628c4b2c40cSGreg Kurz } 629c4b2c40cSGreg Kurz 630c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 631c4b2c40cSGreg Kurz uint32_t core_id) 632c4b2c40cSGreg Kurz { 633c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 634c4b2c40cSGreg Kurz } 635c4b2c40cSGreg Kurz 636c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 637c4b2c40cSGreg Kurz uint32_t core_id) 638c4b2c40cSGreg Kurz { 639c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 640c4b2c40cSGreg Kurz } 641c4b2c40cSGreg Kurz 642f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 643f30c843cSCédric Le Goater { 644f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 645f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 646f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 647f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 648f30c843cSCédric Le Goater 649f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 650f30c843cSCédric Le Goater } 651f30c843cSCédric Le Goater 652e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 653e2392d43SCédric Le Goater { 654e2392d43SCédric Le Goater Object *obj; 655e2392d43SCédric Le Goater 656e2392d43SCédric Le Goater obj = OBJECT(isa_create(bus, "isa-ipmi-bt")); 657e2392d43SCédric Le Goater object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal); 658e2392d43SCédric Le Goater object_property_set_int(obj, irq, "irq", &error_fatal); 659e2392d43SCédric Le Goater object_property_set_bool(obj, true, "realized", &error_fatal); 660e2392d43SCédric Le Goater } 661e2392d43SCédric Le Goater 6622b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 6632b548a42SCédric Le Goater { 6648b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6658b50ce85SCédric Le Goater 6668b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 6672b548a42SCédric Le Goater } 6682b548a42SCédric Le Goater 669b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 6709e933f4aSBenjamin Herrenschmidt { 671b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 672f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 6739e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 6749e933f4aSBenjamin Herrenschmidt char *fw_filename; 6759e933f4aSBenjamin Herrenschmidt long fw_size; 676e997040eSCédric Le Goater int i; 677e997040eSCédric Le Goater char *chip_typename; 67835dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 67935dde576SCédric Le Goater DeviceState *dev; 6809e933f4aSBenjamin Herrenschmidt 6819e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 682d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 6833dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 6849e933f4aSBenjamin Herrenschmidt } 6859e933f4aSBenjamin Herrenschmidt 6869e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 687b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6889e933f4aSBenjamin Herrenschmidt machine->ram_size); 6899e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6909e933f4aSBenjamin Herrenschmidt 69135dde576SCédric Le Goater /* 69235dde576SCédric Le Goater * Create our simple PNOR device 69335dde576SCédric Le Goater */ 69435dde576SCédric Le Goater dev = qdev_create(NULL, TYPE_PNV_PNOR); 69535dde576SCédric Le Goater if (pnor) { 69635dde576SCédric Le Goater qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor), 69735dde576SCédric Le Goater &error_abort); 69835dde576SCédric Le Goater } 69935dde576SCédric Le Goater qdev_init_nofail(dev); 70035dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 70135dde576SCédric Le Goater 7029e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 7039e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 7049e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 7059e933f4aSBenjamin Herrenschmidt } 7069e933f4aSBenjamin Herrenschmidt 7079e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 70815fcedb2SCédric Le Goater if (!fw_filename) { 70915fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 71015fcedb2SCédric Le Goater exit(1); 71115fcedb2SCédric Le Goater } 7129e933f4aSBenjamin Herrenschmidt 7139e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 7149e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 71515fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 7169e933f4aSBenjamin Herrenschmidt exit(1); 7179e933f4aSBenjamin Herrenschmidt } 7189e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 7199e933f4aSBenjamin Herrenschmidt 7209e933f4aSBenjamin Herrenschmidt /* load kernel */ 7219e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 7229e933f4aSBenjamin Herrenschmidt long kernel_size; 7239e933f4aSBenjamin Herrenschmidt 7249e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 725b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 7269e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 727802fc7abSThomas Huth error_report("Could not load kernel '%s'", 7289e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 7299e933f4aSBenjamin Herrenschmidt exit(1); 7309e933f4aSBenjamin Herrenschmidt } 7319e933f4aSBenjamin Herrenschmidt } 7329e933f4aSBenjamin Herrenschmidt 7339e933f4aSBenjamin Herrenschmidt /* load initrd */ 7349e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 7359e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 7369e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 737584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 7389e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 739802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 7409e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 7419e933f4aSBenjamin Herrenschmidt exit(1); 7429e933f4aSBenjamin Herrenschmidt } 7439e933f4aSBenjamin Herrenschmidt } 744e997040eSCédric Le Goater 745f30c843cSCédric Le Goater /* 746f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 747f30c843cSCédric Le Goater * default. 748f30c843cSCédric Le Goater */ 749f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 750f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 751f30c843cSCédric Le Goater machine->cpu_type, mc->name); 752f30c843cSCédric Le Goater exit(1); 753f30c843cSCédric Le Goater } 754f30c843cSCédric Le Goater 755e997040eSCédric Le Goater /* Create the processor chips */ 7564a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7577fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 7584a12c699SIgor Mammedov i, machine->cpu_type); 759e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 760f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 761f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 762e997040eSCédric Le Goater exit(1); 763e997040eSCédric Le Goater } 764e997040eSCédric Le Goater 765e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 766e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 767e997040eSCédric Le Goater char chip_name[32]; 768e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 769e997040eSCédric Le Goater 770e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 771e997040eSCédric Le Goater 77259b7c1c2SBalamuruhan S /* 77359b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 774e997040eSCédric Le Goater * way to specify different ranges for each chip 775e997040eSCédric Le Goater */ 776e997040eSCédric Le Goater if (i == 0) { 777e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 778e997040eSCédric Le Goater &error_fatal); 779e997040eSCédric Le Goater } 780e997040eSCédric Le Goater 781e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 782e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 783e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 784e997040eSCédric Le Goater &error_fatal); 785fe6b6346SLike Xu object_property_set_int(chip, machine->smp.cores, 786fe6b6346SLike Xu "nr-cores", &error_fatal); 787e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 788e997040eSCédric Le Goater } 789e997040eSCédric Le Goater g_free(chip_typename); 7903495b6b6SCédric Le Goater 791e2392d43SCédric Le Goater /* Create the machine BMC simulator */ 792e2392d43SCédric Le Goater pnv->bmc = pnv_bmc_create(); 793e2392d43SCédric Le Goater 7943495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 79504026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 7963495b6b6SCédric Le Goater 7973495b6b6SCédric Le Goater /* Create serial port */ 798def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 7993495b6b6SCédric Le Goater 8003495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 8016c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 802bce0b691SCédric Le Goater 803e2392d43SCédric Le Goater /* Create the IPMI BT device for communication with the BMC */ 804e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 805e2392d43SCédric Le Goater 80659b7c1c2SBalamuruhan S /* 80759b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 80859b7c1c2SBalamuruhan S * host to powerdown 80959b7c1c2SBalamuruhan S */ 810bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 811bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 812e997040eSCédric Le Goater } 813e997040eSCédric Le Goater 814631adaffSCédric Le Goater /* 815631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 816631adaffSCédric Le Goater * 22:24 Chip ID 817631adaffSCédric Le Goater * 25:28 Core number 818631adaffSCédric Le Goater * 29:31 Thread ID 819631adaffSCédric Le Goater */ 820631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 821631adaffSCédric Le Goater { 822631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 823631adaffSCédric Le Goater } 824631adaffSCédric Le Goater 8258fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 826d35aefa9SCédric Le Goater Error **errp) 827d35aefa9SCédric Le Goater { 8288fa1f4efSCédric Le Goater Error *local_err = NULL; 8298fa1f4efSCédric Le Goater Object *obj; 8308907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8318fa1f4efSCédric Le Goater 8328fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 8338fa1f4efSCédric Le Goater &local_err); 8348fa1f4efSCédric Le Goater if (local_err) { 8358fa1f4efSCédric Le Goater error_propagate(errp, local_err); 8368fa1f4efSCédric Le Goater return; 8378fa1f4efSCédric Le Goater } 8388fa1f4efSCédric Le Goater 839956b8f46SCédric Le Goater pnv_cpu->intc = obj; 840d35aefa9SCédric Le Goater } 841d35aefa9SCédric Le Goater 8420990ce6aSGreg Kurz 843d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 844d49e8a9bSCédric Le Goater { 845d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 846d49e8a9bSCédric Le Goater 847d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 848d49e8a9bSCédric Le Goater } 849d49e8a9bSCédric Le Goater 8500990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 8510990ce6aSGreg Kurz { 8520990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8530990ce6aSGreg Kurz 8540990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 8550990ce6aSGreg Kurz pnv_cpu->intc = NULL; 8560990ce6aSGreg Kurz } 8570990ce6aSGreg Kurz 85885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 85985913070SGreg Kurz Monitor *mon) 86085913070SGreg Kurz { 86185913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 86285913070SGreg Kurz } 86385913070SGreg Kurz 864631adaffSCédric Le Goater /* 865631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 866631adaffSCédric Le Goater * 49:52 Node ID 867631adaffSCédric Le Goater * 53:55 Chip ID 868631adaffSCédric Le Goater * 56 Reserved - Read as zero 869631adaffSCédric Le Goater * 57:61 Core number 870631adaffSCédric Le Goater * 62:63 Thread ID 871631adaffSCédric Le Goater * 872631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 873631adaffSCédric Le Goater */ 874631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 875631adaffSCédric Le Goater { 876631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 877631adaffSCédric Le Goater } 878631adaffSCédric Le Goater 8792b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 8802b548a42SCédric Le Goater { 8812b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 8822b548a42SCédric Le Goater } 8832b548a42SCédric Le Goater 8848fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 885d35aefa9SCédric Le Goater Error **errp) 886d35aefa9SCédric Le Goater { 8872dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 8882dfa91a2SCédric Le Goater Error *local_err = NULL; 8892dfa91a2SCédric Le Goater Object *obj; 8902dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8912dfa91a2SCédric Le Goater 8922dfa91a2SCédric Le Goater /* 8932dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 8942dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 8952dfa91a2SCédric Le Goater * only used at runtime. 8962dfa91a2SCédric Le Goater */ 89726aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 8982dfa91a2SCédric Le Goater if (local_err) { 8992dfa91a2SCédric Le Goater error_propagate(errp, local_err); 9008fa1f4efSCédric Le Goater return; 901d35aefa9SCédric Le Goater } 902d35aefa9SCédric Le Goater 9032dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 9042dfa91a2SCédric Le Goater } 9052dfa91a2SCédric Le Goater 906d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 907d49e8a9bSCédric Le Goater { 908d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 909d49e8a9bSCédric Le Goater 910d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 911d49e8a9bSCédric Le Goater } 912d49e8a9bSCédric Le Goater 9130990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9140990ce6aSGreg Kurz { 9150990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9160990ce6aSGreg Kurz 9170990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 9180990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9190990ce6aSGreg Kurz } 9200990ce6aSGreg Kurz 92185913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 92285913070SGreg Kurz Monitor *mon) 92385913070SGreg Kurz { 92485913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 92585913070SGreg Kurz } 92685913070SGreg Kurz 9272b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 9282b548a42SCédric Le Goater Error **errp) 9292b548a42SCédric Le Goater { 9302b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9312b548a42SCédric Le Goater 9322b548a42SCédric Le Goater /* Will be defined when the interrupt controller is */ 9332b548a42SCédric Le Goater pnv_cpu->intc = NULL; 9342b548a42SCédric Le Goater } 9352b548a42SCédric Le Goater 9362b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 9372b548a42SCédric Le Goater { 9382b548a42SCédric Le Goater ; 9392b548a42SCédric Le Goater } 9402b548a42SCédric Le Goater 9412b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9422b548a42SCédric Le Goater { 9432b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9442b548a42SCédric Le Goater 9452b548a42SCédric Le Goater pnv_cpu->intc = NULL; 9462b548a42SCédric Le Goater } 9472b548a42SCédric Le Goater 94885913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 94985913070SGreg Kurz Monitor *mon) 95085913070SGreg Kurz { 95185913070SGreg Kurz } 95285913070SGreg Kurz 95359b7c1c2SBalamuruhan S /* 95459b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 955397a79e7SCédric Le Goater * 956397a79e7SCédric Le Goater * <EX0 reserved> 957397a79e7SCédric Le Goater * EX1 - Venice only 958397a79e7SCédric Le Goater * EX2 - Venice only 959397a79e7SCédric Le Goater * EX3 - Venice only 960397a79e7SCédric Le Goater * EX4 961397a79e7SCédric Le Goater * EX5 962397a79e7SCédric Le Goater * EX6 963397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 964397a79e7SCédric Le Goater * EX9 - Venice only 965397a79e7SCédric Le Goater * EX10 - Venice only 966397a79e7SCédric Le Goater * EX11 - Venice only 967397a79e7SCédric Le Goater * EX12 968397a79e7SCédric Le Goater * EX13 969397a79e7SCédric Le Goater * EX14 970397a79e7SCédric Le Goater * <EX15 reserved> 971397a79e7SCédric Le Goater */ 972397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 973397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 974397a79e7SCédric Le Goater 975397a79e7SCédric Le Goater /* 97609279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 977397a79e7SCédric Le Goater */ 97809279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 979397a79e7SCédric Le Goater 9802b548a42SCédric Le Goater 9812b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 9822b548a42SCédric Le Goater 98377864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 98477864267SCédric Le Goater { 98577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 98677864267SCédric Le Goater 987f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 988ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 98977864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 99077864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 99177864267SCédric Le Goater 992f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 99382514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 99477864267SCédric Le Goater 995f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 9963233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 9973887d241SBalamuruhan S 9983887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), 9993887d241SBalamuruhan S TYPE_PNV8_HOMER, &error_abort, NULL); 100077864267SCédric Le Goater } 100177864267SCédric Le Goater 100277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 100377864267SCédric Le Goater { 100477864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 100577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 100677864267SCédric Le Goater int i, j; 100777864267SCédric Le Goater char *name; 100877864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 100977864267SCédric Le Goater 101077864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 101177864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 101277864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 101377864267SCédric Le Goater g_free(name); 101477864267SCédric Le Goater 101577864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 101677864267SCédric Le Goater 101777864267SCédric Le Goater /* Map the ICP registers for each thread */ 101877864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 10194fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 102077864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 102177864267SCédric Le Goater 102277864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 102377864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 102477864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 102577864267SCédric Le Goater 102677864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 102777864267SCédric Le Goater &icp->mmio); 102877864267SCédric Le Goater } 102977864267SCédric Le Goater } 103077864267SCédric Le Goater } 103177864267SCédric Le Goater 103277864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 103377864267SCédric Le Goater { 103477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 103577864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 103677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1037ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 103877864267SCédric Le Goater Error *local_err = NULL; 103977864267SCédric Le Goater 1040709044fdSCédric Le Goater /* XSCOM bridge is first */ 1041709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1042709044fdSCédric Le Goater if (local_err) { 1043709044fdSCédric Le Goater error_propagate(errp, local_err); 1044709044fdSCédric Le Goater return; 1045709044fdSCédric Le Goater } 1046709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1047709044fdSCédric Le Goater 104877864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 104977864267SCédric Le Goater if (local_err) { 105077864267SCédric Le Goater error_propagate(errp, local_err); 105177864267SCédric Le Goater return; 105277864267SCédric Le Goater } 105377864267SCédric Le Goater 105477864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 105577864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 105677864267SCédric Le Goater "bar", &error_fatal); 105777864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 105877864267SCédric Le Goater if (local_err) { 105977864267SCédric Le Goater error_propagate(errp, local_err); 106077864267SCédric Le Goater return; 106177864267SCédric Le Goater } 1062ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1063ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 106477864267SCédric Le Goater 106577864267SCédric Le Goater /* Create LPC controller */ 1066b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi", 1067b63f3893SGreg Kurz &error_abort); 106877864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 106977864267SCédric Le Goater &error_fatal); 107077864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 107177864267SCédric Le Goater 107264d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 107364d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 107464d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 107564d011d5SCédric Le Goater 107659b7c1c2SBalamuruhan S /* 107759b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 107859b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 107959b7c1c2SBalamuruhan S */ 108077864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 108177864267SCédric Le Goater if (local_err) { 108277864267SCédric Le Goater error_propagate(errp, local_err); 108377864267SCédric Le Goater return; 108477864267SCédric Le Goater } 108577864267SCédric Le Goater 108677864267SCédric Le Goater /* Create the simplified OCC model */ 1087ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi", 1088ee3d2713SGreg Kurz &error_abort); 108977864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 109077864267SCédric Le Goater if (local_err) { 109177864267SCédric Le Goater error_propagate(errp, local_err); 109277864267SCédric Le Goater return; 109377864267SCédric Le Goater } 109477864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1095f3db8266SBalamuruhan S 1096f3db8266SBalamuruhan S /* OCC SRAM model */ 10973a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1098f3db8266SBalamuruhan S &chip8->occ.sram_regs); 10993887d241SBalamuruhan S 11003887d241SBalamuruhan S /* HOMER */ 1101f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip", 1102f2582acfSGreg Kurz &error_abort); 11033887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip8->homer), true, "realized", 11043887d241SBalamuruhan S &local_err); 11053887d241SBalamuruhan S if (local_err) { 11063887d241SBalamuruhan S error_propagate(errp, local_err); 11073887d241SBalamuruhan S return; 11083887d241SBalamuruhan S } 11098f092316SCédric Le Goater /* Homer Xscom region */ 11108f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 11118f092316SCédric Le Goater 11128f092316SCédric Le Goater /* Homer mmio region */ 11133887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 11143887d241SBalamuruhan S &chip8->homer.regs); 111577864267SCédric Le Goater } 111677864267SCédric Le Goater 1117e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1118e997040eSCédric Le Goater { 1119e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1120e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1121e997040eSCédric Le Goater 1122e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 1123e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1124397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 1125631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1126d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1127d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11280990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 112985913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 113004026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1131eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1132d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1133c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 1134e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 113577864267SCédric Le Goater 113677864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 113777864267SCédric Le Goater &k->parent_realize); 1138e997040eSCédric Le Goater } 1139e997040eSCédric Le Goater 1140e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1141e997040eSCédric Le Goater { 1142e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1143e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1144e997040eSCédric Le Goater 1145e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 1146e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1147397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1148631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1149d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1150d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11510990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 115285913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 115304026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1154eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1155d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1156c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 1157e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 115877864267SCédric Le Goater 115977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 116077864267SCédric Le Goater &k->parent_realize); 1161e997040eSCédric Le Goater } 1162e997040eSCédric Le Goater 1163e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1164e997040eSCédric Le Goater { 1165e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1166e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1167e997040eSCédric Le Goater 1168e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 1169e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1170397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1171631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1172d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1173d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11740990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 117585913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 117604026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1177eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1178d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1179c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 1180e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 118177864267SCédric Le Goater 118277864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 118377864267SCédric Le Goater &k->parent_realize); 118477864267SCédric Le Goater } 118577864267SCédric Le Goater 118677864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 118777864267SCédric Le Goater { 11882dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 11892dfa91a2SCédric Le Goater 11902dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 11912dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 1192c38536bcSCédric Le Goater 1193c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1194c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 119515376c66SCédric Le Goater 119615376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 119715376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 11986598a70dSCédric Le Goater 11996598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 12006598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 12013887d241SBalamuruhan S 12023887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 12033887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 120477864267SCédric Le Goater } 120577864267SCédric Le Goater 12065dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 12075dad902cSCédric Le Goater { 12085dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 12095dad902cSCédric Le Goater int i; 12105dad902cSCédric Le Goater 12115dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 12125dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 12135dad902cSCédric Le Goater 12145dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 12155dad902cSCédric Le Goater char eq_name[32]; 12165dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 12174fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 12185dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 12195dad902cSCédric Le Goater 12205dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1221bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1222bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 12235dad902cSCédric Le Goater 12245dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 12255dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 12265dad902cSCédric Le Goater 12275dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 12285dad902cSCédric Le Goater &eq->xscom_regs); 12295dad902cSCédric Le Goater } 12305dad902cSCédric Le Goater } 12315dad902cSCédric Le Goater 123277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 123377864267SCédric Le Goater { 123477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 12352dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 12362dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1237c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 123877864267SCédric Le Goater Error *local_err = NULL; 123977864267SCédric Le Goater 1240709044fdSCédric Le Goater /* XSCOM bridge is first */ 1241709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1242709044fdSCédric Le Goater if (local_err) { 1243709044fdSCédric Le Goater error_propagate(errp, local_err); 1244709044fdSCédric Le Goater return; 1245709044fdSCédric Le Goater } 1246709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1247709044fdSCédric Le Goater 124877864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 124977864267SCédric Le Goater if (local_err) { 125077864267SCédric Le Goater error_propagate(errp, local_err); 125177864267SCédric Le Goater return; 125277864267SCédric Le Goater } 12532dfa91a2SCédric Le Goater 12545dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 12555dad902cSCédric Le Goater if (local_err) { 12565dad902cSCédric Le Goater error_propagate(errp, local_err); 12575dad902cSCédric Le Goater return; 12585dad902cSCédric Le Goater } 12595dad902cSCédric Le Goater 12602dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 12612dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 12622dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 12632dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 12642dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 12652dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 12662dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 12672dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 12682dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 12697ae54cc3SGreg Kurz object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", 12707ae54cc3SGreg Kurz &error_abort); 12712dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 12722dfa91a2SCédric Le Goater &local_err); 12732dfa91a2SCédric Le Goater if (local_err) { 12742dfa91a2SCédric Le Goater error_propagate(errp, local_err); 12752dfa91a2SCédric Le Goater return; 12762dfa91a2SCédric Le Goater } 12772dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 12782dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1279c38536bcSCédric Le Goater 1280c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1281c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1282c38536bcSCédric Le Goater "bar", &error_fatal); 1283c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1284c38536bcSCédric Le Goater if (local_err) { 1285c38536bcSCédric Le Goater error_propagate(errp, local_err); 1286c38536bcSCédric Le Goater return; 1287c38536bcSCédric Le Goater } 1288c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1289c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 129015376c66SCédric Le Goater 129115376c66SCédric Le Goater /* LPC */ 1292b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", 1293b63f3893SGreg Kurz &error_abort); 129415376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 129515376c66SCédric Le Goater if (local_err) { 129615376c66SCédric Le Goater error_propagate(errp, local_err); 129715376c66SCédric Le Goater return; 129815376c66SCédric Le Goater } 129915376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 130015376c66SCédric Le Goater &chip9->lpc.xscom_regs); 130115376c66SCédric Le Goater 130215376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 130315376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 13046598a70dSCédric Le Goater 13056598a70dSCédric Le Goater /* Create the simplified OCC model */ 1306ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", 1307ee3d2713SGreg Kurz &error_abort); 13086598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 13096598a70dSCédric Le Goater if (local_err) { 13106598a70dSCédric Le Goater error_propagate(errp, local_err); 13116598a70dSCédric Le Goater return; 13126598a70dSCédric Le Goater } 13136598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1314f3db8266SBalamuruhan S 1315f3db8266SBalamuruhan S /* OCC SRAM model */ 13163a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1317f3db8266SBalamuruhan S &chip9->occ.sram_regs); 13183887d241SBalamuruhan S 13193887d241SBalamuruhan S /* HOMER */ 1320f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", 1321f2582acfSGreg Kurz &error_abort); 13223887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 13233887d241SBalamuruhan S &local_err); 13243887d241SBalamuruhan S if (local_err) { 13253887d241SBalamuruhan S error_propagate(errp, local_err); 13263887d241SBalamuruhan S return; 13273887d241SBalamuruhan S } 13288f092316SCédric Le Goater /* Homer Xscom region */ 13298f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 13308f092316SCédric Le Goater 13318f092316SCédric Le Goater /* Homer mmio region */ 13323887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 13333887d241SBalamuruhan S &chip9->homer.regs); 1334e997040eSCédric Le Goater } 1335e997040eSCédric Le Goater 1336e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1337e997040eSCédric Le Goater { 1338e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1339e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1340e997040eSCédric Le Goater 1341e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 134283028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1343397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1344631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1345d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1346d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 13470990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 134885913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 134904026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1350eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1351d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1352c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 1353e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 135477864267SCédric Le Goater 135577864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 135677864267SCédric Le Goater &k->parent_realize); 1357e997040eSCédric Le Goater } 1358e997040eSCédric Le Goater 13592b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 13602b548a42SCédric Le Goater { 13618b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 13628b50ce85SCédric Le Goater 13638b50ce85SCédric Le Goater object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), 13648b50ce85SCédric Le Goater TYPE_PNV10_PSI, &error_abort, NULL); 13652661f6abSCédric Le Goater object_initialize_child(obj, "lpc", &chip10->lpc, sizeof(chip10->lpc), 13662661f6abSCédric Le Goater TYPE_PNV10_LPC, &error_abort, NULL); 13672b548a42SCédric Le Goater } 13682b548a42SCédric Le Goater 13692b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 13702b548a42SCédric Le Goater { 13712b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 13722b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 13738b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 13742b548a42SCédric Le Goater Error *local_err = NULL; 13752b548a42SCédric Le Goater 13762b548a42SCédric Le Goater /* XSCOM bridge is first */ 13772b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 13782b548a42SCédric Le Goater if (local_err) { 13792b548a42SCédric Le Goater error_propagate(errp, local_err); 13802b548a42SCédric Le Goater return; 13812b548a42SCédric Le Goater } 13822b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 13832b548a42SCédric Le Goater 13842b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 13852b548a42SCédric Le Goater if (local_err) { 13862b548a42SCédric Le Goater error_propagate(errp, local_err); 13872b548a42SCédric Le Goater return; 13882b548a42SCédric Le Goater } 13898b50ce85SCédric Le Goater 13908b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 13918b50ce85SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), 13928b50ce85SCédric Le Goater "bar", &error_fatal); 13938b50ce85SCédric Le Goater object_property_set_bool(OBJECT(&chip10->psi), true, "realized", 13948b50ce85SCédric Le Goater &local_err); 13958b50ce85SCédric Le Goater if (local_err) { 13968b50ce85SCédric Le Goater error_propagate(errp, local_err); 13978b50ce85SCédric Le Goater return; 13988b50ce85SCédric Le Goater } 13998b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 14008b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 14012661f6abSCédric Le Goater 14022661f6abSCédric Le Goater /* LPC */ 14032661f6abSCédric Le Goater object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi", 14042661f6abSCédric Le Goater &error_abort); 14052661f6abSCédric Le Goater object_property_set_bool(OBJECT(&chip10->lpc), true, "realized", 14062661f6abSCédric Le Goater &local_err); 14072661f6abSCédric Le Goater if (local_err) { 14082661f6abSCédric Le Goater error_propagate(errp, local_err); 14092661f6abSCédric Le Goater return; 14102661f6abSCédric Le Goater } 14112661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 14122661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 14132661f6abSCédric Le Goater 14142661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 14152661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 14162b548a42SCédric Le Goater } 14172b548a42SCédric Le Goater 14182b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 14192b548a42SCédric Le Goater { 14202b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 14212b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 14222b548a42SCédric Le Goater 14232b548a42SCédric Le Goater k->chip_type = PNV_CHIP_POWER10; 14242b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 14252b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 14262b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 14272b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 14282b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 14292b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 143085913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 14312b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 14322b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 14332b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1434c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 14352b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 14362b548a42SCédric Le Goater 14372b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 14382b548a42SCédric Le Goater &k->parent_realize); 14392b548a42SCédric Le Goater } 14402b548a42SCédric Le Goater 1441397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1442397a79e7SCédric Le Goater { 1443397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1444397a79e7SCédric Le Goater int cores_max; 1445397a79e7SCédric Le Goater 1446397a79e7SCédric Le Goater /* 1447397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1448397a79e7SCédric Le Goater * the chip class 1449397a79e7SCédric Le Goater */ 1450397a79e7SCédric Le Goater if (!chip->cores_mask) { 1451397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1452397a79e7SCédric Le Goater } 1453397a79e7SCédric Le Goater 1454397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1455397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1456397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1457397a79e7SCédric Le Goater chip->cores_mask); 1458397a79e7SCédric Le Goater return; 1459397a79e7SCédric Le Goater } 1460397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1461397a79e7SCédric Le Goater 1462397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 146327d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1464397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1465397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1466397a79e7SCédric Le Goater cores_max); 1467397a79e7SCédric Le Goater return; 1468397a79e7SCédric Le Goater } 1469397a79e7SCédric Le Goater } 1470397a79e7SCédric Le Goater 147151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1472e997040eSCédric Le Goater { 1473fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1474397a79e7SCédric Le Goater Error *error = NULL; 1475d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 147640abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1477d2fd9612SCédric Le Goater int i, core_hwid; 1478397a79e7SCédric Le Goater 1479d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1480d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1481d2fd9612SCédric Le Goater return; 1482d2fd9612SCédric Le Goater } 1483d2fd9612SCédric Le Goater 1484d2fd9612SCédric Le Goater /* Cores */ 1485397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1486397a79e7SCédric Le Goater if (error) { 1487397a79e7SCédric Le Goater error_propagate(errp, error); 1488397a79e7SCédric Le Goater return; 1489397a79e7SCédric Le Goater } 1490d2fd9612SCédric Le Goater 14914fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1492d2fd9612SCédric Le Goater 1493d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1494d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1495d2fd9612SCédric Le Goater char core_name[32]; 14964fa28f23SGreg Kurz PnvCore *pnv_core; 1497c035851aSCédric Le Goater uint64_t xscom_core_base; 1498d2fd9612SCédric Le Goater 1499d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1500d2fd9612SCédric Le Goater continue; 1501d2fd9612SCédric Le Goater } 1502d2fd9612SCédric Le Goater 15034fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 15044fa28f23SGreg Kurz 1505d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 15064fa28f23SGreg Kurz object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), 15074fa28f23SGreg Kurz &error_abort); 15084fa28f23SGreg Kurz chip->cores[i] = pnv_core; 1509fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1510d2fd9612SCédric Le Goater &error_fatal); 1511d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1512d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1513d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1514d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1515d2fd9612SCédric Le Goater "pir", &error_fatal); 1516158e17a6SGreg Kurz object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", 1517158e17a6SGreg Kurz &error_abort); 1518d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1519d2fd9612SCédric Le Goater &error_fatal); 152024ece072SCédric Le Goater 152124ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1522c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1523c035851aSCédric Le Goater 1524c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 15254fa28f23SGreg Kurz &pnv_core->xscom_regs); 1526d2fd9612SCédric Le Goater i++; 1527d2fd9612SCédric Le Goater } 152851c04728SCédric Le Goater } 152951c04728SCédric Le Goater 153051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 153151c04728SCédric Le Goater { 153251c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 153351c04728SCédric Le Goater Error *error = NULL; 153451c04728SCédric Le Goater 153551c04728SCédric Le Goater /* Cores */ 153651c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 153751c04728SCédric Le Goater if (error) { 153851c04728SCédric Le Goater error_propagate(errp, error); 153951c04728SCédric Le Goater return; 154051c04728SCédric Le Goater } 1541e997040eSCédric Le Goater } 1542e997040eSCédric Le Goater 1543e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1544e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1545e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1546e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1547397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1548397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1549e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1550e997040eSCédric Le Goater }; 1551e997040eSCédric Le Goater 1552e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1553e997040eSCédric Le Goater { 1554e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1555e997040eSCédric Le Goater 15569d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1557e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1558e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1559e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1560e997040eSCédric Le Goater } 1561e997040eSCédric Le Goater 1562119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1563119eaa9dSCédric Le Goater { 1564119eaa9dSCédric Le Goater int i, j; 1565119eaa9dSCédric Le Goater 1566119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1567119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1568119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1569119eaa9dSCédric Le Goater 1570119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1571119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1572119eaa9dSCédric Le Goater return pc->threads[j]; 1573119eaa9dSCédric Le Goater } 1574119eaa9dSCédric Le Goater } 1575119eaa9dSCédric Le Goater } 1576119eaa9dSCédric Le Goater return NULL; 1577119eaa9dSCédric Le Goater } 1578119eaa9dSCédric Le Goater 157954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 158054f59d78SCédric Le Goater { 1581b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 158254f59d78SCédric Le Goater int i; 158354f59d78SCédric Le Goater 158454f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 158577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 158677864267SCédric Le Goater 158777864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 158877864267SCédric Le Goater return &chip8->psi.ics; 158954f59d78SCédric Le Goater } 159054f59d78SCédric Le Goater } 159154f59d78SCédric Le Goater return NULL; 159254f59d78SCédric Le Goater } 159354f59d78SCédric Le Goater 159454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 159554f59d78SCédric Le Goater { 1596b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 159754f59d78SCédric Le Goater int i; 159854f59d78SCédric Le Goater 159954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 160077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 160177864267SCédric Le Goater ics_resend(&chip8->psi.ics); 160254f59d78SCédric Le Goater } 160354f59d78SCédric Le Goater } 160454f59d78SCédric Le Goater 160536fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 160636fc6f08SCédric Le Goater { 160736fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 160836fc6f08SCédric Le Goater 1609956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 161036fc6f08SCédric Le Goater } 161136fc6f08SCédric Le Goater 161247fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 161347fea43aSCédric Le Goater Monitor *mon) 161447fea43aSCédric Le Goater { 1615b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 161654f59d78SCédric Le Goater int i; 161747fea43aSCédric Le Goater CPUState *cs; 161847fea43aSCédric Le Goater 161947fea43aSCédric Le Goater CPU_FOREACH(cs) { 162047fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 162147fea43aSCédric Le Goater 162285913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 162385913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 162485913070SGreg Kurz mon); 1625d8e4aad5SCédric Le Goater } 162654f59d78SCédric Le Goater 162754f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1628d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 162954f59d78SCédric Le Goater } 163047fea43aSCédric Le Goater } 163147fea43aSCédric Le Goater 1632c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1633c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1634c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1635c722579eSCédric Le Goater uint32_t logic_serv, 1636c722579eSCédric Le Goater XiveTCTXMatch *match) 1637c722579eSCédric Le Goater { 1638c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1639c722579eSCédric Le Goater int total_count = 0; 1640c722579eSCédric Le Goater int i; 1641c722579eSCédric Le Goater 1642c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1643c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1644c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1645c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1646c722579eSCédric Le Goater int count; 1647c722579eSCédric Le Goater 1648c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1649c722579eSCédric Le Goater priority, logic_serv, match); 1650c722579eSCédric Le Goater 1651c722579eSCédric Le Goater if (count < 0) { 1652c722579eSCédric Le Goater return count; 1653c722579eSCédric Le Goater } 1654c722579eSCédric Le Goater 1655c722579eSCédric Le Goater total_count += count; 1656c722579eSCédric Le Goater } 1657c722579eSCédric Le Goater 1658c722579eSCédric Le Goater return total_count; 1659c722579eSCédric Le Goater } 1660c722579eSCédric Le Goater 16615373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id) 16625373c61dSCédric Le Goater { 16635373c61dSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 16645373c61dSCédric Le Goater int i; 16655373c61dSCédric Le Goater 16665373c61dSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 16675373c61dSCédric Le Goater PnvChip *chip = pnv->chips[i]; 16685373c61dSCédric Le Goater if (chip->chip_id == chip_id) { 16695373c61dSCédric Le Goater return chip; 16705373c61dSCédric Le Goater } 16715373c61dSCédric Le Goater } 16725373c61dSCédric Le Goater return NULL; 16735373c61dSCédric Le Goater } 16745373c61dSCédric Le Goater 1675e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1676e997040eSCédric Le Goater void *opaque, Error **errp) 1677e997040eSCédric Le Goater { 1678b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1679e997040eSCédric Le Goater } 1680e997040eSCédric Le Goater 1681e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1682e997040eSCédric Le Goater void *opaque, Error **errp) 1683e997040eSCédric Le Goater { 1684b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1685e997040eSCédric Le Goater uint32_t num_chips; 1686e997040eSCédric Le Goater Error *local_err = NULL; 1687e997040eSCédric Le Goater 1688e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1689e997040eSCédric Le Goater if (local_err) { 1690e997040eSCédric Le Goater error_propagate(errp, local_err); 1691e997040eSCédric Le Goater return; 1692e997040eSCédric Le Goater } 1693e997040eSCédric Le Goater 1694e997040eSCédric Le Goater /* 1695e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1696e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1697e997040eSCédric Le Goater */ 1698e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1699e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1700e997040eSCédric Le Goater return; 1701e997040eSCédric Le Goater } 1702e997040eSCédric Le Goater 1703e997040eSCédric Le Goater pnv->num_chips = num_chips; 1704e997040eSCédric Le Goater } 1705e997040eSCédric Le Goater 170677864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1707e997040eSCédric Le Goater { 1708b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1709e997040eSCédric Le Goater pnv->num_chips = 1; 1710e997040eSCédric Le Goater } 1711e997040eSCédric Le Goater 1712b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1713e997040eSCédric Le Goater { 17141e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1715e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1716e997040eSCédric Le Goater NULL, NULL, NULL); 1717e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1718e997040eSCédric Le Goater "Specifies the number of processor chips", 1719e997040eSCédric Le Goater NULL); 17209e933f4aSBenjamin Herrenschmidt } 17219e933f4aSBenjamin Herrenschmidt 1722f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 17239e933f4aSBenjamin Herrenschmidt { 17249e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 172536fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1726d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1727d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 1728f30c843cSCédric Le Goater 1729f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1730f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1731f30c843cSCédric Le Goater 1732f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1733f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1734f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1735d76f2da7SGreg Kurz 1736d76f2da7SGreg Kurz pmc->compat = compat; 1737d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 1738f30c843cSCédric Le Goater } 1739f30c843cSCédric Le Goater 1740f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1741f30c843cSCédric Le Goater { 1742f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1743c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1744d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1745d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 1746f30c843cSCédric Le Goater 1747f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1748f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1749c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1750f30c843cSCédric Le Goater 1751f30c843cSCédric Le Goater mc->alias = "powernv"; 1752d76f2da7SGreg Kurz 1753d76f2da7SGreg Kurz pmc->compat = compat; 1754d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 17557a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 1756f30c843cSCédric Le Goater } 1757f30c843cSCédric Le Goater 17582b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 17592b548a42SCédric Le Goater { 17602b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1761d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1762d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 17632b548a42SCédric Le Goater 17642b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 17652b548a42SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); 1766d76f2da7SGreg Kurz 1767d76f2da7SGreg Kurz pmc->compat = compat; 1768d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 17697a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 17702b548a42SCédric Le Goater } 17712b548a42SCédric Le Goater 1772f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1773f30c843cSCédric Le Goater { 1774f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 177547fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 17769e933f4aSBenjamin Herrenschmidt 17779e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1778b168a138SCédric Le Goater mc->init = pnv_init; 1779b168a138SCédric Le Goater mc->reset = pnv_reset; 17809e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 178159b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 178259b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 17839e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 17849e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1785f1d18b0aSJoel Stanley /* 1786f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1787f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1788f1d18b0aSJoel Stanley */ 1789f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 179047fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1791e997040eSCédric Le Goater 1792b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 17939e933f4aSBenjamin Herrenschmidt } 17949e933f4aSBenjamin Herrenschmidt 179577864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1796beba5c0fSIgor Mammedov { \ 1797beba5c0fSIgor Mammedov .name = type, \ 1798beba5c0fSIgor Mammedov .class_init = class_initfn, \ 179977864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 180077864267SCédric Le Goater } 180177864267SCédric Le Goater 180277864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 180377864267SCédric Le Goater { \ 180477864267SCédric Le Goater .name = type, \ 180577864267SCédric Le Goater .class_init = class_initfn, \ 180677864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1807beba5c0fSIgor Mammedov } 1808beba5c0fSIgor Mammedov 18092b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 18102b548a42SCédric Le Goater { \ 18112b548a42SCédric Le Goater .name = type, \ 18122b548a42SCédric Le Goater .class_init = class_initfn, \ 18132b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 18142b548a42SCédric Le Goater } 18152b548a42SCédric Le Goater 1816beba5c0fSIgor Mammedov static const TypeInfo types[] = { 18171aba8716SCédric Le Goater { 18182b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 18192b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18202b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 18212b548a42SCédric Le Goater }, 18222b548a42SCédric Le Goater { 18231aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 18241aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18251aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 1826c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 1827c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 1828c722579eSCédric Le Goater { }, 1829c722579eSCédric Le Goater }, 18301aba8716SCédric Le Goater }, 18311aba8716SCédric Le Goater { 18321aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 18331aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18341aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 18351aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 18361aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 18371aba8716SCédric Le Goater { }, 18381aba8716SCédric Le Goater }, 18391aba8716SCédric Le Goater }, 1840beba5c0fSIgor Mammedov { 1841b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 18429e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1843f30c843cSCédric Le Goater .abstract = true, 18449e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 184577864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1846b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 1847d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 184836fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 184947fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 185036fc6f08SCédric Le Goater { }, 185136fc6f08SCédric Le Goater }, 1852beba5c0fSIgor Mammedov }, 1853beba5c0fSIgor Mammedov { 1854beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1855beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1856beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1857beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1858beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1859beba5c0fSIgor Mammedov .abstract = true, 1860beba5c0fSIgor Mammedov }, 186177864267SCédric Le Goater 186277864267SCédric Le Goater /* 18632b548a42SCédric Le Goater * P10 chip and variants 18642b548a42SCédric Le Goater */ 18652b548a42SCédric Le Goater { 18662b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 18672b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 18682b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 18692b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 18702b548a42SCédric Le Goater }, 18712b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 18722b548a42SCédric Le Goater 18732b548a42SCédric Le Goater /* 187477864267SCédric Le Goater * P9 chip and variants 187577864267SCédric Le Goater */ 187677864267SCédric Le Goater { 187777864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 187877864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 187977864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 188077864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 188177864267SCédric Le Goater }, 188277864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 188377864267SCédric Le Goater 188477864267SCédric Le Goater /* 188577864267SCédric Le Goater * P8 chip and variants 188677864267SCédric Le Goater */ 188777864267SCédric Le Goater { 188877864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 188977864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 189077864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 189177864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 189277864267SCédric Le Goater }, 189377864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 189477864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 189577864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1896beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 18979e933f4aSBenjamin Herrenschmidt }; 18989e933f4aSBenjamin Herrenschmidt 1899beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1900