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 { 564*8f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 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 112370c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 112470c059e9SGreg Kurz { 112570c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 112670c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 112770c059e9SGreg Kurz } 112870c059e9SGreg 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_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1135397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 1136631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1137d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1138d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11390990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 114085913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 114104026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1142eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1143d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1144c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 114570c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1146e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 114777864267SCédric Le Goater 114877864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 114977864267SCédric Le Goater &k->parent_realize); 1150e997040eSCédric Le Goater } 1151e997040eSCédric Le Goater 1152e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1153e997040eSCédric Le Goater { 1154e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1155e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1156e997040eSCédric Le Goater 1157e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1158397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1159631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1160d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1161d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11620990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 116385913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 116404026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1165eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1166d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1167c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 116870c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1169e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 117077864267SCédric Le Goater 117177864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 117277864267SCédric Le Goater &k->parent_realize); 1173e997040eSCédric Le Goater } 1174e997040eSCédric Le Goater 1175e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1176e997040eSCédric Le Goater { 1177e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1178e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1179e997040eSCédric Le Goater 1180e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1181397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1182631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1183d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1184d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 11850990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 118685913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 118704026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1188eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1189d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1190c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 119170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1192e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 119377864267SCédric Le Goater 119477864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 119577864267SCédric Le Goater &k->parent_realize); 119677864267SCédric Le Goater } 119777864267SCédric Le Goater 119877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 119977864267SCédric Le Goater { 12002dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 12012dfa91a2SCédric Le Goater 12022dfa91a2SCédric Le Goater object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive), 12032dfa91a2SCédric Le Goater TYPE_PNV_XIVE, &error_abort, NULL); 1204c38536bcSCédric Le Goater 1205c38536bcSCédric Le Goater object_initialize_child(obj, "psi", &chip9->psi, sizeof(chip9->psi), 1206c38536bcSCédric Le Goater TYPE_PNV9_PSI, &error_abort, NULL); 120715376c66SCédric Le Goater 120815376c66SCédric Le Goater object_initialize_child(obj, "lpc", &chip9->lpc, sizeof(chip9->lpc), 120915376c66SCédric Le Goater TYPE_PNV9_LPC, &error_abort, NULL); 12106598a70dSCédric Le Goater 12116598a70dSCédric Le Goater object_initialize_child(obj, "occ", &chip9->occ, sizeof(chip9->occ), 12126598a70dSCédric Le Goater TYPE_PNV9_OCC, &error_abort, NULL); 12133887d241SBalamuruhan S 12143887d241SBalamuruhan S object_initialize_child(obj, "homer", &chip9->homer, sizeof(chip9->homer), 12153887d241SBalamuruhan S TYPE_PNV9_HOMER, &error_abort, NULL); 121677864267SCédric Le Goater } 121777864267SCédric Le Goater 12185dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 12195dad902cSCédric Le Goater { 12205dad902cSCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 12215dad902cSCédric Le Goater int i; 12225dad902cSCédric Le Goater 12235dad902cSCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 12245dad902cSCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 12255dad902cSCédric Le Goater 12265dad902cSCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 12275dad902cSCédric Le Goater char eq_name[32]; 12285dad902cSCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 12294fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i * 4]; 12305dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 12315dad902cSCédric Le Goater 12325dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 1233bc4c406cSPhilippe Mathieu-Daudé object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq), 1234bc4c406cSPhilippe Mathieu-Daudé TYPE_PNV_QUAD, &error_fatal, NULL); 12355dad902cSCédric Le Goater 12365dad902cSCédric Le Goater object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal); 12375dad902cSCédric Le Goater object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal); 12385dad902cSCédric Le Goater 12395dad902cSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id), 12405dad902cSCédric Le Goater &eq->xscom_regs); 12415dad902cSCédric Le Goater } 12425dad902cSCédric Le Goater } 12435dad902cSCédric Le Goater 124477864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 124577864267SCédric Le Goater { 124677864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 12472dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 12482dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1249c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 125077864267SCédric Le Goater Error *local_err = NULL; 125177864267SCédric Le Goater 1252709044fdSCédric Le Goater /* XSCOM bridge is first */ 1253709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1254709044fdSCédric Le Goater if (local_err) { 1255709044fdSCédric Le Goater error_propagate(errp, local_err); 1256709044fdSCédric Le Goater return; 1257709044fdSCédric Le Goater } 1258709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1259709044fdSCédric Le Goater 126077864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 126177864267SCédric Le Goater if (local_err) { 126277864267SCédric Le Goater error_propagate(errp, local_err); 126377864267SCédric Le Goater return; 126477864267SCédric Le Goater } 12652dfa91a2SCédric Le Goater 12665dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 12675dad902cSCédric Le Goater if (local_err) { 12685dad902cSCédric Le Goater error_propagate(errp, local_err); 12695dad902cSCédric Le Goater return; 12705dad902cSCédric Le Goater } 12715dad902cSCédric Le Goater 12722dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 12732dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip), 12742dfa91a2SCédric Le Goater "ic-bar", &error_fatal); 12752dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip), 12762dfa91a2SCédric Le Goater "vc-bar", &error_fatal); 12772dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip), 12782dfa91a2SCédric Le Goater "pc-bar", &error_fatal); 12792dfa91a2SCédric Le Goater object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip), 12802dfa91a2SCédric Le Goater "tm-bar", &error_fatal); 12817ae54cc3SGreg Kurz object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip", 12827ae54cc3SGreg Kurz &error_abort); 12832dfa91a2SCédric Le Goater object_property_set_bool(OBJECT(&chip9->xive), true, "realized", 12842dfa91a2SCédric Le Goater &local_err); 12852dfa91a2SCédric Le Goater if (local_err) { 12862dfa91a2SCédric Le Goater error_propagate(errp, local_err); 12872dfa91a2SCédric Le Goater return; 12882dfa91a2SCédric Le Goater } 12892dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 12902dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1291c38536bcSCédric Le Goater 1292c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 1293c38536bcSCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip), 1294c38536bcSCédric Le Goater "bar", &error_fatal); 1295c38536bcSCédric Le Goater object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err); 1296c38536bcSCédric Le Goater if (local_err) { 1297c38536bcSCédric Le Goater error_propagate(errp, local_err); 1298c38536bcSCédric Le Goater return; 1299c38536bcSCédric Le Goater } 1300c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1301c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 130215376c66SCédric Le Goater 130315376c66SCédric Le Goater /* LPC */ 1304b63f3893SGreg Kurz object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi", 1305b63f3893SGreg Kurz &error_abort); 130615376c66SCédric Le Goater object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err); 130715376c66SCédric Le Goater if (local_err) { 130815376c66SCédric Le Goater error_propagate(errp, local_err); 130915376c66SCédric Le Goater return; 131015376c66SCédric Le Goater } 131115376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 131215376c66SCédric Le Goater &chip9->lpc.xscom_regs); 131315376c66SCédric Le Goater 131415376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 131515376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 13166598a70dSCédric Le Goater 13176598a70dSCédric Le Goater /* Create the simplified OCC model */ 1318ee3d2713SGreg Kurz object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi", 1319ee3d2713SGreg Kurz &error_abort); 13206598a70dSCédric Le Goater object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err); 13216598a70dSCédric Le Goater if (local_err) { 13226598a70dSCédric Le Goater error_propagate(errp, local_err); 13236598a70dSCédric Le Goater return; 13246598a70dSCédric Le Goater } 13256598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1326f3db8266SBalamuruhan S 1327f3db8266SBalamuruhan S /* OCC SRAM model */ 13283a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1329f3db8266SBalamuruhan S &chip9->occ.sram_regs); 13303887d241SBalamuruhan S 13313887d241SBalamuruhan S /* HOMER */ 1332f2582acfSGreg Kurz object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip", 1333f2582acfSGreg Kurz &error_abort); 13343887d241SBalamuruhan S object_property_set_bool(OBJECT(&chip9->homer), true, "realized", 13353887d241SBalamuruhan S &local_err); 13363887d241SBalamuruhan S if (local_err) { 13373887d241SBalamuruhan S error_propagate(errp, local_err); 13383887d241SBalamuruhan S return; 13393887d241SBalamuruhan S } 13408f092316SCédric Le Goater /* Homer Xscom region */ 13418f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 13428f092316SCédric Le Goater 13438f092316SCédric Le Goater /* Homer mmio region */ 13443887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 13453887d241SBalamuruhan S &chip9->homer.regs); 1346e997040eSCédric Le Goater } 1347e997040eSCédric Le Goater 134870c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 134970c059e9SGreg Kurz { 135070c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 135170c059e9SGreg Kurz return addr >> 3; 135270c059e9SGreg Kurz } 135370c059e9SGreg Kurz 1354e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1355e997040eSCédric Le Goater { 1356e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1357e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1358e997040eSCédric Le Goater 135983028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1360397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1361631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1362d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1363d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 13640990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 136585913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 136604026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1367eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1368d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1369c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 137070c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1371e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 137277864267SCédric Le Goater 137377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 137477864267SCédric Le Goater &k->parent_realize); 1375e997040eSCédric Le Goater } 1376e997040eSCédric Le Goater 13772b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 13782b548a42SCédric Le Goater { 13798b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 13808b50ce85SCédric Le Goater 13818b50ce85SCédric Le Goater object_initialize_child(obj, "psi", &chip10->psi, sizeof(chip10->psi), 13828b50ce85SCédric Le Goater TYPE_PNV10_PSI, &error_abort, NULL); 13832661f6abSCédric Le Goater object_initialize_child(obj, "lpc", &chip10->lpc, sizeof(chip10->lpc), 13842661f6abSCédric Le Goater TYPE_PNV10_LPC, &error_abort, NULL); 13852b548a42SCédric Le Goater } 13862b548a42SCédric Le Goater 13872b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 13882b548a42SCédric Le Goater { 13892b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 13902b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 13918b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 13922b548a42SCédric Le Goater Error *local_err = NULL; 13932b548a42SCédric Le Goater 13942b548a42SCédric Le Goater /* XSCOM bridge is first */ 13952b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 13962b548a42SCédric Le Goater if (local_err) { 13972b548a42SCédric Le Goater error_propagate(errp, local_err); 13982b548a42SCédric Le Goater return; 13992b548a42SCédric Le Goater } 14002b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 14012b548a42SCédric Le Goater 14022b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 14032b548a42SCédric Le Goater if (local_err) { 14042b548a42SCédric Le Goater error_propagate(errp, local_err); 14052b548a42SCédric Le Goater return; 14062b548a42SCédric Le Goater } 14078b50ce85SCédric Le Goater 14088b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 14098b50ce85SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip), 14108b50ce85SCédric Le Goater "bar", &error_fatal); 14118b50ce85SCédric Le Goater object_property_set_bool(OBJECT(&chip10->psi), true, "realized", 14128b50ce85SCédric Le Goater &local_err); 14138b50ce85SCédric Le Goater if (local_err) { 14148b50ce85SCédric Le Goater error_propagate(errp, local_err); 14158b50ce85SCédric Le Goater return; 14168b50ce85SCédric Le Goater } 14178b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 14188b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 14192661f6abSCédric Le Goater 14202661f6abSCédric Le Goater /* LPC */ 14212661f6abSCédric Le Goater object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi", 14222661f6abSCédric Le Goater &error_abort); 14232661f6abSCédric Le Goater object_property_set_bool(OBJECT(&chip10->lpc), true, "realized", 14242661f6abSCédric Le Goater &local_err); 14252661f6abSCédric Le Goater if (local_err) { 14262661f6abSCédric Le Goater error_propagate(errp, local_err); 14272661f6abSCédric Le Goater return; 14282661f6abSCédric Le Goater } 14292661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 14302661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 14312661f6abSCédric Le Goater 14322661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 14332661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 14342b548a42SCédric Le Goater } 14352b548a42SCédric Le Goater 143670c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 143770c059e9SGreg Kurz { 143870c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 143970c059e9SGreg Kurz return addr >> 3; 144070c059e9SGreg Kurz } 144170c059e9SGreg Kurz 14422b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 14432b548a42SCédric Le Goater { 14442b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 14452b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 14462b548a42SCédric Le Goater 14472b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 14482b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 14492b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 14502b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 14512b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 14522b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 145385913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 14542b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 14552b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 14562b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1457c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 145870c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 14592b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 14602b548a42SCédric Le Goater 14612b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 14622b548a42SCédric Le Goater &k->parent_realize); 14632b548a42SCédric Le Goater } 14642b548a42SCédric Le Goater 1465397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1466397a79e7SCédric Le Goater { 1467397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1468397a79e7SCédric Le Goater int cores_max; 1469397a79e7SCédric Le Goater 1470397a79e7SCédric Le Goater /* 1471397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1472397a79e7SCédric Le Goater * the chip class 1473397a79e7SCédric Le Goater */ 1474397a79e7SCédric Le Goater if (!chip->cores_mask) { 1475397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1476397a79e7SCédric Le Goater } 1477397a79e7SCédric Le Goater 1478397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1479397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1480397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1481397a79e7SCédric Le Goater chip->cores_mask); 1482397a79e7SCédric Le Goater return; 1483397a79e7SCédric Le Goater } 1484397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1485397a79e7SCédric Le Goater 1486397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 148727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1488397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1489397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1490397a79e7SCédric Le Goater cores_max); 1491397a79e7SCédric Le Goater return; 1492397a79e7SCédric Le Goater } 1493397a79e7SCédric Le Goater } 1494397a79e7SCédric Le Goater 149551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1496e997040eSCédric Le Goater { 1497fe6b6346SLike Xu MachineState *ms = MACHINE(qdev_get_machine()); 1498397a79e7SCédric Le Goater Error *error = NULL; 1499d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 150040abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1501d2fd9612SCédric Le Goater int i, core_hwid; 1502397a79e7SCédric Le Goater 1503d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1504d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1505d2fd9612SCédric Le Goater return; 1506d2fd9612SCédric Le Goater } 1507d2fd9612SCédric Le Goater 1508d2fd9612SCédric Le Goater /* Cores */ 1509397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1510397a79e7SCédric Le Goater if (error) { 1511397a79e7SCédric Le Goater error_propagate(errp, error); 1512397a79e7SCédric Le Goater return; 1513397a79e7SCédric Le Goater } 1514d2fd9612SCédric Le Goater 15154fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1516d2fd9612SCédric Le Goater 1517d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1518d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1519d2fd9612SCédric Le Goater char core_name[32]; 15204fa28f23SGreg Kurz PnvCore *pnv_core; 1521c035851aSCédric Le Goater uint64_t xscom_core_base; 1522d2fd9612SCédric Le Goater 1523d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1524d2fd9612SCédric Le Goater continue; 1525d2fd9612SCédric Le Goater } 1526d2fd9612SCédric Le Goater 15274fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 15284fa28f23SGreg Kurz 1529d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 15304fa28f23SGreg Kurz object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core), 15314fa28f23SGreg Kurz &error_abort); 15324fa28f23SGreg Kurz chip->cores[i] = pnv_core; 1533fe6b6346SLike Xu object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads", 1534d2fd9612SCédric Le Goater &error_fatal); 1535d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), core_hwid, 1536d2fd9612SCédric Le Goater CPU_CORE_PROP_CORE_ID, &error_fatal); 1537d2fd9612SCédric Le Goater object_property_set_int(OBJECT(pnv_core), 1538d2fd9612SCédric Le Goater pcc->core_pir(chip, core_hwid), 1539d2fd9612SCédric Le Goater "pir", &error_fatal); 1540158e17a6SGreg Kurz object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip", 1541158e17a6SGreg Kurz &error_abort); 1542d2fd9612SCédric Le Goater object_property_set_bool(OBJECT(pnv_core), true, "realized", 1543d2fd9612SCédric Le Goater &error_fatal); 154424ece072SCédric Le Goater 154524ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1546c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1547c035851aSCédric Le Goater 1548c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 15494fa28f23SGreg Kurz &pnv_core->xscom_regs); 1550d2fd9612SCédric Le Goater i++; 1551d2fd9612SCédric Le Goater } 155251c04728SCédric Le Goater } 155351c04728SCédric Le Goater 155451c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 155551c04728SCédric Le Goater { 155651c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 155751c04728SCédric Le Goater Error *error = NULL; 155851c04728SCédric Le Goater 155951c04728SCédric Le Goater /* Cores */ 156051c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 156151c04728SCédric Le Goater if (error) { 156251c04728SCédric Le Goater error_propagate(errp, error); 156351c04728SCédric Le Goater return; 156451c04728SCédric Le Goater } 1565e997040eSCédric Le Goater } 1566e997040eSCédric Le Goater 1567e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1568e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1569e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1570e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1571397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1572397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1573e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1574e997040eSCédric Le Goater }; 1575e997040eSCédric Le Goater 1576e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1577e997040eSCédric Le Goater { 1578e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1579e997040eSCédric Le Goater 15809d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1581e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 1582e997040eSCédric Le Goater dc->props = pnv_chip_properties; 1583e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1584e997040eSCédric Le Goater } 1585e997040eSCédric Le Goater 1586119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1587119eaa9dSCédric Le Goater { 1588119eaa9dSCédric Le Goater int i, j; 1589119eaa9dSCédric Le Goater 1590119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1591119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1592119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1593119eaa9dSCédric Le Goater 1594119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1595119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1596119eaa9dSCédric Le Goater return pc->threads[j]; 1597119eaa9dSCédric Le Goater } 1598119eaa9dSCédric Le Goater } 1599119eaa9dSCédric Le Goater } 1600119eaa9dSCédric Le Goater return NULL; 1601119eaa9dSCédric Le Goater } 1602119eaa9dSCédric Le Goater 160354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 160454f59d78SCédric Le Goater { 1605b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 160654f59d78SCédric Le Goater int i; 160754f59d78SCédric Le Goater 160854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 160977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 161077864267SCédric Le Goater 161177864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 161277864267SCédric Le Goater return &chip8->psi.ics; 161354f59d78SCédric Le Goater } 161454f59d78SCédric Le Goater } 161554f59d78SCédric Le Goater return NULL; 161654f59d78SCédric Le Goater } 161754f59d78SCédric Le Goater 161854f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 161954f59d78SCédric Le Goater { 1620b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 162154f59d78SCédric Le Goater int i; 162254f59d78SCédric Le Goater 162354f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 162477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 162577864267SCédric Le Goater ics_resend(&chip8->psi.ics); 162654f59d78SCédric Le Goater } 162754f59d78SCédric Le Goater } 162854f59d78SCédric Le Goater 162936fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 163036fc6f08SCédric Le Goater { 163136fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 163236fc6f08SCédric Le Goater 1633956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 163436fc6f08SCédric Le Goater } 163536fc6f08SCédric Le Goater 163647fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 163747fea43aSCédric Le Goater Monitor *mon) 163847fea43aSCédric Le Goater { 1639b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 164054f59d78SCédric Le Goater int i; 164147fea43aSCédric Le Goater CPUState *cs; 164247fea43aSCédric Le Goater 164347fea43aSCédric Le Goater CPU_FOREACH(cs) { 164447fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 164547fea43aSCédric Le Goater 164685913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 164785913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 164885913070SGreg Kurz mon); 1649d8e4aad5SCédric Le Goater } 165054f59d78SCédric Le Goater 165154f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1652d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 165354f59d78SCédric Le Goater } 165447fea43aSCédric Le Goater } 165547fea43aSCédric Le Goater 1656c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 1657c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 1658c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 1659c722579eSCédric Le Goater uint32_t logic_serv, 1660c722579eSCédric Le Goater XiveTCTXMatch *match) 1661c722579eSCédric Le Goater { 1662c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 1663c722579eSCédric Le Goater int total_count = 0; 1664c722579eSCédric Le Goater int i; 1665c722579eSCédric Le Goater 1666c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 1667c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 1668c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 1669c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 1670c722579eSCédric Le Goater int count; 1671c722579eSCédric Le Goater 1672c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 1673c722579eSCédric Le Goater priority, logic_serv, match); 1674c722579eSCédric Le Goater 1675c722579eSCédric Le Goater if (count < 0) { 1676c722579eSCédric Le Goater return count; 1677c722579eSCédric Le Goater } 1678c722579eSCédric Le Goater 1679c722579eSCédric Le Goater total_count += count; 1680c722579eSCédric Le Goater } 1681c722579eSCédric Le Goater 1682c722579eSCédric Le Goater return total_count; 1683c722579eSCédric Le Goater } 1684c722579eSCédric Le Goater 16855373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id) 16865373c61dSCédric Le Goater { 16875373c61dSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 16885373c61dSCédric Le Goater int i; 16895373c61dSCédric Le Goater 16905373c61dSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 16915373c61dSCédric Le Goater PnvChip *chip = pnv->chips[i]; 16925373c61dSCédric Le Goater if (chip->chip_id == chip_id) { 16935373c61dSCédric Le Goater return chip; 16945373c61dSCédric Le Goater } 16955373c61dSCédric Le Goater } 16965373c61dSCédric Le Goater return NULL; 16975373c61dSCédric Le Goater } 16985373c61dSCédric Le Goater 1699e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name, 1700e997040eSCédric Le Goater void *opaque, Error **errp) 1701e997040eSCédric Le Goater { 1702b168a138SCédric Le Goater visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp); 1703e997040eSCédric Le Goater } 1704e997040eSCédric Le Goater 1705e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name, 1706e997040eSCédric Le Goater void *opaque, Error **errp) 1707e997040eSCédric Le Goater { 1708b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1709e997040eSCédric Le Goater uint32_t num_chips; 1710e997040eSCédric Le Goater Error *local_err = NULL; 1711e997040eSCédric Le Goater 1712e997040eSCédric Le Goater visit_type_uint32(v, name, &num_chips, &local_err); 1713e997040eSCédric Le Goater if (local_err) { 1714e997040eSCédric Le Goater error_propagate(errp, local_err); 1715e997040eSCédric Le Goater return; 1716e997040eSCédric Le Goater } 1717e997040eSCédric Le Goater 1718e997040eSCédric Le Goater /* 1719e997040eSCédric Le Goater * TODO: should we decide on how many chips we can create based 1720e997040eSCédric Le Goater * on #cores and Venice vs. Murano vs. Naples chip type etc..., 1721e997040eSCédric Le Goater */ 1722e997040eSCédric Le Goater if (!is_power_of_2(num_chips) || num_chips > 4) { 1723e997040eSCédric Le Goater error_setg(errp, "invalid number of chips: '%d'", num_chips); 1724e997040eSCédric Le Goater return; 1725e997040eSCédric Le Goater } 1726e997040eSCédric Le Goater 1727e997040eSCédric Le Goater pnv->num_chips = num_chips; 1728e997040eSCédric Le Goater } 1729e997040eSCédric Le Goater 173077864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj) 1731e997040eSCédric Le Goater { 1732b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 1733e997040eSCédric Le Goater pnv->num_chips = 1; 1734e997040eSCédric Le Goater } 1735e997040eSCédric Le Goater 1736b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc) 1737e997040eSCédric Le Goater { 17381e507bb0SMarc-André Lureau object_class_property_add(oc, "num-chips", "uint32", 1739e997040eSCédric Le Goater pnv_get_num_chips, pnv_set_num_chips, 1740e997040eSCédric Le Goater NULL, NULL, NULL); 1741e997040eSCédric Le Goater object_class_property_set_description(oc, "num-chips", 1742e997040eSCédric Le Goater "Specifies the number of processor chips", 1743e997040eSCédric Le Goater NULL); 17449e933f4aSBenjamin Herrenschmidt } 17459e933f4aSBenjamin Herrenschmidt 1746f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 17479e933f4aSBenjamin Herrenschmidt { 17489e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 174936fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 1750d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1751d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 1752f30c843cSCédric Le Goater 1753f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 1754f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 1755f30c843cSCédric Le Goater 1756f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 1757f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 1758f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 1759d76f2da7SGreg Kurz 1760d76f2da7SGreg Kurz pmc->compat = compat; 1761d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 1762f30c843cSCédric Le Goater } 1763f30c843cSCédric Le Goater 1764f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 1765f30c843cSCédric Le Goater { 1766f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1767c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 1768d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1769d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 1770f30c843cSCédric Le Goater 1771f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 1772f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); 1773c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 1774f30c843cSCédric Le Goater 1775f30c843cSCédric Le Goater mc->alias = "powernv"; 1776d76f2da7SGreg Kurz 1777d76f2da7SGreg Kurz pmc->compat = compat; 1778d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 17797a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 1780f30c843cSCédric Le Goater } 1781f30c843cSCédric Le Goater 17822b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 17832b548a42SCédric Le Goater { 17842b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 1785d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 1786d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 17872b548a42SCédric Le Goater 17882b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 17892b548a42SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0"); 1790d76f2da7SGreg Kurz 1791d76f2da7SGreg Kurz pmc->compat = compat; 1792d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 17937a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 17942b548a42SCédric Le Goater } 17952b548a42SCédric Le Goater 1796f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 1797f30c843cSCédric Le Goater { 1798f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 179947fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 18009e933f4aSBenjamin Herrenschmidt 18019e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 1802b168a138SCédric Le Goater mc->init = pnv_init; 1803b168a138SCédric Le Goater mc->reset = pnv_reset; 18049e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 180559b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 180659b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 18079e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 18089e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 1809f1d18b0aSJoel Stanley /* 1810f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 1811f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 1812f1d18b0aSJoel Stanley */ 1813f1d18b0aSJoel Stanley mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE; 181447fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 1815e997040eSCédric Le Goater 1816b168a138SCédric Le Goater pnv_machine_class_props_init(oc); 18179e933f4aSBenjamin Herrenschmidt } 18189e933f4aSBenjamin Herrenschmidt 181977864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 1820beba5c0fSIgor Mammedov { \ 1821beba5c0fSIgor Mammedov .name = type, \ 1822beba5c0fSIgor Mammedov .class_init = class_initfn, \ 182377864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 182477864267SCédric Le Goater } 182577864267SCédric Le Goater 182677864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 182777864267SCédric Le Goater { \ 182877864267SCédric Le Goater .name = type, \ 182977864267SCédric Le Goater .class_init = class_initfn, \ 183077864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 1831beba5c0fSIgor Mammedov } 1832beba5c0fSIgor Mammedov 18332b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 18342b548a42SCédric Le Goater { \ 18352b548a42SCédric Le Goater .name = type, \ 18362b548a42SCédric Le Goater .class_init = class_initfn, \ 18372b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 18382b548a42SCédric Le Goater } 18392b548a42SCédric Le Goater 1840beba5c0fSIgor Mammedov static const TypeInfo types[] = { 18411aba8716SCédric Le Goater { 18422b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 18432b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18442b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 18452b548a42SCédric Le Goater }, 18462b548a42SCédric Le Goater { 18471aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 18481aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18491aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 1850c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 1851c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 1852c722579eSCédric Le Goater { }, 1853c722579eSCédric Le Goater }, 18541aba8716SCédric Le Goater }, 18551aba8716SCédric Le Goater { 18561aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 18571aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 18581aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 18591aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 18601aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 18611aba8716SCédric Le Goater { }, 18621aba8716SCédric Le Goater }, 18631aba8716SCédric Le Goater }, 1864beba5c0fSIgor Mammedov { 1865b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 18669e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 1867f30c843cSCédric Le Goater .abstract = true, 18689e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 186977864267SCédric Le Goater .instance_init = pnv_machine_instance_init, 1870b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 1871d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 187236fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 187347fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 187436fc6f08SCédric Le Goater { }, 187536fc6f08SCédric Le Goater }, 1876beba5c0fSIgor Mammedov }, 1877beba5c0fSIgor Mammedov { 1878beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 1879beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 1880beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 1881beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 1882beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 1883beba5c0fSIgor Mammedov .abstract = true, 1884beba5c0fSIgor Mammedov }, 188577864267SCédric Le Goater 188677864267SCédric Le Goater /* 18872b548a42SCédric Le Goater * P10 chip and variants 18882b548a42SCédric Le Goater */ 18892b548a42SCédric Le Goater { 18902b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 18912b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 18922b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 18932b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 18942b548a42SCédric Le Goater }, 18952b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 18962b548a42SCédric Le Goater 18972b548a42SCédric Le Goater /* 189877864267SCédric Le Goater * P9 chip and variants 189977864267SCédric Le Goater */ 190077864267SCédric Le Goater { 190177864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 190277864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 190377864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 190477864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 190577864267SCédric Le Goater }, 190677864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 190777864267SCédric Le Goater 190877864267SCédric Le Goater /* 190977864267SCédric Le Goater * P8 chip and variants 191077864267SCédric Le Goater */ 191177864267SCédric Le Goater { 191277864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 191377864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 191477864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 191577864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 191677864267SCédric Le Goater }, 191777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 191877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 191977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 1920beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 19219e933f4aSBenjamin Herrenschmidt }; 19229e933f4aSBenjamin Herrenschmidt 1923beba5c0fSIgor Mammedov DEFINE_TYPES(types) 1924