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))); 190*59b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 191*59b7c1c2SBalamuruhan 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 204*59b7c1c2SBalamuruhan S /* 205*59b7c1c2SBalamuruhan 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 208*59b7c1c2SBalamuruhan S * 2 == VSX available 209*59b7c1c2SBalamuruhan 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 216*59b7c1c2SBalamuruhan S /* 217*59b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 218d2fd9612SCédric Le Goater * 0 / no property == no DFP 219*59b7c1c2SBalamuruhan S * 1 == DFP available 220*59b7c1c2SBalamuruhan 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 432*59b7c1c2SBalamuruhan S /* 433*59b7c1c2SBalamuruhan 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 451*59b7c1c2SBalamuruhan S /* 452*59b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 453*59b7c1c2SBalamuruhan S * can not use object_child_foreach() 454*59b7c1c2SBalamuruhan 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 556*59b7c1c2SBalamuruhan S /* 557*59b7c1c2SBalamuruhan 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 717*59b7c1c2SBalamuruhan S /* 718*59b7c1c2SBalamuruhan 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 745*59b7c1c2SBalamuruhan S /* 746*59b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 747*59b7c1c2SBalamuruhan S * host to powerdown 748*59b7c1c2SBalamuruhan 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 818*59b7c1c2SBalamuruhan S /* 819*59b7c1c2SBalamuruhan 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); 86377864267SCédric Le Goater } 86477864267SCédric Le Goater 86577864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 86677864267SCédric Le Goater { 86777864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 86877864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 86977864267SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 87077864267SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 87177864267SCédric Le Goater int i, j; 87277864267SCédric Le Goater char *name; 87377864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 87477864267SCédric Le Goater 87577864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 87677864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 87777864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 87877864267SCédric Le Goater g_free(name); 87977864267SCédric Le Goater 88077864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 88177864267SCédric Le Goater 88277864267SCédric Le Goater /* Map the ICP registers for each thread */ 88377864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 88477864267SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 88577864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 88677864267SCédric Le Goater 88777864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 88877864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 88977864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 89077864267SCédric Le Goater 89177864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 89277864267SCédric Le Goater &icp->mmio); 89377864267SCédric Le Goater } 89477864267SCédric Le Goater } 89577864267SCédric Le Goater } 89677864267SCédric Le Goater 89777864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 89877864267SCédric Le Goater { 89977864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 90077864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 90177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 902ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 90377864267SCédric Le Goater Error *local_err = NULL; 90477864267SCédric Le Goater 905709044fdSCédric Le Goater /* XSCOM bridge is first */ 906709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 907709044fdSCédric Le Goater if (local_err) { 908709044fdSCédric Le Goater error_propagate(errp, local_err); 909709044fdSCédric Le Goater return; 910709044fdSCédric Le Goater } 911709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 912709044fdSCédric Le Goater 91377864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 91477864267SCédric Le Goater if (local_err) { 91577864267SCédric Le Goater error_propagate(errp, local_err); 91677864267SCédric Le Goater return; 91777864267SCédric Le Goater } 91877864267SCédric Le Goater 91977864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 92077864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 92177864267SCédric Le Goater "bar", &error_fatal); 92277864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 92377864267SCédric Le Goater if (local_err) { 92477864267SCédric Le Goater error_propagate(errp, local_err); 92577864267SCédric Le Goater return; 92677864267SCédric Le Goater } 927ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 928ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 92977864267SCédric Le Goater 93077864267SCédric Le Goater /* Create LPC controller */ 93177864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 93277864267SCédric Le Goater &error_fatal); 93377864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 93477864267SCédric Le Goater 93564d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 93664d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 93764d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 93864d011d5SCédric Le Goater 939*59b7c1c2SBalamuruhan S /* 940*59b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 941*59b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 942*59b7c1c2SBalamuruhan S */ 94377864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 94477864267SCédric Le Goater if (local_err) { 94577864267SCédric Le Goater error_propagate(errp, local_err); 94677864267SCédric Le Goater return; 94777864267SCédric Le Goater } 94877864267SCédric Le Goater 94977864267SCédric Le Goater /* Create the simplified OCC model */ 95077864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 95177864267SCédric Le Goater if (local_err) { 95277864267SCédric Le Goater error_propagate(errp, local_err); 95377864267SCédric Le Goater return; 95477864267SCédric Le Goater } 95577864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 95677864267SCédric Le Goater } 95777864267SCédric Le Goater 958e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 959e997040eSCédric Le Goater { 960e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 961e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 962e997040eSCédric Le Goater 963e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 964e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 965397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 966631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 967d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 96804026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 969eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 970d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 971e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 97277864267SCédric Le Goater 97377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 97477864267SCédric Le Goater &k->parent_realize); 975e997040eSCédric Le Goater } 976e997040eSCédric Le Goater 977e997040eSCédric Le Goater static void pnv_chip_power8_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_POWER8; 983e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 984397a79e7SCédric Le Goater k->cores_mask = POWER8_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 POWER8"; 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_power8nvl_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_POWER8NVL; 1002e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.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_power8nvl_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 POWER8NVL"; 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); 101377864267SCédric Le Goater } 101477864267SCédric Le Goater 101577864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 101677864267SCédric Le Goater { 10172dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 10182dfa91a2SCédric Le Goater 10192dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 10202dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 10212dfa91a2SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj, 10222dfa91a2SCédric Le Goater &error_abort); 1023c38536bcSCédric Le Goater 1024c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1025c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 1026c38536bcSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj, 1027c38536bcSCédric Le Goater &error_abort); 102815376c66SCédric Le Goater 102915376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 103015376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 103115376c66SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->lpc), "psi", 103215376c66SCédric Le Goater OBJECT(&chip9->psi), &error_abort); 10336598a70dSCédric Le Goater 10346598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 10356598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 10366598a70dSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->occ), "psi", 10376598a70dSCédric Le Goater OBJECT(&chip9->psi), &error_abort); 103877864267SCédric Le Goater } 103977864267SCédric Le Goater 10405dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 10415dad902cSCédric Le Goater { 10425dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 10435dad902cSCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 10445dad902cSCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 10455dad902cSCédric Le Goater int i; 10465dad902cSCédric Le Goater 10475dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 10485dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 10495dad902cSCédric Le Goater 10505dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 10515dad902cSCédric Le Goater char eq_name[32]; 10525dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 10535dad902cSCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); 10545dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 10555dad902cSCédric Le Goater 10565dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1057bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1058bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 10595dad902cSCédric Le Goater 10605dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 10615dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 10625dad902cSCédric Le Goater 10635dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 10645dad902cSCédric Le Goater &eq->xscom_regs); 10655dad902cSCédric Le Goater } 10665dad902cSCédric Le Goater } 10675dad902cSCédric Le Goater 106877864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 106977864267SCédric Le Goater { 107077864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 10712dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 10722dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1073c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 107477864267SCédric Le Goater Error *local_err = NULL; 107577864267SCédric Le Goater 1076709044fdSCédric Le Goater /* XSCOM bridge is first */ 1077709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1078709044fdSCédric Le Goater if (local_err) { 1079709044fdSCédric Le Goater error_propagate(errp, local_err); 1080709044fdSCédric Le Goater return; 1081709044fdSCédric Le Goater } 1082709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1083709044fdSCédric Le Goater 108477864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 108577864267SCédric Le Goater if (local_err) { 108677864267SCédric Le Goater error_propagate(errp, local_err); 108777864267SCédric Le Goater return; 108877864267SCédric Le Goater } 10892dfa91a2SCédric Le Goater 10905dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 10915dad902cSCédric Le Goater if (local_err) { 10925dad902cSCédric Le Goater error_propagate(errp, local_err); 10935dad902cSCédric Le Goater return; 10945dad902cSCédric Le Goater } 10955dad902cSCédric Le Goater 10962dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 10972dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 10982dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 10992dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 11002dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 11012dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 11022dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 11032dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 11042dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 11052dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 11062dfa91a2SCédric Le Goater &local_err); 11072dfa91a2SCédric Le Goater if (local_err) { 11082dfa91a2SCédric Le Goater error_propagate(errp, local_err); 11092dfa91a2SCédric Le Goater return; 11102dfa91a2SCédric Le Goater } 11112dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 11122dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1113c38536bcSCédric Le Goater 1114c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1115c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1116c38536bcSCédric Le Goater "bar", &error_fatal); 1117c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1118c38536bcSCédric Le Goater if (local_err) { 1119c38536bcSCédric Le Goater error_propagate(errp, local_err); 1120c38536bcSCédric Le Goater return; 1121c38536bcSCédric Le Goater } 1122c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1123c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 112415376c66SCédric Le Goater 112515376c66SCédric Le Goater /* LPC */ 112615376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 112715376c66SCédric Le Goater if (local_err) { 112815376c66SCédric Le Goater error_propagate(errp, local_err); 112915376c66SCédric Le Goater return; 113015376c66SCédric Le Goater } 113115376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 113215376c66SCédric Le Goater &chip9->lpc.xscom_regs); 113315376c66SCédric Le Goater 113415376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 113515376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 11366598a70dSCédric Le Goater 11376598a70dSCédric Le Goater /* Create the simplified OCC model */ 11386598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 11396598a70dSCédric Le Goater if (local_err) { 11406598a70dSCédric Le Goater error_propagate(errp, local_err); 11416598a70dSCédric Le Goater return; 11426598a70dSCédric Le Goater } 11436598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1144e997040eSCédric Le Goater } 1145e997040eSCédric Le Goater 1146e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1147e997040eSCédric Le Goater { 1148e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1149e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1150e997040eSCédric Le Goater 1151e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 115283028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1153397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1154631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1155d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 115604026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1157eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1158d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1159e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 116077864267SCédric Le Goater 116177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 116277864267SCédric Le Goater &k->parent_realize); 1163e997040eSCédric Le Goater } 1164e997040eSCédric Le Goater 1165397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1166397a79e7SCédric Le Goater { 1167397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1168397a79e7SCédric Le Goater int cores_max; 1169397a79e7SCédric Le Goater 1170397a79e7SCédric Le Goater /* 1171397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1172397a79e7SCédric Le Goater * the chip class 1173397a79e7SCédric Le Goater */ 1174397a79e7SCédric Le Goater if (!chip->cores_mask) { 1175397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1176397a79e7SCédric Le Goater } 1177397a79e7SCédric Le Goater 1178397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1179397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1180397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1181397a79e7SCédric Le Goater chip->cores_mask); 1182397a79e7SCédric Le Goater return; 1183397a79e7SCédric Le Goater } 1184397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1185397a79e7SCédric Le Goater 1186397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 118727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1188397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1189397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1190397a79e7SCédric Le Goater cores_max); 1191397a79e7SCédric Le Goater return; 1192397a79e7SCédric Le Goater } 1193397a79e7SCédric Le Goater } 1194397a79e7SCédric Le Goater 119551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1196e997040eSCédric Le Goater { 1197fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1198397a79e7SCédric Le Goater Error *error = NULL; 1199d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 120040abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1201d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 1202d2fd9612SCédric Le Goater int i, core_hwid; 1203397a79e7SCédric Le Goater 1204d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1205d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1206d2fd9612SCédric Le Goater return; 1207d2fd9612SCédric Le Goater } 1208d2fd9612SCédric Le Goater 1209d2fd9612SCédric Le Goater /* Cores */ 1210397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1211397a79e7SCédric Le Goater if (error) { 1212397a79e7SCédric Le Goater error_propagate(errp, error); 1213397a79e7SCédric Le Goater return; 1214397a79e7SCédric Le Goater } 1215d2fd9612SCédric Le Goater 1216d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 1217d2fd9612SCédric Le Goater 1218d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1219d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1220d2fd9612SCédric Le Goater char core_name[32]; 1221d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 1222c035851aSCédric Le Goater uint64_t xscom_core_base; 1223d2fd9612SCédric Le Goater 1224d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1225d2fd9612SCédric Le Goater continue; 1226d2fd9612SCédric Le Goater } 1227d2fd9612SCédric Le Goater 1228d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1229bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize, 1230bc4c406cSPhilippe Mathieu-Daudé typename, &error_fatal, NULL); 1231fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1232d2fd9612SCédric Le Goater &error_fatal); 1233d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1234d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1235d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1236d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1237d2fd9612SCédric Le Goater "pir", &error_fatal); 1238d35aefa9SCédric Le Goater object_property_add_const_link(OBJECT(pnv_core), "chip", 1239d35aefa9SCédric Le Goater OBJECT(chip), &error_fatal); 1240d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1241d2fd9612SCédric Le Goater &error_fatal); 124224ece072SCédric Le Goater 124324ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1244c035851aSCédric Le Goater if (!pnv_chip_is_power9(chip)) { 1245c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1246c035851aSCédric Le Goater } else { 12475dad902cSCédric Le Goater xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); 1248c035851aSCédric Le Goater } 1249c035851aSCédric Le Goater 1250c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 125124ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 1252d2fd9612SCédric Le Goater i++; 1253d2fd9612SCédric Le Goater } 125451c04728SCédric Le Goater } 125551c04728SCédric Le Goater 125651c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 125751c04728SCédric Le Goater { 125851c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 125951c04728SCédric Le Goater Error *error = NULL; 126051c04728SCédric Le Goater 126151c04728SCédric Le Goater /* Cores */ 126251c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 126351c04728SCédric Le Goater if (error) { 126451c04728SCédric Le Goater error_propagate(errp, error); 126551c04728SCédric Le Goater return; 126651c04728SCédric Le Goater } 1267e997040eSCédric Le Goater } 1268e997040eSCédric Le Goater 1269e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1270e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1271e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1272e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1273397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1274397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1275e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1276e997040eSCédric Le Goater }; 1277e997040eSCédric Le Goater 1278e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1279e997040eSCédric Le Goater { 1280e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1281e997040eSCédric Le Goater 12829d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1283e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1284e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1285e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1286e997040eSCédric Le Goater } 1287e997040eSCédric Le Goater 128854f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 128954f59d78SCédric Le Goater { 1290b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 129154f59d78SCédric Le Goater int i; 129254f59d78SCédric Le Goater 129354f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 129477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 129577864267SCédric Le Goater 129677864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 129777864267SCédric Le Goater return &chip8->psi.ics; 129854f59d78SCédric Le Goater } 129954f59d78SCédric Le Goater } 130054f59d78SCédric Le Goater return NULL; 130154f59d78SCédric Le Goater } 130254f59d78SCédric Le Goater 130354f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 130454f59d78SCédric Le Goater { 1305b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 130654f59d78SCédric Le Goater int i; 130754f59d78SCédric Le Goater 130854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 130977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 131077864267SCédric Le Goater ics_resend(&chip8->psi.ics); 131154f59d78SCédric Le Goater } 131254f59d78SCédric Le Goater } 131354f59d78SCédric Le Goater 131436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 131536fc6f08SCédric Le Goater { 131636fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 131736fc6f08SCédric Le Goater 1318956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 131936fc6f08SCédric Le Goater } 132036fc6f08SCédric Le Goater 132147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 132247fea43aSCédric Le Goater Monitor *mon) 132347fea43aSCédric Le Goater { 1324b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 132554f59d78SCédric Le Goater int i; 132647fea43aSCédric Le Goater CPUState *cs; 132747fea43aSCédric Le Goater 132847fea43aSCédric Le Goater CPU_FOREACH(cs) { 132947fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 133047fea43aSCédric Le Goater 1331d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1332d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1333d8e4aad5SCédric Le Goater } else { 1334956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 133547fea43aSCédric Le Goater } 1336d8e4aad5SCédric Le Goater } 133754f59d78SCédric Le Goater 133854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1339d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 134054f59d78SCédric Le Goater } 134147fea43aSCédric Le Goater } 134247fea43aSCédric Le Goater 1343e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1344e997040eSCédric Le Goater void *opaque, Error **errp) 1345e997040eSCédric Le Goater { 1346b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1347e997040eSCédric Le Goater } 1348e997040eSCédric Le Goater 1349e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1350e997040eSCédric Le Goater void *opaque, Error **errp) 1351e997040eSCédric Le Goater { 1352b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1353e997040eSCédric Le Goater uint32_t num_chips; 1354e997040eSCédric Le Goater Error *local_err = NULL; 1355e997040eSCédric Le Goater 1356e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1357e997040eSCédric Le Goater if (local_err) { 1358e997040eSCédric Le Goater error_propagate(errp, local_err); 1359e997040eSCédric Le Goater return; 1360e997040eSCédric Le Goater } 1361e997040eSCédric Le Goater 1362e997040eSCédric Le Goater /* 1363e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1364e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1365e997040eSCédric Le Goater */ 1366e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1367e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1368e997040eSCédric Le Goater return; 1369e997040eSCédric Le Goater } 1370e997040eSCédric Le Goater 1371e997040eSCédric Le Goater pnv->num_chips = num_chips; 1372e997040eSCédric Le Goater } 1373e997040eSCédric Le Goater 137477864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1375e997040eSCédric Le Goater { 1376b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1377e997040eSCédric Le Goater pnv->num_chips = 1; 1378e997040eSCédric Le Goater } 1379e997040eSCédric Le Goater 1380b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1381e997040eSCédric Le Goater { 13821e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1383e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1384e997040eSCédric Le Goater NULL, NULL, NULL); 1385e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1386e997040eSCédric Le Goater "Specifies the number of processor chips", 1387e997040eSCédric Le Goater NULL); 13889e933f4aSBenjamin Herrenschmidt } 13899e933f4aSBenjamin Herrenschmidt 1390f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 13919e933f4aSBenjamin Herrenschmidt { 13929e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 139336fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1394f30c843cSCédric Le Goater 1395f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1396f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1397f30c843cSCédric Le Goater 1398f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1399f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1400f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1401f30c843cSCédric Le Goater } 1402f30c843cSCédric Le Goater 1403f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1404f30c843cSCédric Le Goater { 1405f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1406f30c843cSCédric Le Goater 1407f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1408f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1409f30c843cSCédric Le Goater 1410f30c843cSCédric Le Goater mc->alias = "powernv"; 1411f30c843cSCédric Le Goater } 1412f30c843cSCédric Le Goater 1413f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1414f30c843cSCédric Le Goater { 1415f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 141647fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 14179e933f4aSBenjamin Herrenschmidt 14189e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1419b168a138SCédric Le Goater mc->init = pnv_init; 1420b168a138SCédric Le Goater mc->reset = pnv_reset; 14219e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 1422*59b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 1423*59b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 14249e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 14259e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1426f1d18b0aSJoel Stanley /* 1427f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1428f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1429f1d18b0aSJoel Stanley */ 1430f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 143147fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1432e997040eSCédric Le Goater 1433b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 14349e933f4aSBenjamin Herrenschmidt } 14359e933f4aSBenjamin Herrenschmidt 143677864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1437beba5c0fSIgor Mammedov { \ 1438beba5c0fSIgor Mammedov .name = type, \ 1439beba5c0fSIgor Mammedov .class_init = class_initfn, \ 144077864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 144177864267SCédric Le Goater } 144277864267SCédric Le Goater 144377864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 144477864267SCédric Le Goater { \ 144577864267SCédric Le Goater .name = type, \ 144677864267SCédric Le Goater .class_init = class_initfn, \ 144777864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1448beba5c0fSIgor Mammedov } 1449beba5c0fSIgor Mammedov 1450f30c843cSCédric Le Goater #define DEFINE_PNV_MACHINE_TYPE(cpu, class_initfn) \ 1451f30c843cSCédric Le Goater { \ 1452f30c843cSCédric Le Goater .name = MACHINE_TYPE_NAME(cpu), \ 1453f30c843cSCédric Le Goater .parent = TYPE_PNV_MACHINE, \ 1454f30c843cSCédric Le Goater .instance_size = sizeof(PnvMachineState), \ 1455f30c843cSCédric Le Goater .instance_init = pnv_machine_instance_init, \ 1456f30c843cSCédric Le Goater .class_init = class_initfn, \ 1457f30c843cSCédric Le Goater .interfaces = (InterfaceInfo[]) { \ 1458f30c843cSCédric Le Goater { TYPE_XICS_FABRIC }, \ 1459f30c843cSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, \ 1460f30c843cSCédric Le Goater { }, \ 1461f30c843cSCédric Le Goater }, \ 1462f30c843cSCédric Le Goater } 1463f30c843cSCédric Le Goater 1464beba5c0fSIgor Mammedov static const TypeInfo types[] = { 1465f30c843cSCédric Le Goater DEFINE_PNV_MACHINE_TYPE("powernv8", pnv_machine_power8_class_init), 1466f30c843cSCédric Le Goater DEFINE_PNV_MACHINE_TYPE("powernv9", pnv_machine_power9_class_init), 1467beba5c0fSIgor Mammedov { 1468b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 14699e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1470f30c843cSCédric Le Goater .abstract = true, 14719e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 147277864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1473b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 147436fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 147536fc6f08SCédric Le Goater { TYPE_XICS_FABRIC }, 147647fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 147736fc6f08SCédric Le Goater { }, 147836fc6f08SCédric Le Goater }, 1479beba5c0fSIgor Mammedov }, 1480beba5c0fSIgor Mammedov { 1481beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1482beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1483beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1484beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1485beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1486beba5c0fSIgor Mammedov .abstract = true, 1487beba5c0fSIgor Mammedov }, 148877864267SCédric Le Goater 148977864267SCédric Le Goater /* 149077864267SCédric Le Goater * P9 chip and variants 149177864267SCédric Le Goater */ 149277864267SCédric Le Goater { 149377864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 149477864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 149577864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 149677864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 149777864267SCédric Le Goater }, 149877864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 149977864267SCédric Le Goater 150077864267SCédric Le Goater /* 150177864267SCédric Le Goater * P8 chip and variants 150277864267SCédric Le Goater */ 150377864267SCédric Le Goater { 150477864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 150577864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 150677864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 150777864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 150877864267SCédric Le Goater }, 150977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 151077864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 151177864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1512beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 15139e933f4aSBenjamin Herrenschmidt }; 15149e933f4aSBenjamin Herrenschmidt 1515beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1516