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" 26d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 278d409261SCédric Le Goater #include "sysemu/device_tree.h" 289e933f4aSBenjamin Herrenschmidt #include "hw/hw.h" 29fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 309e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 319e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 34d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 359e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 369e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 37e997040eSCédric Le Goater #include "qapi/visitor.h" 3847fea43aSCédric Le Goater #include "monitor/monitor.h" 3947fea43aSCédric Le Goater #include "hw/intc/intc.h" 40aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4158969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 429e933f4aSBenjamin Herrenschmidt 4336fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 44967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 45967b7523SCédric Le Goater 463495b6b6SCédric Le Goater #include "hw/isa/isa.h" 473495b6b6SCédric Le Goater #include "hw/char/serial.h" 483495b6b6SCédric Le Goater #include "hw/timer/mc146818rtc.h" 493495b6b6SCédric Le Goater 509e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 519e933f4aSBenjamin Herrenschmidt 52b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 539e933f4aSBenjamin Herrenschmidt 549e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 559e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 56b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 579e933f4aSBenjamin Herrenschmidt 589e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 59b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 60fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 61584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 629e933f4aSBenjamin Herrenschmidt 6340abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 6440abf43fSIgor Mammedov { 6540abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 6640abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 6740abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 6840abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 6940abf43fSIgor Mammedov g_free(s); 7040abf43fSIgor Mammedov return core_type; 7140abf43fSIgor Mammedov } 7240abf43fSIgor Mammedov 739e933f4aSBenjamin Herrenschmidt /* 749e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 759e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 769e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 779e933f4aSBenjamin Herrenschmidt */ 789e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 799e933f4aSBenjamin Herrenschmidt 809e933f4aSBenjamin Herrenschmidt /* 819e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 829e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 839e933f4aSBenjamin Herrenschmidt * per chip. 849e933f4aSBenjamin Herrenschmidt */ 85b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 869e933f4aSBenjamin Herrenschmidt { 879e933f4aSBenjamin Herrenschmidt char *mem_name; 889e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 899e933f4aSBenjamin Herrenschmidt int off; 909e933f4aSBenjamin Herrenschmidt 919e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 929e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 939e933f4aSBenjamin Herrenschmidt 949e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 959e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 969e933f4aSBenjamin Herrenschmidt g_free(mem_name); 979e933f4aSBenjamin Herrenschmidt 989e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 999e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1009e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1019e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1029e933f4aSBenjamin Herrenschmidt } 1039e933f4aSBenjamin Herrenschmidt 104d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 105d2fd9612SCédric Le Goater { 106d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 107d2fd9612SCédric Le Goater 108d2fd9612SCédric Le Goater if (cpus_offset < 0) { 109a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 110d2fd9612SCédric Le Goater if (cpus_offset) { 111d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 112d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 113d2fd9612SCédric Le Goater } 114d2fd9612SCédric Le Goater } 115d2fd9612SCédric Le Goater _FDT(cpus_offset); 116d2fd9612SCédric Le Goater return cpus_offset; 117d2fd9612SCédric Le Goater } 118d2fd9612SCédric Le Goater 119d2fd9612SCédric Le Goater /* 120d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 121d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 122d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 123d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 124d2fd9612SCédric Le Goater * servers. 125d2fd9612SCédric Le Goater */ 126b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 127d2fd9612SCédric Le Goater { 12808304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 12908304a86SDavid Gibson CPUState *cs = CPU(cpu); 130d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1318bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 132d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 133d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 134d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 135d2fd9612SCédric Le Goater int i; 136d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 137d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 138d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 139d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 140d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 141d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 142d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 143d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 144d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 145d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 146d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 147d2fd9612SCédric Le Goater int offset; 148d2fd9612SCédric Le Goater char *nodename; 149d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 150d2fd9612SCédric Le Goater 151d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 152d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 153d2fd9612SCédric Le Goater _FDT(offset); 154d2fd9612SCédric Le Goater g_free(nodename); 155d2fd9612SCédric Le Goater 156d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 157d2fd9612SCédric Le Goater 158d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 159d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 160d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 161d2fd9612SCédric Le Goater 162d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 164d2fd9612SCédric Le Goater env->dcache_line_size))); 165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 166d2fd9612SCédric Le Goater env->dcache_line_size))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 168d2fd9612SCédric Le Goater env->icache_line_size))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 170d2fd9612SCédric Le Goater env->icache_line_size))); 171d2fd9612SCédric Le Goater 172d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 174d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 175d2fd9612SCédric Le Goater } else { 1763dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 177d2fd9612SCédric Le Goater } 178d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 179d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 180d2fd9612SCédric Le Goater pcc->l1_icache_size))); 181d2fd9612SCédric Le Goater } else { 1823dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 183d2fd9612SCédric Le Goater } 184d2fd9612SCédric Le Goater 185d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 186d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 18767d7d66fSDavid Gibson _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size))); 188d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 189d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 190d2fd9612SCédric Le Goater 191d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 192d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 193d2fd9612SCédric Le Goater } 194d2fd9612SCédric Le Goater 19558969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 196d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 197d2fd9612SCédric Le Goater segs, sizeof(segs)))); 198d2fd9612SCédric Le Goater } 199d2fd9612SCédric Le Goater 200d2fd9612SCédric Le Goater /* Advertise VMX/VSX (vector extensions) if available 201d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 202d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 203d2fd9612SCédric Le Goater * 2 == VSX available */ 204d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 205d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 206d2fd9612SCédric Le Goater 207d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 208d2fd9612SCédric Le Goater } 209d2fd9612SCédric Le Goater 210d2fd9612SCédric Le Goater /* Advertise DFP (Decimal Floating Point) if available 211d2fd9612SCédric Le Goater * 0 / no property == no DFP 212d2fd9612SCédric Le Goater * 1 == DFP available */ 213d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 214d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 215d2fd9612SCédric Le Goater } 216d2fd9612SCédric Le Goater 217644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 218d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 219d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 220d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 221d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 222d2fd9612SCédric Le Goater } 223d2fd9612SCédric Le Goater 224d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 225d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 226d2fd9612SCédric Le Goater 227d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 228d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 229d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 230d2fd9612SCédric Le Goater } 231d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 232d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 233d2fd9612SCédric Le Goater } 234d2fd9612SCédric Le Goater 235b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 236bf5615e7SCédric Le Goater uint32_t nr_threads) 237bf5615e7SCédric Le Goater { 238bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 239bf5615e7SCédric Le Goater char *name; 240bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 241bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 242bf5615e7SCédric Le Goater uint64_t *reg; 243bf5615e7SCédric Le Goater int offset; 244bf5615e7SCédric Le Goater 245bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 246bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 247bf5615e7SCédric Le Goater 248bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 249bf5615e7SCédric Le Goater reg = g_malloc(rsize); 250bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 251bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 252bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 253bf5615e7SCédric Le Goater } 254bf5615e7SCédric Le Goater 255bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 256bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 257bf5615e7SCédric Le Goater _FDT(offset); 258bf5615e7SCédric Le Goater g_free(name); 259bf5615e7SCédric Le Goater 260bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 261bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 262bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 263bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 264bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 265bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 266bf5615e7SCédric Le Goater irange, sizeof(irange)))); 267bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 268bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 269bf5615e7SCédric Le Goater g_free(reg); 270bf5615e7SCédric Le Goater } 271bf5615e7SCédric Le Goater 272eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 273e997040eSCédric Le Goater { 27440abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 275d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 276d2fd9612SCédric Le Goater int i; 277d2fd9612SCédric Le Goater 278b168a138SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 279967b7523SCédric Le Goater 280d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 281d2fd9612SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 282d2fd9612SCédric Le Goater 283b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 284bf5615e7SCédric Le Goater 285bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 286b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 287d2fd9612SCédric Le Goater } 288d2fd9612SCédric Le Goater 289e997040eSCédric Le Goater if (chip->ram_size) { 290b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 291e997040eSCédric Le Goater } 292e997040eSCédric Le Goater } 293e997040eSCédric Le Goater 294eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 295eb859a27SCédric Le Goater { 296eb859a27SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 297eb859a27SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 298eb859a27SCédric Le Goater int i; 299eb859a27SCédric Le Goater 300eb859a27SCédric Le Goater pnv_dt_xscom(chip, fdt, 0); 301eb859a27SCédric Le Goater 302eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 303eb859a27SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 304eb859a27SCédric Le Goater 305eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 306eb859a27SCédric Le Goater } 307eb859a27SCédric Le Goater 308eb859a27SCédric Le Goater if (chip->ram_size) { 309eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 310eb859a27SCédric Le Goater } 31115376c66SCédric Le Goater 31215376c66SCédric Le Goater pnv_dt_lpc(chip, fdt, 0); 313eb859a27SCédric Le Goater } 314eb859a27SCédric Le Goater 315b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 316c5ffdcaeSCédric Le Goater { 317c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 318c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 319c5ffdcaeSCédric Le Goater cpu_to_be32(1), 320c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 321c5ffdcaeSCédric Le Goater cpu_to_be32(2) 322c5ffdcaeSCédric Le Goater }; 323c5ffdcaeSCédric Le Goater char *name; 324c5ffdcaeSCédric Le Goater int node; 325c5ffdcaeSCédric Le Goater 326c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 327c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 328c5ffdcaeSCédric Le Goater _FDT(node); 329c5ffdcaeSCédric Le Goater g_free(name); 330c5ffdcaeSCédric Le Goater 331c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 332c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 333c5ffdcaeSCédric Le Goater } 334c5ffdcaeSCédric Le Goater 335b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 336cb228f5aSCédric Le Goater { 337cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 338cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 339cb228f5aSCédric Le Goater uint32_t io_regs[] = { 340cb228f5aSCédric Le Goater cpu_to_be32(1), 341cb228f5aSCédric Le Goater cpu_to_be32(io_base), 342cb228f5aSCédric Le Goater cpu_to_be32(8) 343cb228f5aSCédric Le Goater }; 344cb228f5aSCédric Le Goater char *name; 345cb228f5aSCédric Le Goater int node; 346cb228f5aSCédric Le Goater 347cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 348cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 349cb228f5aSCédric Le Goater _FDT(node); 350cb228f5aSCédric Le Goater g_free(name); 351cb228f5aSCédric Le Goater 352cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 353cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 354cb228f5aSCédric Le Goater sizeof(compatible)))); 355cb228f5aSCédric Le Goater 356cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 357cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 358cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 359cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 360cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 361cb228f5aSCédric Le Goater 362cb228f5aSCédric Le Goater /* This is needed by Linux */ 363cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 364cb228f5aSCédric Le Goater } 365cb228f5aSCédric Le Goater 366b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 36704f6c8b2SCédric Le Goater { 36804f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 36904f6c8b2SCédric Le Goater uint32_t io_base; 37004f6c8b2SCédric Le Goater uint32_t io_regs[] = { 37104f6c8b2SCédric Le Goater cpu_to_be32(1), 37204f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 37304f6c8b2SCédric Le Goater cpu_to_be32(3) 37404f6c8b2SCédric Le Goater }; 37504f6c8b2SCédric Le Goater uint32_t irq; 37604f6c8b2SCédric Le Goater char *name; 37704f6c8b2SCédric Le Goater int node; 37804f6c8b2SCédric Le Goater 37904f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 38004f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 38104f6c8b2SCédric Le Goater 38204f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 38304f6c8b2SCédric Le Goater 38404f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 38504f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 38604f6c8b2SCédric Le Goater _FDT(node); 38704f6c8b2SCédric Le Goater g_free(name); 38804f6c8b2SCédric Le Goater 3897032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 3907032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 3917032d92aSCédric Le Goater sizeof(compatible)))); 39204f6c8b2SCédric Le Goater 39304f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 39404f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 39504f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 39604f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 39704f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 39804f6c8b2SCédric Le Goater } 39904f6c8b2SCédric Le Goater 400e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 401e7a3fee3SCédric Le Goater void *fdt; 402e7a3fee3SCédric Le Goater int offset; 403e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 404e7a3fee3SCédric Le Goater 405b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 406e7a3fee3SCédric Le Goater { 407c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 408c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 409c5ffdcaeSCédric Le Goater 410c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 411b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 412cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 413b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 41404f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 415b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 416c5ffdcaeSCédric Le Goater } else { 417c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 418c5ffdcaeSCédric Le Goater d->ioport_id); 419c5ffdcaeSCédric Le Goater } 420c5ffdcaeSCédric Le Goater 421e7a3fee3SCédric Le Goater return 0; 422e7a3fee3SCédric Le Goater } 423e7a3fee3SCédric Le Goater 424bb7ab95cSCédric Le Goater /* The default LPC bus of a multichip system is on chip 0. It's 425bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 426bb7ab95cSCédric Le Goater */ 427bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 428bb7ab95cSCédric Le Goater { 42964d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 430e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 431e7a3fee3SCédric Le Goater .fdt = fdt, 432bb7ab95cSCédric Le Goater .offset = isa_offset, 433e7a3fee3SCédric Le Goater }; 434e7a3fee3SCédric Le Goater 435bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 436bb7ab95cSCédric Le Goater 437e7a3fee3SCédric Le Goater /* ISA devices are not necessarily parented to the ISA bus so we 438e7a3fee3SCédric Le Goater * can not use object_child_foreach() */ 439bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 440bb7ab95cSCédric Le Goater &args); 441e7a3fee3SCédric Le Goater } 442e7a3fee3SCédric Le Goater 443e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt) 444e5694793SCédric Le Goater { 445e5694793SCédric Le Goater int off; 446e5694793SCédric Le Goater 447e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 448e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 449e5694793SCédric Le Goater 450e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 451e5694793SCédric Le Goater } 452e5694793SCédric Le Goater 453b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4549e933f4aSBenjamin Herrenschmidt { 45583b90bf0SCédric Le Goater const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 45683b90bf0SCédric Le Goater const char plat_compat9[] = "qemu,powernv9\0ibm,powernv"; 457b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 4589e933f4aSBenjamin Herrenschmidt void *fdt; 4599e933f4aSBenjamin Herrenschmidt char *buf; 4609e933f4aSBenjamin Herrenschmidt int off; 461e997040eSCédric Le Goater int i; 4629e933f4aSBenjamin Herrenschmidt 4639e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 4649e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 4659e933f4aSBenjamin Herrenschmidt 4669e933f4aSBenjamin Herrenschmidt /* Root node */ 4679e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 4689e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 4699e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 4709e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 47183b90bf0SCédric Le Goater if (pnv_is_power9(pnv)) { 47283b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9, 47383b90bf0SCédric Le Goater sizeof(plat_compat9)))); 47483b90bf0SCédric Le Goater } else { 47583b90bf0SCédric Le Goater _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8, 47683b90bf0SCédric Le Goater sizeof(plat_compat8)))); 47783b90bf0SCédric Le Goater } 47883b90bf0SCédric Le Goater 4799e933f4aSBenjamin Herrenschmidt 4809e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 4819e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 4829e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 4839e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 4849e933f4aSBenjamin Herrenschmidt } 4859e933f4aSBenjamin Herrenschmidt g_free(buf); 4869e933f4aSBenjamin Herrenschmidt 4879e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 4889e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 4899e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 4909e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 4919e933f4aSBenjamin Herrenschmidt } 4929e933f4aSBenjamin Herrenschmidt 4939e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 4949e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 4959e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 4969e933f4aSBenjamin Herrenschmidt 4979e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 4989e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 4999e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5009e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5019e933f4aSBenjamin Herrenschmidt } 5029e933f4aSBenjamin Herrenschmidt 503e997040eSCédric Le Goater /* Populate device tree for each chip */ 504e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 505eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 506e997040eSCédric Le Goater } 507e7a3fee3SCédric Le Goater 508e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 509bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 510aeaef83dSCédric Le Goater 511aeaef83dSCédric Le Goater if (pnv->bmc) { 512b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 513aeaef83dSCédric Le Goater } 514aeaef83dSCédric Le Goater 515e5694793SCédric Le Goater /* Create an extra node for power management on Power9 */ 516e5694793SCédric Le Goater if (pnv_is_power9(pnv)) { 517e5694793SCédric Le Goater pnv_dt_power_mgt(fdt); 518e5694793SCédric Le Goater } 519e5694793SCédric Le Goater 5209e933f4aSBenjamin Herrenschmidt return fdt; 5219e933f4aSBenjamin Herrenschmidt } 5229e933f4aSBenjamin Herrenschmidt 523bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 524bce0b691SCédric Le Goater { 525b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 526bce0b691SCédric Le Goater 527bce0b691SCédric Le Goater if (pnv->bmc) { 528bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 529bce0b691SCédric Le Goater } 530bce0b691SCédric Le Goater } 531bce0b691SCédric Le Goater 532b168a138SCédric Le Goater static void pnv_reset(void) 5339e933f4aSBenjamin Herrenschmidt { 5349e933f4aSBenjamin Herrenschmidt MachineState *machine = MACHINE(qdev_get_machine()); 535b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5369e933f4aSBenjamin Herrenschmidt void *fdt; 537aeaef83dSCédric Le Goater Object *obj; 5389e933f4aSBenjamin Herrenschmidt 5399e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5409e933f4aSBenjamin Herrenschmidt 541aeaef83dSCédric Le Goater /* OpenPOWER systems have a BMC, which can be defined on the 542aeaef83dSCédric Le Goater * command line with: 543aeaef83dSCédric Le Goater * 544aeaef83dSCédric Le Goater * -device ipmi-bmc-sim,id=bmc0 545aeaef83dSCédric Le Goater * 546aeaef83dSCédric Le Goater * This is the internal simulator but it could also be an external 547aeaef83dSCédric Le Goater * BMC. 548aeaef83dSCédric Le Goater */ 549a1a636b8SCédric Le Goater obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL); 550aeaef83dSCédric Le Goater if (obj) { 551aeaef83dSCédric Le Goater pnv->bmc = IPMI_BMC(obj); 552aeaef83dSCédric Le Goater } 553aeaef83dSCédric Le Goater 554b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5559e933f4aSBenjamin Herrenschmidt 5569e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5579e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5589e933f4aSBenjamin Herrenschmidt 5598d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 5609e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5619e933f4aSBenjamin Herrenschmidt } 5629e933f4aSBenjamin Herrenschmidt 56304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5643495b6b6SCédric Le Goater { 56577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 56677864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 56704026890SCédric Le Goater } 5683495b6b6SCédric Le Goater 56904026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 57004026890SCédric Le Goater { 57177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 57277864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 57304026890SCédric Le Goater } 5743495b6b6SCédric Le Goater 57504026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 57604026890SCédric Le Goater { 57715376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 57815376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 57904026890SCédric Le Goater } 5803495b6b6SCédric Le Goater 58104026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 58204026890SCédric Le Goater { 58304026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 5843495b6b6SCédric Le Goater } 5853495b6b6SCédric Le Goater 586d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 587d8e4aad5SCédric Le Goater { 588d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 589d8e4aad5SCédric Le Goater 590d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 591d8e4aad5SCédric Le Goater } 592d8e4aad5SCédric Le Goater 593d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 594d8e4aad5SCédric Le Goater { 595d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 596d8e4aad5SCédric Le Goater 597d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 598c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 599d8e4aad5SCédric Le Goater } 600d8e4aad5SCédric Le Goater 601b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 6029e933f4aSBenjamin Herrenschmidt { 603b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 6049e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 6059e933f4aSBenjamin Herrenschmidt char *fw_filename; 6069e933f4aSBenjamin Herrenschmidt long fw_size; 607e997040eSCédric Le Goater int i; 608e997040eSCédric Le Goater char *chip_typename; 6099e933f4aSBenjamin Herrenschmidt 6109e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 611d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 6123dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 6139e933f4aSBenjamin Herrenschmidt } 6149e933f4aSBenjamin Herrenschmidt 6159e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 616b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6179e933f4aSBenjamin Herrenschmidt machine->ram_size); 6189e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6199e933f4aSBenjamin Herrenschmidt 6209e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 6219e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 6229e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 6239e933f4aSBenjamin Herrenschmidt } 6249e933f4aSBenjamin Herrenschmidt 6259e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 62615fcedb2SCédric Le Goater if (!fw_filename) { 62715fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 62815fcedb2SCédric Le Goater exit(1); 62915fcedb2SCédric Le Goater } 6309e933f4aSBenjamin Herrenschmidt 6319e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 6329e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 63315fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 6349e933f4aSBenjamin Herrenschmidt exit(1); 6359e933f4aSBenjamin Herrenschmidt } 6369e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 6379e933f4aSBenjamin Herrenschmidt 6389e933f4aSBenjamin Herrenschmidt /* load kernel */ 6399e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 6409e933f4aSBenjamin Herrenschmidt long kernel_size; 6419e933f4aSBenjamin Herrenschmidt 6429e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 643b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 6449e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 645802fc7abSThomas Huth error_report("Could not load kernel '%s'", 6469e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 6479e933f4aSBenjamin Herrenschmidt exit(1); 6489e933f4aSBenjamin Herrenschmidt } 6499e933f4aSBenjamin Herrenschmidt } 6509e933f4aSBenjamin Herrenschmidt 6519e933f4aSBenjamin Herrenschmidt /* load initrd */ 6529e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 6539e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 6549e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 655584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 6569e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 657802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 6589e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 6599e933f4aSBenjamin Herrenschmidt exit(1); 6609e933f4aSBenjamin Herrenschmidt } 6619e933f4aSBenjamin Herrenschmidt } 662e997040eSCédric Le Goater 663e997040eSCédric Le Goater /* Create the processor chips */ 6644a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 6657fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 6664a12c699SIgor Mammedov i, machine->cpu_type); 667e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 6684a12c699SIgor Mammedov error_report("invalid CPU model '%.*s' for %s machine", 6694a12c699SIgor Mammedov i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name); 670e997040eSCédric Le Goater exit(1); 671e997040eSCédric Le Goater } 672e997040eSCédric Le Goater 673e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 674e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 675e997040eSCédric Le Goater char chip_name[32]; 676e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 677e997040eSCédric Le Goater 678e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 679e997040eSCédric Le Goater 680e997040eSCédric Le Goater /* TODO: put all the memory in one node on chip 0 until we find a 681e997040eSCédric Le Goater * way to specify different ranges for each chip 682e997040eSCédric Le Goater */ 683e997040eSCédric Le Goater if (i == 0) { 684e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 685e997040eSCédric Le Goater &error_fatal); 686e997040eSCédric Le Goater } 687e997040eSCédric Le Goater 688e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 689e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 690e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 691e997040eSCédric Le Goater &error_fatal); 692397a79e7SCédric Le Goater object_property_set_int(chip, smp_cores, "nr-cores", &error_fatal); 693e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 694e997040eSCédric Le Goater } 695e997040eSCédric Le Goater g_free(chip_typename); 6963495b6b6SCédric Le Goater 6973495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 69804026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 6993495b6b6SCédric Le Goater 7003495b6b6SCédric Le Goater /* Create serial port */ 701def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 7023495b6b6SCédric Le Goater 7033495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 7046c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 705bce0b691SCédric Le Goater 706bce0b691SCédric Le Goater /* OpenPOWER systems use a IPMI SEL Event message to notify the 707bce0b691SCédric Le Goater * host to powerdown */ 708bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 709bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 710e997040eSCédric Le Goater } 711e997040eSCédric Le Goater 712631adaffSCédric Le Goater /* 713631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 714631adaffSCédric Le Goater * 22:24 Chip ID 715631adaffSCédric Le Goater * 25:28 Core number 716631adaffSCédric Le Goater * 29:31 Thread ID 717631adaffSCédric Le Goater */ 718631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 719631adaffSCédric Le Goater { 720631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 721631adaffSCédric Le Goater } 722631adaffSCédric Le Goater 7238fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 724d35aefa9SCédric Le Goater Error **errp) 725d35aefa9SCédric Le Goater { 7268fa1f4efSCédric Le Goater Error *local_err = NULL; 7278fa1f4efSCédric Le Goater Object *obj; 7288907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 7298fa1f4efSCédric Le Goater 7308fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 7318fa1f4efSCédric Le Goater &local_err); 7328fa1f4efSCédric Le Goater if (local_err) { 7338fa1f4efSCédric Le Goater error_propagate(errp, local_err); 7348fa1f4efSCédric Le Goater return; 7358fa1f4efSCédric Le Goater } 7368fa1f4efSCédric Le Goater 737956b8f46SCédric Le Goater pnv_cpu->intc = obj; 738d35aefa9SCédric Le Goater } 739d35aefa9SCédric Le Goater 740631adaffSCédric Le Goater /* 741631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 742631adaffSCédric Le Goater * 49:52 Node ID 743631adaffSCédric Le Goater * 53:55 Chip ID 744631adaffSCédric Le Goater * 56 Reserved - Read as zero 745631adaffSCédric Le Goater * 57:61 Core number 746631adaffSCédric Le Goater * 62:63 Thread ID 747631adaffSCédric Le Goater * 748631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 749631adaffSCédric Le Goater */ 750631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 751631adaffSCédric Le Goater { 752631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 753631adaffSCédric Le Goater } 754631adaffSCédric Le Goater 7558fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 756d35aefa9SCédric Le Goater Error **errp) 757d35aefa9SCédric Le Goater { 7582dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 7592dfa91a2SCédric Le Goater Error *local_err = NULL; 7602dfa91a2SCédric Le Goater Object *obj; 7612dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 7622dfa91a2SCédric Le Goater 7632dfa91a2SCédric Le Goater /* 7642dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 7652dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 7662dfa91a2SCédric Le Goater * only used at runtime. 7672dfa91a2SCédric Le Goater */ 76826aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 7692dfa91a2SCédric Le Goater if (local_err) { 7702dfa91a2SCédric Le Goater error_propagate(errp, local_err); 7718fa1f4efSCédric Le Goater return; 772d35aefa9SCédric Le Goater } 773d35aefa9SCédric Le Goater 7742dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 7752dfa91a2SCédric Le Goater } 7762dfa91a2SCédric Le Goater 777397a79e7SCédric Le Goater /* Allowed core identifiers on a POWER8 Processor Chip : 778397a79e7SCédric Le Goater * 779397a79e7SCédric Le Goater * <EX0 reserved> 780397a79e7SCédric Le Goater * EX1 - Venice only 781397a79e7SCédric Le Goater * EX2 - Venice only 782397a79e7SCédric Le Goater * EX3 - Venice only 783397a79e7SCédric Le Goater * EX4 784397a79e7SCédric Le Goater * EX5 785397a79e7SCédric Le Goater * EX6 786397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 787397a79e7SCédric Le Goater * EX9 - Venice only 788397a79e7SCédric Le Goater * EX10 - Venice only 789397a79e7SCédric Le Goater * EX11 - Venice only 790397a79e7SCédric Le Goater * EX12 791397a79e7SCédric Le Goater * EX13 792397a79e7SCédric Le Goater * EX14 793397a79e7SCédric Le Goater * <EX15 reserved> 794397a79e7SCédric Le Goater */ 795397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 796397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 797397a79e7SCédric Le Goater 798397a79e7SCédric Le Goater /* 79909279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 800397a79e7SCédric Le Goater */ 80109279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 802397a79e7SCédric Le Goater 80377864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 80477864267SCédric Le Goater { 80577864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 80677864267SCédric Le Goater 807f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 808ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 80977864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 81077864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 81177864267SCédric Le Goater 812f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 81382514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 81477864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->lpc), "psi", 81577864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 81677864267SCédric Le Goater 817f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 8183233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 81977864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->occ), "psi", 82077864267SCédric Le Goater OBJECT(&chip8->psi), &error_abort); 82177864267SCédric Le Goater } 82277864267SCédric Le Goater 82377864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 82477864267SCédric Le Goater { 82577864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 82677864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 82777864267SCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 82877864267SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 82977864267SCédric Le Goater int i, j; 83077864267SCédric Le Goater char *name; 83177864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 83277864267SCédric Le Goater 83377864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 83477864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 83577864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 83677864267SCédric Le Goater g_free(name); 83777864267SCédric Le Goater 83877864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 83977864267SCédric Le Goater 84077864267SCédric Le Goater /* Map the ICP registers for each thread */ 84177864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 84277864267SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 84377864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 84477864267SCédric Le Goater 84577864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 84677864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 84777864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 84877864267SCédric Le Goater 84977864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 85077864267SCédric Le Goater &icp->mmio); 85177864267SCédric Le Goater } 85277864267SCédric Le Goater } 85377864267SCédric Le Goater } 85477864267SCédric Le Goater 85577864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 85677864267SCédric Le Goater { 85777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 85877864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 85977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 860ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 86177864267SCédric Le Goater Error *local_err = NULL; 86277864267SCédric Le Goater 863*709044fdSCédric Le Goater /* XSCOM bridge is first */ 864*709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 865*709044fdSCédric Le Goater if (local_err) { 866*709044fdSCédric Le Goater error_propagate(errp, local_err); 867*709044fdSCédric Le Goater return; 868*709044fdSCédric Le Goater } 869*709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 870*709044fdSCédric Le Goater 87177864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 87277864267SCédric Le Goater if (local_err) { 87377864267SCédric Le Goater error_propagate(errp, local_err); 87477864267SCédric Le Goater return; 87577864267SCédric Le Goater } 87677864267SCédric Le Goater 87777864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 87877864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 87977864267SCédric Le Goater "bar", &error_fatal); 88077864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 88177864267SCédric Le Goater if (local_err) { 88277864267SCédric Le Goater error_propagate(errp, local_err); 88377864267SCédric Le Goater return; 88477864267SCédric Le Goater } 885ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 886ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 88777864267SCédric Le Goater 88877864267SCédric Le Goater /* Create LPC controller */ 88977864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 89077864267SCédric Le Goater &error_fatal); 89177864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 89277864267SCédric Le Goater 89364d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 89464d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 89564d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 89664d011d5SCédric Le Goater 89777864267SCédric Le Goater /* Interrupt Management Area. This is the memory region holding 89877864267SCédric Le Goater * all the Interrupt Control Presenter (ICP) registers */ 89977864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 90077864267SCédric Le Goater if (local_err) { 90177864267SCédric Le Goater error_propagate(errp, local_err); 90277864267SCédric Le Goater return; 90377864267SCédric Le Goater } 90477864267SCédric Le Goater 90577864267SCédric Le Goater /* Create the simplified OCC model */ 90677864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 90777864267SCédric Le Goater if (local_err) { 90877864267SCédric Le Goater error_propagate(errp, local_err); 90977864267SCédric Le Goater return; 91077864267SCédric Le Goater } 91177864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 91277864267SCédric Le Goater } 91377864267SCédric Le Goater 914e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 915e997040eSCédric Le Goater { 916e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 917e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 918e997040eSCédric Le Goater 919e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 920e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 921397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 922631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 923d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 92404026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 925eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 926d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 927967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 928e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 92977864267SCédric Le Goater 93077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 93177864267SCédric Le Goater &k->parent_realize); 932e997040eSCédric Le Goater } 933e997040eSCédric Le Goater 934e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 935e997040eSCédric Le Goater { 936e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 937e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 938e997040eSCédric Le Goater 939e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 940e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 941397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 942631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 943d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 94404026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 945eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 946d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 947967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 948e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 94977864267SCédric Le Goater 95077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 95177864267SCédric Le Goater &k->parent_realize); 952e997040eSCédric Le Goater } 953e997040eSCédric Le Goater 954e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 955e997040eSCédric Le Goater { 956e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 957e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 958e997040eSCédric Le Goater 959e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 960e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 961397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 962631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 963d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 96404026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 965eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 966d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 967967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 968e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 96977864267SCédric Le Goater 97077864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 97177864267SCédric Le Goater &k->parent_realize); 97277864267SCédric Le Goater } 97377864267SCédric Le Goater 97477864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 97577864267SCédric Le Goater { 9762dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 9772dfa91a2SCédric Le Goater 9782dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 9792dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 9802dfa91a2SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj, 9812dfa91a2SCédric Le Goater &error_abort); 982c38536bcSCédric Le Goater 983c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 984c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 985c38536bcSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj, 986c38536bcSCédric Le Goater &error_abort); 98715376c66SCédric Le Goater 98815376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 98915376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 99015376c66SCédric Le Goater object_property_add_const_link(OBJECT(&chip9->lpc), "psi", 99115376c66SCédric Le Goater OBJECT(&chip9->psi), &error_abort); 9926598a70dSCédric Le Goater 9936598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 9946598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 9956598a70dSCédric Le Goater object_property_add_const_link(OBJECT(&chip9->occ), "psi", 9966598a70dSCédric Le Goater OBJECT(&chip9->psi), &error_abort); 99777864267SCédric Le Goater } 99877864267SCédric Le Goater 9995dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 10005dad902cSCédric Le Goater { 10015dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 10025dad902cSCédric Le Goater const char *typename = pnv_chip_core_typename(chip); 10035dad902cSCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 10045dad902cSCédric Le Goater int i; 10055dad902cSCédric Le Goater 10065dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 10075dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 10085dad902cSCédric Le Goater 10095dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 10105dad902cSCédric Le Goater char eq_name[32]; 10115dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 10125dad902cSCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize); 10135dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 10145dad902cSCédric Le Goater 10155dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1016bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1017bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 10185dad902cSCédric Le Goater 10195dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 10205dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 10215dad902cSCédric Le Goater 10225dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 10235dad902cSCédric Le Goater &eq->xscom_regs); 10245dad902cSCédric Le Goater } 10255dad902cSCédric Le Goater } 10265dad902cSCédric Le Goater 102777864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 102877864267SCédric Le Goater { 102977864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 10302dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 10312dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1032c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 103377864267SCédric Le Goater Error *local_err = NULL; 103477864267SCédric Le Goater 1035*709044fdSCédric Le Goater /* XSCOM bridge is first */ 1036*709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1037*709044fdSCédric Le Goater if (local_err) { 1038*709044fdSCédric Le Goater error_propagate(errp, local_err); 1039*709044fdSCédric Le Goater return; 1040*709044fdSCédric Le Goater } 1041*709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1042*709044fdSCédric Le Goater 104377864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 104477864267SCédric Le Goater if (local_err) { 104577864267SCédric Le Goater error_propagate(errp, local_err); 104677864267SCédric Le Goater return; 104777864267SCédric Le Goater } 10482dfa91a2SCédric Le Goater 10495dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 10505dad902cSCédric Le Goater if (local_err) { 10515dad902cSCédric Le Goater error_propagate(errp, local_err); 10525dad902cSCédric Le Goater return; 10535dad902cSCédric Le Goater } 10545dad902cSCédric Le Goater 10552dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 10562dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 10572dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 10582dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 10592dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 10602dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 10612dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 10622dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 10632dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 10642dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 10652dfa91a2SCédric Le Goater &local_err); 10662dfa91a2SCédric Le Goater if (local_err) { 10672dfa91a2SCédric Le Goater error_propagate(errp, local_err); 10682dfa91a2SCédric Le Goater return; 10692dfa91a2SCédric Le Goater } 10702dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 10712dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1072c38536bcSCédric Le Goater 1073c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1074c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1075c38536bcSCédric Le Goater "bar", &error_fatal); 1076c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1077c38536bcSCédric Le Goater if (local_err) { 1078c38536bcSCédric Le Goater error_propagate(errp, local_err); 1079c38536bcSCédric Le Goater return; 1080c38536bcSCédric Le Goater } 1081c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1082c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 108315376c66SCédric Le Goater 108415376c66SCédric Le Goater /* LPC */ 108515376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 108615376c66SCédric Le Goater if (local_err) { 108715376c66SCédric Le Goater error_propagate(errp, local_err); 108815376c66SCédric Le Goater return; 108915376c66SCédric Le Goater } 109015376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 109115376c66SCédric Le Goater &chip9->lpc.xscom_regs); 109215376c66SCédric Le Goater 109315376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 109415376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 10956598a70dSCédric Le Goater 10966598a70dSCédric Le Goater /* Create the simplified OCC model */ 10976598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 10986598a70dSCédric Le Goater if (local_err) { 10996598a70dSCédric Le Goater error_propagate(errp, local_err); 11006598a70dSCédric Le Goater return; 11016598a70dSCédric Le Goater } 11026598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1103e997040eSCédric Le Goater } 1104e997040eSCédric Le Goater 1105e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1106e997040eSCédric Le Goater { 1107e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1108e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1109e997040eSCédric Le Goater 1110e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 111183028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1112397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1113631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1114d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 111504026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1116eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1117d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1118967b7523SCédric Le Goater k->xscom_base = 0x00603fc00000000ull; 1119e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 112077864267SCédric Le Goater 112177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 112277864267SCédric Le Goater &k->parent_realize); 1123e997040eSCédric Le Goater } 1124e997040eSCédric Le Goater 1125397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1126397a79e7SCédric Le Goater { 1127397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1128397a79e7SCédric Le Goater int cores_max; 1129397a79e7SCédric Le Goater 1130397a79e7SCédric Le Goater /* 1131397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1132397a79e7SCédric Le Goater * the chip class 1133397a79e7SCédric Le Goater */ 1134397a79e7SCédric Le Goater if (!chip->cores_mask) { 1135397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1136397a79e7SCédric Le Goater } 1137397a79e7SCédric Le Goater 1138397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1139397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1140397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1141397a79e7SCédric Le Goater chip->cores_mask); 1142397a79e7SCédric Le Goater return; 1143397a79e7SCédric Le Goater } 1144397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1145397a79e7SCédric Le Goater 1146397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 114727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1148397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1149397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1150397a79e7SCédric Le Goater cores_max); 1151397a79e7SCédric Le Goater return; 1152397a79e7SCédric Le Goater } 1153397a79e7SCédric Le Goater } 1154397a79e7SCédric Le Goater 115577864267SCédric Le Goater static void pnv_chip_instance_init(Object *obj) 1156967b7523SCédric Le Goater { 115777864267SCédric Le Goater PNV_CHIP(obj)->xscom_base = PNV_CHIP_GET_CLASS(obj)->xscom_base; 1158bf5615e7SCédric Le Goater } 1159bf5615e7SCédric Le Goater 116051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1161e997040eSCédric Le Goater { 1162397a79e7SCédric Le Goater Error *error = NULL; 1163d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 116440abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1165d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 1166d2fd9612SCédric Le Goater int i, core_hwid; 1167397a79e7SCédric Le Goater 1168d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1169d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1170d2fd9612SCédric Le Goater return; 1171d2fd9612SCédric Le Goater } 1172d2fd9612SCédric Le Goater 1173d2fd9612SCédric Le Goater /* Cores */ 1174397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1175397a79e7SCédric Le Goater if (error) { 1176397a79e7SCédric Le Goater error_propagate(errp, error); 1177397a79e7SCédric Le Goater return; 1178397a79e7SCédric Le Goater } 1179d2fd9612SCédric Le Goater 1180d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 1181d2fd9612SCédric Le Goater 1182d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1183d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1184d2fd9612SCédric Le Goater char core_name[32]; 1185d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 1186c035851aSCédric Le Goater uint64_t xscom_core_base; 1187d2fd9612SCédric Le Goater 1188d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1189d2fd9612SCédric Le Goater continue; 1190d2fd9612SCédric Le Goater } 1191d2fd9612SCédric Le Goater 1192d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1193bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize, 1194bc4c406cSPhilippe Mathieu-Daudé typename, &error_fatal, NULL); 1195d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads", 1196d2fd9612SCédric Le Goater &error_fatal); 1197d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1198d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1199d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1200d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1201d2fd9612SCédric Le Goater "pir", &error_fatal); 1202d35aefa9SCédric Le Goater object_property_add_const_link(OBJECT(pnv_core), "chip", 1203d35aefa9SCédric Le Goater OBJECT(chip), &error_fatal); 1204d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1205d2fd9612SCédric Le Goater &error_fatal); 120624ece072SCédric Le Goater 120724ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1208c035851aSCédric Le Goater if (!pnv_chip_is_power9(chip)) { 1209c035851aSCédric Le Goater xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid); 1210c035851aSCédric Le Goater } else { 12115dad902cSCédric Le Goater xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid); 1212c035851aSCédric Le Goater } 1213c035851aSCédric Le Goater 1214c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 121524ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 1216d2fd9612SCédric Le Goater i++; 1217d2fd9612SCédric Le Goater } 121851c04728SCédric Le Goater } 121951c04728SCédric Le Goater 122051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 122151c04728SCédric Le Goater { 122251c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 122351c04728SCédric Le Goater Error *error = NULL; 122451c04728SCédric Le Goater 122551c04728SCédric Le Goater /* Cores */ 122651c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 122751c04728SCédric Le Goater if (error) { 122851c04728SCédric Le Goater error_propagate(errp, error); 122951c04728SCédric Le Goater return; 123051c04728SCédric Le Goater } 1231e997040eSCédric Le Goater } 1232e997040eSCédric Le Goater 1233e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1234e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1235e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1236e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1237397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1238397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1239e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1240e997040eSCédric Le Goater }; 1241e997040eSCédric Le Goater 1242e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1243e997040eSCédric Le Goater { 1244e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1245e997040eSCédric Le Goater 12469d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1247e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1248e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1249e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1250e997040eSCédric Le Goater } 1251e997040eSCédric Le Goater 125254f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 125354f59d78SCédric Le Goater { 1254b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 125554f59d78SCédric Le Goater int i; 125654f59d78SCédric Le Goater 125754f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 125877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 125977864267SCédric Le Goater 126077864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 126177864267SCédric Le Goater return &chip8->psi.ics; 126254f59d78SCédric Le Goater } 126354f59d78SCédric Le Goater } 126454f59d78SCédric Le Goater return NULL; 126554f59d78SCédric Le Goater } 126654f59d78SCédric Le Goater 126754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 126854f59d78SCédric Le Goater { 1269b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 127054f59d78SCédric Le Goater int i; 127154f59d78SCédric Le Goater 127254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 127377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 127477864267SCédric Le Goater ics_resend(&chip8->psi.ics); 127554f59d78SCédric Le Goater } 127654f59d78SCédric Le Goater } 127754f59d78SCédric Le Goater 127836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 127936fc6f08SCédric Le Goater { 128036fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 128136fc6f08SCédric Le Goater 1282956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 128336fc6f08SCédric Le Goater } 128436fc6f08SCédric Le Goater 128547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 128647fea43aSCédric Le Goater Monitor *mon) 128747fea43aSCédric Le Goater { 1288b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 128954f59d78SCédric Le Goater int i; 129047fea43aSCédric Le Goater CPUState *cs; 129147fea43aSCédric Le Goater 129247fea43aSCédric Le Goater CPU_FOREACH(cs) { 129347fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 129447fea43aSCédric Le Goater 1295d8e4aad5SCédric Le Goater if (pnv_chip_is_power9(pnv->chips[0])) { 1296d8e4aad5SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 1297d8e4aad5SCédric Le Goater } else { 1298956b8f46SCédric Le Goater icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 129947fea43aSCédric Le Goater } 1300d8e4aad5SCédric Le Goater } 130154f59d78SCédric Le Goater 130254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1303d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 130454f59d78SCédric Le Goater } 130547fea43aSCédric Le Goater } 130647fea43aSCédric Le Goater 1307e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1308e997040eSCédric Le Goater void *opaque, Error **errp) 1309e997040eSCédric Le Goater { 1310b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1311e997040eSCédric Le Goater } 1312e997040eSCédric Le Goater 1313e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1314e997040eSCédric Le Goater void *opaque, Error **errp) 1315e997040eSCédric Le Goater { 1316b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1317e997040eSCédric Le Goater uint32_t num_chips; 1318e997040eSCédric Le Goater Error *local_err = NULL; 1319e997040eSCédric Le Goater 1320e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1321e997040eSCédric Le Goater if (local_err) { 1322e997040eSCédric Le Goater error_propagate(errp, local_err); 1323e997040eSCédric Le Goater return; 1324e997040eSCédric Le Goater } 1325e997040eSCédric Le Goater 1326e997040eSCédric Le Goater /* 1327e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1328e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1329e997040eSCédric Le Goater */ 1330e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1331e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1332e997040eSCédric Le Goater return; 1333e997040eSCédric Le Goater } 1334e997040eSCédric Le Goater 1335e997040eSCédric Le Goater pnv->num_chips = num_chips; 1336e997040eSCédric Le Goater } 1337e997040eSCédric Le Goater 133877864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1339e997040eSCédric Le Goater { 1340b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1341e997040eSCédric Le Goater pnv->num_chips = 1; 1342e997040eSCédric Le Goater } 1343e997040eSCédric Le Goater 1344b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1345e997040eSCédric Le Goater { 13461e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1347e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1348e997040eSCédric Le Goater NULL, NULL, NULL); 1349e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1350e997040eSCédric Le Goater "Specifies the number of processor chips", 1351e997040eSCédric Le Goater NULL); 13529e933f4aSBenjamin Herrenschmidt } 13539e933f4aSBenjamin Herrenschmidt 1354b168a138SCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 13559e933f4aSBenjamin Herrenschmidt { 13569e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 135736fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 135847fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 13599e933f4aSBenjamin Herrenschmidt 13609e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1361b168a138SCédric Le Goater mc->init = pnv_init; 1362b168a138SCédric Le Goater mc->reset = pnv_reset; 13639e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 13644a12c699SIgor Mammedov mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 13659e933f4aSBenjamin Herrenschmidt mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for 13669e933f4aSBenjamin Herrenschmidt * storage */ 13679e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 13689e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1369d23b6caaSPhilippe Mathieu-Daudé mc->default_ram_size = 1 * GiB; 137036fc6f08SCédric Le Goater xic->icp_get = pnv_icp_get; 137154f59d78SCédric Le Goater xic->ics_get = pnv_ics_get; 137254f59d78SCédric Le Goater xic->ics_resend = pnv_ics_resend; 137347fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1374e997040eSCédric Le Goater 1375b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 13769e933f4aSBenjamin Herrenschmidt } 13779e933f4aSBenjamin Herrenschmidt 137877864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1379beba5c0fSIgor Mammedov { \ 1380beba5c0fSIgor Mammedov .name = type, \ 1381beba5c0fSIgor Mammedov .class_init = class_initfn, \ 138277864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 138377864267SCédric Le Goater } 138477864267SCédric Le Goater 138577864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 138677864267SCédric Le Goater { \ 138777864267SCédric Le Goater .name = type, \ 138877864267SCédric Le Goater .class_init = class_initfn, \ 138977864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1390beba5c0fSIgor Mammedov } 1391beba5c0fSIgor Mammedov 1392beba5c0fSIgor Mammedov static const TypeInfo types[] = { 1393beba5c0fSIgor Mammedov { 1394b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 13959e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 13969e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 139777864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1398b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 139936fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 140036fc6f08SCédric Le Goater { TYPE_XICS_FABRIC }, 140147fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 140236fc6f08SCédric Le Goater { }, 140336fc6f08SCédric Le Goater }, 1404beba5c0fSIgor Mammedov }, 1405beba5c0fSIgor Mammedov { 1406beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1407beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1408beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 140977864267SCédric Le Goater .instance_init = pnv_chip_instance_init, 1410beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1411beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1412beba5c0fSIgor Mammedov .abstract = true, 1413beba5c0fSIgor Mammedov }, 141477864267SCédric Le Goater 141577864267SCédric Le Goater /* 141677864267SCédric Le Goater * P9 chip and variants 141777864267SCédric Le Goater */ 141877864267SCédric Le Goater { 141977864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 142077864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 142177864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 142277864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 142377864267SCédric Le Goater }, 142477864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 142577864267SCédric Le Goater 142677864267SCédric Le Goater /* 142777864267SCédric Le Goater * P8 chip and variants 142877864267SCédric Le Goater */ 142977864267SCédric Le Goater { 143077864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 143177864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 143277864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 143377864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 143477864267SCédric Le Goater }, 143577864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 143677864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 143777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1438beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 14399e933f4aSBenjamin Herrenschmidt }; 14409e933f4aSBenjamin Herrenschmidt 1441beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1442