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" 219e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 229e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 239e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 24d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 259e933f4aSBenjamin Herrenschmidt #include "hw/hw.h" 26fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 279e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 289e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 299e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 309e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 31d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 329e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 339e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 349e933f4aSBenjamin Herrenschmidt #include "qemu/cutils.h" 35e997040eSCédric Le Goater #include "qapi/visitor.h" 3647fea43aSCédric Le Goater #include "monitor/monitor.h" 3747fea43aSCédric Le Goater #include "hw/intc/intc.h" 389e933f4aSBenjamin Herrenschmidt 3936fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 40967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 41967b7523SCédric Le Goater 423495b6b6SCédric Le Goater #include "hw/isa/isa.h" 433495b6b6SCédric Le Goater #include "hw/char/serial.h" 443495b6b6SCédric Le Goater #include "hw/timer/mc146818rtc.h" 453495b6b6SCédric Le Goater 469e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 479e933f4aSBenjamin Herrenschmidt 489e933f4aSBenjamin Herrenschmidt #define FDT_MAX_SIZE 0x00100000 499e933f4aSBenjamin Herrenschmidt 509e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 519e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 529e933f4aSBenjamin Herrenschmidt #define FW_MAX_SIZE 0x00400000 539e933f4aSBenjamin Herrenschmidt 549e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 559e933f4aSBenjamin Herrenschmidt #define INITRD_LOAD_ADDR 0x40000000 569e933f4aSBenjamin Herrenschmidt 579e933f4aSBenjamin Herrenschmidt /* 589e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 599e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 609e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 619e933f4aSBenjamin Herrenschmidt */ 629e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 639e933f4aSBenjamin Herrenschmidt 649e933f4aSBenjamin Herrenschmidt /* 659e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 669e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 679e933f4aSBenjamin Herrenschmidt * per chip. 689e933f4aSBenjamin Herrenschmidt */ 699e933f4aSBenjamin Herrenschmidt static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start, 709e933f4aSBenjamin Herrenschmidt hwaddr size) 719e933f4aSBenjamin Herrenschmidt { 729e933f4aSBenjamin Herrenschmidt char *mem_name; 739e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 749e933f4aSBenjamin Herrenschmidt int off; 759e933f4aSBenjamin Herrenschmidt 769e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 779e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 789e933f4aSBenjamin Herrenschmidt 799e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 809e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 819e933f4aSBenjamin Herrenschmidt g_free(mem_name); 829e933f4aSBenjamin Herrenschmidt 839e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 849e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 859e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 869e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 879e933f4aSBenjamin Herrenschmidt } 889e933f4aSBenjamin Herrenschmidt 89d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 90d2fd9612SCédric Le Goater { 91d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 92d2fd9612SCédric Le Goater 93d2fd9612SCédric Le Goater if (cpus_offset < 0) { 94d2fd9612SCédric Le Goater cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), 95d2fd9612SCédric Le Goater "cpus"); 96d2fd9612SCédric Le Goater if (cpus_offset) { 97d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 98d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 99d2fd9612SCédric Le Goater } 100d2fd9612SCédric Le Goater } 101d2fd9612SCédric Le Goater _FDT(cpus_offset); 102d2fd9612SCédric Le Goater return cpus_offset; 103d2fd9612SCédric Le Goater } 104d2fd9612SCédric Le Goater 105d2fd9612SCédric Le Goater /* 106d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 107d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 108d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 109d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 110d2fd9612SCédric Le Goater * servers. 111d2fd9612SCédric Le Goater */ 112d2fd9612SCédric Le Goater static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt) 113d2fd9612SCédric Le Goater { 114d2fd9612SCédric Le Goater CPUState *cs = CPU(DEVICE(pc->threads)); 115d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 116d2fd9612SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 1178bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 118d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 119d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 120d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 121d2fd9612SCédric Le Goater int i; 122d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 123d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 124d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 125d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 126d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 127d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 128d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 129d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 130d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 131d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 132d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 133d2fd9612SCédric Le Goater int offset; 134d2fd9612SCédric Le Goater char *nodename; 135d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 136d2fd9612SCédric Le Goater 137d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 138d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 139d2fd9612SCédric Le Goater _FDT(offset); 140d2fd9612SCédric Le Goater g_free(nodename); 141d2fd9612SCédric Le Goater 142d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 143d2fd9612SCédric Le Goater 144d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 145d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 146d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 147d2fd9612SCédric Le Goater 148d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 149d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 150d2fd9612SCédric Le Goater env->dcache_line_size))); 151d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 152d2fd9612SCédric Le Goater env->dcache_line_size))); 153d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 154d2fd9612SCédric Le Goater env->icache_line_size))); 155d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 156d2fd9612SCédric Le Goater env->icache_line_size))); 157d2fd9612SCédric Le Goater 158d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 159d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 160d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 161d2fd9612SCédric Le Goater } else { 162d2fd9612SCédric Le Goater error_report("Warning: Unknown L1 dcache size for cpu"); 163d2fd9612SCédric Le Goater } 164d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 166d2fd9612SCédric Le Goater pcc->l1_icache_size))); 167d2fd9612SCédric Le Goater } else { 168d2fd9612SCédric Le Goater error_report("Warning: Unknown L1 icache size for cpu"); 169d2fd9612SCédric Le Goater } 170d2fd9612SCédric Le Goater 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 172d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 174d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 175d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 176d2fd9612SCédric Le Goater 177d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 178d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 179d2fd9612SCédric Le Goater } 180d2fd9612SCédric Le Goater 181d2fd9612SCédric Le Goater if (env->mmu_model & POWERPC_MMU_1TSEG) { 182d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 183d2fd9612SCédric Le Goater segs, sizeof(segs)))); 184d2fd9612SCédric Le Goater } 185d2fd9612SCédric Le Goater 186d2fd9612SCédric Le Goater /* Advertise VMX/VSX (vector extensions) if available 187d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 188d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 189d2fd9612SCédric Le Goater * 2 == VSX available */ 190d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 191d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 192d2fd9612SCédric Le Goater 193d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 194d2fd9612SCédric Le Goater } 195d2fd9612SCédric Le Goater 196d2fd9612SCédric Le Goater /* Advertise DFP (Decimal Floating Point) if available 197d2fd9612SCédric Le Goater * 0 / no property == no DFP 198d2fd9612SCédric Le Goater * 1 == DFP available */ 199d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 200d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 201d2fd9612SCédric Le Goater } 202d2fd9612SCédric Le Goater 203d2fd9612SCédric Le Goater page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, 204d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 205d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 206d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 207d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 208d2fd9612SCédric Le Goater } 209d2fd9612SCédric Le Goater 210d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 211d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 212d2fd9612SCédric Le Goater 213d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 214d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 215d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 216d2fd9612SCédric Le Goater } 217d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 218d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 219d2fd9612SCédric Le Goater } 220d2fd9612SCédric Le Goater 221bf5615e7SCédric Le Goater static void powernv_populate_icp(PnvChip *chip, void *fdt, uint32_t pir, 222bf5615e7SCédric Le Goater uint32_t nr_threads) 223bf5615e7SCédric Le Goater { 224bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 225bf5615e7SCédric Le Goater char *name; 226bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 227bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 228bf5615e7SCédric Le Goater uint64_t *reg; 229bf5615e7SCédric Le Goater int offset; 230bf5615e7SCédric Le Goater 231bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 232bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 233bf5615e7SCédric Le Goater 234bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 235bf5615e7SCédric Le Goater reg = g_malloc(rsize); 236bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 237bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 238bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 239bf5615e7SCédric Le Goater } 240bf5615e7SCédric Le Goater 241bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 242bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 243bf5615e7SCédric Le Goater _FDT(offset); 244bf5615e7SCédric Le Goater g_free(name); 245bf5615e7SCédric Le Goater 246bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 247bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 248bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 249bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 250bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 251bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 252bf5615e7SCédric Le Goater irange, sizeof(irange)))); 253bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 254bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 255bf5615e7SCédric Le Goater g_free(reg); 256bf5615e7SCédric Le Goater } 257bf5615e7SCédric Le Goater 2585a7e14a2SCédric Le Goater static int pnv_chip_lpc_offset(PnvChip *chip, void *fdt) 2595a7e14a2SCédric Le Goater { 2605a7e14a2SCédric Le Goater char *name; 2615a7e14a2SCédric Le Goater int offset; 2625a7e14a2SCédric Le Goater 2635a7e14a2SCédric Le Goater name = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 2645a7e14a2SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), PNV_XSCOM_LPC_BASE); 2655a7e14a2SCédric Le Goater offset = fdt_path_offset(fdt, name); 2665a7e14a2SCédric Le Goater g_free(name); 2675a7e14a2SCédric Le Goater return offset; 2685a7e14a2SCédric Le Goater } 2695a7e14a2SCédric Le Goater 270e997040eSCédric Le Goater static void powernv_populate_chip(PnvChip *chip, void *fdt) 271e997040eSCédric Le Goater { 272d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 273d2fd9612SCédric Le Goater char *typename = pnv_core_typename(pcc->cpu_model); 274d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 275d2fd9612SCédric Le Goater int i; 276d2fd9612SCédric Le Goater 277967b7523SCédric Le Goater pnv_xscom_populate(chip, fdt, 0); 278967b7523SCédric Le Goater 2795a7e14a2SCédric Le Goater /* The default LPC bus of a multichip system is on chip 0. It's 2805a7e14a2SCédric Le Goater * recognized by the firmware (skiboot) using a "primary" 2815a7e14a2SCédric Le Goater * property. 2825a7e14a2SCédric Le Goater */ 2835a7e14a2SCédric Le Goater if (chip->chip_id == 0x0) { 2845a7e14a2SCédric Le Goater int lpc_offset = pnv_chip_lpc_offset(chip, fdt); 2855a7e14a2SCédric Le Goater 2865a7e14a2SCédric Le Goater _FDT((fdt_setprop(fdt, lpc_offset, "primary", NULL, 0))); 2875a7e14a2SCédric Le Goater } 2885a7e14a2SCédric Le Goater 289d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 290d2fd9612SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 291d2fd9612SCédric Le Goater 292d2fd9612SCédric Le Goater powernv_create_core_node(chip, pnv_core, fdt); 293bf5615e7SCédric Le Goater 294bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 295bf5615e7SCédric Le Goater powernv_populate_icp(chip, fdt, pnv_core->pir, 296bf5615e7SCédric Le Goater CPU_CORE(pnv_core)->nr_threads); 297d2fd9612SCédric Le Goater } 298d2fd9612SCédric Le Goater 299e997040eSCédric Le Goater if (chip->ram_size) { 300e997040eSCédric Le Goater powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start, 301e997040eSCédric Le Goater chip->ram_size); 302e997040eSCédric Le Goater } 303d2fd9612SCédric Le Goater g_free(typename); 304e997040eSCédric Le Goater } 305e997040eSCédric Le Goater 306*e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 307*e7a3fee3SCédric Le Goater void *fdt; 308*e7a3fee3SCédric Le Goater int offset; 309*e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 310*e7a3fee3SCédric Le Goater 311*e7a3fee3SCédric Le Goater static int powernv_populate_isa_device(DeviceState *dev, void *opaque) 312*e7a3fee3SCédric Le Goater { 313*e7a3fee3SCédric Le Goater return 0; 314*e7a3fee3SCédric Le Goater } 315*e7a3fee3SCédric Le Goater 316*e7a3fee3SCédric Le Goater static void powernv_populate_isa(ISABus *bus, void *fdt, int lpc_offset) 317*e7a3fee3SCédric Le Goater { 318*e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 319*e7a3fee3SCédric Le Goater .fdt = fdt, 320*e7a3fee3SCédric Le Goater .offset = lpc_offset, 321*e7a3fee3SCédric Le Goater }; 322*e7a3fee3SCédric Le Goater 323*e7a3fee3SCédric Le Goater /* ISA devices are not necessarily parented to the ISA bus so we 324*e7a3fee3SCédric Le Goater * can not use object_child_foreach() */ 325*e7a3fee3SCédric Le Goater qbus_walk_children(BUS(bus), powernv_populate_isa_device, 326*e7a3fee3SCédric Le Goater NULL, NULL, NULL, &args); 327*e7a3fee3SCédric Le Goater } 328*e7a3fee3SCédric Le Goater 3299e933f4aSBenjamin Herrenschmidt static void *powernv_create_fdt(MachineState *machine) 3309e933f4aSBenjamin Herrenschmidt { 3319e933f4aSBenjamin Herrenschmidt const char plat_compat[] = "qemu,powernv\0ibm,powernv"; 3329e933f4aSBenjamin Herrenschmidt PnvMachineState *pnv = POWERNV_MACHINE(machine); 3339e933f4aSBenjamin Herrenschmidt void *fdt; 3349e933f4aSBenjamin Herrenschmidt char *buf; 3359e933f4aSBenjamin Herrenschmidt int off; 336e997040eSCédric Le Goater int i; 337*e7a3fee3SCédric Le Goater int lpc_offset; 3389e933f4aSBenjamin Herrenschmidt 3399e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 3409e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 3419e933f4aSBenjamin Herrenschmidt 3429e933f4aSBenjamin Herrenschmidt /* Root node */ 3439e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 3449e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 3459e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 3469e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 3479e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat, 3489e933f4aSBenjamin Herrenschmidt sizeof(plat_compat)))); 3499e933f4aSBenjamin Herrenschmidt 3509e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 3519e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 3529e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 3539e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 3549e933f4aSBenjamin Herrenschmidt } 3559e933f4aSBenjamin Herrenschmidt g_free(buf); 3569e933f4aSBenjamin Herrenschmidt 3579e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 3589e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 3599e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 3609e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 3619e933f4aSBenjamin Herrenschmidt } 3629e933f4aSBenjamin Herrenschmidt 3639e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 3649e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 3659e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 3669e933f4aSBenjamin Herrenschmidt 3679e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 3689e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 3699e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 3709e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 3719e933f4aSBenjamin Herrenschmidt } 3729e933f4aSBenjamin Herrenschmidt 373e997040eSCédric Le Goater /* Populate device tree for each chip */ 374e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 375e997040eSCédric Le Goater powernv_populate_chip(pnv->chips[i], fdt); 376e997040eSCédric Le Goater } 377*e7a3fee3SCédric Le Goater 378*e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 379*e7a3fee3SCédric Le Goater lpc_offset = pnv_chip_lpc_offset(pnv->chips[0], fdt); 380*e7a3fee3SCédric Le Goater powernv_populate_isa(pnv->isa_bus, fdt, lpc_offset); 3819e933f4aSBenjamin Herrenschmidt return fdt; 3829e933f4aSBenjamin Herrenschmidt } 3839e933f4aSBenjamin Herrenschmidt 3849e933f4aSBenjamin Herrenschmidt static void ppc_powernv_reset(void) 3859e933f4aSBenjamin Herrenschmidt { 3869e933f4aSBenjamin Herrenschmidt MachineState *machine = MACHINE(qdev_get_machine()); 3879e933f4aSBenjamin Herrenschmidt void *fdt; 3889e933f4aSBenjamin Herrenschmidt 3899e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 3909e933f4aSBenjamin Herrenschmidt 3919e933f4aSBenjamin Herrenschmidt fdt = powernv_create_fdt(machine); 3929e933f4aSBenjamin Herrenschmidt 3939e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 3949e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 3959e933f4aSBenjamin Herrenschmidt 3969e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 3979e933f4aSBenjamin Herrenschmidt } 3989e933f4aSBenjamin Herrenschmidt 3993495b6b6SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip) 4003495b6b6SCédric Le Goater { 4013495b6b6SCédric Le Goater PnvLpcController *lpc = &chip->lpc; 4023495b6b6SCédric Le Goater ISABus *isa_bus; 4033495b6b6SCédric Le Goater qemu_irq *irqs; 4043495b6b6SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 4053495b6b6SCédric Le Goater 4063495b6b6SCédric Le Goater /* let isa_bus_new() create its own bridge on SysBus otherwise 4073495b6b6SCédric Le Goater * devices speficied on the command line won't find the bus and 4083495b6b6SCédric Le Goater * will fail to create. 4093495b6b6SCédric Le Goater */ 4103495b6b6SCédric Le Goater isa_bus = isa_bus_new(NULL, &lpc->isa_mem, &lpc->isa_io, 4113495b6b6SCédric Le Goater &error_fatal); 4123495b6b6SCédric Le Goater 4134d1df88bSBenjamin Herrenschmidt irqs = pnv_lpc_isa_irq_create(lpc, pcc->chip_type, ISA_NUM_IRQS); 4143495b6b6SCédric Le Goater 4153495b6b6SCédric Le Goater isa_bus_irqs(isa_bus, irqs); 4163495b6b6SCédric Le Goater return isa_bus; 4173495b6b6SCédric Le Goater } 4183495b6b6SCédric Le Goater 4199e933f4aSBenjamin Herrenschmidt static void ppc_powernv_init(MachineState *machine) 4209e933f4aSBenjamin Herrenschmidt { 4219e933f4aSBenjamin Herrenschmidt PnvMachineState *pnv = POWERNV_MACHINE(machine); 4229e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 4239e933f4aSBenjamin Herrenschmidt char *fw_filename; 4249e933f4aSBenjamin Herrenschmidt long fw_size; 425e997040eSCédric Le Goater int i; 426e997040eSCédric Le Goater char *chip_typename; 4279e933f4aSBenjamin Herrenschmidt 4289e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 4299e933f4aSBenjamin Herrenschmidt if (machine->ram_size < (1 * G_BYTE)) { 4309e933f4aSBenjamin Herrenschmidt error_report("Warning: skiboot may not work with < 1GB of RAM"); 4319e933f4aSBenjamin Herrenschmidt } 4329e933f4aSBenjamin Herrenschmidt 4339e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 4349e933f4aSBenjamin Herrenschmidt memory_region_allocate_system_memory(ram, NULL, "ppc_powernv.ram", 4359e933f4aSBenjamin Herrenschmidt machine->ram_size); 4369e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 4379e933f4aSBenjamin Herrenschmidt 4389e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 4399e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 4409e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 4419e933f4aSBenjamin Herrenschmidt } 4429e933f4aSBenjamin Herrenschmidt 4439e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 4449e933f4aSBenjamin Herrenschmidt 4459e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 4469e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 447802fc7abSThomas Huth error_report("Could not load OPAL '%s'", fw_filename); 4489e933f4aSBenjamin Herrenschmidt exit(1); 4499e933f4aSBenjamin Herrenschmidt } 4509e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 4519e933f4aSBenjamin Herrenschmidt 4529e933f4aSBenjamin Herrenschmidt /* load kernel */ 4539e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 4549e933f4aSBenjamin Herrenschmidt long kernel_size; 4559e933f4aSBenjamin Herrenschmidt 4569e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 4579e933f4aSBenjamin Herrenschmidt KERNEL_LOAD_ADDR, 0x2000000); 4589e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 459802fc7abSThomas Huth error_report("Could not load kernel '%s'", 4609e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 4619e933f4aSBenjamin Herrenschmidt exit(1); 4629e933f4aSBenjamin Herrenschmidt } 4639e933f4aSBenjamin Herrenschmidt } 4649e933f4aSBenjamin Herrenschmidt 4659e933f4aSBenjamin Herrenschmidt /* load initrd */ 4669e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 4679e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 4689e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 4699e933f4aSBenjamin Herrenschmidt pnv->initrd_base, 0x10000000); /* 128MB max */ 4709e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 471802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 4729e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 4739e933f4aSBenjamin Herrenschmidt exit(1); 4749e933f4aSBenjamin Herrenschmidt } 4759e933f4aSBenjamin Herrenschmidt } 476e997040eSCédric Le Goater 477e997040eSCédric Le Goater /* We need some cpu model to instantiate the PnvChip class */ 478e997040eSCédric Le Goater if (machine->cpu_model == NULL) { 479e997040eSCédric Le Goater machine->cpu_model = "POWER8"; 480e997040eSCédric Le Goater } 481e997040eSCédric Le Goater 482e997040eSCédric Le Goater /* Create the processor chips */ 483e997040eSCédric Le Goater chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", machine->cpu_model); 484e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 485e997040eSCédric Le Goater error_report("qemu: invalid CPU model '%s' for %s machine", 486e997040eSCédric Le Goater machine->cpu_model, MACHINE_GET_CLASS(machine)->name); 487e997040eSCédric Le Goater exit(1); 488e997040eSCédric Le Goater } 489e997040eSCédric Le Goater 490e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 491e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 492e997040eSCédric Le Goater char chip_name[32]; 493e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 494e997040eSCédric Le Goater 495e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 496e997040eSCédric Le Goater 497e997040eSCédric Le Goater /* TODO: put all the memory in one node on chip 0 until we find a 498e997040eSCédric Le Goater * way to specify different ranges for each chip 499e997040eSCédric Le Goater */ 500e997040eSCédric Le Goater if (i == 0) { 501e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 502e997040eSCédric Le Goater &error_fatal); 503e997040eSCédric Le Goater } 504e997040eSCédric Le Goater 505e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 506e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 507e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 508e997040eSCédric Le Goater &error_fatal); 509397a79e7SCédric Le Goater object_property_set_int(chip, smp_cores, "nr-cores", &error_fatal); 510e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 511e997040eSCédric Le Goater } 512e997040eSCédric Le Goater g_free(chip_typename); 5133495b6b6SCédric Le Goater 5143495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 5153495b6b6SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0]); 5163495b6b6SCédric Le Goater 5173495b6b6SCédric Le Goater /* Create serial port */ 5183495b6b6SCédric Le Goater serial_hds_isa_init(pnv->isa_bus, 0, MAX_SERIAL_PORTS); 5193495b6b6SCédric Le Goater 5203495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 5213495b6b6SCédric Le Goater rtc_init(pnv->isa_bus, 2000, NULL); 522e997040eSCédric Le Goater } 523e997040eSCédric Le Goater 524631adaffSCédric Le Goater /* 525631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 526631adaffSCédric Le Goater * 22:24 Chip ID 527631adaffSCédric Le Goater * 25:28 Core number 528631adaffSCédric Le Goater * 29:31 Thread ID 529631adaffSCédric Le Goater */ 530631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 531631adaffSCédric Le Goater { 532631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 533631adaffSCédric Le Goater } 534631adaffSCédric Le Goater 535631adaffSCédric Le Goater /* 536631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 537631adaffSCédric Le Goater * 49:52 Node ID 538631adaffSCédric Le Goater * 53:55 Chip ID 539631adaffSCédric Le Goater * 56 Reserved - Read as zero 540631adaffSCédric Le Goater * 57:61 Core number 541631adaffSCédric Le Goater * 62:63 Thread ID 542631adaffSCédric Le Goater * 543631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 544631adaffSCédric Le Goater */ 545631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 546631adaffSCédric Le Goater { 547631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 548631adaffSCédric Le Goater } 549631adaffSCédric Le Goater 550397a79e7SCédric Le Goater /* Allowed core identifiers on a POWER8 Processor Chip : 551397a79e7SCédric Le Goater * 552397a79e7SCédric Le Goater * <EX0 reserved> 553397a79e7SCédric Le Goater * EX1 - Venice only 554397a79e7SCédric Le Goater * EX2 - Venice only 555397a79e7SCédric Le Goater * EX3 - Venice only 556397a79e7SCédric Le Goater * EX4 557397a79e7SCédric Le Goater * EX5 558397a79e7SCédric Le Goater * EX6 559397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 560397a79e7SCédric Le Goater * EX9 - Venice only 561397a79e7SCédric Le Goater * EX10 - Venice only 562397a79e7SCédric Le Goater * EX11 - Venice only 563397a79e7SCédric Le Goater * EX12 564397a79e7SCédric Le Goater * EX13 565397a79e7SCédric Le Goater * EX14 566397a79e7SCédric Le Goater * <EX15 reserved> 567397a79e7SCédric Le Goater */ 568397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 569397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 570397a79e7SCédric Le Goater 571397a79e7SCédric Le Goater /* 572397a79e7SCédric Le Goater * POWER9 has 24 cores, ids starting at 0x20 573397a79e7SCédric Le Goater */ 574397a79e7SCédric Le Goater #define POWER9_CORE_MASK (0xffffff00000000ull) 575397a79e7SCédric Le Goater 576e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 577e997040eSCédric Le Goater { 578e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 579e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 580e997040eSCédric Le Goater 581e997040eSCédric Le Goater k->cpu_model = "POWER8E"; 582e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 583e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 584397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 585631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 586967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 587ad521238SCédric Le Goater k->xscom_core_base = 0x10000000ull; 588e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 589e997040eSCédric Le Goater } 590e997040eSCédric Le Goater 591e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8e_info = { 592e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER8E, 593e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 594e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 595e997040eSCédric Le Goater .class_init = pnv_chip_power8e_class_init, 596e997040eSCédric Le Goater }; 597e997040eSCédric Le Goater 598e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 599e997040eSCédric Le Goater { 600e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 601e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 602e997040eSCédric Le Goater 603e997040eSCédric Le Goater k->cpu_model = "POWER8"; 604e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 605e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 606397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 607631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 608967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 609ad521238SCédric Le Goater k->xscom_core_base = 0x10000000ull; 610e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 611e997040eSCédric Le Goater } 612e997040eSCédric Le Goater 613e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8_info = { 614e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER8, 615e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 616e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 617e997040eSCédric Le Goater .class_init = pnv_chip_power8_class_init, 618e997040eSCédric Le Goater }; 619e997040eSCédric Le Goater 620e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 621e997040eSCédric Le Goater { 622e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 623e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 624e997040eSCédric Le Goater 625e997040eSCédric Le Goater k->cpu_model = "POWER8NVL"; 626e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 627e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 628397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 629631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 630967b7523SCédric Le Goater k->xscom_base = 0x003fc0000000000ull; 631ad521238SCédric Le Goater k->xscom_core_base = 0x10000000ull; 632e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 633e997040eSCédric Le Goater } 634e997040eSCédric Le Goater 635e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8nvl_info = { 636e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER8NVL, 637e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 638e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 639e997040eSCédric Le Goater .class_init = pnv_chip_power8nvl_class_init, 640e997040eSCédric Le Goater }; 641e997040eSCédric Le Goater 642e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 643e997040eSCédric Le Goater { 644e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 645e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 646e997040eSCédric Le Goater 647e997040eSCédric Le Goater k->cpu_model = "POWER9"; 648e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 649e997040eSCédric Le Goater k->chip_cfam_id = 0x100d104980000000ull; /* P9 Nimbus DD1.0 */ 650397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 651631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 652967b7523SCédric Le Goater k->xscom_base = 0x00603fc00000000ull; 653ad521238SCédric Le Goater k->xscom_core_base = 0x0ull; 654e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 655e997040eSCédric Le Goater } 656e997040eSCédric Le Goater 657e997040eSCédric Le Goater static const TypeInfo pnv_chip_power9_info = { 658e997040eSCédric Le Goater .name = TYPE_PNV_CHIP_POWER9, 659e997040eSCédric Le Goater .parent = TYPE_PNV_CHIP, 660e997040eSCédric Le Goater .instance_size = sizeof(PnvChip), 661e997040eSCédric Le Goater .class_init = pnv_chip_power9_class_init, 662e997040eSCédric Le Goater }; 663e997040eSCédric Le Goater 664397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 665397a79e7SCédric Le Goater { 666397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 667397a79e7SCédric Le Goater int cores_max; 668397a79e7SCédric Le Goater 669397a79e7SCédric Le Goater /* 670397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 671397a79e7SCédric Le Goater * the chip class 672397a79e7SCédric Le Goater */ 673397a79e7SCédric Le Goater if (!chip->cores_mask) { 674397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 675397a79e7SCédric Le Goater } 676397a79e7SCédric Le Goater 677397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 678397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 679397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 680397a79e7SCédric Le Goater chip->cores_mask); 681397a79e7SCédric Le Goater return; 682397a79e7SCédric Le Goater } 683397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 684397a79e7SCédric Le Goater 685397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 68627d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 687397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 688397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 689397a79e7SCédric Le Goater cores_max); 690397a79e7SCédric Le Goater return; 691397a79e7SCédric Le Goater } 692397a79e7SCédric Le Goater } 693397a79e7SCédric Le Goater 694967b7523SCédric Le Goater static void pnv_chip_init(Object *obj) 695967b7523SCédric Le Goater { 696967b7523SCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 697967b7523SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 698967b7523SCédric Le Goater 699967b7523SCédric Le Goater chip->xscom_base = pcc->xscom_base; 700a3980bf5SBenjamin Herrenschmidt 701a3980bf5SBenjamin Herrenschmidt object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC); 702a3980bf5SBenjamin Herrenschmidt object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL); 70354f59d78SCédric Le Goater 70454f59d78SCédric Le Goater object_initialize(&chip->psi, sizeof(chip->psi), TYPE_PNV_PSI); 70554f59d78SCédric Le Goater object_property_add_child(obj, "psi", OBJECT(&chip->psi), NULL); 70654f59d78SCédric Le Goater object_property_add_const_link(OBJECT(&chip->psi), "xics", 70754f59d78SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 7080722d05aSBenjamin Herrenschmidt 7090722d05aSBenjamin Herrenschmidt object_initialize(&chip->occ, sizeof(chip->occ), TYPE_PNV_OCC); 7100722d05aSBenjamin Herrenschmidt object_property_add_child(obj, "occ", OBJECT(&chip->occ), NULL); 7110722d05aSBenjamin Herrenschmidt object_property_add_const_link(OBJECT(&chip->occ), "psi", 7120722d05aSBenjamin Herrenschmidt OBJECT(&chip->psi), &error_abort); 7134d1df88bSBenjamin Herrenschmidt 7144d1df88bSBenjamin Herrenschmidt /* The LPC controller needs PSI to generate interrupts */ 7154d1df88bSBenjamin Herrenschmidt object_property_add_const_link(OBJECT(&chip->lpc), "psi", 7164d1df88bSBenjamin Herrenschmidt OBJECT(&chip->psi), &error_abort); 717967b7523SCédric Le Goater } 718967b7523SCédric Le Goater 719bf5615e7SCédric Le Goater static void pnv_chip_icp_realize(PnvChip *chip, Error **errp) 720bf5615e7SCédric Le Goater { 721bf5615e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 722bf5615e7SCédric Le Goater char *typename = pnv_core_typename(pcc->cpu_model); 723bf5615e7SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 724bf5615e7SCédric Le Goater int i, j; 725bf5615e7SCédric Le Goater char *name; 726bf5615e7SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 727bf5615e7SCédric Le Goater 728bf5615e7SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 729bf5615e7SCédric Le Goater memory_region_init(&chip->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 730bf5615e7SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip->icp_mmio); 731bf5615e7SCédric Le Goater g_free(name); 732bf5615e7SCédric Le Goater 733bf5615e7SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 734bf5615e7SCédric Le Goater 735bf5615e7SCédric Le Goater /* Map the ICP registers for each thread */ 736bf5615e7SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 737bf5615e7SCédric Le Goater PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize); 738bf5615e7SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 739bf5615e7SCédric Le Goater 740bf5615e7SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 741bf5615e7SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 742bf5615e7SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 743bf5615e7SCédric Le Goater 744bf5615e7SCédric Le Goater memory_region_add_subregion(&chip->icp_mmio, pir << 12, &icp->mmio); 745bf5615e7SCédric Le Goater } 746bf5615e7SCédric Le Goater } 747bf5615e7SCédric Le Goater 748bf5615e7SCédric Le Goater g_free(typename); 749bf5615e7SCédric Le Goater } 750bf5615e7SCédric Le Goater 751e997040eSCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 752e997040eSCédric Le Goater { 753397a79e7SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 754397a79e7SCédric Le Goater Error *error = NULL; 755d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 756d2fd9612SCédric Le Goater char *typename = pnv_core_typename(pcc->cpu_model); 757d2fd9612SCédric Le Goater size_t typesize = object_type_get_instance_size(typename); 758d2fd9612SCédric Le Goater int i, core_hwid; 759397a79e7SCédric Le Goater 760d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 761d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 762d2fd9612SCédric Le Goater return; 763d2fd9612SCédric Le Goater } 764d2fd9612SCédric Le Goater 765967b7523SCédric Le Goater /* XSCOM bridge */ 766967b7523SCédric Le Goater pnv_xscom_realize(chip, &error); 767967b7523SCédric Le Goater if (error) { 768967b7523SCédric Le Goater error_propagate(errp, error); 769967b7523SCédric Le Goater return; 770967b7523SCédric Le Goater } 771967b7523SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 772967b7523SCédric Le Goater 773d2fd9612SCédric Le Goater /* Cores */ 774397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 775397a79e7SCédric Le Goater if (error) { 776397a79e7SCédric Le Goater error_propagate(errp, error); 777397a79e7SCédric Le Goater return; 778397a79e7SCédric Le Goater } 779d2fd9612SCédric Le Goater 780d2fd9612SCédric Le Goater chip->cores = g_malloc0(typesize * chip->nr_cores); 781d2fd9612SCédric Le Goater 782d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 783d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 784d2fd9612SCédric Le Goater char core_name[32]; 785d2fd9612SCédric Le Goater void *pnv_core = chip->cores + i * typesize; 786d2fd9612SCédric Le Goater 787d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 788d2fd9612SCédric Le Goater continue; 789d2fd9612SCédric Le Goater } 790d2fd9612SCédric Le Goater 791d2fd9612SCédric Le Goater object_initialize(pnv_core, typesize, typename); 792d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 793d2fd9612SCédric Le Goater object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), 794d2fd9612SCédric Le Goater &error_fatal); 795d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads", 796d2fd9612SCédric Le Goater &error_fatal); 797d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 798d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 799d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 800d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 801d2fd9612SCédric Le Goater "pir", &error_fatal); 802960fbd29SCédric Le Goater object_property_add_const_link(OBJECT(pnv_core), "xics", 803960fbd29SCédric Le Goater qdev_get_machine(), &error_fatal); 804d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 805d2fd9612SCédric Le Goater &error_fatal); 806d2fd9612SCédric Le Goater object_unref(OBJECT(pnv_core)); 80724ece072SCédric Le Goater 80824ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 809ad521238SCédric Le Goater pnv_xscom_add_subregion(chip, 810ad521238SCédric Le Goater PNV_XSCOM_EX_CORE_BASE(pcc->xscom_core_base, 811ad521238SCédric Le Goater core_hwid), 81224ece072SCédric Le Goater &PNV_CORE(pnv_core)->xscom_regs); 813d2fd9612SCédric Le Goater i++; 814d2fd9612SCédric Le Goater } 815d2fd9612SCédric Le Goater g_free(typename); 816a3980bf5SBenjamin Herrenschmidt 817a3980bf5SBenjamin Herrenschmidt /* Create LPC controller */ 818a3980bf5SBenjamin Herrenschmidt object_property_set_bool(OBJECT(&chip->lpc), true, "realized", 819a3980bf5SBenjamin Herrenschmidt &error_fatal); 820a3980bf5SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip->lpc.xscom_regs); 821bf5615e7SCédric Le Goater 822bf5615e7SCédric Le Goater /* Interrupt Management Area. This is the memory region holding 823bf5615e7SCédric Le Goater * all the Interrupt Control Presenter (ICP) registers */ 824bf5615e7SCédric Le Goater pnv_chip_icp_realize(chip, &error); 825bf5615e7SCédric Le Goater if (error) { 826bf5615e7SCédric Le Goater error_propagate(errp, error); 827bf5615e7SCédric Le Goater return; 828bf5615e7SCédric Le Goater } 82954f59d78SCédric Le Goater 83054f59d78SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 83154f59d78SCédric Le Goater object_property_set_int(OBJECT(&chip->psi), PNV_PSIHB_BASE(chip), 83254f59d78SCédric Le Goater "bar", &error_fatal); 83354f59d78SCédric Le Goater object_property_set_bool(OBJECT(&chip->psi), true, "realized", &error); 83454f59d78SCédric Le Goater if (error) { 83554f59d78SCédric Le Goater error_propagate(errp, error); 83654f59d78SCédric Le Goater return; 83754f59d78SCédric Le Goater } 83854f59d78SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, &chip->psi.xscom_regs); 8390722d05aSBenjamin Herrenschmidt 8400722d05aSBenjamin Herrenschmidt /* Create the simplified OCC model */ 8410722d05aSBenjamin Herrenschmidt object_property_set_bool(OBJECT(&chip->occ), true, "realized", &error); 8420722d05aSBenjamin Herrenschmidt if (error) { 8430722d05aSBenjamin Herrenschmidt error_propagate(errp, error); 8440722d05aSBenjamin Herrenschmidt return; 8450722d05aSBenjamin Herrenschmidt } 8460722d05aSBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip->occ.xscom_regs); 847e997040eSCédric Le Goater } 848e997040eSCédric Le Goater 849e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 850e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 851e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 852e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 853397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 854397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 855e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 856e997040eSCédric Le Goater }; 857e997040eSCédric Le Goater 858e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 859e997040eSCédric Le Goater { 860e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 861e997040eSCédric Le Goater 8629d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 863e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 864e997040eSCédric Le Goater dc->props = pnv_chip_properties; 865e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 866e997040eSCédric Le Goater } 867e997040eSCédric Le Goater 868e997040eSCédric Le Goater static const TypeInfo pnv_chip_info = { 869e997040eSCédric Le Goater .name = TYPE_PNV_CHIP, 870e997040eSCédric Le Goater .parent = TYPE_SYS_BUS_DEVICE, 871e997040eSCédric Le Goater .class_init = pnv_chip_class_init, 872967b7523SCédric Le Goater .instance_init = pnv_chip_init, 873e997040eSCédric Le Goater .class_size = sizeof(PnvChipClass), 874e997040eSCédric Le Goater .abstract = true, 875e997040eSCédric Le Goater }; 876e997040eSCédric Le Goater 87754f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 87854f59d78SCédric Le Goater { 87954f59d78SCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(xi); 88054f59d78SCédric Le Goater int i; 88154f59d78SCédric Le Goater 88254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 88354f59d78SCédric Le Goater if (ics_valid_irq(&pnv->chips[i]->psi.ics, irq)) { 88454f59d78SCédric Le Goater return &pnv->chips[i]->psi.ics; 88554f59d78SCédric Le Goater } 88654f59d78SCédric Le Goater } 88754f59d78SCédric Le Goater return NULL; 88854f59d78SCédric Le Goater } 88954f59d78SCédric Le Goater 89054f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 89154f59d78SCédric Le Goater { 89254f59d78SCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(xi); 89354f59d78SCédric Le Goater int i; 89454f59d78SCédric Le Goater 89554f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 89654f59d78SCédric Le Goater ics_resend(&pnv->chips[i]->psi.ics); 89754f59d78SCédric Le Goater } 89854f59d78SCédric Le Goater } 89954f59d78SCédric Le Goater 90036fc6f08SCédric Le Goater static PowerPCCPU *ppc_get_vcpu_by_pir(int pir) 90136fc6f08SCédric Le Goater { 90236fc6f08SCédric Le Goater CPUState *cs; 90336fc6f08SCédric Le Goater 90436fc6f08SCédric Le Goater CPU_FOREACH(cs) { 90536fc6f08SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 90636fc6f08SCédric Le Goater CPUPPCState *env = &cpu->env; 90736fc6f08SCédric Le Goater 90836fc6f08SCédric Le Goater if (env->spr_cb[SPR_PIR].default_value == pir) { 90936fc6f08SCédric Le Goater return cpu; 91036fc6f08SCédric Le Goater } 91136fc6f08SCédric Le Goater } 91236fc6f08SCédric Le Goater 91336fc6f08SCédric Le Goater return NULL; 91436fc6f08SCédric Le Goater } 91536fc6f08SCédric Le Goater 91636fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 91736fc6f08SCédric Le Goater { 91836fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 91936fc6f08SCédric Le Goater 92036fc6f08SCédric Le Goater return cpu ? ICP(cpu->intc) : NULL; 92136fc6f08SCédric Le Goater } 92236fc6f08SCédric Le Goater 92347fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 92447fea43aSCédric Le Goater Monitor *mon) 92547fea43aSCédric Le Goater { 92654f59d78SCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(obj); 92754f59d78SCédric Le Goater int i; 92847fea43aSCédric Le Goater CPUState *cs; 92947fea43aSCédric Le Goater 93047fea43aSCédric Le Goater CPU_FOREACH(cs) { 93147fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 93247fea43aSCédric Le Goater 93347fea43aSCédric Le Goater icp_pic_print_info(ICP(cpu->intc), mon); 93447fea43aSCédric Le Goater } 93554f59d78SCédric Le Goater 93654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 93754f59d78SCédric Le Goater ics_pic_print_info(&pnv->chips[i]->psi.ics, mon); 93854f59d78SCédric Le Goater } 93947fea43aSCédric Le Goater } 94047fea43aSCédric Le Goater 941e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 942e997040eSCédric Le Goater void *opaque, Error **errp) 943e997040eSCédric Le Goater { 944e997040eSCédric Le Goater visit_type_uint32(v, name, &POWERNV_MACHINE(obj)->num_chips, errp); 945e997040eSCédric Le Goater } 946e997040eSCédric Le Goater 947e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 948e997040eSCédric Le Goater void *opaque, Error **errp) 949e997040eSCédric Le Goater { 950e997040eSCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(obj); 951e997040eSCédric Le Goater uint32_t num_chips; 952e997040eSCédric Le Goater Error *local_err = NULL; 953e997040eSCédric Le Goater 954e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 955e997040eSCédric Le Goater if (local_err) { 956e997040eSCédric Le Goater error_propagate(errp, local_err); 957e997040eSCédric Le Goater return; 958e997040eSCédric Le Goater } 959e997040eSCédric Le Goater 960e997040eSCédric Le Goater /* 961e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 962e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 963e997040eSCédric Le Goater */ 964e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 965e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 966e997040eSCédric Le Goater return; 967e997040eSCédric Le Goater } 968e997040eSCédric Le Goater 969e997040eSCédric Le Goater pnv->num_chips = num_chips; 970e997040eSCédric Le Goater } 971e997040eSCédric Le Goater 972e997040eSCédric Le Goater static void powernv_machine_initfn(Object *obj) 973e997040eSCédric Le Goater { 974e997040eSCédric Le Goater PnvMachineState *pnv = POWERNV_MACHINE(obj); 975e997040eSCédric Le Goater pnv->num_chips = 1; 976e997040eSCédric Le Goater } 977e997040eSCédric Le Goater 978e997040eSCédric Le Goater static void powernv_machine_class_props_init(ObjectClass *oc) 979e997040eSCédric Le Goater { 980e997040eSCédric Le Goater object_class_property_add(oc, "num-chips", "uint32_t", 981e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 982e997040eSCédric Le Goater NULL, NULL, NULL); 983e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 984e997040eSCédric Le Goater "Specifies the number of processor chips", 985e997040eSCédric Le Goater NULL); 9869e933f4aSBenjamin Herrenschmidt } 9879e933f4aSBenjamin Herrenschmidt 9889e933f4aSBenjamin Herrenschmidt static void powernv_machine_class_init(ObjectClass *oc, void *data) 9899e933f4aSBenjamin Herrenschmidt { 9909e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 99136fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 99247fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 9939e933f4aSBenjamin Herrenschmidt 9949e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 9959e933f4aSBenjamin Herrenschmidt mc->init = ppc_powernv_init; 9969e933f4aSBenjamin Herrenschmidt mc->reset = ppc_powernv_reset; 9979e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 9989e933f4aSBenjamin Herrenschmidt mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for 9999e933f4aSBenjamin Herrenschmidt * storage */ 10009e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 10019e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 10029e933f4aSBenjamin Herrenschmidt mc->default_ram_size = 1 * G_BYTE; 100336fc6f08SCédric Le Goater xic->icp_get = pnv_icp_get; 100454f59d78SCédric Le Goater xic->ics_get = pnv_ics_get; 100554f59d78SCédric Le Goater xic->ics_resend = pnv_ics_resend; 100647fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1007e997040eSCédric Le Goater 1008e997040eSCédric Le Goater powernv_machine_class_props_init(oc); 10099e933f4aSBenjamin Herrenschmidt } 10109e933f4aSBenjamin Herrenschmidt 10119e933f4aSBenjamin Herrenschmidt static const TypeInfo powernv_machine_info = { 10129e933f4aSBenjamin Herrenschmidt .name = TYPE_POWERNV_MACHINE, 10139e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 10149e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 1015e997040eSCédric Le Goater .instance_init = powernv_machine_initfn, 10169e933f4aSBenjamin Herrenschmidt .class_init = powernv_machine_class_init, 101736fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 101836fc6f08SCédric Le Goater { TYPE_XICS_FABRIC }, 101947fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 102036fc6f08SCédric Le Goater { }, 102136fc6f08SCédric Le Goater }, 10229e933f4aSBenjamin Herrenschmidt }; 10239e933f4aSBenjamin Herrenschmidt 10249e933f4aSBenjamin Herrenschmidt static void powernv_machine_register_types(void) 10259e933f4aSBenjamin Herrenschmidt { 10269e933f4aSBenjamin Herrenschmidt type_register_static(&powernv_machine_info); 1027e997040eSCédric Le Goater type_register_static(&pnv_chip_info); 1028e997040eSCédric Le Goater type_register_static(&pnv_chip_power8e_info); 1029e997040eSCédric Le Goater type_register_static(&pnv_chip_power8_info); 1030e997040eSCédric Le Goater type_register_static(&pnv_chip_power8nvl_info); 1031e997040eSCédric Le Goater type_register_static(&pnv_chip_power9_info); 10329e933f4aSBenjamin Herrenschmidt } 10339e933f4aSBenjamin Herrenschmidt 10349e933f4aSBenjamin Herrenschmidt type_init(powernv_machine_register_types) 1035