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 { 28340abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 284d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 285d2fd9612SCédric Le Goater int i; 286d2fd9612SCédric Le Goater 287b168a138SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 288967b7523SCédric Le Goater 289d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 290d2fd9612SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 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 const char *typename = pnv_chip_core_typename(chip); 306eb859a27SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 307eb859a27SCédric Le Goater int i; 308eb859a27SCédric Le Goater 309eb859a27SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 310eb859a27SCédric Le Goater 311eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 312eb859a27SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 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 32115376c66SCédric Le Goater pnv_dt_lpc(chip, fdt, 0); 322eb859a27SCédric Le Goater } 323eb859a27SCédric Le Goater 324b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 325c5ffdcaeSCédric Le Goater { 326c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 327c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 328c5ffdcaeSCédric Le Goater cpu_to_be32(1), 329c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 330c5ffdcaeSCédric Le Goater cpu_to_be32(2) 331c5ffdcaeSCédric Le Goater }; 332c5ffdcaeSCédric Le Goater char *name; 333c5ffdcaeSCédric Le Goater int node; 334c5ffdcaeSCédric Le Goater 335c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 336c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 337c5ffdcaeSCédric Le Goater _FDT(node); 338c5ffdcaeSCédric Le Goater g_free(name); 339c5ffdcaeSCédric Le Goater 340c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 341c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 342c5ffdcaeSCédric Le Goater } 343c5ffdcaeSCédric Le Goater 344b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 345cb228f5aSCédric Le Goater { 346cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 347cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 348cb228f5aSCédric Le Goater uint32_t io_regs[] = { 349cb228f5aSCédric Le Goater cpu_to_be32(1), 350cb228f5aSCédric Le Goater cpu_to_be32(io_base), 351cb228f5aSCédric Le Goater cpu_to_be32(8) 352cb228f5aSCédric Le Goater }; 353cb228f5aSCédric Le Goater char *name; 354cb228f5aSCédric Le Goater int node; 355cb228f5aSCédric Le Goater 356cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 357cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 358cb228f5aSCédric Le Goater _FDT(node); 359cb228f5aSCédric Le Goater g_free(name); 360cb228f5aSCédric Le Goater 361cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 362cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 363cb228f5aSCédric Le Goater sizeof(compatible)))); 364cb228f5aSCédric Le Goater 365cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 366cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 367cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 368cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 369cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 370cb228f5aSCédric Le Goater 371cb228f5aSCédric Le Goater /* This is needed by Linux */ 372cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 373cb228f5aSCédric Le Goater } 374cb228f5aSCédric Le Goater 375b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 37604f6c8b2SCédric Le Goater { 37704f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 37804f6c8b2SCédric Le Goater uint32_t io_base; 37904f6c8b2SCédric Le Goater uint32_t io_regs[] = { 38004f6c8b2SCédric Le Goater cpu_to_be32(1), 38104f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 38204f6c8b2SCédric Le Goater cpu_to_be32(3) 38304f6c8b2SCédric Le Goater }; 38404f6c8b2SCédric Le Goater uint32_t irq; 38504f6c8b2SCédric Le Goater char *name; 38604f6c8b2SCédric Le Goater int node; 38704f6c8b2SCédric Le Goater 38804f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 38904f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 39004f6c8b2SCédric Le Goater 39104f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 39204f6c8b2SCédric Le Goater 39304f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 39404f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 39504f6c8b2SCédric Le Goater _FDT(node); 39604f6c8b2SCédric Le Goater g_free(name); 39704f6c8b2SCédric Le Goater 3987032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 3997032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4007032d92aSCédric Le Goater sizeof(compatible)))); 40104f6c8b2SCédric Le Goater 40204f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 40304f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 40404f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 40504f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 40604f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 40704f6c8b2SCédric Le Goater } 40804f6c8b2SCédric Le Goater 409e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 410e7a3fee3SCédric Le Goater void *fdt; 411e7a3fee3SCédric Le Goater int offset; 412e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 413e7a3fee3SCédric Le Goater 414b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 415e7a3fee3SCédric Le Goater { 416c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 417c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 418c5ffdcaeSCédric Le Goater 419c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 420b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 421cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 422b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 42304f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 424b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 425c5ffdcaeSCédric Le Goater } else { 426c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 427c5ffdcaeSCédric Le Goater d->ioport_id); 428c5ffdcaeSCédric Le Goater } 429c5ffdcaeSCédric Le Goater 430e7a3fee3SCédric Le Goater return 0; 431e7a3fee3SCédric Le Goater } 432e7a3fee3SCédric Le Goater 43359b7c1c2SBalamuruhan S /* 43459b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 435bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 436bb7ab95cSCédric Le Goater */ 437bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 438bb7ab95cSCédric Le Goater { 43964d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 440e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 441e7a3fee3SCédric Le Goater .fdt = fdt, 442bb7ab95cSCédric Le Goater .offset = isa_offset, 443e7a3fee3SCédric Le Goater }; 444f47a08d1SCédric Le Goater uint32_t phandle; 445e7a3fee3SCédric Le Goater 446bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 447bb7ab95cSCédric Le Goater 448f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 449f47a08d1SCédric Le Goater assert(phandle > 0); 450f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 451f47a08d1SCédric Le Goater 45259b7c1c2SBalamuruhan S /* 45359b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 45459b7c1c2SBalamuruhan S * can not use object_child_foreach() 45559b7c1c2SBalamuruhan S */ 456bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 457bb7ab95cSCédric Le Goater &args); 458e7a3fee3SCédric Le Goater } 459e7a3fee3SCédric Le Goater 460e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt) 461e5694793SCédric Le Goater { 462e5694793SCédric Le Goater int off; 463e5694793SCédric Le Goater 464e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 465e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 466e5694793SCédric Le Goater 467e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 468e5694793SCédric Le Goater } 469e5694793SCédric Le Goater 470b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4719e933f4aSBenjamin Herrenschmidt { 47283b90bf0SCédric Le Goater const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 47383b90bf0SCédric Le Goater const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; 474b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 4759e933f4aSBenjamin Herrenschmidt void *fdt; 4769e933f4aSBenjamin Herrenschmidt char *buf; 4779e933f4aSBenjamin Herrenschmidt int off; 478e997040eSCédric Le Goater int i; 4799e933f4aSBenjamin Herrenschmidt 4809e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 4819e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 4829e933f4aSBenjamin Herrenschmidt 483ccb099b3SCédric Le Goater /* /qemu node */ 484ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 485ccb099b3SCédric Le Goater 4869e933f4aSBenjamin Herrenschmidt /* Root node */ 4879e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 4889e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 4899e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 4909e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 49183b90bf0SCédric Le Goater if (pnv_is_power9(pnv)) { 49283b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, 49383b90bf0SCédric Le Goater sizeof(plat_compat9)))); 49483b90bf0SCédric Le Goater } else { 49583b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8, 49683b90bf0SCédric Le Goater sizeof(plat_compat8)))); 49783b90bf0SCédric Le Goater } 49883b90bf0SCédric Le Goater 4999e933f4aSBenjamin Herrenschmidt 5009e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5019e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5029e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 5039e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5049e933f4aSBenjamin Herrenschmidt } 5059e933f4aSBenjamin Herrenschmidt g_free(buf); 5069e933f4aSBenjamin Herrenschmidt 5079e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5089e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5099e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5109e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5119e933f4aSBenjamin Herrenschmidt } 5129e933f4aSBenjamin Herrenschmidt 5139e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5149e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5159e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5169e933f4aSBenjamin Herrenschmidt 5179e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5189e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5199e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5209e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5219e933f4aSBenjamin Herrenschmidt } 5229e933f4aSBenjamin Herrenschmidt 523e997040eSCédric Le Goater /* Populate device tree for each chip */ 524e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 525eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 526e997040eSCédric Le Goater } 527e7a3fee3SCédric Le Goater 528e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 529bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 530aeaef83dSCédric Le Goater 531aeaef83dSCédric Le Goater if (pnv->bmc) { 532b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 533aeaef83dSCédric Le Goater } 534aeaef83dSCédric Le Goater 535e5694793SCédric Le Goater /* Create an extra node for power management on Power9 */ 536e5694793SCédric Le Goater if (pnv_is_power9(pnv)) { 537e5694793SCédric Le Goater pnv_dt_power_mgt(fdt); 538e5694793SCédric Le Goater } 539e5694793SCédric Le Goater 5409e933f4aSBenjamin Herrenschmidt return fdt; 5419e933f4aSBenjamin Herrenschmidt } 5429e933f4aSBenjamin Herrenschmidt 543bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 544bce0b691SCédric Le Goater { 545b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 546bce0b691SCédric Le Goater 547bce0b691SCédric Le Goater if (pnv->bmc) { 548bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 549bce0b691SCédric Le Goater } 550bce0b691SCédric Le Goater } 551bce0b691SCédric Le Goater 552a0628599SLike Xu static void pnv_reset(MachineState *machine) 5539e933f4aSBenjamin Herrenschmidt { 554b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5559e933f4aSBenjamin Herrenschmidt void *fdt; 556aeaef83dSCédric Le Goater Object *obj; 5579e933f4aSBenjamin Herrenschmidt 5589e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5599e933f4aSBenjamin Herrenschmidt 56059b7c1c2SBalamuruhan S /* 56159b7c1c2SBalamuruhan S * OpenPOWER systems have a BMC, which can be defined on the 562aeaef83dSCédric Le Goater * command line with: 563aeaef83dSCédric Le Goater * 564aeaef83dSCédric Le Goater * -device ipmi-bmc-sim,id=bmc0 565aeaef83dSCédric Le Goater * 566aeaef83dSCédric Le Goater * This is the internal simulator but it could also be an external 567aeaef83dSCédric Le Goater * BMC. 568aeaef83dSCédric Le Goater */ 569a1a636b8SCédric Le Goater obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL); 570aeaef83dSCédric Le Goater if (obj) { 571aeaef83dSCédric Le Goater pnv->bmc = IPMI_BMC(obj); 572aeaef83dSCédric Le Goater } 573aeaef83dSCédric Le Goater 574b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5759e933f4aSBenjamin Herrenschmidt 5769e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5779e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5789e933f4aSBenjamin Herrenschmidt 5798d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 5809e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5819e933f4aSBenjamin Herrenschmidt } 5829e933f4aSBenjamin Herrenschmidt 58304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5843495b6b6SCédric Le Goater { 58577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58677864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 58704026890SCédric Le Goater } 5883495b6b6SCédric Le Goater 58904026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 59004026890SCédric Le Goater { 59177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 59277864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 59304026890SCédric Le Goater } 5943495b6b6SCédric Le Goater 59504026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 59604026890SCédric Le Goater { 59715376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 59815376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 59904026890SCédric Le Goater } 6003495b6b6SCédric Le Goater 60104026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 60204026890SCédric Le Goater { 60304026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6043495b6b6SCédric Le Goater } 6053495b6b6SCédric Le Goater 606d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 607d8e4aad5SCédric Le Goater { 608d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 609d8e4aad5SCédric Le Goater 610d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 611d8e4aad5SCédric Le Goater } 612d8e4aad5SCédric Le Goater 613d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 614d8e4aad5SCédric Le Goater { 615d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 616d8e4aad5SCédric Le Goater 617d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 618c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 619d8e4aad5SCédric Le Goater } 620d8e4aad5SCédric Le Goater 621f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 622f30c843cSCédric Le Goater { 623f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 624f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 625f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 626f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 627f30c843cSCédric Le Goater 628f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 629f30c843cSCédric Le Goater } 630f30c843cSCédric Le Goater 631b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 6329e933f4aSBenjamin Herrenschmidt { 633b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 634f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 6359e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 6369e933f4aSBenjamin Herrenschmidt char *fw_filename; 6379e933f4aSBenjamin Herrenschmidt long fw_size; 638e997040eSCédric Le Goater int i; 639e997040eSCédric Le Goater char *chip_typename; 64035dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 64135dde576SCédric Le Goater DeviceState *dev; 6429e933f4aSBenjamin Herrenschmidt 6439e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 644d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 6453dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 6469e933f4aSBenjamin Herrenschmidt } 6479e933f4aSBenjamin Herrenschmidt 6489e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 649b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6509e933f4aSBenjamin Herrenschmidt machine->ram_size); 6519e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6529e933f4aSBenjamin Herrenschmidt 65335dde576SCédric Le Goater /* 65435dde576SCédric Le Goater * Create our simple PNOR device 65535dde576SCédric Le Goater */ 65635dde576SCédric Le Goater dev = qdev_create(NULL, TYPE_PNV_PNOR); 65735dde576SCédric Le Goater if (pnor) { 65835dde576SCédric Le Goater qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor), 65935dde576SCédric Le Goater &error_abort); 66035dde576SCédric Le Goater } 66135dde576SCédric Le Goater qdev_init_nofail(dev); 66235dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 66335dde576SCédric Le Goater 6649e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 6659e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 6669e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 6679e933f4aSBenjamin Herrenschmidt } 6689e933f4aSBenjamin Herrenschmidt 6699e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 67015fcedb2SCédric Le Goater if (!fw_filename) { 67115fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 67215fcedb2SCédric Le Goater exit(1); 67315fcedb2SCédric Le Goater } 6749e933f4aSBenjamin Herrenschmidt 6759e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 6769e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 67715fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 6789e933f4aSBenjamin Herrenschmidt exit(1); 6799e933f4aSBenjamin Herrenschmidt } 6809e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 6819e933f4aSBenjamin Herrenschmidt 6829e933f4aSBenjamin Herrenschmidt /* load kernel */ 6839e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 6849e933f4aSBenjamin Herrenschmidt long kernel_size; 6859e933f4aSBenjamin Herrenschmidt 6869e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 687b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 6889e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 689802fc7abSThomas Huth error_report("Could not load kernel '%s'", 6909e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 6919e933f4aSBenjamin Herrenschmidt exit(1); 6929e933f4aSBenjamin Herrenschmidt } 6939e933f4aSBenjamin Herrenschmidt } 6949e933f4aSBenjamin Herrenschmidt 6959e933f4aSBenjamin Herrenschmidt /* load initrd */ 6969e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 6979e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 6989e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 699584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 7009e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 701802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 7029e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 7039e933f4aSBenjamin Herrenschmidt exit(1); 7049e933f4aSBenjamin Herrenschmidt } 7059e933f4aSBenjamin Herrenschmidt } 706e997040eSCédric Le Goater 707f30c843cSCédric Le Goater /* 708f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 709f30c843cSCédric Le Goater * default. 710f30c843cSCédric Le Goater */ 711f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 712f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 713f30c843cSCédric Le Goater machine->cpu_type, mc->name); 714f30c843cSCédric Le Goater exit(1); 715f30c843cSCédric Le Goater } 716f30c843cSCédric Le Goater 717e997040eSCédric Le Goater /* Create the processor chips */ 7184a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7197fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 7204a12c699SIgor Mammedov i, machine->cpu_type); 721e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 722f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 723f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 724e997040eSCédric Le Goater exit(1); 725e997040eSCédric Le Goater } 726e997040eSCédric Le Goater 727e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 728e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 729e997040eSCédric Le Goater char chip_name[32]; 730e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 731e997040eSCédric Le Goater 732e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 733e997040eSCédric Le Goater 73459b7c1c2SBalamuruhan S /* 73559b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 736e997040eSCédric Le Goater * way to specify different ranges for each chip 737e997040eSCédric Le Goater */ 738e997040eSCédric Le Goater if (i == 0) { 739e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 740e997040eSCédric Le Goater &error_fatal); 741e997040eSCédric Le Goater } 742e997040eSCédric Le Goater 743e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 744e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 745e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 746e997040eSCédric Le Goater &error_fatal); 747fe6b6346SLike Xu object_property_set_int(chip, machine->smp.cores, 748fe6b6346SLike Xu "nr-cores", &error_fatal); 749e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 750e997040eSCédric Le Goater } 751e997040eSCédric Le Goater g_free(chip_typename); 7523495b6b6SCédric Le Goater 7533495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 75404026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 7553495b6b6SCédric Le Goater 7563495b6b6SCédric Le Goater /* Create serial port */ 757def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 7583495b6b6SCédric Le Goater 7593495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 7606c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 761bce0b691SCédric Le Goater 76259b7c1c2SBalamuruhan S /* 76359b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 76459b7c1c2SBalamuruhan S * host to powerdown 76559b7c1c2SBalamuruhan S */ 766bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 767bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 768e997040eSCédric Le Goater } 769e997040eSCédric Le Goater 770631adaffSCédric Le Goater /* 771631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 772631adaffSCédric Le Goater * 22:24 Chip ID 773631adaffSCédric Le Goater * 25:28 Core number 774631adaffSCédric Le Goater * 29:31 Thread ID 775631adaffSCédric Le Goater */ 776631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 777631adaffSCédric Le Goater { 778631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 779631adaffSCédric Le Goater } 780631adaffSCédric Le Goater 7818fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 782d35aefa9SCédric Le Goater Error **errp) 783d35aefa9SCédric Le Goater { 7848fa1f4efSCédric Le Goater Error *local_err = NULL; 7858fa1f4efSCédric Le Goater Object *obj; 7868907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 7878fa1f4efSCédric Le Goater 7888fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 7898fa1f4efSCédric Le Goater &local_err); 7908fa1f4efSCédric Le Goater if (local_err) { 7918fa1f4efSCédric Le Goater error_propagate(errp, local_err); 7928fa1f4efSCédric Le Goater return; 7938fa1f4efSCédric Le Goater } 7948fa1f4efSCédric Le Goater 795956b8f46SCédric Le Goater pnv_cpu->intc = obj; 796d35aefa9SCédric Le Goater } 797d35aefa9SCédric Le Goater 7980990ce6aSGreg Kurz 799d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 800d49e8a9bSCédric Le Goater { 801d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 802d49e8a9bSCédric Le Goater 803d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 804d49e8a9bSCédric Le Goater } 805d49e8a9bSCédric Le Goater 8060990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 8070990ce6aSGreg Kurz { 8080990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8090990ce6aSGreg Kurz 8100990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 8110990ce6aSGreg Kurz pnv_cpu->intc = NULL; 8120990ce6aSGreg Kurz } 8130990ce6aSGreg Kurz 814631adaffSCédric Le Goater /* 815631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 816631adaffSCédric Le Goater * 49:52 Node ID 817631adaffSCédric Le Goater * 53:55 Chip ID 818631adaffSCédric Le Goater * 56 Reserved - Read as zero 819631adaffSCédric Le Goater * 57:61 Core number 820631adaffSCédric Le Goater * 62:63 Thread ID 821631adaffSCédric Le Goater * 822631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 823631adaffSCédric Le Goater */ 824631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 825631adaffSCédric Le Goater { 826631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 827631adaffSCédric Le Goater } 828631adaffSCédric Le Goater 8298fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 830d35aefa9SCédric Le Goater Error **errp) 831d35aefa9SCédric Le Goater { 8322dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 8332dfa91a2SCédric Le Goater Error *local_err = NULL; 8342dfa91a2SCédric Le Goater Object *obj; 8352dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8362dfa91a2SCédric Le Goater 8372dfa91a2SCédric Le Goater /* 8382dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 8392dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 8402dfa91a2SCédric Le Goater * only used at runtime. 8412dfa91a2SCédric Le Goater */ 84226aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 8432dfa91a2SCédric Le Goater if (local_err) { 8442dfa91a2SCédric Le Goater error_propagate(errp, local_err); 8458fa1f4efSCédric Le Goater return; 846d35aefa9SCédric Le Goater } 847d35aefa9SCédric Le Goater 8482dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 8492dfa91a2SCédric Le Goater } 8502dfa91a2SCédric Le Goater 851d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 852d49e8a9bSCédric Le Goater { 853d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 854d49e8a9bSCédric Le Goater 855d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 856d49e8a9bSCédric Le Goater } 857d49e8a9bSCédric Le Goater 8580990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 8590990ce6aSGreg Kurz { 8600990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8610990ce6aSGreg Kurz 8620990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 8630990ce6aSGreg Kurz pnv_cpu->intc = NULL; 8640990ce6aSGreg Kurz } 8650990ce6aSGreg Kurz 86659b7c1c2SBalamuruhan S /* 86759b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 868397a79e7SCédric Le Goater * 869397a79e7SCédric Le Goater * <EX0 reserved> 870397a79e7SCédric Le Goater * EX1 - Venice only 871397a79e7SCédric Le Goater * EX2 - Venice only 872397a79e7SCédric Le Goater * EX3 - Venice only 873397a79e7SCédric Le Goater * EX4 874397a79e7SCédric Le Goater * EX5 875397a79e7SCédric Le Goater * EX6 876397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 877397a79e7SCédric Le Goater * EX9 - Venice only 878397a79e7SCédric Le Goater * EX10 - Venice only 879397a79e7SCédric Le Goater * EX11 - Venice only 880397a79e7SCédric Le Goater * EX12 881397a79e7SCédric Le Goater * EX13 882397a79e7SCédric Le Goater * EX14 883397a79e7SCédric Le Goater * <EX15 reserved> 884397a79e7SCédric Le Goater */ 885397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 886397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 887397a79e7SCédric Le Goater 888397a79e7SCédric Le Goater /* 88909279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 890397a79e7SCédric Le Goater */ 89109279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 892397a79e7SCédric Le Goater 89377864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 89477864267SCédric Le Goater { 89577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 89677864267SCédric Le Goater 897f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 898ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 89977864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 90077864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 90177864267SCédric Le Goater 902f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 90382514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 90477864267SCédric Le Goater 905f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 9063233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 9073887d241SBalamuruhan S 9083887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), 9093887d241SBalamuruhan S TYPE_PNV8_HOMER, &error_abort, NULL); 91077864267SCédric Le Goater } 91177864267SCédric Le Goater 91277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 91377864267SCédric Le Goater { 91477864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 91577864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 91677864267SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 91777864267SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 91877864267SCédric Le Goater int i, j; 91977864267SCédric Le Goater char *name; 92077864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 92177864267SCédric Le Goater 92277864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 92377864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 92477864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 92577864267SCédric Le Goater g_free(name); 92677864267SCédric Le Goater 92777864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 92877864267SCédric Le Goater 92977864267SCédric Le Goater /* Map the ICP registers for each thread */ 93077864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 93177864267SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 93277864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 93377864267SCédric Le Goater 93477864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 93577864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 93677864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 93777864267SCédric Le Goater 93877864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 93977864267SCédric Le Goater &icp->mmio); 94077864267SCédric Le Goater } 94177864267SCédric Le Goater } 94277864267SCédric Le Goater } 94377864267SCédric Le Goater 94477864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 94577864267SCédric Le Goater { 94677864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 94777864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 94877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 949ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 95077864267SCédric Le Goater Error *local_err = NULL; 95177864267SCédric Le Goater 952709044fdSCédric Le Goater /* XSCOM bridge is first */ 953709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 954709044fdSCédric Le Goater if (local_err) { 955709044fdSCédric Le Goater error_propagate(errp, local_err); 956709044fdSCédric Le Goater return; 957709044fdSCédric Le Goater } 958709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 959709044fdSCédric Le Goater 96077864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 96177864267SCédric Le Goater if (local_err) { 96277864267SCédric Le Goater error_propagate(errp, local_err); 96377864267SCédric Le Goater return; 96477864267SCédric Le Goater } 96577864267SCédric Le Goater 96677864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 96777864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 96877864267SCédric Le Goater "bar", &error_fatal); 96977864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 97077864267SCédric Le Goater if (local_err) { 97177864267SCédric Le Goater error_propagate(errp, local_err); 97277864267SCédric Le Goater return; 97377864267SCédric Le Goater } 974ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 975ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 97677864267SCédric Le Goater 97777864267SCédric Le Goater /* Create LPC controller */ 978b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi", 979b63f3893SGreg Kurz &error_abort); 98077864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 98177864267SCédric Le Goater &error_fatal); 98277864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 98377864267SCédric Le Goater 98464d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 98564d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 98664d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 98764d011d5SCédric Le Goater 98859b7c1c2SBalamuruhan S /* 98959b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 99059b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 99159b7c1c2SBalamuruhan S */ 99277864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 99377864267SCédric Le Goater if (local_err) { 99477864267SCédric Le Goater error_propagate(errp, local_err); 99577864267SCédric Le Goater return; 99677864267SCédric Le Goater } 99777864267SCédric Le Goater 99877864267SCédric Le Goater /* Create the simplified OCC model */ 999ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi", 1000ee3d2713SGreg Kurz &error_abort); 100177864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 100277864267SCédric Le Goater if (local_err) { 100377864267SCédric Le Goater error_propagate(errp, local_err); 100477864267SCédric Le Goater return; 100577864267SCédric Le Goater } 100677864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1007f3db8266SBalamuruhan S 1008f3db8266SBalamuruhan S /* OCC SRAM model */ 1009f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip), 1010f3db8266SBalamuruhan S &chip8->occ.sram_regs); 10113887d241SBalamuruhan S 10123887d241SBalamuruhan S /* HOMER */ 1013f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip", 1014f2582acfSGreg Kurz &error_abort); 10153887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip8->homer), true, "realized", 10163887d241SBalamuruhan S &local_err); 10173887d241SBalamuruhan S if (local_err) { 10183887d241SBalamuruhan S error_propagate(errp, local_err); 10193887d241SBalamuruhan S return; 10203887d241SBalamuruhan S } 10213887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 10223887d241SBalamuruhan S &chip8->homer.regs); 102377864267SCédric Le Goater } 102477864267SCédric Le Goater 1025e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1026e997040eSCédric Le Goater { 1027e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1028e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1029e997040eSCédric Le Goater 1030e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 1031e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1032397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 1033631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1034d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1035d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 10360990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 103704026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1038eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1039d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1040e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 104177864267SCédric Le Goater 104277864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 104377864267SCédric Le Goater &k->parent_realize); 1044e997040eSCédric Le Goater } 1045e997040eSCédric Le Goater 1046e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1047e997040eSCédric Le Goater { 1048e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1049e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1050e997040eSCédric Le Goater 1051e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 1052e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1053397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1054631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1055d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1056d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 10570990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 105804026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1059eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1060d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1061e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 106277864267SCédric Le Goater 106377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 106477864267SCédric Le Goater &k->parent_realize); 1065e997040eSCédric Le Goater } 1066e997040eSCédric Le Goater 1067e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1068e997040eSCédric Le Goater { 1069e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1070e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1071e997040eSCédric Le Goater 1072e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 1073e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1074397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1075631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1076d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1077d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 10780990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 107904026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1080eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1081d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1082e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 108377864267SCédric Le Goater 108477864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 108577864267SCédric Le Goater &k->parent_realize); 108677864267SCédric Le Goater } 108777864267SCédric Le Goater 108877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 108977864267SCédric Le Goater { 10902dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 10912dfa91a2SCédric Le Goater 10922dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 10932dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 1094c38536bcSCédric Le Goater 1095c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1096c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 109715376c66SCédric Le Goater 109815376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 109915376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 11006598a70dSCédric Le Goater 11016598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 11026598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 11033887d241SBalamuruhan S 11043887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 11053887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 110677864267SCédric Le Goater } 110777864267SCédric Le Goater 11085dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 11095dad902cSCédric Le Goater { 11105dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 11115dad902cSCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 11125dad902cSCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 11135dad902cSCédric Le Goater int i; 11145dad902cSCédric Le Goater 11155dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 11165dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 11175dad902cSCédric Le Goater 11185dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 11195dad902cSCédric Le Goater char eq_name[32]; 11205dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 11215dad902cSCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); 11225dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 11235dad902cSCédric Le Goater 11245dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1125bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1126bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 11275dad902cSCédric Le Goater 11285dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 11295dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 11305dad902cSCédric Le Goater 11315dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 11325dad902cSCédric Le Goater &eq->xscom_regs); 11335dad902cSCédric Le Goater } 11345dad902cSCédric Le Goater } 11355dad902cSCédric Le Goater 113677864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 113777864267SCédric Le Goater { 113877864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 11392dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 11402dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1141c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 114277864267SCédric Le Goater Error *local_err = NULL; 114377864267SCédric Le Goater 1144709044fdSCédric Le Goater /* XSCOM bridge is first */ 1145709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1146709044fdSCédric Le Goater if (local_err) { 1147709044fdSCédric Le Goater error_propagate(errp, local_err); 1148709044fdSCédric Le Goater return; 1149709044fdSCédric Le Goater } 1150709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1151709044fdSCédric Le Goater 115277864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 115377864267SCédric Le Goater if (local_err) { 115477864267SCédric Le Goater error_propagate(errp, local_err); 115577864267SCédric Le Goater return; 115677864267SCédric Le Goater } 11572dfa91a2SCédric Le Goater 11585dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 11595dad902cSCédric Le Goater if (local_err) { 11605dad902cSCédric Le Goater error_propagate(errp, local_err); 11615dad902cSCédric Le Goater return; 11625dad902cSCédric Le Goater } 11635dad902cSCédric Le Goater 11642dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 11652dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 11662dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 11672dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 11682dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 11692dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 11702dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 11712dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 11722dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 1173*7ae54cc3SGreg Kurz object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", 1174*7ae54cc3SGreg Kurz &error_abort); 11752dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 11762dfa91a2SCédric Le Goater &local_err); 11772dfa91a2SCédric Le Goater if (local_err) { 11782dfa91a2SCédric Le Goater error_propagate(errp, local_err); 11792dfa91a2SCédric Le Goater return; 11802dfa91a2SCédric Le Goater } 11812dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 11822dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1183c38536bcSCédric Le Goater 1184c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1185c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1186c38536bcSCédric Le Goater "bar", &error_fatal); 1187c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1188c38536bcSCédric Le Goater if (local_err) { 1189c38536bcSCédric Le Goater error_propagate(errp, local_err); 1190c38536bcSCédric Le Goater return; 1191c38536bcSCédric Le Goater } 1192c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1193c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 119415376c66SCédric Le Goater 119515376c66SCédric Le Goater /* LPC */ 1196b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", 1197b63f3893SGreg Kurz &error_abort); 119815376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 119915376c66SCédric Le Goater if (local_err) { 120015376c66SCédric Le Goater error_propagate(errp, local_err); 120115376c66SCédric Le Goater return; 120215376c66SCédric Le Goater } 120315376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 120415376c66SCédric Le Goater &chip9->lpc.xscom_regs); 120515376c66SCédric Le Goater 120615376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 120715376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 12086598a70dSCédric Le Goater 12096598a70dSCédric Le Goater /* Create the simplified OCC model */ 1210ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", 1211ee3d2713SGreg Kurz &error_abort); 12126598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 12136598a70dSCédric Le Goater if (local_err) { 12146598a70dSCédric Le Goater error_propagate(errp, local_err); 12156598a70dSCédric Le Goater return; 12166598a70dSCédric Le Goater } 12176598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1218f3db8266SBalamuruhan S 1219f3db8266SBalamuruhan S /* OCC SRAM model */ 1220f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip), 1221f3db8266SBalamuruhan S &chip9->occ.sram_regs); 12223887d241SBalamuruhan S 12233887d241SBalamuruhan S /* HOMER */ 1224f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", 1225f2582acfSGreg Kurz &error_abort); 12263887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 12273887d241SBalamuruhan S &local_err); 12283887d241SBalamuruhan S if (local_err) { 12293887d241SBalamuruhan S error_propagate(errp, local_err); 12303887d241SBalamuruhan S return; 12313887d241SBalamuruhan S } 12323887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 12333887d241SBalamuruhan S &chip9->homer.regs); 1234e997040eSCédric Le Goater } 1235e997040eSCédric Le Goater 1236e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1237e997040eSCédric Le Goater { 1238e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1239e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1240e997040eSCédric Le Goater 1241e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 124283028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1243397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1244631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1245d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1246d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 12470990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 124804026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1249eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1250d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1251e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 125277864267SCédric Le Goater 125377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 125477864267SCédric Le Goater &k->parent_realize); 1255e997040eSCédric Le Goater } 1256e997040eSCédric Le Goater 1257397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1258397a79e7SCédric Le Goater { 1259397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1260397a79e7SCédric Le Goater int cores_max; 1261397a79e7SCédric Le Goater 1262397a79e7SCédric Le Goater /* 1263397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1264397a79e7SCédric Le Goater * the chip class 1265397a79e7SCédric Le Goater */ 1266397a79e7SCédric Le Goater if (!chip->cores_mask) { 1267397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1268397a79e7SCédric Le Goater } 1269397a79e7SCédric Le Goater 1270397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1271397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1272397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1273397a79e7SCédric Le Goater chip->cores_mask); 1274397a79e7SCédric Le Goater return; 1275397a79e7SCédric Le Goater } 1276397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1277397a79e7SCédric Le Goater 1278397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 127927d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1280397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1281397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1282397a79e7SCédric Le Goater cores_max); 1283397a79e7SCédric Le Goater return; 1284397a79e7SCédric Le Goater } 1285397a79e7SCédric Le Goater } 1286397a79e7SCédric Le Goater 128751c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1288e997040eSCédric Le Goater { 1289fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1290397a79e7SCédric Le Goater Error *error = NULL; 1291d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 129240abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1293d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 1294d2fd9612SCédric Le Goater int i, core_hwid; 1295397a79e7SCédric Le Goater 1296d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1297d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1298d2fd9612SCédric Le Goater return; 1299d2fd9612SCédric Le Goater } 1300d2fd9612SCédric Le Goater 1301d2fd9612SCédric Le Goater /* Cores */ 1302397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1303397a79e7SCédric Le Goater if (error) { 1304397a79e7SCédric Le Goater error_propagate(errp, error); 1305397a79e7SCédric Le Goater return; 1306397a79e7SCédric Le Goater } 1307d2fd9612SCédric Le Goater 1308d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 1309d2fd9612SCédric Le Goater 1310d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1311d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1312d2fd9612SCédric Le Goater char core_name[32]; 1313d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 1314c035851aSCédric Le Goater uint64_t xscom_core_base; 1315d2fd9612SCédric Le Goater 1316d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1317d2fd9612SCédric Le Goater continue; 1318d2fd9612SCédric Le Goater } 1319d2fd9612SCédric Le Goater 1320d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1321bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize, 1322bc4c406cSPhilippe Mathieu-Daudé typename, &error_fatal, NULL); 1323fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1324d2fd9612SCédric Le Goater &error_fatal); 1325d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1326d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1327d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1328d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1329d2fd9612SCédric Le Goater "pir", &error_fatal); 1330158e17a6SGreg Kurz object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", 1331158e17a6SGreg Kurz &error_abort); 1332d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1333d2fd9612SCédric Le Goater &error_fatal); 133424ece072SCédric Le Goater 133524ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1336c035851aSCédric Le Goater if (!pnv_chip_is_power9(chip)) { 1337c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1338c035851aSCédric Le Goater } else { 13395dad902cSCédric Le Goater xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); 1340c035851aSCédric Le Goater } 1341c035851aSCédric Le Goater 1342c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 134324ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 1344d2fd9612SCédric Le Goater i++; 1345d2fd9612SCédric Le Goater } 134651c04728SCédric Le Goater } 134751c04728SCédric Le Goater 134851c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 134951c04728SCédric Le Goater { 135051c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 135151c04728SCédric Le Goater Error *error = NULL; 135251c04728SCédric Le Goater 135351c04728SCédric Le Goater /* Cores */ 135451c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 135551c04728SCédric Le Goater if (error) { 135651c04728SCédric Le Goater error_propagate(errp, error); 135751c04728SCédric Le Goater return; 135851c04728SCédric Le Goater } 1359e997040eSCédric Le Goater } 1360e997040eSCédric Le Goater 1361e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1362e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1363e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1364e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1365397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1366397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1367e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1368e997040eSCédric Le Goater }; 1369e997040eSCédric Le Goater 1370e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1371e997040eSCédric Le Goater { 1372e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1373e997040eSCédric Le Goater 13749d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1375e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1376e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1377e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1378e997040eSCédric Le Goater } 1379e997040eSCédric Le Goater 138054f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 138154f59d78SCédric Le Goater { 1382b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 138354f59d78SCédric Le Goater int i; 138454f59d78SCédric Le Goater 138554f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 138677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 138777864267SCédric Le Goater 138877864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 138977864267SCédric Le Goater return &chip8->psi.ics; 139054f59d78SCédric Le Goater } 139154f59d78SCédric Le Goater } 139254f59d78SCédric Le Goater return NULL; 139354f59d78SCédric Le Goater } 139454f59d78SCédric Le Goater 139554f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 139654f59d78SCédric Le Goater { 1397b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 139854f59d78SCédric Le Goater int i; 139954f59d78SCédric Le Goater 140054f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 140177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 140277864267SCédric Le Goater ics_resend(&chip8->psi.ics); 140354f59d78SCédric Le Goater } 140454f59d78SCédric Le Goater } 140554f59d78SCédric Le Goater 140636fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 140736fc6f08SCédric Le Goater { 140836fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 140936fc6f08SCédric Le Goater 1410956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 141136fc6f08SCédric Le Goater } 141236fc6f08SCédric Le Goater 141347fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 141447fea43aSCédric Le Goater Monitor *mon) 141547fea43aSCédric Le Goater { 1416b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 141754f59d78SCédric Le Goater int i; 141847fea43aSCédric Le Goater CPUState *cs; 141947fea43aSCédric Le Goater 142047fea43aSCédric Le Goater CPU_FOREACH(cs) { 142147fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 142247fea43aSCédric Le Goater 1423d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1424d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1425d8e4aad5SCédric Le Goater } else { 1426956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 142747fea43aSCédric Le Goater } 1428d8e4aad5SCédric Le Goater } 142954f59d78SCédric Le Goater 143054f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1431d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 143254f59d78SCédric Le Goater } 143347fea43aSCédric Le Goater } 143447fea43aSCédric Le Goater 1435e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1436e997040eSCédric Le Goater void *opaque, Error **errp) 1437e997040eSCédric Le Goater { 1438b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1439e997040eSCédric Le Goater } 1440e997040eSCédric Le Goater 1441e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1442e997040eSCédric Le Goater void *opaque, Error **errp) 1443e997040eSCédric Le Goater { 1444b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1445e997040eSCédric Le Goater uint32_t num_chips; 1446e997040eSCédric Le Goater Error *local_err = NULL; 1447e997040eSCédric Le Goater 1448e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1449e997040eSCédric Le Goater if (local_err) { 1450e997040eSCédric Le Goater error_propagate(errp, local_err); 1451e997040eSCédric Le Goater return; 1452e997040eSCédric Le Goater } 1453e997040eSCédric Le Goater 1454e997040eSCédric Le Goater /* 1455e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1456e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1457e997040eSCédric Le Goater */ 1458e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1459e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1460e997040eSCédric Le Goater return; 1461e997040eSCédric Le Goater } 1462e997040eSCédric Le Goater 1463e997040eSCédric Le Goater pnv->num_chips = num_chips; 1464e997040eSCédric Le Goater } 1465e997040eSCédric Le Goater 146677864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1467e997040eSCédric Le Goater { 1468b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1469e997040eSCédric Le Goater pnv->num_chips = 1; 1470e997040eSCédric Le Goater } 1471e997040eSCédric Le Goater 1472b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1473e997040eSCédric Le Goater { 14741e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1475e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1476e997040eSCédric Le Goater NULL, NULL, NULL); 1477e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1478e997040eSCédric Le Goater "Specifies the number of processor chips", 1479e997040eSCédric Le Goater NULL); 14809e933f4aSBenjamin Herrenschmidt } 14819e933f4aSBenjamin Herrenschmidt 1482f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 14839e933f4aSBenjamin Herrenschmidt { 14849e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 148536fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1486f30c843cSCédric Le Goater 1487f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1488f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1489f30c843cSCédric Le Goater 1490f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1491f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1492f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1493f30c843cSCédric Le Goater } 1494f30c843cSCédric Le Goater 1495f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1496f30c843cSCédric Le Goater { 1497f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1498f30c843cSCédric Le Goater 1499f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1500f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1501f30c843cSCédric Le Goater 1502f30c843cSCédric Le Goater mc->alias = "powernv"; 1503f30c843cSCédric Le Goater } 1504f30c843cSCédric Le Goater 1505f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1506f30c843cSCédric Le Goater { 1507f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 150847fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 15099e933f4aSBenjamin Herrenschmidt 15109e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1511b168a138SCédric Le Goater mc->init = pnv_init; 1512b168a138SCédric Le Goater mc->reset = pnv_reset; 15139e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 151459b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 151559b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 15169e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 15179e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1518f1d18b0aSJoel Stanley /* 1519f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1520f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1521f1d18b0aSJoel Stanley */ 1522f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 152347fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1524e997040eSCédric Le Goater 1525b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 15269e933f4aSBenjamin Herrenschmidt } 15279e933f4aSBenjamin Herrenschmidt 152877864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1529beba5c0fSIgor Mammedov { \ 1530beba5c0fSIgor Mammedov .name = type, \ 1531beba5c0fSIgor Mammedov .class_init = class_initfn, \ 153277864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 153377864267SCédric Le Goater } 153477864267SCédric Le Goater 153577864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 153677864267SCédric Le Goater { \ 153777864267SCédric Le Goater .name = type, \ 153877864267SCédric Le Goater .class_init = class_initfn, \ 153977864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1540beba5c0fSIgor Mammedov } 1541beba5c0fSIgor Mammedov 1542beba5c0fSIgor Mammedov static const TypeInfo types[] = { 15431aba8716SCédric Le Goater { 15441aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 15451aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 15461aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 15471aba8716SCédric Le Goater }, 15481aba8716SCédric Le Goater { 15491aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 15501aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 15511aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 15521aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 15531aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 15541aba8716SCédric Le Goater { }, 15551aba8716SCédric Le Goater }, 15561aba8716SCédric Le Goater }, 1557beba5c0fSIgor Mammedov { 1558b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 15599e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1560f30c843cSCédric Le Goater .abstract = true, 15619e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 156277864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1563b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 156436fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 156547fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 156636fc6f08SCédric Le Goater { }, 156736fc6f08SCédric Le Goater }, 1568beba5c0fSIgor Mammedov }, 1569beba5c0fSIgor Mammedov { 1570beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1571beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1572beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1573beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1574beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1575beba5c0fSIgor Mammedov .abstract = true, 1576beba5c0fSIgor Mammedov }, 157777864267SCédric Le Goater 157877864267SCédric Le Goater /* 157977864267SCédric Le Goater * P9 chip and variants 158077864267SCédric Le Goater */ 158177864267SCédric Le Goater { 158277864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 158377864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 158477864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 158577864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 158677864267SCédric Le Goater }, 158777864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 158877864267SCédric Le Goater 158977864267SCédric Le Goater /* 159077864267SCédric Le Goater * P8 chip and variants 159177864267SCédric Le Goater */ 159277864267SCédric Le Goater { 159377864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 159477864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 159577864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 159677864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 159777864267SCédric Le Goater }, 159877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 159977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 160077864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1601beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 16029e933f4aSBenjamin Herrenschmidt }; 16039e933f4aSBenjamin Herrenschmidt 1604beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1605