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" 47967b7523SCédric Le Goater 483495b6b6SCédric Le Goater #include "hw/isa/isa.h" 4912e9493dSMarkus Armbruster #include "hw/boards.h" 503495b6b6SCédric Le Goater #include "hw/char/serial.h" 51*bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 523495b6b6SCédric Le Goater 539e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 549e933f4aSBenjamin Herrenschmidt 55b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 569e933f4aSBenjamin Herrenschmidt 579e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 589e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 59b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 609e933f4aSBenjamin Herrenschmidt 619e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 62b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 63fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 64584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 659e933f4aSBenjamin Herrenschmidt 6640abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 6740abf43fSIgor Mammedov { 6840abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 6940abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7040abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7140abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7240abf43fSIgor Mammedov g_free(s); 7340abf43fSIgor Mammedov return core_type; 7440abf43fSIgor Mammedov } 7540abf43fSIgor Mammedov 769e933f4aSBenjamin Herrenschmidt /* 779e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 789e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 799e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 809e933f4aSBenjamin Herrenschmidt */ 819e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 829e933f4aSBenjamin Herrenschmidt 839e933f4aSBenjamin Herrenschmidt /* 849e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 859e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 869e933f4aSBenjamin Herrenschmidt * per chip. 879e933f4aSBenjamin Herrenschmidt */ 88b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 899e933f4aSBenjamin Herrenschmidt { 909e933f4aSBenjamin Herrenschmidt char *mem_name; 919e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 929e933f4aSBenjamin Herrenschmidt int off; 939e933f4aSBenjamin Herrenschmidt 949e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 959e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 969e933f4aSBenjamin Herrenschmidt 979e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 989e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 999e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1009e933f4aSBenjamin Herrenschmidt 1019e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1029e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1039e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1049e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1059e933f4aSBenjamin Herrenschmidt } 1069e933f4aSBenjamin Herrenschmidt 107d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 108d2fd9612SCédric Le Goater { 109d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 110d2fd9612SCédric Le Goater 111d2fd9612SCédric Le Goater if (cpus_offset < 0) { 112a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 113d2fd9612SCédric Le Goater if (cpus_offset) { 114d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 115d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 116d2fd9612SCédric Le Goater } 117d2fd9612SCédric Le Goater } 118d2fd9612SCédric Le Goater _FDT(cpus_offset); 119d2fd9612SCédric Le Goater return cpus_offset; 120d2fd9612SCédric Le Goater } 121d2fd9612SCédric Le Goater 122d2fd9612SCédric Le Goater /* 123d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 124d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 125d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 126d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 127d2fd9612SCédric Le Goater * servers. 128d2fd9612SCédric Le Goater */ 129b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 130d2fd9612SCédric Le Goater { 13108304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13208304a86SDavid Gibson CPUState *cs = CPU(cpu); 133d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1348bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 135d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 136d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 137d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 138d2fd9612SCédric Le Goater int i; 139d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 140d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 141d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 142d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 143d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 144d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 145d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 146d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 147d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 148d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 149d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 150d2fd9612SCédric Le Goater int offset; 151d2fd9612SCédric Le Goater char *nodename; 152d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 153d2fd9612SCédric Le Goater 154d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 155d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 156d2fd9612SCédric Le Goater _FDT(offset); 157d2fd9612SCédric Le Goater g_free(nodename); 158d2fd9612SCédric Le Goater 159d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 160d2fd9612SCédric Le Goater 161d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 162d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 164d2fd9612SCédric Le Goater 165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 167d2fd9612SCédric Le Goater env->dcache_line_size))); 168d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 169d2fd9612SCédric Le Goater env->dcache_line_size))); 170d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 171d2fd9612SCédric Le Goater env->icache_line_size))); 172d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 173d2fd9612SCédric Le Goater env->icache_line_size))); 174d2fd9612SCédric Le Goater 175d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 176d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 177d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 178d2fd9612SCédric Le Goater } else { 1793dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 180d2fd9612SCédric Le Goater } 181d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 182d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 183d2fd9612SCédric Le Goater pcc->l1_icache_size))); 184d2fd9612SCédric Le Goater } else { 1853dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 186d2fd9612SCédric Le Goater } 187d2fd9612SCédric Le Goater 188d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 189d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19059b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19159b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 192d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 193d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 194d2fd9612SCédric Le Goater 195d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 196d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 197d2fd9612SCédric Le Goater } 198d2fd9612SCédric Le Goater 19958969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 200d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 201d2fd9612SCédric Le Goater segs, sizeof(segs)))); 202d2fd9612SCédric Le Goater } 203d2fd9612SCédric Le Goater 20459b7c1c2SBalamuruhan S /* 20559b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 206d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 207d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 20859b7c1c2SBalamuruhan S * 2 == VSX available 20959b7c1c2SBalamuruhan S */ 210d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 211d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 212d2fd9612SCédric Le Goater 213d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 214d2fd9612SCédric Le Goater } 215d2fd9612SCédric Le Goater 21659b7c1c2SBalamuruhan S /* 21759b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 218d2fd9612SCédric Le Goater * 0 / no property == no DFP 21959b7c1c2SBalamuruhan S * 1 == DFP available 22059b7c1c2SBalamuruhan S */ 221d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 222d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 223d2fd9612SCédric Le Goater } 224d2fd9612SCédric Le Goater 225644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 226d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 227d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 228d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 229d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 230d2fd9612SCédric Le Goater } 231d2fd9612SCédric Le Goater 232d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 233d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 234d2fd9612SCédric Le Goater 235d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 236d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 237d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 238d2fd9612SCédric Le Goater } 239d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 240d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 241d2fd9612SCédric Le Goater } 242d2fd9612SCédric Le Goater 243b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 244bf5615e7SCédric Le Goater uint32_t nr_threads) 245bf5615e7SCédric Le Goater { 246bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 247bf5615e7SCédric Le Goater char *name; 248bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 249bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 250bf5615e7SCédric Le Goater uint64_t *reg; 251bf5615e7SCédric Le Goater int offset; 252bf5615e7SCédric Le Goater 253bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 254bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 255bf5615e7SCédric Le Goater 256bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 257bf5615e7SCédric Le Goater reg = g_malloc(rsize); 258bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 259bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 260bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 261bf5615e7SCédric Le Goater } 262bf5615e7SCédric Le Goater 263bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 264bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 265bf5615e7SCédric Le Goater _FDT(offset); 266bf5615e7SCédric Le Goater g_free(name); 267bf5615e7SCédric Le Goater 268bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 269bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 270bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 271bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 272bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 273bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 274bf5615e7SCédric Le Goater irange, sizeof(irange)))); 275bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 277bf5615e7SCédric Le Goater g_free(reg); 278bf5615e7SCédric Le Goater } 279bf5615e7SCédric Le Goater 280eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 281e997040eSCédric Le Goater { 28240abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 283d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 284d2fd9612SCédric Le Goater int i; 285d2fd9612SCédric Le Goater 286b168a138SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 287967b7523SCédric Le Goater 288d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 289d2fd9612SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 290d2fd9612SCédric Le Goater 291b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 292bf5615e7SCédric Le Goater 293bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 294b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 295d2fd9612SCédric Le Goater } 296d2fd9612SCédric Le Goater 297e997040eSCédric Le Goater if (chip->ram_size) { 298b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 299e997040eSCédric Le Goater } 300e997040eSCédric Le Goater } 301e997040eSCédric Le Goater 302eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 303eb859a27SCédric Le Goater { 304eb859a27SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 305eb859a27SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 306eb859a27SCédric Le Goater int i; 307eb859a27SCédric Le Goater 308eb859a27SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 309eb859a27SCédric Le Goater 310eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 311eb859a27SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 312eb859a27SCédric Le Goater 313eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 314eb859a27SCédric Le Goater } 315eb859a27SCédric Le Goater 316eb859a27SCédric Le Goater if (chip->ram_size) { 317eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 318eb859a27SCédric Le Goater } 31915376c66SCédric Le Goater 32015376c66SCédric Le Goater pnv_dt_lpc(chip, fdt, 0); 321eb859a27SCédric Le Goater } 322eb859a27SCédric Le Goater 323b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 324c5ffdcaeSCédric Le Goater { 325c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 326c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 327c5ffdcaeSCédric Le Goater cpu_to_be32(1), 328c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 329c5ffdcaeSCédric Le Goater cpu_to_be32(2) 330c5ffdcaeSCédric Le Goater }; 331c5ffdcaeSCédric Le Goater char *name; 332c5ffdcaeSCédric Le Goater int node; 333c5ffdcaeSCédric Le Goater 334c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 335c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 336c5ffdcaeSCédric Le Goater _FDT(node); 337c5ffdcaeSCédric Le Goater g_free(name); 338c5ffdcaeSCédric Le Goater 339c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 340c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 341c5ffdcaeSCédric Le Goater } 342c5ffdcaeSCédric Le Goater 343b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 344cb228f5aSCédric Le Goater { 345cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 346cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 347cb228f5aSCédric Le Goater uint32_t io_regs[] = { 348cb228f5aSCédric Le Goater cpu_to_be32(1), 349cb228f5aSCédric Le Goater cpu_to_be32(io_base), 350cb228f5aSCédric Le Goater cpu_to_be32(8) 351cb228f5aSCédric Le Goater }; 352cb228f5aSCédric Le Goater char *name; 353cb228f5aSCédric Le Goater int node; 354cb228f5aSCédric Le Goater 355cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 356cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 357cb228f5aSCédric Le Goater _FDT(node); 358cb228f5aSCédric Le Goater g_free(name); 359cb228f5aSCédric Le Goater 360cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 361cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 362cb228f5aSCédric Le Goater sizeof(compatible)))); 363cb228f5aSCédric Le Goater 364cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 365cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 366cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 367cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 368cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 369cb228f5aSCédric Le Goater 370cb228f5aSCédric Le Goater /* This is needed by Linux */ 371cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 372cb228f5aSCédric Le Goater } 373cb228f5aSCédric Le Goater 374b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 37504f6c8b2SCédric Le Goater { 37604f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 37704f6c8b2SCédric Le Goater uint32_t io_base; 37804f6c8b2SCédric Le Goater uint32_t io_regs[] = { 37904f6c8b2SCédric Le Goater cpu_to_be32(1), 38004f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 38104f6c8b2SCédric Le Goater cpu_to_be32(3) 38204f6c8b2SCédric Le Goater }; 38304f6c8b2SCédric Le Goater uint32_t irq; 38404f6c8b2SCédric Le Goater char *name; 38504f6c8b2SCédric Le Goater int node; 38604f6c8b2SCédric Le Goater 38704f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 38804f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 38904f6c8b2SCédric Le Goater 39004f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 39104f6c8b2SCédric Le Goater 39204f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 39304f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 39404f6c8b2SCédric Le Goater _FDT(node); 39504f6c8b2SCédric Le Goater g_free(name); 39604f6c8b2SCédric Le Goater 3977032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 3987032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 3997032d92aSCédric Le Goater sizeof(compatible)))); 40004f6c8b2SCédric Le Goater 40104f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 40204f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 40304f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 40404f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 40504f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 40604f6c8b2SCédric Le Goater } 40704f6c8b2SCédric Le Goater 408e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 409e7a3fee3SCédric Le Goater void *fdt; 410e7a3fee3SCédric Le Goater int offset; 411e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 412e7a3fee3SCédric Le Goater 413b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 414e7a3fee3SCédric Le Goater { 415c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 416c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 417c5ffdcaeSCédric Le Goater 418c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 419b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 420cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 421b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 42204f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 423b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 424c5ffdcaeSCédric Le Goater } else { 425c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 426c5ffdcaeSCédric Le Goater d->ioport_id); 427c5ffdcaeSCédric Le Goater } 428c5ffdcaeSCédric Le Goater 429e7a3fee3SCédric Le Goater return 0; 430e7a3fee3SCédric Le Goater } 431e7a3fee3SCédric Le Goater 43259b7c1c2SBalamuruhan S /* 43359b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 434bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 435bb7ab95cSCédric Le Goater */ 436bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 437bb7ab95cSCédric Le Goater { 43864d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 439e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 440e7a3fee3SCédric Le Goater .fdt = fdt, 441bb7ab95cSCédric Le Goater .offset = isa_offset, 442e7a3fee3SCédric Le Goater }; 443f47a08d1SCédric Le Goater uint32_t phandle; 444e7a3fee3SCédric Le Goater 445bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 446bb7ab95cSCédric Le Goater 447f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 448f47a08d1SCédric Le Goater assert(phandle > 0); 449f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 450f47a08d1SCédric Le Goater 45159b7c1c2SBalamuruhan S /* 45259b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 45359b7c1c2SBalamuruhan S * can not use object_child_foreach() 45459b7c1c2SBalamuruhan S */ 455bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 456bb7ab95cSCédric Le Goater &args); 457e7a3fee3SCédric Le Goater } 458e7a3fee3SCédric Le Goater 459e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt) 460e5694793SCédric Le Goater { 461e5694793SCédric Le Goater int off; 462e5694793SCédric Le Goater 463e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 464e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 465e5694793SCédric Le Goater 466e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 467e5694793SCédric Le Goater } 468e5694793SCédric Le Goater 469b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4709e933f4aSBenjamin Herrenschmidt { 47183b90bf0SCédric Le Goater const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 47283b90bf0SCédric Le Goater const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; 473b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 4749e933f4aSBenjamin Herrenschmidt void *fdt; 4759e933f4aSBenjamin Herrenschmidt char *buf; 4769e933f4aSBenjamin Herrenschmidt int off; 477e997040eSCédric Le Goater int i; 4789e933f4aSBenjamin Herrenschmidt 4799e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 4809e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 4819e933f4aSBenjamin Herrenschmidt 4829e933f4aSBenjamin Herrenschmidt /* Root node */ 4839e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 4849e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 4859e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 4869e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 48783b90bf0SCédric Le Goater if (pnv_is_power9(pnv)) { 48883b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, 48983b90bf0SCédric Le Goater sizeof(plat_compat9)))); 49083b90bf0SCédric Le Goater } else { 49183b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8, 49283b90bf0SCédric Le Goater sizeof(plat_compat8)))); 49383b90bf0SCédric Le Goater } 49483b90bf0SCédric Le Goater 4959e933f4aSBenjamin Herrenschmidt 4969e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 4979e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 4989e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 4999e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5009e933f4aSBenjamin Herrenschmidt } 5019e933f4aSBenjamin Herrenschmidt g_free(buf); 5029e933f4aSBenjamin Herrenschmidt 5039e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5049e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5059e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5069e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5079e933f4aSBenjamin Herrenschmidt } 5089e933f4aSBenjamin Herrenschmidt 5099e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5109e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5119e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5129e933f4aSBenjamin Herrenschmidt 5139e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5149e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5159e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5169e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5179e933f4aSBenjamin Herrenschmidt } 5189e933f4aSBenjamin Herrenschmidt 519e997040eSCédric Le Goater /* Populate device tree for each chip */ 520e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 521eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 522e997040eSCédric Le Goater } 523e7a3fee3SCédric Le Goater 524e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 525bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 526aeaef83dSCédric Le Goater 527aeaef83dSCédric Le Goater if (pnv->bmc) { 528b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 529aeaef83dSCédric Le Goater } 530aeaef83dSCédric Le Goater 531e5694793SCédric Le Goater /* Create an extra node for power management on Power9 */ 532e5694793SCédric Le Goater if (pnv_is_power9(pnv)) { 533e5694793SCédric Le Goater pnv_dt_power_mgt(fdt); 534e5694793SCédric Le Goater } 535e5694793SCédric Le Goater 5369e933f4aSBenjamin Herrenschmidt return fdt; 5379e933f4aSBenjamin Herrenschmidt } 5389e933f4aSBenjamin Herrenschmidt 539bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 540bce0b691SCédric Le Goater { 541b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 542bce0b691SCédric Le Goater 543bce0b691SCédric Le Goater if (pnv->bmc) { 544bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 545bce0b691SCédric Le Goater } 546bce0b691SCédric Le Goater } 547bce0b691SCédric Le Goater 548a0628599SLike Xu static void pnv_reset(MachineState *machine) 5499e933f4aSBenjamin Herrenschmidt { 550b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5519e933f4aSBenjamin Herrenschmidt void *fdt; 552aeaef83dSCédric Le Goater Object *obj; 5539e933f4aSBenjamin Herrenschmidt 5549e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5559e933f4aSBenjamin Herrenschmidt 55659b7c1c2SBalamuruhan S /* 55759b7c1c2SBalamuruhan S * OpenPOWER systems have a BMC, which can be defined on the 558aeaef83dSCédric Le Goater * command line with: 559aeaef83dSCédric Le Goater * 560aeaef83dSCédric Le Goater * -device ipmi-bmc-sim,id=bmc0 561aeaef83dSCédric Le Goater * 562aeaef83dSCédric Le Goater * This is the internal simulator but it could also be an external 563aeaef83dSCédric Le Goater * BMC. 564aeaef83dSCédric Le Goater */ 565a1a636b8SCédric Le Goater obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL); 566aeaef83dSCédric Le Goater if (obj) { 567aeaef83dSCédric Le Goater pnv->bmc = IPMI_BMC(obj); 568aeaef83dSCédric Le Goater } 569aeaef83dSCédric Le Goater 570b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5719e933f4aSBenjamin Herrenschmidt 5729e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5739e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5749e933f4aSBenjamin Herrenschmidt 5758d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 5769e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5779e933f4aSBenjamin Herrenschmidt } 5789e933f4aSBenjamin Herrenschmidt 57904026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5803495b6b6SCédric Le Goater { 58177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58277864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 58304026890SCédric Le Goater } 5843495b6b6SCédric Le Goater 58504026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 58604026890SCédric Le Goater { 58777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58877864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 58904026890SCédric Le Goater } 5903495b6b6SCédric Le Goater 59104026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 59204026890SCédric Le Goater { 59315376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 59415376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 59504026890SCédric Le Goater } 5963495b6b6SCédric Le Goater 59704026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 59804026890SCédric Le Goater { 59904026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6003495b6b6SCédric Le Goater } 6013495b6b6SCédric Le Goater 602d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 603d8e4aad5SCédric Le Goater { 604d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 605d8e4aad5SCédric Le Goater 606d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 607d8e4aad5SCédric Le Goater } 608d8e4aad5SCédric Le Goater 609d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 610d8e4aad5SCédric Le Goater { 611d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 612d8e4aad5SCédric Le Goater 613d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 614c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 615d8e4aad5SCédric Le Goater } 616d8e4aad5SCédric Le Goater 617f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 618f30c843cSCédric Le Goater { 619f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 620f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 621f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 622f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 623f30c843cSCédric Le Goater 624f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 625f30c843cSCédric Le Goater } 626f30c843cSCédric Le Goater 627b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 6289e933f4aSBenjamin Herrenschmidt { 629b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 630f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 6319e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 6329e933f4aSBenjamin Herrenschmidt char *fw_filename; 6339e933f4aSBenjamin Herrenschmidt long fw_size; 634e997040eSCédric Le Goater int i; 635e997040eSCédric Le Goater char *chip_typename; 6369e933f4aSBenjamin Herrenschmidt 6379e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 638d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 6393dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 6409e933f4aSBenjamin Herrenschmidt } 6419e933f4aSBenjamin Herrenschmidt 6429e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 643b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6449e933f4aSBenjamin Herrenschmidt machine->ram_size); 6459e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6469e933f4aSBenjamin Herrenschmidt 6479e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 6489e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 6499e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 6509e933f4aSBenjamin Herrenschmidt } 6519e933f4aSBenjamin Herrenschmidt 6529e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 65315fcedb2SCédric Le Goater if (!fw_filename) { 65415fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 65515fcedb2SCédric Le Goater exit(1); 65615fcedb2SCédric Le Goater } 6579e933f4aSBenjamin Herrenschmidt 6589e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 6599e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 66015fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 6619e933f4aSBenjamin Herrenschmidt exit(1); 6629e933f4aSBenjamin Herrenschmidt } 6639e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 6649e933f4aSBenjamin Herrenschmidt 6659e933f4aSBenjamin Herrenschmidt /* load kernel */ 6669e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 6679e933f4aSBenjamin Herrenschmidt long kernel_size; 6689e933f4aSBenjamin Herrenschmidt 6699e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 670b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 6719e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 672802fc7abSThomas Huth error_report("Could not load kernel '%s'", 6739e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 6749e933f4aSBenjamin Herrenschmidt exit(1); 6759e933f4aSBenjamin Herrenschmidt } 6769e933f4aSBenjamin Herrenschmidt } 6779e933f4aSBenjamin Herrenschmidt 6789e933f4aSBenjamin Herrenschmidt /* load initrd */ 6799e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 6809e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 6819e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 682584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 6839e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 684802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 6859e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 6869e933f4aSBenjamin Herrenschmidt exit(1); 6879e933f4aSBenjamin Herrenschmidt } 6889e933f4aSBenjamin Herrenschmidt } 689e997040eSCédric Le Goater 690f30c843cSCédric Le Goater /* 691f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 692f30c843cSCédric Le Goater * default. 693f30c843cSCédric Le Goater */ 694f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 695f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 696f30c843cSCédric Le Goater machine->cpu_type, mc->name); 697f30c843cSCédric Le Goater exit(1); 698f30c843cSCédric Le Goater } 699f30c843cSCédric Le Goater 700e997040eSCédric Le Goater /* Create the processor chips */ 7014a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7027fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 7034a12c699SIgor Mammedov i, machine->cpu_type); 704e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 705f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 706f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 707e997040eSCédric Le Goater exit(1); 708e997040eSCédric Le Goater } 709e997040eSCédric Le Goater 710e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 711e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 712e997040eSCédric Le Goater char chip_name[32]; 713e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 714e997040eSCédric Le Goater 715e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 716e997040eSCédric Le Goater 71759b7c1c2SBalamuruhan S /* 71859b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 719e997040eSCédric Le Goater * way to specify different ranges for each chip 720e997040eSCédric Le Goater */ 721e997040eSCédric Le Goater if (i == 0) { 722e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 723e997040eSCédric Le Goater &error_fatal); 724e997040eSCédric Le Goater } 725e997040eSCédric Le Goater 726e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 727e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 728e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 729e997040eSCédric Le Goater &error_fatal); 730fe6b6346SLike Xu object_property_set_int(chip, machine->smp.cores, 731fe6b6346SLike Xu "nr-cores", &error_fatal); 732e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 733e997040eSCédric Le Goater } 734e997040eSCédric Le Goater g_free(chip_typename); 7353495b6b6SCédric Le Goater 7363495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 73704026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 7383495b6b6SCédric Le Goater 7393495b6b6SCédric Le Goater /* Create serial port */ 740def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 7413495b6b6SCédric Le Goater 7423495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 7436c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 744bce0b691SCédric Le Goater 74559b7c1c2SBalamuruhan S /* 74659b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 74759b7c1c2SBalamuruhan S * host to powerdown 74859b7c1c2SBalamuruhan S */ 749bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 750bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 751e997040eSCédric Le Goater } 752e997040eSCédric Le Goater 753631adaffSCédric Le Goater /* 754631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 755631adaffSCédric Le Goater * 22:24 Chip ID 756631adaffSCédric Le Goater * 25:28 Core number 757631adaffSCédric Le Goater * 29:31 Thread ID 758631adaffSCédric Le Goater */ 759631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 760631adaffSCédric Le Goater { 761631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 762631adaffSCédric Le Goater } 763631adaffSCédric Le Goater 7648fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 765d35aefa9SCédric Le Goater Error **errp) 766d35aefa9SCédric Le Goater { 7678fa1f4efSCédric Le Goater Error *local_err = NULL; 7688fa1f4efSCédric Le Goater Object *obj; 7698907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 7708fa1f4efSCédric Le Goater 7718fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 7728fa1f4efSCédric Le Goater &local_err); 7738fa1f4efSCédric Le Goater if (local_err) { 7748fa1f4efSCédric Le Goater error_propagate(errp, local_err); 7758fa1f4efSCédric Le Goater return; 7768fa1f4efSCédric Le Goater } 7778fa1f4efSCédric Le Goater 778956b8f46SCédric Le Goater pnv_cpu->intc = obj; 779d35aefa9SCédric Le Goater } 780d35aefa9SCédric Le Goater 781d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 782d49e8a9bSCédric Le Goater { 783d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 784d49e8a9bSCédric Le Goater 785d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 786d49e8a9bSCédric Le Goater } 787d49e8a9bSCédric Le Goater 788631adaffSCédric Le Goater /* 789631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 790631adaffSCédric Le Goater * 49:52 Node ID 791631adaffSCédric Le Goater * 53:55 Chip ID 792631adaffSCédric Le Goater * 56 Reserved - Read as zero 793631adaffSCédric Le Goater * 57:61 Core number 794631adaffSCédric Le Goater * 62:63 Thread ID 795631adaffSCédric Le Goater * 796631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 797631adaffSCédric Le Goater */ 798631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 799631adaffSCédric Le Goater { 800631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 801631adaffSCédric Le Goater } 802631adaffSCédric Le Goater 8038fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 804d35aefa9SCédric Le Goater Error **errp) 805d35aefa9SCédric Le Goater { 8062dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 8072dfa91a2SCédric Le Goater Error *local_err = NULL; 8082dfa91a2SCédric Le Goater Object *obj; 8092dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8102dfa91a2SCédric Le Goater 8112dfa91a2SCédric Le Goater /* 8122dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 8132dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 8142dfa91a2SCédric Le Goater * only used at runtime. 8152dfa91a2SCédric Le Goater */ 81626aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 8172dfa91a2SCédric Le Goater if (local_err) { 8182dfa91a2SCédric Le Goater error_propagate(errp, local_err); 8198fa1f4efSCédric Le Goater return; 820d35aefa9SCédric Le Goater } 821d35aefa9SCédric Le Goater 8222dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 8232dfa91a2SCédric Le Goater } 8242dfa91a2SCédric Le Goater 825d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 826d49e8a9bSCédric Le Goater { 827d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 828d49e8a9bSCédric Le Goater 829d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 830d49e8a9bSCédric Le Goater } 831d49e8a9bSCédric Le Goater 83259b7c1c2SBalamuruhan S /* 83359b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 834397a79e7SCédric Le Goater * 835397a79e7SCédric Le Goater * <EX0 reserved> 836397a79e7SCédric Le Goater * EX1 - Venice only 837397a79e7SCédric Le Goater * EX2 - Venice only 838397a79e7SCédric Le Goater * EX3 - Venice only 839397a79e7SCédric Le Goater * EX4 840397a79e7SCédric Le Goater * EX5 841397a79e7SCédric Le Goater * EX6 842397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 843397a79e7SCédric Le Goater * EX9 - Venice only 844397a79e7SCédric Le Goater * EX10 - Venice only 845397a79e7SCédric Le Goater * EX11 - Venice only 846397a79e7SCédric Le Goater * EX12 847397a79e7SCédric Le Goater * EX13 848397a79e7SCédric Le Goater * EX14 849397a79e7SCédric Le Goater * <EX15 reserved> 850397a79e7SCédric Le Goater */ 851397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 852397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 853397a79e7SCédric Le Goater 854397a79e7SCédric Le Goater /* 85509279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 856397a79e7SCédric Le Goater */ 85709279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 858397a79e7SCédric Le Goater 85977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 86077864267SCédric Le Goater { 86177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 86277864267SCédric Le Goater 863f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 864ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 86577864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 86677864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 86777864267SCédric Le Goater 868f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 86982514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 87077864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->lpc), "psi", 87177864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 87277864267SCédric Le Goater 873f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 8743233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 87577864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->occ), "psi", 87677864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 8773887d241SBalamuruhan S 8783887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), 8793887d241SBalamuruhan S TYPE_PNV8_HOMER, &error_abort, NULL); 8803887d241SBalamuruhan S object_property_add_const_link(OBJECT(&chip8->homer), "chip", obj, 8813887d241SBalamuruhan S &error_abort); 88277864267SCédric Le Goater } 88377864267SCédric Le Goater 88477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 88577864267SCédric Le Goater { 88677864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 88777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 88877864267SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 88977864267SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 89077864267SCédric Le Goater int i, j; 89177864267SCédric Le Goater char *name; 89277864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 89377864267SCédric Le Goater 89477864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 89577864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 89677864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 89777864267SCédric Le Goater g_free(name); 89877864267SCédric Le Goater 89977864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 90077864267SCédric Le Goater 90177864267SCédric Le Goater /* Map the ICP registers for each thread */ 90277864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 90377864267SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 90477864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 90577864267SCédric Le Goater 90677864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 90777864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 90877864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 90977864267SCédric Le Goater 91077864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 91177864267SCédric Le Goater &icp->mmio); 91277864267SCédric Le Goater } 91377864267SCédric Le Goater } 91477864267SCédric Le Goater } 91577864267SCédric Le Goater 91677864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 91777864267SCédric Le Goater { 91877864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 91977864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 92077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 921ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 92277864267SCédric Le Goater Error *local_err = NULL; 92377864267SCédric Le Goater 924709044fdSCédric Le Goater /* XSCOM bridge is first */ 925709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 926709044fdSCédric Le Goater if (local_err) { 927709044fdSCédric Le Goater error_propagate(errp, local_err); 928709044fdSCédric Le Goater return; 929709044fdSCédric Le Goater } 930709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 931709044fdSCédric Le Goater 93277864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 93377864267SCédric Le Goater if (local_err) { 93477864267SCédric Le Goater error_propagate(errp, local_err); 93577864267SCédric Le Goater return; 93677864267SCédric Le Goater } 93777864267SCédric Le Goater 93877864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 93977864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 94077864267SCédric Le Goater "bar", &error_fatal); 94177864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 94277864267SCédric Le Goater if (local_err) { 94377864267SCédric Le Goater error_propagate(errp, local_err); 94477864267SCédric Le Goater return; 94577864267SCédric Le Goater } 946ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 947ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 94877864267SCédric Le Goater 94977864267SCédric Le Goater /* Create LPC controller */ 95077864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 95177864267SCédric Le Goater &error_fatal); 95277864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 95377864267SCédric Le Goater 95464d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 95564d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 95664d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 95764d011d5SCédric Le Goater 95859b7c1c2SBalamuruhan S /* 95959b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 96059b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 96159b7c1c2SBalamuruhan S */ 96277864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 96377864267SCédric Le Goater if (local_err) { 96477864267SCédric Le Goater error_propagate(errp, local_err); 96577864267SCédric Le Goater return; 96677864267SCédric Le Goater } 96777864267SCédric Le Goater 96877864267SCédric Le Goater /* Create the simplified OCC model */ 96977864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), 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 } 97477864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 975f3db8266SBalamuruhan S 976f3db8266SBalamuruhan S /* OCC SRAM model */ 977f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip), 978f3db8266SBalamuruhan S &chip8->occ.sram_regs); 9793887d241SBalamuruhan S 9803887d241SBalamuruhan S /* HOMER */ 9813887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip8->homer), true, "realized", 9823887d241SBalamuruhan S &local_err); 9833887d241SBalamuruhan S if (local_err) { 9843887d241SBalamuruhan S error_propagate(errp, local_err); 9853887d241SBalamuruhan S return; 9863887d241SBalamuruhan S } 9873887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 9883887d241SBalamuruhan S &chip8->homer.regs); 98977864267SCédric Le Goater } 99077864267SCédric Le Goater 991e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 992e997040eSCédric Le Goater { 993e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 994e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 995e997040eSCédric Le Goater 996e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 997e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 998397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 999631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1000d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1001d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 100204026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1003eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1004d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1005e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 100677864267SCédric Le Goater 100777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 100877864267SCédric Le Goater &k->parent_realize); 1009e997040eSCédric Le Goater } 1010e997040eSCédric Le Goater 1011e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1012e997040eSCédric Le Goater { 1013e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1014e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1015e997040eSCédric Le Goater 1016e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 1017e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1018397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1019631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1020d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1021d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 102204026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1023eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1024d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1025e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 102677864267SCédric Le Goater 102777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 102877864267SCédric Le Goater &k->parent_realize); 1029e997040eSCédric Le Goater } 1030e997040eSCédric Le Goater 1031e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1032e997040eSCédric Le Goater { 1033e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1034e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1035e997040eSCédric Le Goater 1036e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 1037e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1038397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1039631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1040d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1041d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 104204026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1043eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1044d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1045e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 104677864267SCédric Le Goater 104777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 104877864267SCédric Le Goater &k->parent_realize); 104977864267SCédric Le Goater } 105077864267SCédric Le Goater 105177864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 105277864267SCédric Le Goater { 10532dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 10542dfa91a2SCédric Le Goater 10552dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 10562dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 10572dfa91a2SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj, 10582dfa91a2SCédric Le Goater &error_abort); 1059c38536bcSCédric Le Goater 1060c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1061c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 1062c38536bcSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj, 1063c38536bcSCédric Le Goater &error_abort); 106415376c66SCédric Le Goater 106515376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 106615376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 106715376c66SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->lpc), "psi", 106815376c66SCédric Le Goater OBJECT(&chip9->psi), &error_abort); 10696598a70dSCédric Le Goater 10706598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 10716598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 10726598a70dSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->occ), "psi", 10736598a70dSCédric Le Goater OBJECT(&chip9->psi), &error_abort); 10743887d241SBalamuruhan S 10753887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 10763887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 10773887d241SBalamuruhan S object_property_add_const_link(OBJECT(&chip9->homer), "chip", obj, 10783887d241SBalamuruhan S &error_abort); 107977864267SCédric Le Goater } 108077864267SCédric Le Goater 10815dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 10825dad902cSCédric Le Goater { 10835dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 10845dad902cSCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 10855dad902cSCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 10865dad902cSCédric Le Goater int i; 10875dad902cSCédric Le Goater 10885dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 10895dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 10905dad902cSCédric Le Goater 10915dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 10925dad902cSCédric Le Goater char eq_name[32]; 10935dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 10945dad902cSCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); 10955dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 10965dad902cSCédric Le Goater 10975dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1098bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1099bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 11005dad902cSCédric Le Goater 11015dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 11025dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 11035dad902cSCédric Le Goater 11045dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 11055dad902cSCédric Le Goater &eq->xscom_regs); 11065dad902cSCédric Le Goater } 11075dad902cSCédric Le Goater } 11085dad902cSCédric Le Goater 110977864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 111077864267SCédric Le Goater { 111177864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 11122dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 11132dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1114c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 111577864267SCédric Le Goater Error *local_err = NULL; 111677864267SCédric Le Goater 1117709044fdSCédric Le Goater /* XSCOM bridge is first */ 1118709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1119709044fdSCédric Le Goater if (local_err) { 1120709044fdSCédric Le Goater error_propagate(errp, local_err); 1121709044fdSCédric Le Goater return; 1122709044fdSCédric Le Goater } 1123709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1124709044fdSCédric Le Goater 112577864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 112677864267SCédric Le Goater if (local_err) { 112777864267SCédric Le Goater error_propagate(errp, local_err); 112877864267SCédric Le Goater return; 112977864267SCédric Le Goater } 11302dfa91a2SCédric Le Goater 11315dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 11325dad902cSCédric Le Goater if (local_err) { 11335dad902cSCédric Le Goater error_propagate(errp, local_err); 11345dad902cSCédric Le Goater return; 11355dad902cSCédric Le Goater } 11365dad902cSCédric Le Goater 11372dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 11382dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 11392dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 11402dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 11412dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 11422dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 11432dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 11442dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 11452dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 11462dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 11472dfa91a2SCédric Le Goater &local_err); 11482dfa91a2SCédric Le Goater if (local_err) { 11492dfa91a2SCédric Le Goater error_propagate(errp, local_err); 11502dfa91a2SCédric Le Goater return; 11512dfa91a2SCédric Le Goater } 11522dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 11532dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1154c38536bcSCédric Le Goater 1155c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1156c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1157c38536bcSCédric Le Goater "bar", &error_fatal); 1158c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1159c38536bcSCédric Le Goater if (local_err) { 1160c38536bcSCédric Le Goater error_propagate(errp, local_err); 1161c38536bcSCédric Le Goater return; 1162c38536bcSCédric Le Goater } 1163c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1164c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 116515376c66SCédric Le Goater 116615376c66SCédric Le Goater /* LPC */ 116715376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 116815376c66SCédric Le Goater if (local_err) { 116915376c66SCédric Le Goater error_propagate(errp, local_err); 117015376c66SCédric Le Goater return; 117115376c66SCédric Le Goater } 117215376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 117315376c66SCédric Le Goater &chip9->lpc.xscom_regs); 117415376c66SCédric Le Goater 117515376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 117615376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 11776598a70dSCédric Le Goater 11786598a70dSCédric Le Goater /* Create the simplified OCC model */ 11796598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 11806598a70dSCédric Le Goater if (local_err) { 11816598a70dSCédric Le Goater error_propagate(errp, local_err); 11826598a70dSCédric Le Goater return; 11836598a70dSCédric Le Goater } 11846598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1185f3db8266SBalamuruhan S 1186f3db8266SBalamuruhan S /* OCC SRAM model */ 1187f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip), 1188f3db8266SBalamuruhan S &chip9->occ.sram_regs); 11893887d241SBalamuruhan S 11903887d241SBalamuruhan S /* HOMER */ 11913887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 11923887d241SBalamuruhan S &local_err); 11933887d241SBalamuruhan S if (local_err) { 11943887d241SBalamuruhan S error_propagate(errp, local_err); 11953887d241SBalamuruhan S return; 11963887d241SBalamuruhan S } 11973887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 11983887d241SBalamuruhan S &chip9->homer.regs); 1199e997040eSCédric Le Goater } 1200e997040eSCédric Le Goater 1201e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1202e997040eSCédric Le Goater { 1203e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1204e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1205e997040eSCédric Le Goater 1206e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 120783028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1208397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1209631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1210d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1211d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 121204026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1213eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1214d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1215e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 121677864267SCédric Le Goater 121777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 121877864267SCédric Le Goater &k->parent_realize); 1219e997040eSCédric Le Goater } 1220e997040eSCédric Le Goater 1221397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1222397a79e7SCédric Le Goater { 1223397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1224397a79e7SCédric Le Goater int cores_max; 1225397a79e7SCédric Le Goater 1226397a79e7SCédric Le Goater /* 1227397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1228397a79e7SCédric Le Goater * the chip class 1229397a79e7SCédric Le Goater */ 1230397a79e7SCédric Le Goater if (!chip->cores_mask) { 1231397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1232397a79e7SCédric Le Goater } 1233397a79e7SCédric Le Goater 1234397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1235397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1236397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1237397a79e7SCédric Le Goater chip->cores_mask); 1238397a79e7SCédric Le Goater return; 1239397a79e7SCédric Le Goater } 1240397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1241397a79e7SCédric Le Goater 1242397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 124327d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1244397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1245397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1246397a79e7SCédric Le Goater cores_max); 1247397a79e7SCédric Le Goater return; 1248397a79e7SCédric Le Goater } 1249397a79e7SCédric Le Goater } 1250397a79e7SCédric Le Goater 125151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1252e997040eSCédric Le Goater { 1253fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1254397a79e7SCédric Le Goater Error *error = NULL; 1255d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 125640abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1257d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 1258d2fd9612SCédric Le Goater int i, core_hwid; 1259397a79e7SCédric Le Goater 1260d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1261d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1262d2fd9612SCédric Le Goater return; 1263d2fd9612SCédric Le Goater } 1264d2fd9612SCédric Le Goater 1265d2fd9612SCédric Le Goater /* Cores */ 1266397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1267397a79e7SCédric Le Goater if (error) { 1268397a79e7SCédric Le Goater error_propagate(errp, error); 1269397a79e7SCédric Le Goater return; 1270397a79e7SCédric Le Goater } 1271d2fd9612SCédric Le Goater 1272d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 1273d2fd9612SCédric Le Goater 1274d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1275d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1276d2fd9612SCédric Le Goater char core_name[32]; 1277d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 1278c035851aSCédric Le Goater uint64_t xscom_core_base; 1279d2fd9612SCédric Le Goater 1280d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1281d2fd9612SCédric Le Goater continue; 1282d2fd9612SCédric Le Goater } 1283d2fd9612SCédric Le Goater 1284d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1285bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize, 1286bc4c406cSPhilippe Mathieu-Daudé typename, &error_fatal, NULL); 1287fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1288d2fd9612SCédric Le Goater &error_fatal); 1289d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1290d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1291d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1292d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1293d2fd9612SCédric Le Goater "pir", &error_fatal); 1294d35aefa9SCédric Le Goater object_property_add_const_link(OBJECT(pnv_core), "chip", 1295d35aefa9SCédric Le Goater OBJECT(chip), &error_fatal); 1296d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1297d2fd9612SCédric Le Goater &error_fatal); 129824ece072SCédric Le Goater 129924ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1300c035851aSCédric Le Goater if (!pnv_chip_is_power9(chip)) { 1301c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1302c035851aSCédric Le Goater } else { 13035dad902cSCédric Le Goater xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); 1304c035851aSCédric Le Goater } 1305c035851aSCédric Le Goater 1306c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 130724ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 1308d2fd9612SCédric Le Goater i++; 1309d2fd9612SCédric Le Goater } 131051c04728SCédric Le Goater } 131151c04728SCédric Le Goater 131251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 131351c04728SCédric Le Goater { 131451c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 131551c04728SCédric Le Goater Error *error = NULL; 131651c04728SCédric Le Goater 131751c04728SCédric Le Goater /* Cores */ 131851c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 131951c04728SCédric Le Goater if (error) { 132051c04728SCédric Le Goater error_propagate(errp, error); 132151c04728SCédric Le Goater return; 132251c04728SCédric Le Goater } 1323e997040eSCédric Le Goater } 1324e997040eSCédric Le Goater 1325e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1326e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1327e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1328e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1329397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1330397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1331e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1332e997040eSCédric Le Goater }; 1333e997040eSCédric Le Goater 1334e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1335e997040eSCédric Le Goater { 1336e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1337e997040eSCédric Le Goater 13389d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1339e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1340e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1341e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1342e997040eSCédric Le Goater } 1343e997040eSCédric Le Goater 134454f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 134554f59d78SCédric Le Goater { 1346b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 134754f59d78SCédric Le Goater int i; 134854f59d78SCédric Le Goater 134954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 135077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 135177864267SCédric Le Goater 135277864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 135377864267SCédric Le Goater return &chip8->psi.ics; 135454f59d78SCédric Le Goater } 135554f59d78SCédric Le Goater } 135654f59d78SCédric Le Goater return NULL; 135754f59d78SCédric Le Goater } 135854f59d78SCédric Le Goater 135954f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 136054f59d78SCédric Le Goater { 1361b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 136254f59d78SCédric Le Goater int i; 136354f59d78SCédric Le Goater 136454f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 136577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 136677864267SCédric Le Goater ics_resend(&chip8->psi.ics); 136754f59d78SCédric Le Goater } 136854f59d78SCédric Le Goater } 136954f59d78SCédric Le Goater 137036fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 137136fc6f08SCédric Le Goater { 137236fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 137336fc6f08SCédric Le Goater 1374956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 137536fc6f08SCédric Le Goater } 137636fc6f08SCédric Le Goater 137747fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 137847fea43aSCédric Le Goater Monitor *mon) 137947fea43aSCédric Le Goater { 1380b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 138154f59d78SCédric Le Goater int i; 138247fea43aSCédric Le Goater CPUState *cs; 138347fea43aSCédric Le Goater 138447fea43aSCédric Le Goater CPU_FOREACH(cs) { 138547fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 138647fea43aSCédric Le Goater 1387d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1388d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1389d8e4aad5SCédric Le Goater } else { 1390956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 139147fea43aSCédric Le Goater } 1392d8e4aad5SCédric Le Goater } 139354f59d78SCédric Le Goater 139454f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1395d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 139654f59d78SCédric Le Goater } 139747fea43aSCédric Le Goater } 139847fea43aSCédric Le Goater 1399e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1400e997040eSCédric Le Goater void *opaque, Error **errp) 1401e997040eSCédric Le Goater { 1402b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1403e997040eSCédric Le Goater } 1404e997040eSCédric Le Goater 1405e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1406e997040eSCédric Le Goater void *opaque, Error **errp) 1407e997040eSCédric Le Goater { 1408b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1409e997040eSCédric Le Goater uint32_t num_chips; 1410e997040eSCédric Le Goater Error *local_err = NULL; 1411e997040eSCédric Le Goater 1412e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1413e997040eSCédric Le Goater if (local_err) { 1414e997040eSCédric Le Goater error_propagate(errp, local_err); 1415e997040eSCédric Le Goater return; 1416e997040eSCédric Le Goater } 1417e997040eSCédric Le Goater 1418e997040eSCédric Le Goater /* 1419e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1420e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1421e997040eSCédric Le Goater */ 1422e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1423e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1424e997040eSCédric Le Goater return; 1425e997040eSCédric Le Goater } 1426e997040eSCédric Le Goater 1427e997040eSCédric Le Goater pnv->num_chips = num_chips; 1428e997040eSCédric Le Goater } 1429e997040eSCédric Le Goater 143077864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1431e997040eSCédric Le Goater { 1432b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1433e997040eSCédric Le Goater pnv->num_chips = 1; 1434e997040eSCédric Le Goater } 1435e997040eSCédric Le Goater 1436b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1437e997040eSCédric Le Goater { 14381e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1439e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1440e997040eSCédric Le Goater NULL, NULL, NULL); 1441e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1442e997040eSCédric Le Goater "Specifies the number of processor chips", 1443e997040eSCédric Le Goater NULL); 14449e933f4aSBenjamin Herrenschmidt } 14459e933f4aSBenjamin Herrenschmidt 1446f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 14479e933f4aSBenjamin Herrenschmidt { 14489e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 144936fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1450f30c843cSCédric Le Goater 1451f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1452f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1453f30c843cSCédric Le Goater 1454f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1455f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1456f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1457f30c843cSCédric Le Goater } 1458f30c843cSCédric Le Goater 1459f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1460f30c843cSCédric Le Goater { 1461f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1462f30c843cSCédric Le Goater 1463f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1464f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1465f30c843cSCédric Le Goater 1466f30c843cSCédric Le Goater mc->alias = "powernv"; 1467f30c843cSCédric Le Goater } 1468f30c843cSCédric Le Goater 1469f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1470f30c843cSCédric Le Goater { 1471f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 147247fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 14739e933f4aSBenjamin Herrenschmidt 14749e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1475b168a138SCédric Le Goater mc->init = pnv_init; 1476b168a138SCédric Le Goater mc->reset = pnv_reset; 14779e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 147859b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 147959b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 14809e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 14819e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1482f1d18b0aSJoel Stanley /* 1483f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1484f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1485f1d18b0aSJoel Stanley */ 1486f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 148747fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1488e997040eSCédric Le Goater 1489b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 14909e933f4aSBenjamin Herrenschmidt } 14919e933f4aSBenjamin Herrenschmidt 149277864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1493beba5c0fSIgor Mammedov { \ 1494beba5c0fSIgor Mammedov .name = type, \ 1495beba5c0fSIgor Mammedov .class_init = class_initfn, \ 149677864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 149777864267SCédric Le Goater } 149877864267SCédric Le Goater 149977864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 150077864267SCédric Le Goater { \ 150177864267SCédric Le Goater .name = type, \ 150277864267SCédric Le Goater .class_init = class_initfn, \ 150377864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1504beba5c0fSIgor Mammedov } 1505beba5c0fSIgor Mammedov 1506beba5c0fSIgor Mammedov static const TypeInfo types[] = { 15071aba8716SCédric Le Goater { 15081aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 15091aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 15101aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 15111aba8716SCédric Le Goater }, 15121aba8716SCédric Le Goater { 15131aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 15141aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 15151aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 15161aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 15171aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 15181aba8716SCédric Le Goater { }, 15191aba8716SCédric Le Goater }, 15201aba8716SCédric Le Goater }, 1521beba5c0fSIgor Mammedov { 1522b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 15239e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1524f30c843cSCédric Le Goater .abstract = true, 15259e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 152677864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1527b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 152836fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 152947fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 153036fc6f08SCédric Le Goater { }, 153136fc6f08SCédric Le Goater }, 1532beba5c0fSIgor Mammedov }, 1533beba5c0fSIgor Mammedov { 1534beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1535beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1536beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1537beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1538beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1539beba5c0fSIgor Mammedov .abstract = true, 1540beba5c0fSIgor Mammedov }, 154177864267SCédric Le Goater 154277864267SCédric Le Goater /* 154377864267SCédric Le Goater * P9 chip and variants 154477864267SCédric Le Goater */ 154577864267SCédric Le Goater { 154677864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 154777864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 154877864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 154977864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 155077864267SCédric Le Goater }, 155177864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 155277864267SCédric Le Goater 155377864267SCédric Le Goater /* 155477864267SCédric Le Goater * P8 chip and variants 155577864267SCédric Le Goater */ 155677864267SCédric Le Goater { 155777864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 155877864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 155977864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 156077864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 156177864267SCédric Le Goater }, 156277864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 156377864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 156477864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1565beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 15669e933f4aSBenjamin Herrenschmidt }; 15679e933f4aSBenjamin Herrenschmidt 1568beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1569