19e933f4aSBenjamin Herrenschmidt /* 29e933f4aSBenjamin Herrenschmidt * QEMU PowerPC PowerNV machine model 39e933f4aSBenjamin Herrenschmidt * 49e933f4aSBenjamin Herrenschmidt * Copyright (c) 2016, IBM Corporation. 59e933f4aSBenjamin Herrenschmidt * 69e933f4aSBenjamin Herrenschmidt * This library is free software; you can redistribute it and/or 79e933f4aSBenjamin Herrenschmidt * modify it under the terms of the GNU Lesser General Public 89e933f4aSBenjamin Herrenschmidt * License as published by the Free Software Foundation; either 99e933f4aSBenjamin Herrenschmidt * version 2 of the License, or (at your option) any later version. 109e933f4aSBenjamin Herrenschmidt * 119e933f4aSBenjamin Herrenschmidt * This library is distributed in the hope that it will be useful, 129e933f4aSBenjamin Herrenschmidt * but WITHOUT ANY WARRANTY; without even the implied warranty of 139e933f4aSBenjamin Herrenschmidt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 149e933f4aSBenjamin Herrenschmidt * Lesser General Public License for more details. 159e933f4aSBenjamin Herrenschmidt * 169e933f4aSBenjamin Herrenschmidt * You should have received a copy of the GNU Lesser General Public 179e933f4aSBenjamin Herrenschmidt * License along with this library; if not, see <http://www.gnu.org/licenses/>. 189e933f4aSBenjamin Herrenschmidt */ 199e933f4aSBenjamin Herrenschmidt 209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h" 21a8d25326SMarkus Armbruster #include "qemu-common.h" 22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2671e8a915SMarkus Armbruster #include "sysemu/reset.h" 2754d31236SMarkus Armbruster #include "sysemu/runstate.h" 28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 298d409261SCédric Le Goater #include "sysemu/device_tree.h" 30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h" 329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h" 38e997040eSCédric Le Goater #include "qapi/visitor.h" 3947fea43aSCédric Le Goater #include "monitor/monitor.h" 4047fea43aSCédric Le Goater #include "hw/intc/intc.h" 41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 439e933f4aSBenjamin Herrenschmidt 4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 4735dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 48967b7523SCédric Le Goater 493495b6b6SCédric Le Goater #include "hw/isa/isa.h" 5012e9493dSMarkus Armbruster #include "hw/boards.h" 513495b6b6SCédric Le Goater #include "hw/char/serial.h" 52bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 533495b6b6SCédric Le Goater 549e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 559e933f4aSBenjamin Herrenschmidt 56b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 579e933f4aSBenjamin Herrenschmidt 589e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 599e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 60b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE (4 * MiB) 619e933f4aSBenjamin Herrenschmidt 629e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 63b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE (256 * MiB) 64fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR 0x60000000 65584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE (256 * MiB) 669e933f4aSBenjamin Herrenschmidt 6740abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 6840abf43fSIgor Mammedov { 6940abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7040abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7140abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7240abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7340abf43fSIgor Mammedov g_free(s); 7440abf43fSIgor Mammedov return core_type; 7540abf43fSIgor Mammedov } 7640abf43fSIgor Mammedov 779e933f4aSBenjamin Herrenschmidt /* 789e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 799e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 809e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 819e933f4aSBenjamin Herrenschmidt */ 829e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 839e933f4aSBenjamin Herrenschmidt 849e933f4aSBenjamin Herrenschmidt /* 859e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 869e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 879e933f4aSBenjamin Herrenschmidt * per chip. 889e933f4aSBenjamin Herrenschmidt */ 89b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 909e933f4aSBenjamin Herrenschmidt { 919e933f4aSBenjamin Herrenschmidt char *mem_name; 929e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 939e933f4aSBenjamin Herrenschmidt int off; 949e933f4aSBenjamin Herrenschmidt 959e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 969e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 979e933f4aSBenjamin Herrenschmidt 989e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 999e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1009e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1019e933f4aSBenjamin Herrenschmidt 1029e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1039e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1049e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1059e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1069e933f4aSBenjamin Herrenschmidt } 1079e933f4aSBenjamin Herrenschmidt 108d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 109d2fd9612SCédric Le Goater { 110d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 111d2fd9612SCédric Le Goater 112d2fd9612SCédric Le Goater if (cpus_offset < 0) { 113a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 114d2fd9612SCédric Le Goater if (cpus_offset) { 115d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 116d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 117d2fd9612SCédric Le Goater } 118d2fd9612SCédric Le Goater } 119d2fd9612SCédric Le Goater _FDT(cpus_offset); 120d2fd9612SCédric Le Goater return cpus_offset; 121d2fd9612SCédric Le Goater } 122d2fd9612SCédric Le Goater 123d2fd9612SCédric Le Goater /* 124d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 125d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 126d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 127d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 128d2fd9612SCédric Le Goater * servers. 129d2fd9612SCédric Le Goater */ 130b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 131d2fd9612SCédric Le Goater { 13208304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13308304a86SDavid Gibson CPUState *cs = CPU(cpu); 134d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1358bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 136d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 137d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 138d2fd9612SCédric Le Goater uint32_t servers_prop[smt_threads]; 139d2fd9612SCédric Le Goater int i; 140d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 141d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 142d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 143d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 144d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 145d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 146d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 147d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 148d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 149d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 150d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 151d2fd9612SCédric Le Goater int offset; 152d2fd9612SCédric Le Goater char *nodename; 153d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 154d2fd9612SCédric Le Goater 155d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 156d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 157d2fd9612SCédric Le Goater _FDT(offset); 158d2fd9612SCédric Le Goater g_free(nodename); 159d2fd9612SCédric Le Goater 160d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 161d2fd9612SCédric Le Goater 162d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 163d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 164d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 165d2fd9612SCédric Le Goater 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 167d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 168d2fd9612SCédric Le Goater env->dcache_line_size))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 170d2fd9612SCédric Le Goater env->dcache_line_size))); 171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 172d2fd9612SCédric Le Goater env->icache_line_size))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 174d2fd9612SCédric Le Goater env->icache_line_size))); 175d2fd9612SCédric Le Goater 176d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 178d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 179d2fd9612SCédric Le Goater } else { 1803dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 181d2fd9612SCédric Le Goater } 182d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 183d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 184d2fd9612SCédric Le Goater pcc->l1_icache_size))); 185d2fd9612SCédric Le Goater } else { 1863dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 187d2fd9612SCédric Le Goater } 188d2fd9612SCédric Le Goater 189d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 190d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19159b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19259b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 193d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 194d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 195d2fd9612SCédric Le Goater 196d2fd9612SCédric Le Goater if (env->spr_cb[SPR_PURR].oea_read) { 197d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 198d2fd9612SCédric Le Goater } 199d2fd9612SCédric Le Goater 20058969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 201d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 202d2fd9612SCédric Le Goater segs, sizeof(segs)))); 203d2fd9612SCédric Le Goater } 204d2fd9612SCédric Le Goater 20559b7c1c2SBalamuruhan S /* 20659b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 207d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 208d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 20959b7c1c2SBalamuruhan S * 2 == VSX available 21059b7c1c2SBalamuruhan S */ 211d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 212d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 213d2fd9612SCédric Le Goater 214d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 215d2fd9612SCédric Le Goater } 216d2fd9612SCédric Le Goater 21759b7c1c2SBalamuruhan S /* 21859b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 219d2fd9612SCédric Le Goater * 0 / no property == no DFP 22059b7c1c2SBalamuruhan S * 1 == DFP available 22159b7c1c2SBalamuruhan S */ 222d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 223d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 224d2fd9612SCédric Le Goater } 225d2fd9612SCédric Le Goater 226644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 227d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 228d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 229d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 230d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 231d2fd9612SCédric Le Goater } 232d2fd9612SCédric Le Goater 233d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 234d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 235d2fd9612SCédric Le Goater 236d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 237d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 238d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 239d2fd9612SCédric Le Goater } 240d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 241d2fd9612SCédric Le Goater servers_prop, sizeof(servers_prop)))); 242d2fd9612SCédric Le Goater } 243d2fd9612SCédric Le Goater 244b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 245bf5615e7SCédric Le Goater uint32_t nr_threads) 246bf5615e7SCédric Le Goater { 247bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 248bf5615e7SCédric Le Goater char *name; 249bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 250bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 251bf5615e7SCédric Le Goater uint64_t *reg; 252bf5615e7SCédric Le Goater int offset; 253bf5615e7SCédric Le Goater 254bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 255bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 256bf5615e7SCédric Le Goater 257bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 258bf5615e7SCédric Le Goater reg = g_malloc(rsize); 259bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 260bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 261bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 262bf5615e7SCédric Le Goater } 263bf5615e7SCédric Le Goater 264bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 265bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 266bf5615e7SCédric Le Goater _FDT(offset); 267bf5615e7SCédric Le Goater g_free(name); 268bf5615e7SCédric Le Goater 269bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 270bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 271bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 272bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 273bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 274bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 275bf5615e7SCédric Le Goater irange, sizeof(irange)))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 278bf5615e7SCédric Le Goater g_free(reg); 279bf5615e7SCédric Le Goater } 280bf5615e7SCédric Le Goater 281eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 282e997040eSCédric Le Goater { 283c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; 284d2fd9612SCédric Le Goater int i; 285d2fd9612SCédric Le Goater 2863f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 2873f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 288c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE), 289c396c58aSGreg Kurz compat, sizeof(compat)); 290967b7523SCédric Le Goater 291d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 2924fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 293d2fd9612SCédric Le Goater 294b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 295bf5615e7SCédric Le Goater 296bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 297b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 298d2fd9612SCédric Le Goater } 299d2fd9612SCédric Le Goater 300e997040eSCédric Le Goater if (chip->ram_size) { 301b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 302e997040eSCédric Le Goater } 303e997040eSCédric Le Goater } 304e997040eSCédric Le Goater 305eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 306eb859a27SCédric Le Goater { 307c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom"; 308eb859a27SCédric Le Goater int i; 309eb859a27SCédric Le Goater 3103f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3113f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 312c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE), 313c396c58aSGreg Kurz compat, sizeof(compat)); 314eb859a27SCédric Le Goater 315eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3164fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 317eb859a27SCédric Le Goater 318eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 319eb859a27SCédric Le Goater } 320eb859a27SCédric Le Goater 321eb859a27SCédric Le Goater if (chip->ram_size) { 322eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 323eb859a27SCédric Le Goater } 32415376c66SCédric Le Goater 3252661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 326eb859a27SCédric Le Goater } 327eb859a27SCédric Le Goater 3282b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3292b548a42SCédric Le Goater { 330c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom"; 3312b548a42SCédric Le Goater int i; 3322b548a42SCédric Le Goater 3333f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3343f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 335c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE), 336c396c58aSGreg Kurz compat, sizeof(compat)); 3372b548a42SCédric Le Goater 3382b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3392b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3402b548a42SCédric Le Goater 3412b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3422b548a42SCédric Le Goater } 3432b548a42SCédric Le Goater 3442b548a42SCédric Le Goater if (chip->ram_size) { 3452b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3462b548a42SCédric Le Goater } 3472661f6abSCédric Le Goater 3482661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 3492b548a42SCédric Le Goater } 3502b548a42SCédric Le Goater 351b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 352c5ffdcaeSCédric Le Goater { 353c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 354c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 355c5ffdcaeSCédric Le Goater cpu_to_be32(1), 356c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 357c5ffdcaeSCédric Le Goater cpu_to_be32(2) 358c5ffdcaeSCédric Le Goater }; 359c5ffdcaeSCédric Le Goater char *name; 360c5ffdcaeSCédric Le Goater int node; 361c5ffdcaeSCédric Le Goater 362c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 363c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 364c5ffdcaeSCédric Le Goater _FDT(node); 365c5ffdcaeSCédric Le Goater g_free(name); 366c5ffdcaeSCédric Le Goater 367c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 368c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 369c5ffdcaeSCédric Le Goater } 370c5ffdcaeSCédric Le Goater 371b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 372cb228f5aSCédric Le Goater { 373cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 374cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 375cb228f5aSCédric Le Goater uint32_t io_regs[] = { 376cb228f5aSCédric Le Goater cpu_to_be32(1), 377cb228f5aSCédric Le Goater cpu_to_be32(io_base), 378cb228f5aSCédric Le Goater cpu_to_be32(8) 379cb228f5aSCédric Le Goater }; 380cb228f5aSCédric Le Goater char *name; 381cb228f5aSCédric Le Goater int node; 382cb228f5aSCédric Le Goater 383cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 384cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 385cb228f5aSCédric Le Goater _FDT(node); 386cb228f5aSCédric Le Goater g_free(name); 387cb228f5aSCédric Le Goater 388cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 389cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 390cb228f5aSCédric Le Goater sizeof(compatible)))); 391cb228f5aSCédric Le Goater 392cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 393cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 394cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0]))); 395cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 396cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 397cb228f5aSCédric Le Goater 398cb228f5aSCédric Le Goater /* This is needed by Linux */ 399cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 400cb228f5aSCédric Le Goater } 401cb228f5aSCédric Le Goater 402b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 40304f6c8b2SCédric Le Goater { 40404f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 40504f6c8b2SCédric Le Goater uint32_t io_base; 40604f6c8b2SCédric Le Goater uint32_t io_regs[] = { 40704f6c8b2SCédric Le Goater cpu_to_be32(1), 40804f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 40904f6c8b2SCédric Le Goater cpu_to_be32(3) 41004f6c8b2SCédric Le Goater }; 41104f6c8b2SCédric Le Goater uint32_t irq; 41204f6c8b2SCédric Le Goater char *name; 41304f6c8b2SCédric Le Goater int node; 41404f6c8b2SCédric Le Goater 41504f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 41604f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 41704f6c8b2SCédric Le Goater 41804f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 41904f6c8b2SCédric Le Goater 42004f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 42104f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 42204f6c8b2SCédric Le Goater _FDT(node); 42304f6c8b2SCédric Le Goater g_free(name); 42404f6c8b2SCédric Le Goater 4257032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4267032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4277032d92aSCédric Le Goater sizeof(compatible)))); 42804f6c8b2SCédric Le Goater 42904f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 43004f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 43104f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 43204f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 43304f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 43404f6c8b2SCédric Le Goater } 43504f6c8b2SCédric Le Goater 436e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 437e7a3fee3SCédric Le Goater void *fdt; 438e7a3fee3SCédric Le Goater int offset; 439e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 440e7a3fee3SCédric Le Goater 441b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 442e7a3fee3SCédric Le Goater { 443c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 444c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 445c5ffdcaeSCédric Le Goater 446c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 447b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 448cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 449b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 45004f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 451b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 452c5ffdcaeSCédric Le Goater } else { 453c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 454c5ffdcaeSCédric Le Goater d->ioport_id); 455c5ffdcaeSCédric Le Goater } 456c5ffdcaeSCédric Le Goater 457e7a3fee3SCédric Le Goater return 0; 458e7a3fee3SCédric Le Goater } 459e7a3fee3SCédric Le Goater 46059b7c1c2SBalamuruhan S /* 46159b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 462bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 463bb7ab95cSCédric Le Goater */ 464bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 465bb7ab95cSCédric Le Goater { 46664d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 467e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 468e7a3fee3SCédric Le Goater .fdt = fdt, 469bb7ab95cSCédric Le Goater .offset = isa_offset, 470e7a3fee3SCédric Le Goater }; 471f47a08d1SCédric Le Goater uint32_t phandle; 472e7a3fee3SCédric Le Goater 473bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 474bb7ab95cSCédric Le Goater 475f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 476f47a08d1SCédric Le Goater assert(phandle > 0); 477f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 478f47a08d1SCédric Le Goater 47959b7c1c2SBalamuruhan S /* 48059b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 48159b7c1c2SBalamuruhan S * can not use object_child_foreach() 48259b7c1c2SBalamuruhan S */ 483bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 484bb7ab95cSCédric Le Goater &args); 485e7a3fee3SCédric Le Goater } 486e7a3fee3SCédric Le Goater 4877a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 488e5694793SCédric Le Goater { 489e5694793SCédric Le Goater int off; 490e5694793SCédric Le Goater 491e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 492e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 493e5694793SCédric Le Goater 494e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 495e5694793SCédric Le Goater } 496e5694793SCédric Le Goater 497b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 4989e933f4aSBenjamin Herrenschmidt { 499d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 500b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5019e933f4aSBenjamin Herrenschmidt void *fdt; 5029e933f4aSBenjamin Herrenschmidt char *buf; 5039e933f4aSBenjamin Herrenschmidt int off; 504e997040eSCédric Le Goater int i; 5059e933f4aSBenjamin Herrenschmidt 5069e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5079e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5089e933f4aSBenjamin Herrenschmidt 509ccb099b3SCédric Le Goater /* /qemu node */ 510ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 511ccb099b3SCédric Le Goater 5129e933f4aSBenjamin Herrenschmidt /* Root node */ 5139e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5149e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5159e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5169e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 517d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5189e933f4aSBenjamin Herrenschmidt 5199e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5209e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5219e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 5229e933f4aSBenjamin Herrenschmidt _FDT((fdt_property_string(fdt, "system-id", buf))); 5239e933f4aSBenjamin Herrenschmidt } 5249e933f4aSBenjamin Herrenschmidt g_free(buf); 5259e933f4aSBenjamin Herrenschmidt 5269e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5279e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5289e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5299e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5309e933f4aSBenjamin Herrenschmidt } 5319e933f4aSBenjamin Herrenschmidt 5329e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5339e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5349e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5359e933f4aSBenjamin Herrenschmidt 5369e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5379e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5389e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5399e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5409e933f4aSBenjamin Herrenschmidt } 5419e933f4aSBenjamin Herrenschmidt 542e997040eSCédric Le Goater /* Populate device tree for each chip */ 543e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 544eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 545e997040eSCédric Le Goater } 546e7a3fee3SCédric Le Goater 547e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 548bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 549aeaef83dSCédric Le Goater 550aeaef83dSCédric Le Goater if (pnv->bmc) { 551b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 552aeaef83dSCédric Le Goater } 553aeaef83dSCédric Le Goater 5547a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5557a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5567a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 557e5694793SCédric Le Goater } 558e5694793SCédric Le Goater 5599e933f4aSBenjamin Herrenschmidt return fdt; 5609e933f4aSBenjamin Herrenschmidt } 5619e933f4aSBenjamin Herrenschmidt 562bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 563bce0b691SCédric Le Goater { 564b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 565bce0b691SCédric Le Goater 566bce0b691SCédric Le Goater if (pnv->bmc) { 567bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 568bce0b691SCédric Le Goater } 569bce0b691SCédric Le Goater } 570bce0b691SCédric Le Goater 571a0628599SLike Xu static void pnv_reset(MachineState *machine) 5729e933f4aSBenjamin Herrenschmidt { 5739e933f4aSBenjamin Herrenschmidt void *fdt; 5749e933f4aSBenjamin Herrenschmidt 5759e933f4aSBenjamin Herrenschmidt qemu_devices_reset(); 5769e933f4aSBenjamin Herrenschmidt 577b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 5789e933f4aSBenjamin Herrenschmidt 5799e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 5809e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 5819e933f4aSBenjamin Herrenschmidt 5828d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 5839e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 5849e933f4aSBenjamin Herrenschmidt } 5859e933f4aSBenjamin Herrenschmidt 58604026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 5873495b6b6SCédric Le Goater { 58877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 58977864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 59004026890SCédric Le Goater } 5913495b6b6SCédric Le Goater 59204026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 59304026890SCédric Le Goater { 59477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 59577864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 59604026890SCédric Le Goater } 5973495b6b6SCédric Le Goater 59804026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 59904026890SCédric Le Goater { 60015376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 60115376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 60204026890SCédric Le Goater } 6033495b6b6SCédric Le Goater 6042b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6052b548a42SCédric Le Goater { 6062661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6072661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6082b548a42SCédric Le Goater } 6092b548a42SCédric Le Goater 61004026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 61104026890SCédric Le Goater { 61204026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6133495b6b6SCédric Le Goater } 6143495b6b6SCédric Le Goater 615d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 616d8e4aad5SCédric Le Goater { 617d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 618d8e4aad5SCédric Le Goater 619d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 620d8e4aad5SCédric Le Goater } 621d8e4aad5SCédric Le Goater 622d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 623d8e4aad5SCédric Le Goater { 624d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 625d8e4aad5SCédric Le Goater 626d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 627c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 628d8e4aad5SCédric Le Goater } 629d8e4aad5SCédric Le Goater 630c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 631c4b2c40cSGreg Kurz uint32_t core_id) 632c4b2c40cSGreg Kurz { 633c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 634c4b2c40cSGreg Kurz } 635c4b2c40cSGreg Kurz 636c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 637c4b2c40cSGreg Kurz uint32_t core_id) 638c4b2c40cSGreg Kurz { 639c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 640c4b2c40cSGreg Kurz } 641c4b2c40cSGreg Kurz 642c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 643c4b2c40cSGreg Kurz uint32_t core_id) 644c4b2c40cSGreg Kurz { 645c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 646c4b2c40cSGreg Kurz } 647c4b2c40cSGreg Kurz 648f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 649f30c843cSCédric Le Goater { 650f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 651f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 652f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 653f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 654f30c843cSCédric Le Goater 655f30c843cSCédric Le Goater return ppc_default->pvr_match(ppc_default, ppc->pvr); 656f30c843cSCédric Le Goater } 657f30c843cSCédric Le Goater 658e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 659e2392d43SCédric Le Goater { 660e2392d43SCédric Le Goater Object *obj; 661e2392d43SCédric Le Goater 662e2392d43SCédric Le Goater obj = OBJECT(isa_create(bus, "isa-ipmi-bt")); 663e2392d43SCédric Le Goater object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal); 664e2392d43SCédric Le Goater object_property_set_int(obj, irq, "irq", &error_fatal); 665e2392d43SCédric Le Goater object_property_set_bool(obj, true, "realized", &error_fatal); 666e2392d43SCédric Le Goater } 667e2392d43SCédric Le Goater 6682b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 6692b548a42SCédric Le Goater { 6708b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 6718b50ce85SCédric Le Goater 6728b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 6732b548a42SCédric Le Goater } 6742b548a42SCédric Le Goater 675b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 6769e933f4aSBenjamin Herrenschmidt { 677b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 678f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 6799e933f4aSBenjamin Herrenschmidt MemoryRegion *ram; 6809e933f4aSBenjamin Herrenschmidt char *fw_filename; 6819e933f4aSBenjamin Herrenschmidt long fw_size; 682e997040eSCédric Le Goater int i; 683e997040eSCédric Le Goater char *chip_typename; 68435dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 68535dde576SCédric Le Goater DeviceState *dev; 6869e933f4aSBenjamin Herrenschmidt 6879e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 688d23b6caaSPhilippe Mathieu-Daudé if (machine->ram_size < (1 * GiB)) { 6893dc6f869SAlistair Francis warn_report("skiboot may not work with < 1GB of RAM"); 6909e933f4aSBenjamin Herrenschmidt } 6919e933f4aSBenjamin Herrenschmidt 6929e933f4aSBenjamin Herrenschmidt ram = g_new(MemoryRegion, 1); 693b168a138SCédric Le Goater memory_region_allocate_system_memory(ram, NULL, "pnv.ram", 6949e933f4aSBenjamin Herrenschmidt machine->ram_size); 6959e933f4aSBenjamin Herrenschmidt memory_region_add_subregion(get_system_memory(), 0, ram); 6969e933f4aSBenjamin Herrenschmidt 69735dde576SCédric Le Goater /* 69835dde576SCédric Le Goater * Create our simple PNOR device 69935dde576SCédric Le Goater */ 70035dde576SCédric Le Goater dev = qdev_create(NULL, TYPE_PNV_PNOR); 70135dde576SCédric Le Goater if (pnor) { 70235dde576SCédric Le Goater qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor), 70335dde576SCédric Le Goater &error_abort); 70435dde576SCédric Le Goater } 70535dde576SCédric Le Goater qdev_init_nofail(dev); 70635dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 70735dde576SCédric Le Goater 7089e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 7099e933f4aSBenjamin Herrenschmidt if (bios_name == NULL) { 7109e933f4aSBenjamin Herrenschmidt bios_name = FW_FILE_NAME; 7119e933f4aSBenjamin Herrenschmidt } 7129e933f4aSBenjamin Herrenschmidt 7139e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 71415fcedb2SCédric Le Goater if (!fw_filename) { 71515fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 71615fcedb2SCédric Le Goater exit(1); 71715fcedb2SCédric Le Goater } 7189e933f4aSBenjamin Herrenschmidt 7199e933f4aSBenjamin Herrenschmidt fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE); 7209e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 72115fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 7229e933f4aSBenjamin Herrenschmidt exit(1); 7239e933f4aSBenjamin Herrenschmidt } 7249e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 7259e933f4aSBenjamin Herrenschmidt 7269e933f4aSBenjamin Herrenschmidt /* load kernel */ 7279e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 7289e933f4aSBenjamin Herrenschmidt long kernel_size; 7299e933f4aSBenjamin Herrenschmidt 7309e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 731b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 7329e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 733802fc7abSThomas Huth error_report("Could not load kernel '%s'", 7349e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 7359e933f4aSBenjamin Herrenschmidt exit(1); 7369e933f4aSBenjamin Herrenschmidt } 7379e933f4aSBenjamin Herrenschmidt } 7389e933f4aSBenjamin Herrenschmidt 7399e933f4aSBenjamin Herrenschmidt /* load initrd */ 7409e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 7419e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 7429e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 743584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 7449e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 745802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 7469e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 7479e933f4aSBenjamin Herrenschmidt exit(1); 7489e933f4aSBenjamin Herrenschmidt } 7499e933f4aSBenjamin Herrenschmidt } 750e997040eSCédric Le Goater 751f30c843cSCédric Le Goater /* 752f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 753f30c843cSCédric Le Goater * default. 754f30c843cSCédric Le Goater */ 755f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 756f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 757f30c843cSCédric Le Goater machine->cpu_type, mc->name); 758f30c843cSCédric Le Goater exit(1); 759f30c843cSCédric Le Goater } 760f30c843cSCédric Le Goater 761e997040eSCédric Le Goater /* Create the processor chips */ 7624a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 7637fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 7644a12c699SIgor Mammedov i, machine->cpu_type); 765e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 766f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 767f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 768e997040eSCédric Le Goater exit(1); 769e997040eSCédric Le Goater } 770e997040eSCédric Le Goater 771e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 772e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 773e997040eSCédric Le Goater char chip_name[32]; 774e997040eSCédric Le Goater Object *chip = object_new(chip_typename); 775e997040eSCédric Le Goater 776e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 777e997040eSCédric Le Goater 77859b7c1c2SBalamuruhan S /* 77959b7c1c2SBalamuruhan S * TODO: put all the memory in one node on chip 0 until we find a 780e997040eSCédric Le Goater * way to specify different ranges for each chip 781e997040eSCédric Le Goater */ 782e997040eSCédric Le Goater if (i == 0) { 783e997040eSCédric Le Goater object_property_set_int(chip, machine->ram_size, "ram-size", 784e997040eSCédric Le Goater &error_fatal); 785e997040eSCédric Le Goater } 786e997040eSCédric Le Goater 787e997040eSCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i)); 788e997040eSCédric Le Goater object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal); 789e997040eSCédric Le Goater object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id", 790e997040eSCédric Le Goater &error_fatal); 791fe6b6346SLike Xu object_property_set_int(chip, machine->smp.cores, 792fe6b6346SLike Xu "nr-cores", &error_fatal); 793e997040eSCédric Le Goater object_property_set_bool(chip, true, "realized", &error_fatal); 794e997040eSCédric Le Goater } 795e997040eSCédric Le Goater g_free(chip_typename); 7963495b6b6SCédric Le Goater 797e2392d43SCédric Le Goater /* Create the machine BMC simulator */ 798e2392d43SCédric Le Goater pnv->bmc = pnv_bmc_create(); 799e2392d43SCédric Le Goater 8003495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 80104026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 8023495b6b6SCédric Le Goater 8033495b6b6SCédric Le Goater /* Create serial port */ 804def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 8053495b6b6SCédric Le Goater 8063495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 8076c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 808bce0b691SCédric Le Goater 809e2392d43SCédric Le Goater /* Create the IPMI BT device for communication with the BMC */ 810e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 811e2392d43SCédric Le Goater 81259b7c1c2SBalamuruhan S /* 81359b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 81459b7c1c2SBalamuruhan S * host to powerdown 81559b7c1c2SBalamuruhan S */ 816bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 817bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 818e997040eSCédric Le Goater } 819e997040eSCédric Le Goater 820631adaffSCédric Le Goater /* 821631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 822631adaffSCédric Le Goater * 22:24 Chip ID 823631adaffSCédric Le Goater * 25:28 Core number 824631adaffSCédric Le Goater * 29:31 Thread ID 825631adaffSCédric Le Goater */ 826631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 827631adaffSCédric Le Goater { 828631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 829631adaffSCédric Le Goater } 830631adaffSCédric Le Goater 8318fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 832d35aefa9SCédric Le Goater Error **errp) 833d35aefa9SCédric Le Goater { 8348fa1f4efSCédric Le Goater Error *local_err = NULL; 8358fa1f4efSCédric Le Goater Object *obj; 8368907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8378fa1f4efSCédric Le Goater 8388fa1f4efSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), 8398fa1f4efSCédric Le Goater &local_err); 8408fa1f4efSCédric Le Goater if (local_err) { 8418fa1f4efSCédric Le Goater error_propagate(errp, local_err); 8428fa1f4efSCédric Le Goater return; 8438fa1f4efSCédric Le Goater } 8448fa1f4efSCédric Le Goater 845956b8f46SCédric Le Goater pnv_cpu->intc = obj; 846d35aefa9SCédric Le Goater } 847d35aefa9SCédric Le Goater 8480990ce6aSGreg Kurz 849d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 850d49e8a9bSCédric Le Goater { 851d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 852d49e8a9bSCédric Le Goater 853d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 854d49e8a9bSCédric Le Goater } 855d49e8a9bSCédric Le Goater 8560990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 8570990ce6aSGreg Kurz { 8580990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8590990ce6aSGreg Kurz 8600990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 8610990ce6aSGreg Kurz pnv_cpu->intc = NULL; 8620990ce6aSGreg Kurz } 8630990ce6aSGreg Kurz 86485913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 86585913070SGreg Kurz Monitor *mon) 86685913070SGreg Kurz { 86785913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 86885913070SGreg Kurz } 86985913070SGreg Kurz 870631adaffSCédric Le Goater /* 871631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 872631adaffSCédric Le Goater * 49:52 Node ID 873631adaffSCédric Le Goater * 53:55 Chip ID 874631adaffSCédric Le Goater * 56 Reserved - Read as zero 875631adaffSCédric Le Goater * 57:61 Core number 876631adaffSCédric Le Goater * 62:63 Thread ID 877631adaffSCédric Le Goater * 878631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 879631adaffSCédric Le Goater */ 880631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 881631adaffSCédric Le Goater { 882631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 883631adaffSCédric Le Goater } 884631adaffSCédric Le Goater 8852b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 8862b548a42SCédric Le Goater { 8872b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 8882b548a42SCédric Le Goater } 8892b548a42SCédric Le Goater 8908fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 891d35aefa9SCédric Le Goater Error **errp) 892d35aefa9SCédric Le Goater { 8932dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 8942dfa91a2SCédric Le Goater Error *local_err = NULL; 8952dfa91a2SCédric Le Goater Object *obj; 8962dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 8972dfa91a2SCédric Le Goater 8982dfa91a2SCédric Le Goater /* 8992dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 9002dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 9012dfa91a2SCédric Le Goater * only used at runtime. 9022dfa91a2SCédric Le Goater */ 90326aa5b1eSGreg Kurz obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err); 9042dfa91a2SCédric Le Goater if (local_err) { 9052dfa91a2SCédric Le Goater error_propagate(errp, local_err); 9068fa1f4efSCédric Le Goater return; 907d35aefa9SCédric Le Goater } 908d35aefa9SCédric Le Goater 9092dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 9102dfa91a2SCédric Le Goater } 9112dfa91a2SCédric Le Goater 912d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 913d49e8a9bSCédric Le Goater { 914d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 915d49e8a9bSCédric Le Goater 916d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 917d49e8a9bSCédric Le Goater } 918d49e8a9bSCédric Le Goater 9190990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9200990ce6aSGreg Kurz { 9210990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9220990ce6aSGreg Kurz 9230990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 9240990ce6aSGreg Kurz pnv_cpu->intc = NULL; 9250990ce6aSGreg Kurz } 9260990ce6aSGreg Kurz 92785913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 92885913070SGreg Kurz Monitor *mon) 92985913070SGreg Kurz { 93085913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 93185913070SGreg Kurz } 93285913070SGreg Kurz 9332b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 9342b548a42SCédric Le Goater Error **errp) 9352b548a42SCédric Le Goater { 9362b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9372b548a42SCédric Le Goater 9382b548a42SCédric Le Goater /* Will be defined when the interrupt controller is */ 9392b548a42SCédric Le Goater pnv_cpu->intc = NULL; 9402b548a42SCédric Le Goater } 9412b548a42SCédric Le Goater 9422b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 9432b548a42SCédric Le Goater { 9442b548a42SCédric Le Goater ; 9452b548a42SCédric Le Goater } 9462b548a42SCédric Le Goater 9472b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 9482b548a42SCédric Le Goater { 9492b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9502b548a42SCédric Le Goater 9512b548a42SCédric Le Goater pnv_cpu->intc = NULL; 9522b548a42SCédric Le Goater } 9532b548a42SCédric Le Goater 95485913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 95585913070SGreg Kurz Monitor *mon) 95685913070SGreg Kurz { 95785913070SGreg Kurz } 95885913070SGreg Kurz 95959b7c1c2SBalamuruhan S /* 96059b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 961397a79e7SCédric Le Goater * 962397a79e7SCédric Le Goater * <EX0 reserved> 963397a79e7SCédric Le Goater * EX1 - Venice only 964397a79e7SCédric Le Goater * EX2 - Venice only 965397a79e7SCédric Le Goater * EX3 - Venice only 966397a79e7SCédric Le Goater * EX4 967397a79e7SCédric Le Goater * EX5 968397a79e7SCédric Le Goater * EX6 969397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 970397a79e7SCédric Le Goater * EX9 - Venice only 971397a79e7SCédric Le Goater * EX10 - Venice only 972397a79e7SCédric Le Goater * EX11 - Venice only 973397a79e7SCédric Le Goater * EX12 974397a79e7SCédric Le Goater * EX13 975397a79e7SCédric Le Goater * EX14 976397a79e7SCédric Le Goater * <EX15 reserved> 977397a79e7SCédric Le Goater */ 978397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 979397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 980397a79e7SCédric Le Goater 981397a79e7SCédric Le Goater /* 98209279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 983397a79e7SCédric Le Goater */ 98409279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 985397a79e7SCédric Le Goater 9862b548a42SCédric Le Goater 9872b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 9882b548a42SCédric Le Goater 98977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 99077864267SCédric Le Goater { 99177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 99277864267SCédric Le Goater 993f6d4dca8SThomas Huth object_initialize_child(obj, "psi", &chip8->psi, sizeof(chip8->psi), 994ae856055SCédric Le Goater TYPE_PNV8_PSI, &error_abort, NULL); 99577864267SCédric Le Goater object_property_add_const_link(OBJECT(&chip8->psi), "xics", 99677864267SCédric Le Goater OBJECT(qdev_get_machine()), &error_abort); 99777864267SCédric Le Goater 998f6d4dca8SThomas Huth object_initialize_child(obj, "lpc", &chip8->lpc, sizeof(chip8->lpc), 99982514be2SCédric Le Goater TYPE_PNV8_LPC, &error_abort, NULL); 100077864267SCédric Le Goater 1001f6d4dca8SThomas Huth object_initialize_child(obj, "occ", &chip8->occ, sizeof(chip8->occ), 10023233838cSCédric Le Goater TYPE_PNV8_OCC, &error_abort, NULL); 10033887d241SBalamuruhan S 10043887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip8->homer, sizeof(chip8->homer), 10053887d241SBalamuruhan S TYPE_PNV8_HOMER, &error_abort, NULL); 100677864267SCédric Le Goater } 100777864267SCédric Le Goater 100877864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 100977864267SCédric Le Goater { 101077864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 101177864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 101277864267SCédric Le Goater int i, j; 101377864267SCédric Le Goater char *name; 101477864267SCédric Le Goater XICSFabric *xi = XICS_FABRIC(qdev_get_machine()); 101577864267SCédric Le Goater 101677864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 101777864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 101877864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 101977864267SCédric Le Goater g_free(name); 102077864267SCédric Le Goater 102177864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 102277864267SCédric Le Goater 102377864267SCédric Le Goater /* Map the ICP registers for each thread */ 102477864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 10254fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 102677864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 102777864267SCédric Le Goater 102877864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 102977864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 103077864267SCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir)); 103177864267SCédric Le Goater 103277864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 103377864267SCédric Le Goater &icp->mmio); 103477864267SCédric Le Goater } 103577864267SCédric Le Goater } 103677864267SCédric Le Goater } 103777864267SCédric Le Goater 103877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 103977864267SCédric Le Goater { 104077864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 104177864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 104277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1043ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 104477864267SCédric Le Goater Error *local_err = NULL; 104577864267SCédric Le Goater 1046709044fdSCédric Le Goater /* XSCOM bridge is first */ 1047709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1048709044fdSCédric Le Goater if (local_err) { 1049709044fdSCédric Le Goater error_propagate(errp, local_err); 1050709044fdSCédric Le Goater return; 1051709044fdSCédric Le Goater } 1052709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1053709044fdSCédric Le Goater 105477864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 105577864267SCédric Le Goater if (local_err) { 105677864267SCédric Le Goater error_propagate(errp, local_err); 105777864267SCédric Le Goater return; 105877864267SCédric Le Goater } 105977864267SCédric Le Goater 106077864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 106177864267SCédric Le Goater object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip), 106277864267SCédric Le Goater "bar", &error_fatal); 106377864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err); 106477864267SCédric Le Goater if (local_err) { 106577864267SCédric Le Goater error_propagate(errp, local_err); 106677864267SCédric Le Goater return; 106777864267SCédric Le Goater } 1068ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1069ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 107077864267SCédric Le Goater 107177864267SCédric Le Goater /* Create LPC controller */ 1072b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi", 1073b63f3893SGreg Kurz &error_abort); 107477864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->lpc), true, "realized", 107577864267SCédric Le Goater &error_fatal); 107677864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 107777864267SCédric Le Goater 107864d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 107964d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 108064d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 108164d011d5SCédric Le Goater 108259b7c1c2SBalamuruhan S /* 108359b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 108459b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 108559b7c1c2SBalamuruhan S */ 108677864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 108777864267SCédric Le Goater if (local_err) { 108877864267SCédric Le Goater error_propagate(errp, local_err); 108977864267SCédric Le Goater return; 109077864267SCédric Le Goater } 109177864267SCédric Le Goater 109277864267SCédric Le Goater /* Create the simplified OCC model */ 1093ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi", 1094ee3d2713SGreg Kurz &error_abort); 109577864267SCédric Le Goater object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err); 109677864267SCédric Le Goater if (local_err) { 109777864267SCédric Le Goater error_propagate(errp, local_err); 109877864267SCédric Le Goater return; 109977864267SCédric Le Goater } 110077864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1101f3db8266SBalamuruhan S 1102f3db8266SBalamuruhan S /* OCC SRAM model */ 11033a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1104f3db8266SBalamuruhan S &chip8->occ.sram_regs); 11053887d241SBalamuruhan S 11063887d241SBalamuruhan S /* HOMER */ 1107f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip", 1108f2582acfSGreg Kurz &error_abort); 11093887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip8->homer), true, "realized", 11103887d241SBalamuruhan S &local_err); 11113887d241SBalamuruhan S if (local_err) { 11123887d241SBalamuruhan S error_propagate(errp, local_err); 11133887d241SBalamuruhan S return; 11143887d241SBalamuruhan S } 11158f092316SCédric Le Goater /* Homer Xscom region */ 11168f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 11178f092316SCédric Le Goater 11188f092316SCédric Le Goater /* Homer mmio region */ 11193887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 11203887d241SBalamuruhan S &chip8->homer.regs); 112177864267SCédric Le Goater } 112277864267SCédric Le Goater 1123*70c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 1124*70c059e9SGreg Kurz { 1125*70c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 1126*70c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 1127*70c059e9SGreg Kurz } 1128*70c059e9SGreg Kurz 1129e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1130e997040eSCédric Le Goater { 1131e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1132e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1133e997040eSCédric Le Goater 1134e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8E; 1135e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1136397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 1137631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1138d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1139d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11400990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 114185913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 114204026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1143eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1144d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1145c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 1146*70c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1147e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 114877864267SCédric Le Goater 114977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 115077864267SCédric Le Goater &k->parent_realize); 1151e997040eSCédric Le Goater } 1152e997040eSCédric Le Goater 1153e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1154e997040eSCédric Le Goater { 1155e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1156e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1157e997040eSCédric Le Goater 1158e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8; 1159e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1160397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1161631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1162d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1163d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11640990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 116585913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 116604026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1167eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1168d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1169c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 1170*70c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1171e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 117277864267SCédric Le Goater 117377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 117477864267SCédric Le Goater &k->parent_realize); 1175e997040eSCédric Le Goater } 1176e997040eSCédric Le Goater 1177e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1178e997040eSCédric Le Goater { 1179e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1180e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1181e997040eSCédric Le Goater 1182e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER8NVL; 1183e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1184397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1185631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1186d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1187d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11880990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 118985913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 119004026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1191eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1192d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1193c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 1194*70c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1195e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 119677864267SCédric Le Goater 119777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 119877864267SCédric Le Goater &k->parent_realize); 119977864267SCédric Le Goater } 120077864267SCédric Le Goater 120177864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 120277864267SCédric Le Goater { 12032dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 12042dfa91a2SCédric Le Goater 12052dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 12062dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 1207c38536bcSCédric Le Goater 1208c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1209c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 121015376c66SCédric Le Goater 121115376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 121215376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 12136598a70dSCédric Le Goater 12146598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 12156598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 12163887d241SBalamuruhan S 12173887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 12183887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 121977864267SCédric Le Goater } 122077864267SCédric Le Goater 12215dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 12225dad902cSCédric Le Goater { 12235dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 12245dad902cSCédric Le Goater int i; 12255dad902cSCédric Le Goater 12265dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 12275dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 12285dad902cSCédric Le Goater 12295dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 12305dad902cSCédric Le Goater char eq_name[32]; 12315dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 12324fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 12335dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 12345dad902cSCédric Le Goater 12355dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1236bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1237bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 12385dad902cSCédric Le Goater 12395dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 12405dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 12415dad902cSCédric Le Goater 12425dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 12435dad902cSCédric Le Goater &eq->xscom_regs); 12445dad902cSCédric Le Goater } 12455dad902cSCédric Le Goater } 12465dad902cSCédric Le Goater 124777864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 124877864267SCédric Le Goater { 124977864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 12502dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 12512dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1252c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 125377864267SCédric Le Goater Error *local_err = NULL; 125477864267SCédric Le Goater 1255709044fdSCédric Le Goater /* XSCOM bridge is first */ 1256709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1257709044fdSCédric Le Goater if (local_err) { 1258709044fdSCédric Le Goater error_propagate(errp, local_err); 1259709044fdSCédric Le Goater return; 1260709044fdSCédric Le Goater } 1261709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1262709044fdSCédric Le Goater 126377864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 126477864267SCédric Le Goater if (local_err) { 126577864267SCédric Le Goater error_propagate(errp, local_err); 126677864267SCédric Le Goater return; 126777864267SCédric Le Goater } 12682dfa91a2SCédric Le Goater 12695dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 12705dad902cSCédric Le Goater if (local_err) { 12715dad902cSCédric Le Goater error_propagate(errp, local_err); 12725dad902cSCédric Le Goater return; 12735dad902cSCédric Le Goater } 12745dad902cSCédric Le Goater 12752dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 12762dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 12772dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 12782dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 12792dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 12802dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 12812dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 12822dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 12832dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 12847ae54cc3SGreg Kurz object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", 12857ae54cc3SGreg Kurz &error_abort); 12862dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 12872dfa91a2SCédric Le Goater &local_err); 12882dfa91a2SCédric Le Goater if (local_err) { 12892dfa91a2SCédric Le Goater error_propagate(errp, local_err); 12902dfa91a2SCédric Le Goater return; 12912dfa91a2SCédric Le Goater } 12922dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 12932dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1294c38536bcSCédric Le Goater 1295c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1296c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1297c38536bcSCédric Le Goater "bar", &error_fatal); 1298c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1299c38536bcSCédric Le Goater if (local_err) { 1300c38536bcSCédric Le Goater error_propagate(errp, local_err); 1301c38536bcSCédric Le Goater return; 1302c38536bcSCédric Le Goater } 1303c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1304c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 130515376c66SCédric Le Goater 130615376c66SCédric Le Goater /* LPC */ 1307b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", 1308b63f3893SGreg Kurz &error_abort); 130915376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 131015376c66SCédric Le Goater if (local_err) { 131115376c66SCédric Le Goater error_propagate(errp, local_err); 131215376c66SCédric Le Goater return; 131315376c66SCédric Le Goater } 131415376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 131515376c66SCédric Le Goater &chip9->lpc.xscom_regs); 131615376c66SCédric Le Goater 131715376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 131815376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 13196598a70dSCédric Le Goater 13206598a70dSCédric Le Goater /* Create the simplified OCC model */ 1321ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", 1322ee3d2713SGreg Kurz &error_abort); 13236598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 13246598a70dSCédric Le Goater if (local_err) { 13256598a70dSCédric Le Goater error_propagate(errp, local_err); 13266598a70dSCédric Le Goater return; 13276598a70dSCédric Le Goater } 13286598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1329f3db8266SBalamuruhan S 1330f3db8266SBalamuruhan S /* OCC SRAM model */ 13313a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1332f3db8266SBalamuruhan S &chip9->occ.sram_regs); 13333887d241SBalamuruhan S 13343887d241SBalamuruhan S /* HOMER */ 1335f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", 1336f2582acfSGreg Kurz &error_abort); 13373887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 13383887d241SBalamuruhan S &local_err); 13393887d241SBalamuruhan S if (local_err) { 13403887d241SBalamuruhan S error_propagate(errp, local_err); 13413887d241SBalamuruhan S return; 13423887d241SBalamuruhan S } 13438f092316SCédric Le Goater /* Homer Xscom region */ 13448f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 13458f092316SCédric Le Goater 13468f092316SCédric Le Goater /* Homer mmio region */ 13473887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 13483887d241SBalamuruhan S &chip9->homer.regs); 1349e997040eSCédric Le Goater } 1350e997040eSCédric Le Goater 1351*70c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 1352*70c059e9SGreg Kurz { 1353*70c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 1354*70c059e9SGreg Kurz return addr >> 3; 1355*70c059e9SGreg Kurz } 1356*70c059e9SGreg Kurz 1357e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1358e997040eSCédric Le Goater { 1359e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1360e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1361e997040eSCédric Le Goater 1362e997040eSCédric Le Goater k->chip_type = PNV_CHIP_POWER9; 136383028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1364397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1365631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1366d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1367d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 13680990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 136985913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 137004026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1371eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1372d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1373c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 1374*70c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1375e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 137677864267SCédric Le Goater 137777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 137877864267SCédric Le Goater &k->parent_realize); 1379e997040eSCédric Le Goater } 1380e997040eSCédric Le Goater 13812b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 13822b548a42SCédric Le Goater { 13838b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 13848b50ce85SCédric Le Goater 13858b50ce85SCédric Le Goater object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), 13868b50ce85SCédric Le Goater TYPE_PNV10_PSI, &error_abort, NULL); 13872661f6abSCédric Le Goater object_initialize_child(obj, "lpc", &chip10->lpc, sizeof(chip10->lpc), 13882661f6abSCédric Le Goater TYPE_PNV10_LPC, &error_abort, NULL); 13892b548a42SCédric Le Goater } 13902b548a42SCédric Le Goater 13912b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 13922b548a42SCédric Le Goater { 13932b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 13942b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 13958b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 13962b548a42SCédric Le Goater Error *local_err = NULL; 13972b548a42SCédric Le Goater 13982b548a42SCédric Le Goater /* XSCOM bridge is first */ 13992b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 14002b548a42SCédric Le Goater if (local_err) { 14012b548a42SCédric Le Goater error_propagate(errp, local_err); 14022b548a42SCédric Le Goater return; 14032b548a42SCédric Le Goater } 14042b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 14052b548a42SCédric Le Goater 14062b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 14072b548a42SCédric Le Goater if (local_err) { 14082b548a42SCédric Le Goater error_propagate(errp, local_err); 14092b548a42SCédric Le Goater return; 14102b548a42SCédric Le Goater } 14118b50ce85SCédric Le Goater 14128b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 14138b50ce85SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), 14148b50ce85SCédric Le Goater "bar", &error_fatal); 14158b50ce85SCédric Le Goater object_property_set_bool(OBJECT(&chip10->psi), true, "realized", 14168b50ce85SCédric Le Goater &local_err); 14178b50ce85SCédric Le Goater if (local_err) { 14188b50ce85SCédric Le Goater error_propagate(errp, local_err); 14198b50ce85SCédric Le Goater return; 14208b50ce85SCédric Le Goater } 14218b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 14228b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 14232661f6abSCédric Le Goater 14242661f6abSCédric Le Goater /* LPC */ 14252661f6abSCédric Le Goater object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi", 14262661f6abSCédric Le Goater &error_abort); 14272661f6abSCédric Le Goater object_property_set_bool(OBJECT(&chip10->lpc), true, "realized", 14282661f6abSCédric Le Goater &local_err); 14292661f6abSCédric Le Goater if (local_err) { 14302661f6abSCédric Le Goater error_propagate(errp, local_err); 14312661f6abSCédric Le Goater return; 14322661f6abSCédric Le Goater } 14332661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 14342661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 14352661f6abSCédric Le Goater 14362661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 14372661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 14382b548a42SCédric Le Goater } 14392b548a42SCédric Le Goater 1440*70c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 1441*70c059e9SGreg Kurz { 1442*70c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 1443*70c059e9SGreg Kurz return addr >> 3; 1444*70c059e9SGreg Kurz } 1445*70c059e9SGreg Kurz 14462b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 14472b548a42SCédric Le Goater { 14482b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 14492b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 14502b548a42SCédric Le Goater 14512b548a42SCédric Le Goater k->chip_type = PNV_CHIP_POWER10; 14522b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 14532b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 14542b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 14552b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 14562b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 14572b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 145885913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 14592b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 14602b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 14612b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1462c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 1463*70c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 14642b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 14652b548a42SCédric Le Goater 14662b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 14672b548a42SCédric Le Goater &k->parent_realize); 14682b548a42SCédric Le Goater } 14692b548a42SCédric Le Goater 1470397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1471397a79e7SCédric Le Goater { 1472397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1473397a79e7SCédric Le Goater int cores_max; 1474397a79e7SCédric Le Goater 1475397a79e7SCédric Le Goater /* 1476397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1477397a79e7SCédric Le Goater * the chip class 1478397a79e7SCédric Le Goater */ 1479397a79e7SCédric Le Goater if (!chip->cores_mask) { 1480397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1481397a79e7SCédric Le Goater } 1482397a79e7SCédric Le Goater 1483397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1484397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1485397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1486397a79e7SCédric Le Goater chip->cores_mask); 1487397a79e7SCédric Le Goater return; 1488397a79e7SCédric Le Goater } 1489397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1490397a79e7SCédric Le Goater 1491397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 149227d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1493397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1494397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1495397a79e7SCédric Le Goater cores_max); 1496397a79e7SCédric Le Goater return; 1497397a79e7SCédric Le Goater } 1498397a79e7SCédric Le Goater } 1499397a79e7SCédric Le Goater 150051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1501e997040eSCédric Le Goater { 1502fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1503397a79e7SCédric Le Goater Error *error = NULL; 1504d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 150540abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1506d2fd9612SCédric Le Goater int i, core_hwid; 1507397a79e7SCédric Le Goater 1508d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1509d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1510d2fd9612SCédric Le Goater return; 1511d2fd9612SCédric Le Goater } 1512d2fd9612SCédric Le Goater 1513d2fd9612SCédric Le Goater /* Cores */ 1514397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1515397a79e7SCédric Le Goater if (error) { 1516397a79e7SCédric Le Goater error_propagate(errp, error); 1517397a79e7SCédric Le Goater return; 1518397a79e7SCédric Le Goater } 1519d2fd9612SCédric Le Goater 15204fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1521d2fd9612SCédric Le Goater 1522d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1523d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1524d2fd9612SCédric Le Goater char core_name[32]; 15254fa28f23SGreg Kurz PnvCore *pnv_core; 1526c035851aSCédric Le Goater uint64_t xscom_core_base; 1527d2fd9612SCédric Le Goater 1528d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1529d2fd9612SCédric Le Goater continue; 1530d2fd9612SCédric Le Goater } 1531d2fd9612SCédric Le Goater 15324fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 15334fa28f23SGreg Kurz 1534d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 15354fa28f23SGreg Kurz object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), 15364fa28f23SGreg Kurz &error_abort); 15374fa28f23SGreg Kurz chip->cores[i] = pnv_core; 1538fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1539d2fd9612SCédric Le Goater &error_fatal); 1540d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1541d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1542d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1543d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1544d2fd9612SCédric Le Goater "pir", &error_fatal); 1545158e17a6SGreg Kurz object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", 1546158e17a6SGreg Kurz &error_abort); 1547d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1548d2fd9612SCédric Le Goater &error_fatal); 154924ece072SCédric Le Goater 155024ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1551c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1552c035851aSCédric Le Goater 1553c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 15544fa28f23SGreg Kurz &pnv_core->xscom_regs); 1555d2fd9612SCédric Le Goater i++; 1556d2fd9612SCédric Le Goater } 155751c04728SCédric Le Goater } 155851c04728SCédric Le Goater 155951c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 156051c04728SCédric Le Goater { 156151c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 156251c04728SCédric Le Goater Error *error = NULL; 156351c04728SCédric Le Goater 156451c04728SCédric Le Goater /* Cores */ 156551c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 156651c04728SCédric Le Goater if (error) { 156751c04728SCédric Le Goater error_propagate(errp, error); 156851c04728SCédric Le Goater return; 156951c04728SCédric Le Goater } 1570e997040eSCédric Le Goater } 1571e997040eSCédric Le Goater 1572e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1573e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1574e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1575e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1576397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1577397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1578e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1579e997040eSCédric Le Goater }; 1580e997040eSCédric Le Goater 1581e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1582e997040eSCédric Le Goater { 1583e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1584e997040eSCédric Le Goater 15859d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1586e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1587e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1588e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1589e997040eSCédric Le Goater } 1590e997040eSCédric Le Goater 1591119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1592119eaa9dSCédric Le Goater { 1593119eaa9dSCédric Le Goater int i, j; 1594119eaa9dSCédric Le Goater 1595119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1596119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1597119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1598119eaa9dSCédric Le Goater 1599119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1600119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1601119eaa9dSCédric Le Goater return pc->threads[j]; 1602119eaa9dSCédric Le Goater } 1603119eaa9dSCédric Le Goater } 1604119eaa9dSCédric Le Goater } 1605119eaa9dSCédric Le Goater return NULL; 1606119eaa9dSCédric Le Goater } 1607119eaa9dSCédric Le Goater 160854f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 160954f59d78SCédric Le Goater { 1610b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 161154f59d78SCédric Le Goater int i; 161254f59d78SCédric Le Goater 161354f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 161477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 161577864267SCédric Le Goater 161677864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 161777864267SCédric Le Goater return &chip8->psi.ics; 161854f59d78SCédric Le Goater } 161954f59d78SCédric Le Goater } 162054f59d78SCédric Le Goater return NULL; 162154f59d78SCédric Le Goater } 162254f59d78SCédric Le Goater 162354f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 162454f59d78SCédric Le Goater { 1625b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 162654f59d78SCédric Le Goater int i; 162754f59d78SCédric Le Goater 162854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 162977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 163077864267SCédric Le Goater ics_resend(&chip8->psi.ics); 163154f59d78SCédric Le Goater } 163254f59d78SCédric Le Goater } 163354f59d78SCédric Le Goater 163436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 163536fc6f08SCédric Le Goater { 163636fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 163736fc6f08SCédric Le Goater 1638956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 163936fc6f08SCédric Le Goater } 164036fc6f08SCédric Le Goater 164147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 164247fea43aSCédric Le Goater Monitor *mon) 164347fea43aSCédric Le Goater { 1644b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 164554f59d78SCédric Le Goater int i; 164647fea43aSCédric Le Goater CPUState *cs; 164747fea43aSCédric Le Goater 164847fea43aSCédric Le Goater CPU_FOREACH(cs) { 164947fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 165047fea43aSCédric Le Goater 165185913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 165285913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 165385913070SGreg Kurz mon); 1654d8e4aad5SCédric Le Goater } 165554f59d78SCédric Le Goater 165654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1657d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 165854f59d78SCédric Le Goater } 165947fea43aSCédric Le Goater } 166047fea43aSCédric Le Goater 1661c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1662c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1663c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1664c722579eSCédric Le Goater uint32_t logic_serv, 1665c722579eSCédric Le Goater XiveTCTXMatch *match) 1666c722579eSCédric Le Goater { 1667c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1668c722579eSCédric Le Goater int total_count = 0; 1669c722579eSCédric Le Goater int i; 1670c722579eSCédric Le Goater 1671c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1672c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1673c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1674c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1675c722579eSCédric Le Goater int count; 1676c722579eSCédric Le Goater 1677c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1678c722579eSCédric Le Goater priority, logic_serv, match); 1679c722579eSCédric Le Goater 1680c722579eSCédric Le Goater if (count < 0) { 1681c722579eSCédric Le Goater return count; 1682c722579eSCédric Le Goater } 1683c722579eSCédric Le Goater 1684c722579eSCédric Le Goater total_count += count; 1685c722579eSCédric Le Goater } 1686c722579eSCédric Le Goater 1687c722579eSCédric Le Goater return total_count; 1688c722579eSCédric Le Goater } 1689c722579eSCédric Le Goater 16905373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id) 16915373c61dSCédric Le Goater { 16925373c61dSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 16935373c61dSCédric Le Goater int i; 16945373c61dSCédric Le Goater 16955373c61dSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 16965373c61dSCédric Le Goater PnvChip *chip = pnv->chips[i]; 16975373c61dSCédric Le Goater if (chip->chip_id == chip_id) { 16985373c61dSCédric Le Goater return chip; 16995373c61dSCédric Le Goater } 17005373c61dSCédric Le Goater } 17015373c61dSCédric Le Goater return NULL; 17025373c61dSCédric Le Goater } 17035373c61dSCédric Le Goater 1704e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1705e997040eSCédric Le Goater void *opaque, Error **errp) 1706e997040eSCédric Le Goater { 1707b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1708e997040eSCédric Le Goater } 1709e997040eSCédric Le Goater 1710e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1711e997040eSCédric Le Goater void *opaque, Error **errp) 1712e997040eSCédric Le Goater { 1713b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1714e997040eSCédric Le Goater uint32_t num_chips; 1715e997040eSCédric Le Goater Error *local_err = NULL; 1716e997040eSCédric Le Goater 1717e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1718e997040eSCédric Le Goater if (local_err) { 1719e997040eSCédric Le Goater error_propagate(errp, local_err); 1720e997040eSCédric Le Goater return; 1721e997040eSCédric Le Goater } 1722e997040eSCédric Le Goater 1723e997040eSCédric Le Goater /* 1724e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1725e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1726e997040eSCédric Le Goater */ 1727e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1728e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1729e997040eSCédric Le Goater return; 1730e997040eSCédric Le Goater } 1731e997040eSCédric Le Goater 1732e997040eSCédric Le Goater pnv->num_chips = num_chips; 1733e997040eSCédric Le Goater } 1734e997040eSCédric Le Goater 173577864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1736e997040eSCédric Le Goater { 1737b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1738e997040eSCédric Le Goater pnv->num_chips = 1; 1739e997040eSCédric Le Goater } 1740e997040eSCédric Le Goater 1741b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1742e997040eSCédric Le Goater { 17431e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1744e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1745e997040eSCédric Le Goater NULL, NULL, NULL); 1746e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1747e997040eSCédric Le Goater "Specifies the number of processor chips", 1748e997040eSCédric Le Goater NULL); 17499e933f4aSBenjamin Herrenschmidt } 17509e933f4aSBenjamin Herrenschmidt 1751f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 17529e933f4aSBenjamin Herrenschmidt { 17539e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 175436fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1755d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1756d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 1757f30c843cSCédric Le Goater 1758f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1759f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1760f30c843cSCédric Le Goater 1761f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1762f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1763f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1764d76f2da7SGreg Kurz 1765d76f2da7SGreg Kurz pmc->compat = compat; 1766d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 1767f30c843cSCédric Le Goater } 1768f30c843cSCédric Le Goater 1769f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1770f30c843cSCédric Le Goater { 1771f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1772c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1773d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1774d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 1775f30c843cSCédric Le Goater 1776f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1777f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1778c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1779f30c843cSCédric Le Goater 1780f30c843cSCédric Le Goater mc->alias = "powernv"; 1781d76f2da7SGreg Kurz 1782d76f2da7SGreg Kurz pmc->compat = compat; 1783d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 17847a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 1785f30c843cSCédric Le Goater } 1786f30c843cSCédric Le Goater 17872b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 17882b548a42SCédric Le Goater { 17892b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1790d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1791d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 17922b548a42SCédric Le Goater 17932b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 17942b548a42SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); 1795d76f2da7SGreg Kurz 1796d76f2da7SGreg Kurz pmc->compat = compat; 1797d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 17987a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 17992b548a42SCédric Le Goater } 18002b548a42SCédric Le Goater 1801f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1802f30c843cSCédric Le Goater { 1803f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 180447fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 18059e933f4aSBenjamin Herrenschmidt 18069e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1807b168a138SCédric Le Goater mc->init = pnv_init; 1808b168a138SCédric Le Goater mc->reset = pnv_reset; 18099e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 181059b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 181159b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 18129e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 18139e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1814f1d18b0aSJoel Stanley /* 1815f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1816f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1817f1d18b0aSJoel Stanley */ 1818f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 181947fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1820e997040eSCédric Le Goater 1821b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 18229e933f4aSBenjamin Herrenschmidt } 18239e933f4aSBenjamin Herrenschmidt 182477864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1825beba5c0fSIgor Mammedov { \ 1826beba5c0fSIgor Mammedov .name = type, \ 1827beba5c0fSIgor Mammedov .class_init = class_initfn, \ 182877864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 182977864267SCédric Le Goater } 183077864267SCédric Le Goater 183177864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 183277864267SCédric Le Goater { \ 183377864267SCédric Le Goater .name = type, \ 183477864267SCédric Le Goater .class_init = class_initfn, \ 183577864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1836beba5c0fSIgor Mammedov } 1837beba5c0fSIgor Mammedov 18382b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 18392b548a42SCédric Le Goater { \ 18402b548a42SCédric Le Goater .name = type, \ 18412b548a42SCédric Le Goater .class_init = class_initfn, \ 18422b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 18432b548a42SCédric Le Goater } 18442b548a42SCédric Le Goater 1845beba5c0fSIgor Mammedov static const TypeInfo types[] = { 18461aba8716SCédric Le Goater { 18472b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 18482b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18492b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 18502b548a42SCédric Le Goater }, 18512b548a42SCédric Le Goater { 18521aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 18531aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18541aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 1855c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 1856c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 1857c722579eSCédric Le Goater { }, 1858c722579eSCédric Le Goater }, 18591aba8716SCédric Le Goater }, 18601aba8716SCédric Le Goater { 18611aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 18621aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18631aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 18641aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 18651aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 18661aba8716SCédric Le Goater { }, 18671aba8716SCédric Le Goater }, 18681aba8716SCédric Le Goater }, 1869beba5c0fSIgor Mammedov { 1870b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 18719e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1872f30c843cSCédric Le Goater .abstract = true, 18739e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 187477864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1875b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 1876d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 187736fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 187847fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 187936fc6f08SCédric Le Goater { }, 188036fc6f08SCédric Le Goater }, 1881beba5c0fSIgor Mammedov }, 1882beba5c0fSIgor Mammedov { 1883beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1884beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1885beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1886beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1887beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1888beba5c0fSIgor Mammedov .abstract = true, 1889beba5c0fSIgor Mammedov }, 189077864267SCédric Le Goater 189177864267SCédric Le Goater /* 18922b548a42SCédric Le Goater * P10 chip and variants 18932b548a42SCédric Le Goater */ 18942b548a42SCédric Le Goater { 18952b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 18962b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 18972b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 18982b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 18992b548a42SCédric Le Goater }, 19002b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 19012b548a42SCédric Le Goater 19022b548a42SCédric Le Goater /* 190377864267SCédric Le Goater * P9 chip and variants 190477864267SCédric Le Goater */ 190577864267SCédric Le Goater { 190677864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 190777864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 190877864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 190977864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 191077864267SCédric Le Goater }, 191177864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 191277864267SCédric Le Goater 191377864267SCédric Le Goater /* 191477864267SCédric Le Goater * P8 chip and variants 191577864267SCédric Le Goater */ 191677864267SCédric Le Goater { 191777864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 191877864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 191977864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 192077864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 192177864267SCédric Le Goater }, 192277864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 192377864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 192477864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1925beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 19269e933f4aSBenjamin Herrenschmidt }; 19279e933f4aSBenjamin Herrenschmidt 1928beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1929