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" 513495b6b6SCédric Le Goater #include "hw/timer/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 781631adaffSCédric Le Goater /* 782631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 783631adaffSCédric Le Goater * 49:52 Node ID 784631adaffSCédric Le Goater * 53:55 Chip ID 785631adaffSCédric Le Goater * 56 Reserved - Read as zero 786631adaffSCédric Le Goater * 57:61 Core number 787631adaffSCédric Le Goater * 62:63 Thread ID 788631adaffSCédric Le Goater * 789631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 790631adaffSCédric Le Goater */ 791631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 792631adaffSCédric Le Goater { 793631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 794631adaffSCédric Le Goater } 795631adaffSCédric Le Goater 7968fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 797d35aefa9SCédric Le Goater Error **errp) 798d35aefa9SCédric Le Goater { 7992dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 8002dfa91a2SCédric Le Goater Error *local_err = NULL; 8012dfa91a2SCédric Le Goater Object *obj; 8022dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8032dfa91a2SCédric Le Goater 8042dfa91a2SCédric Le Goater /* 8052dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 8062dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 8072dfa91a2SCédric Le Goater * only used at runtime. 8082dfa91a2SCédric Le Goater */ 80926aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 8102dfa91a2SCédric Le Goater if (local_err) { 8112dfa91a2SCédric Le Goater error_propagate(errp, local_err); 8128fa1f4efSCédric Le Goater return; 813d35aefa9SCédric Le Goater } 814d35aefa9SCédric Le Goater 8152dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 8162dfa91a2SCédric Le Goater } 8172dfa91a2SCédric Le Goater 81859b7c1c2SBalamuruhan S /* 81959b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 820397a79e7SCédric Le Goater * 821397a79e7SCédric Le Goater * <EX0 reserved> 822397a79e7SCédric Le Goater * EX1 - Venice only 823397a79e7SCédric Le Goater * EX2 - Venice only 824397a79e7SCédric Le Goater * EX3 - Venice only 825397a79e7SCédric Le Goater * EX4 826397a79e7SCédric Le Goater * EX5 827397a79e7SCédric Le Goater * EX6 828397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 829397a79e7SCédric Le Goater * EX9 - Venice only 830397a79e7SCédric Le Goater * EX10 - Venice only 831397a79e7SCédric Le Goater * EX11 - Venice only 832397a79e7SCédric Le Goater * EX12 833397a79e7SCédric Le Goater * EX13 834397a79e7SCédric Le Goater * EX14 835397a79e7SCédric Le Goater * <EX15 reserved> 836397a79e7SCédric Le Goater */ 837397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 838397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 839397a79e7SCédric Le Goater 840397a79e7SCédric Le Goater /* 84109279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 842397a79e7SCédric Le Goater */ 84309279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 844397a79e7SCédric Le Goater 84577864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 84677864267SCédric Le Goater { 84777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 84877864267SCédric Le Goater 849f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 850ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 85177864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 85277864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 85377864267SCédric Le Goater 854f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 85582514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 85677864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->lpc), "psi", 85777864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 85877864267SCédric Le Goater 859f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 8603233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 86177864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->occ), "psi", 86277864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 863*3887d241SBalamuruhan S 864*3887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), 865*3887d241SBalamuruhan S TYPE_PNV8_HOMER, &error_abort, NULL); 866*3887d241SBalamuruhan S object_property_add_const_link(OBJECT(&chip8->homer), "chip", obj, 867*3887d241SBalamuruhan S &error_abort); 86877864267SCédric Le Goater } 86977864267SCédric Le Goater 87077864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 87177864267SCédric Le Goater { 87277864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 87377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 87477864267SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 87577864267SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 87677864267SCédric Le Goater int i, j; 87777864267SCédric Le Goater char *name; 87877864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 87977864267SCédric Le Goater 88077864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 88177864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 88277864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 88377864267SCédric Le Goater g_free(name); 88477864267SCédric Le Goater 88577864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 88677864267SCédric Le Goater 88777864267SCédric Le Goater /* Map the ICP registers for each thread */ 88877864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 88977864267SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 89077864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 89177864267SCédric Le Goater 89277864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 89377864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 89477864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 89577864267SCédric Le Goater 89677864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 89777864267SCédric Le Goater &icp->mmio); 89877864267SCédric Le Goater } 89977864267SCédric Le Goater } 90077864267SCédric Le Goater } 90177864267SCédric Le Goater 90277864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 90377864267SCédric Le Goater { 90477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 90577864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 90677864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 907ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 90877864267SCédric Le Goater Error *local_err = NULL; 90977864267SCédric Le Goater 910709044fdSCédric Le Goater /* XSCOM bridge is first */ 911709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 912709044fdSCédric Le Goater if (local_err) { 913709044fdSCédric Le Goater error_propagate(errp, local_err); 914709044fdSCédric Le Goater return; 915709044fdSCédric Le Goater } 916709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 917709044fdSCédric Le Goater 91877864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 91977864267SCédric Le Goater if (local_err) { 92077864267SCédric Le Goater error_propagate(errp, local_err); 92177864267SCédric Le Goater return; 92277864267SCédric Le Goater } 92377864267SCédric Le Goater 92477864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 92577864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 92677864267SCédric Le Goater "bar", &error_fatal); 92777864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 92877864267SCédric Le Goater if (local_err) { 92977864267SCédric Le Goater error_propagate(errp, local_err); 93077864267SCédric Le Goater return; 93177864267SCédric Le Goater } 932ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 933ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 93477864267SCédric Le Goater 93577864267SCédric Le Goater /* Create LPC controller */ 93677864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 93777864267SCédric Le Goater &error_fatal); 93877864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 93977864267SCédric Le Goater 94064d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 94164d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 94264d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 94364d011d5SCédric Le Goater 94459b7c1c2SBalamuruhan S /* 94559b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 94659b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 94759b7c1c2SBalamuruhan S */ 94877864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 94977864267SCédric Le Goater if (local_err) { 95077864267SCédric Le Goater error_propagate(errp, local_err); 95177864267SCédric Le Goater return; 95277864267SCédric Le Goater } 95377864267SCédric Le Goater 95477864267SCédric Le Goater /* Create the simplified OCC model */ 95577864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 95677864267SCédric Le Goater if (local_err) { 95777864267SCédric Le Goater error_propagate(errp, local_err); 95877864267SCédric Le Goater return; 95977864267SCédric Le Goater } 96077864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 961f3db8266SBalamuruhan S 962f3db8266SBalamuruhan S /* OCC SRAM model */ 963f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip), 964f3db8266SBalamuruhan S &chip8->occ.sram_regs); 965*3887d241SBalamuruhan S 966*3887d241SBalamuruhan S /* HOMER */ 967*3887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip8->homer), true, "realized", 968*3887d241SBalamuruhan S &local_err); 969*3887d241SBalamuruhan S if (local_err) { 970*3887d241SBalamuruhan S error_propagate(errp, local_err); 971*3887d241SBalamuruhan S return; 972*3887d241SBalamuruhan S } 973*3887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 974*3887d241SBalamuruhan S &chip8->homer.regs); 97577864267SCédric Le Goater } 97677864267SCédric Le Goater 977e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 978e997040eSCédric Le Goater { 979e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 980e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 981e997040eSCédric Le Goater 982e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 983e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 984397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 985631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 986d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 98704026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 988eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 989d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 990e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 99177864267SCédric Le Goater 99277864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 99377864267SCédric Le Goater &k->parent_realize); 994e997040eSCédric Le Goater } 995e997040eSCédric Le Goater 996e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 997e997040eSCédric Le Goater { 998e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 999e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1000e997040eSCédric Le Goater 1001e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 1002e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1003397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1004631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1005d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 100604026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1007eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1008d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1009e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 101077864267SCédric Le Goater 101177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 101277864267SCédric Le Goater &k->parent_realize); 1013e997040eSCédric Le Goater } 1014e997040eSCédric Le Goater 1015e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1016e997040eSCédric Le Goater { 1017e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1018e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1019e997040eSCédric Le Goater 1020e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 1021e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1022397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1023631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1024d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 102504026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1026eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1027d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1028e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 102977864267SCédric Le Goater 103077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 103177864267SCédric Le Goater &k->parent_realize); 103277864267SCédric Le Goater } 103377864267SCédric Le Goater 103477864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 103577864267SCédric Le Goater { 10362dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 10372dfa91a2SCédric Le Goater 10382dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 10392dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 10402dfa91a2SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj, 10412dfa91a2SCédric Le Goater &error_abort); 1042c38536bcSCédric Le Goater 1043c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1044c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 1045c38536bcSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj, 1046c38536bcSCédric Le Goater &error_abort); 104715376c66SCédric Le Goater 104815376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 104915376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 105015376c66SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->lpc), "psi", 105115376c66SCédric Le Goater OBJECT(&chip9->psi), &error_abort); 10526598a70dSCédric Le Goater 10536598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 10546598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 10556598a70dSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->occ), "psi", 10566598a70dSCédric Le Goater OBJECT(&chip9->psi), &error_abort); 1057*3887d241SBalamuruhan S 1058*3887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 1059*3887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 1060*3887d241SBalamuruhan S object_property_add_const_link(OBJECT(&chip9->homer), "chip", obj, 1061*3887d241SBalamuruhan S &error_abort); 106277864267SCédric Le Goater } 106377864267SCédric Le Goater 10645dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 10655dad902cSCédric Le Goater { 10665dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 10675dad902cSCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 10685dad902cSCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 10695dad902cSCédric Le Goater int i; 10705dad902cSCédric Le Goater 10715dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 10725dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 10735dad902cSCédric Le Goater 10745dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 10755dad902cSCédric Le Goater char eq_name[32]; 10765dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 10775dad902cSCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); 10785dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 10795dad902cSCédric Le Goater 10805dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1081bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1082bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 10835dad902cSCédric Le Goater 10845dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 10855dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 10865dad902cSCédric Le Goater 10875dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 10885dad902cSCédric Le Goater &eq->xscom_regs); 10895dad902cSCédric Le Goater } 10905dad902cSCédric Le Goater } 10915dad902cSCédric Le Goater 109277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 109377864267SCédric Le Goater { 109477864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 10952dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 10962dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1097c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 109877864267SCédric Le Goater Error *local_err = NULL; 109977864267SCédric Le Goater 1100709044fdSCédric Le Goater /* XSCOM bridge is first */ 1101709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1102709044fdSCédric Le Goater if (local_err) { 1103709044fdSCédric Le Goater error_propagate(errp, local_err); 1104709044fdSCédric Le Goater return; 1105709044fdSCédric Le Goater } 1106709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1107709044fdSCédric Le Goater 110877864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 110977864267SCédric Le Goater if (local_err) { 111077864267SCédric Le Goater error_propagate(errp, local_err); 111177864267SCédric Le Goater return; 111277864267SCédric Le Goater } 11132dfa91a2SCédric Le Goater 11145dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 11155dad902cSCédric Le Goater if (local_err) { 11165dad902cSCédric Le Goater error_propagate(errp, local_err); 11175dad902cSCédric Le Goater return; 11185dad902cSCédric Le Goater } 11195dad902cSCédric Le Goater 11202dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 11212dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 11222dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 11232dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 11242dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 11252dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 11262dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 11272dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 11282dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 11292dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 11302dfa91a2SCédric Le Goater &local_err); 11312dfa91a2SCédric Le Goater if (local_err) { 11322dfa91a2SCédric Le Goater error_propagate(errp, local_err); 11332dfa91a2SCédric Le Goater return; 11342dfa91a2SCédric Le Goater } 11352dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 11362dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1137c38536bcSCédric Le Goater 1138c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1139c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1140c38536bcSCédric Le Goater "bar", &error_fatal); 1141c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1142c38536bcSCédric Le Goater if (local_err) { 1143c38536bcSCédric Le Goater error_propagate(errp, local_err); 1144c38536bcSCédric Le Goater return; 1145c38536bcSCédric Le Goater } 1146c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1147c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 114815376c66SCédric Le Goater 114915376c66SCédric Le Goater /* LPC */ 115015376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 115115376c66SCédric Le Goater if (local_err) { 115215376c66SCédric Le Goater error_propagate(errp, local_err); 115315376c66SCédric Le Goater return; 115415376c66SCédric Le Goater } 115515376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 115615376c66SCédric Le Goater &chip9->lpc.xscom_regs); 115715376c66SCédric Le Goater 115815376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 115915376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 11606598a70dSCédric Le Goater 11616598a70dSCédric Le Goater /* Create the simplified OCC model */ 11626598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 11636598a70dSCédric Le Goater if (local_err) { 11646598a70dSCédric Le Goater error_propagate(errp, local_err); 11656598a70dSCédric Le Goater return; 11666598a70dSCédric Le Goater } 11676598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1168f3db8266SBalamuruhan S 1169f3db8266SBalamuruhan S /* OCC SRAM model */ 1170f3db8266SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip), 1171f3db8266SBalamuruhan S &chip9->occ.sram_regs); 1172*3887d241SBalamuruhan S 1173*3887d241SBalamuruhan S /* HOMER */ 1174*3887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 1175*3887d241SBalamuruhan S &local_err); 1176*3887d241SBalamuruhan S if (local_err) { 1177*3887d241SBalamuruhan S error_propagate(errp, local_err); 1178*3887d241SBalamuruhan S return; 1179*3887d241SBalamuruhan S } 1180*3887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 1181*3887d241SBalamuruhan S &chip9->homer.regs); 1182e997040eSCédric Le Goater } 1183e997040eSCédric Le Goater 1184e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1185e997040eSCédric Le Goater { 1186e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1187e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1188e997040eSCédric Le Goater 1189e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 119083028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1191397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1192631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1193d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 119404026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1195eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1196d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1197e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 119877864267SCédric Le Goater 119977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 120077864267SCédric Le Goater &k->parent_realize); 1201e997040eSCédric Le Goater } 1202e997040eSCédric Le Goater 1203397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1204397a79e7SCédric Le Goater { 1205397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1206397a79e7SCédric Le Goater int cores_max; 1207397a79e7SCédric Le Goater 1208397a79e7SCédric Le Goater /* 1209397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1210397a79e7SCédric Le Goater * the chip class 1211397a79e7SCédric Le Goater */ 1212397a79e7SCédric Le Goater if (!chip->cores_mask) { 1213397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1214397a79e7SCédric Le Goater } 1215397a79e7SCédric Le Goater 1216397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1217397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1218397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1219397a79e7SCédric Le Goater chip->cores_mask); 1220397a79e7SCédric Le Goater return; 1221397a79e7SCédric Le Goater } 1222397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1223397a79e7SCédric Le Goater 1224397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 122527d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1226397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1227397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1228397a79e7SCédric Le Goater cores_max); 1229397a79e7SCédric Le Goater return; 1230397a79e7SCédric Le Goater } 1231397a79e7SCédric Le Goater } 1232397a79e7SCédric Le Goater 123351c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1234e997040eSCédric Le Goater { 1235fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1236397a79e7SCédric Le Goater Error *error = NULL; 1237d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 123840abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1239d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 1240d2fd9612SCédric Le Goater int i, core_hwid; 1241397a79e7SCédric Le Goater 1242d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1243d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1244d2fd9612SCédric Le Goater return; 1245d2fd9612SCédric Le Goater } 1246d2fd9612SCédric Le Goater 1247d2fd9612SCédric Le Goater /* Cores */ 1248397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1249397a79e7SCédric Le Goater if (error) { 1250397a79e7SCédric Le Goater error_propagate(errp, error); 1251397a79e7SCédric Le Goater return; 1252397a79e7SCédric Le Goater } 1253d2fd9612SCédric Le Goater 1254d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 1255d2fd9612SCédric Le Goater 1256d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1257d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1258d2fd9612SCédric Le Goater char core_name[32]; 1259d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 1260c035851aSCédric Le Goater uint64_t xscom_core_base; 1261d2fd9612SCédric Le Goater 1262d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1263d2fd9612SCédric Le Goater continue; 1264d2fd9612SCédric Le Goater } 1265d2fd9612SCédric Le Goater 1266d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1267bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize, 1268bc4c406cSPhilippe Mathieu-Daudé typename, &error_fatal, NULL); 1269fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1270d2fd9612SCédric Le Goater &error_fatal); 1271d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1272d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1273d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1274d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1275d2fd9612SCédric Le Goater "pir", &error_fatal); 1276d35aefa9SCédric Le Goater object_property_add_const_link(OBJECT(pnv_core), "chip", 1277d35aefa9SCédric Le Goater OBJECT(chip), &error_fatal); 1278d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1279d2fd9612SCédric Le Goater &error_fatal); 128024ece072SCédric Le Goater 128124ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1282c035851aSCédric Le Goater if (!pnv_chip_is_power9(chip)) { 1283c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1284c035851aSCédric Le Goater } else { 12855dad902cSCédric Le Goater xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); 1286c035851aSCédric Le Goater } 1287c035851aSCédric Le Goater 1288c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 128924ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 1290d2fd9612SCédric Le Goater i++; 1291d2fd9612SCédric Le Goater } 129251c04728SCédric Le Goater } 129351c04728SCédric Le Goater 129451c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 129551c04728SCédric Le Goater { 129651c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 129751c04728SCédric Le Goater Error *error = NULL; 129851c04728SCédric Le Goater 129951c04728SCédric Le Goater /* Cores */ 130051c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 130151c04728SCédric Le Goater if (error) { 130251c04728SCédric Le Goater error_propagate(errp, error); 130351c04728SCédric Le Goater return; 130451c04728SCédric Le Goater } 1305e997040eSCédric Le Goater } 1306e997040eSCédric Le Goater 1307e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1308e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1309e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1310e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1311397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1312397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1313e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1314e997040eSCédric Le Goater }; 1315e997040eSCédric Le Goater 1316e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1317e997040eSCédric Le Goater { 1318e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1319e997040eSCédric Le Goater 13209d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1321e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1322e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1323e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1324e997040eSCédric Le Goater } 1325e997040eSCédric Le Goater 132654f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 132754f59d78SCédric Le Goater { 1328b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 132954f59d78SCédric Le Goater int i; 133054f59d78SCédric Le Goater 133154f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 133277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 133377864267SCédric Le Goater 133477864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 133577864267SCédric Le Goater return &chip8->psi.ics; 133654f59d78SCédric Le Goater } 133754f59d78SCédric Le Goater } 133854f59d78SCédric Le Goater return NULL; 133954f59d78SCédric Le Goater } 134054f59d78SCédric Le Goater 134154f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 134254f59d78SCédric Le Goater { 1343b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 134454f59d78SCédric Le Goater int i; 134554f59d78SCédric Le Goater 134654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 134777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 134877864267SCédric Le Goater ics_resend(&chip8->psi.ics); 134954f59d78SCédric Le Goater } 135054f59d78SCédric Le Goater } 135154f59d78SCédric Le Goater 135236fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 135336fc6f08SCédric Le Goater { 135436fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 135536fc6f08SCédric Le Goater 1356956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 135736fc6f08SCédric Le Goater } 135836fc6f08SCédric Le Goater 135947fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 136047fea43aSCédric Le Goater Monitor *mon) 136147fea43aSCédric Le Goater { 1362b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 136354f59d78SCédric Le Goater int i; 136447fea43aSCédric Le Goater CPUState *cs; 136547fea43aSCédric Le Goater 136647fea43aSCédric Le Goater CPU_FOREACH(cs) { 136747fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 136847fea43aSCédric Le Goater 1369d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1370d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1371d8e4aad5SCédric Le Goater } else { 1372956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 137347fea43aSCédric Le Goater } 1374d8e4aad5SCédric Le Goater } 137554f59d78SCédric Le Goater 137654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1377d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 137854f59d78SCédric Le Goater } 137947fea43aSCédric Le Goater } 138047fea43aSCédric Le Goater 1381e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1382e997040eSCédric Le Goater void *opaque, Error **errp) 1383e997040eSCédric Le Goater { 1384b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1385e997040eSCédric Le Goater } 1386e997040eSCédric Le Goater 1387e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1388e997040eSCédric Le Goater void *opaque, Error **errp) 1389e997040eSCédric Le Goater { 1390b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1391e997040eSCédric Le Goater uint32_t num_chips; 1392e997040eSCédric Le Goater Error *local_err = NULL; 1393e997040eSCédric Le Goater 1394e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1395e997040eSCédric Le Goater if (local_err) { 1396e997040eSCédric Le Goater error_propagate(errp, local_err); 1397e997040eSCédric Le Goater return; 1398e997040eSCédric Le Goater } 1399e997040eSCédric Le Goater 1400e997040eSCédric Le Goater /* 1401e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1402e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1403e997040eSCédric Le Goater */ 1404e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1405e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1406e997040eSCédric Le Goater return; 1407e997040eSCédric Le Goater } 1408e997040eSCédric Le Goater 1409e997040eSCédric Le Goater pnv->num_chips = num_chips; 1410e997040eSCédric Le Goater } 1411e997040eSCédric Le Goater 141277864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1413e997040eSCédric Le Goater { 1414b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1415e997040eSCédric Le Goater pnv->num_chips = 1; 1416e997040eSCédric Le Goater } 1417e997040eSCédric Le Goater 1418b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1419e997040eSCédric Le Goater { 14201e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1421e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1422e997040eSCédric Le Goater NULL, NULL, NULL); 1423e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1424e997040eSCédric Le Goater "Specifies the number of processor chips", 1425e997040eSCédric Le Goater NULL); 14269e933f4aSBenjamin Herrenschmidt } 14279e933f4aSBenjamin Herrenschmidt 1428f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 14299e933f4aSBenjamin Herrenschmidt { 14309e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 143136fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1432f30c843cSCédric Le Goater 1433f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1434f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1435f30c843cSCédric Le Goater 1436f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1437f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1438f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1439f30c843cSCédric Le Goater } 1440f30c843cSCédric Le Goater 1441f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1442f30c843cSCédric Le Goater { 1443f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1444f30c843cSCédric Le Goater 1445f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1446f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1447f30c843cSCédric Le Goater 1448f30c843cSCédric Le Goater mc->alias = "powernv"; 1449f30c843cSCédric Le Goater } 1450f30c843cSCédric Le Goater 1451f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1452f30c843cSCédric Le Goater { 1453f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 145447fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 14559e933f4aSBenjamin Herrenschmidt 14569e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1457b168a138SCédric Le Goater mc->init = pnv_init; 1458b168a138SCédric Le Goater mc->reset = pnv_reset; 14599e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 146059b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 146159b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 14629e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 14639e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1464f1d18b0aSJoel Stanley /* 1465f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1466f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1467f1d18b0aSJoel Stanley */ 1468f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 146947fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1470e997040eSCédric Le Goater 1471b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 14729e933f4aSBenjamin Herrenschmidt } 14739e933f4aSBenjamin Herrenschmidt 147477864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1475beba5c0fSIgor Mammedov { \ 1476beba5c0fSIgor Mammedov .name = type, \ 1477beba5c0fSIgor Mammedov .class_init = class_initfn, \ 147877864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 147977864267SCédric Le Goater } 148077864267SCédric Le Goater 148177864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 148277864267SCédric Le Goater { \ 148377864267SCédric Le Goater .name = type, \ 148477864267SCédric Le Goater .class_init = class_initfn, \ 148577864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1486beba5c0fSIgor Mammedov } 1487beba5c0fSIgor Mammedov 1488f30c843cSCédric Le Goater #define DEFINE_PNV_MACHINE_TYPE(cpu, class_initfn) \ 1489f30c843cSCédric Le Goater { \ 1490f30c843cSCédric Le Goater .name = MACHINE_TYPE_NAME(cpu), \ 1491f30c843cSCédric Le Goater .parent = TYPE_PNV_MACHINE, \ 1492f30c843cSCédric Le Goater .instance_size = sizeof(PnvMachineState), \ 1493f30c843cSCédric Le Goater .instance_init = pnv_machine_instance_init, \ 1494f30c843cSCédric Le Goater .class_init = class_initfn, \ 1495f30c843cSCédric Le Goater .interfaces = (InterfaceInfo[]) { \ 1496f30c843cSCédric Le Goater { TYPE_XICS_FABRIC }, \ 1497f30c843cSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, \ 1498f30c843cSCédric Le Goater { }, \ 1499f30c843cSCédric Le Goater }, \ 1500f30c843cSCédric Le Goater } 1501f30c843cSCédric Le Goater 1502beba5c0fSIgor Mammedov static const TypeInfo types[] = { 1503f30c843cSCédric Le Goater DEFINE_PNV_MACHINE_TYPE("powernv8", pnv_machine_power8_class_init), 1504f30c843cSCédric Le Goater DEFINE_PNV_MACHINE_TYPE("powernv9", pnv_machine_power9_class_init), 1505beba5c0fSIgor Mammedov { 1506b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 15079e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1508f30c843cSCédric Le Goater .abstract = true, 15099e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 151077864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1511b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 151236fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 151336fc6f08SCédric Le Goater { TYPE_XICS_FABRIC }, 151447fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 151536fc6f08SCédric Le Goater { }, 151636fc6f08SCédric Le Goater }, 1517beba5c0fSIgor Mammedov }, 1518beba5c0fSIgor Mammedov { 1519beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1520beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1521beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1522beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1523beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1524beba5c0fSIgor Mammedov .abstract = true, 1525beba5c0fSIgor Mammedov }, 152677864267SCédric Le Goater 152777864267SCédric Le Goater /* 152877864267SCédric Le Goater * P9 chip and variants 152977864267SCédric Le Goater */ 153077864267SCédric Le Goater { 153177864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 153277864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 153377864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 153477864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 153577864267SCédric Le Goater }, 153677864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 153777864267SCédric Le Goater 153877864267SCédric Le Goater /* 153977864267SCédric Le Goater * P8 chip and variants 154077864267SCédric Le Goater */ 154177864267SCédric Le Goater { 154277864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 154377864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 154477864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 154577864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 154677864267SCédric Le Goater }, 154777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 154877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 154977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1550beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 15519e933f4aSBenjamin Herrenschmidt }; 15529e933f4aSBenjamin Herrenschmidt 1553beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1554