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 9f70c5966SChetan Pant * version 2.1 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" 212c65db5eSPaolo Bonzini #include "qemu/datadir.h" 22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h" 23dd7ef911SCédric Le Goater #include "qemu/cutils.h" 249e933f4aSBenjamin Herrenschmidt #include "qapi/error.h" 2538d2448aSGreg Kurz #include "sysemu/qtest.h" 269e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h" 279e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h" 2871e8a915SMarkus Armbruster #include "sysemu/reset.h" 2954d31236SMarkus Armbruster #include "sysemu/runstate.h" 30d2528bdcSPaolo Bonzini #include "sysemu/cpus.h" 318d409261SCédric Le Goater #include "sysemu/device_tree.h" 3201b552b0SNicholas Piggin #include "sysemu/hw_accel.h" 33fcf5ef2aSThomas Huth #include "target/ppc/cpu.h" 349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h" 359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h" 369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h" 37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h" 389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h" 3901b552b0SNicholas Piggin #include "hw/nmi.h" 40e997040eSCédric Le Goater #include "qapi/visitor.h" 4147fea43aSCédric Le Goater #include "monitor/monitor.h" 4247fea43aSCédric Le Goater #include "hw/intc/intc.h" 43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h" 4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h" 454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h" 461f5d6b2aSDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h" 472c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb3.h" 482c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb4.h" 499e933f4aSBenjamin Herrenschmidt 5036fc6f08SCédric Le Goater #include "hw/ppc/xics.h" 51a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 522c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h" 53967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h" 5435dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h" 55967b7523SCédric Le Goater 563495b6b6SCédric Le Goater #include "hw/isa/isa.h" 573495b6b6SCédric Le Goater #include "hw/char/serial.h" 58bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h" 593495b6b6SCédric Le Goater 609e933f4aSBenjamin Herrenschmidt #include <libfdt.h> 619e933f4aSBenjamin Herrenschmidt 62b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE (1 * MiB) 639e933f4aSBenjamin Herrenschmidt 649e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME "skiboot.lid" 659e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR 0x0 6683fa6e2aSCédric Le Goater #define FW_MAX_SIZE (16 * MiB) 679e933f4aSBenjamin Herrenschmidt 689e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR 0x20000000 6905ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE (128 * MiB) 7005ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR 0x28000000 7105ce9b73SCédric Le Goater #define INITRD_MAX_SIZE (128 * MiB) 729e933f4aSBenjamin Herrenschmidt 7340abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o) 7440abf43fSIgor Mammedov { 7540abf43fSIgor Mammedov const char *chip_type = object_class_get_name(object_get_class(OBJECT(o))); 7640abf43fSIgor Mammedov int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX); 7740abf43fSIgor Mammedov char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type); 7840abf43fSIgor Mammedov const char *core_type = object_class_get_name(object_class_by_name(s)); 7940abf43fSIgor Mammedov g_free(s); 8040abf43fSIgor Mammedov return core_type; 8140abf43fSIgor Mammedov } 8240abf43fSIgor Mammedov 839e933f4aSBenjamin Herrenschmidt /* 849e933f4aSBenjamin Herrenschmidt * On Power Systems E880 (POWER8), the max cpus (threads) should be : 859e933f4aSBenjamin Herrenschmidt * 4 * 4 sockets * 12 cores * 8 threads = 1536 869e933f4aSBenjamin Herrenschmidt * Let's make it 2^11 879e933f4aSBenjamin Herrenschmidt */ 889e933f4aSBenjamin Herrenschmidt #define MAX_CPUS 2048 899e933f4aSBenjamin Herrenschmidt 909e933f4aSBenjamin Herrenschmidt /* 919e933f4aSBenjamin Herrenschmidt * Memory nodes are created by hostboot, one for each range of memory 929e933f4aSBenjamin Herrenschmidt * that has a different "affinity". In practice, it means one range 939e933f4aSBenjamin Herrenschmidt * per chip. 949e933f4aSBenjamin Herrenschmidt */ 95b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size) 969e933f4aSBenjamin Herrenschmidt { 979e933f4aSBenjamin Herrenschmidt char *mem_name; 989e933f4aSBenjamin Herrenschmidt uint64_t mem_reg_property[2]; 999e933f4aSBenjamin Herrenschmidt int off; 1009e933f4aSBenjamin Herrenschmidt 1019e933f4aSBenjamin Herrenschmidt mem_reg_property[0] = cpu_to_be64(start); 1029e933f4aSBenjamin Herrenschmidt mem_reg_property[1] = cpu_to_be64(size); 1039e933f4aSBenjamin Herrenschmidt 1049e933f4aSBenjamin Herrenschmidt mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start); 1059e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, mem_name); 1069e933f4aSBenjamin Herrenschmidt g_free(mem_name); 1079e933f4aSBenjamin Herrenschmidt 1089e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 1099e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 1109e933f4aSBenjamin Herrenschmidt sizeof(mem_reg_property)))); 1119e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id))); 1129e933f4aSBenjamin Herrenschmidt } 1139e933f4aSBenjamin Herrenschmidt 114d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt) 115d2fd9612SCédric Le Goater { 116d2fd9612SCédric Le Goater int cpus_offset = fdt_path_offset(fdt, "/cpus"); 117d2fd9612SCédric Le Goater 118d2fd9612SCédric Le Goater if (cpus_offset < 0) { 119a4f3885cSGreg Kurz cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 120d2fd9612SCédric Le Goater if (cpus_offset) { 121d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 122d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 123d2fd9612SCédric Le Goater } 124d2fd9612SCédric Le Goater } 125d2fd9612SCédric Le Goater _FDT(cpus_offset); 126d2fd9612SCédric Le Goater return cpus_offset; 127d2fd9612SCédric Le Goater } 128d2fd9612SCédric Le Goater 129d2fd9612SCédric Le Goater /* 130d2fd9612SCédric Le Goater * The PowerNV cores (and threads) need to use real HW ids and not an 131d2fd9612SCédric Le Goater * incremental index like it has been done on other platforms. This HW 132d2fd9612SCédric Le Goater * id is stored in the CPU PIR, it is used to create cpu nodes in the 133d2fd9612SCédric Le Goater * device tree, used in XSCOM to address cores and in interrupt 134d2fd9612SCédric Le Goater * servers. 135d2fd9612SCédric Le Goater */ 136b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) 137d2fd9612SCédric Le Goater { 13808304a86SDavid Gibson PowerPCCPU *cpu = pc->threads[0]; 13908304a86SDavid Gibson CPUState *cs = CPU(cpu); 140d2fd9612SCédric Le Goater DeviceClass *dc = DEVICE_GET_CLASS(cs); 1418bd9530eSDavid Gibson int smt_threads = CPU_CORE(pc)->nr_threads; 142d2fd9612SCédric Le Goater CPUPPCState *env = &cpu->env; 143d2fd9612SCédric Le Goater PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 144a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); 145d2fd9612SCédric Le Goater int i; 146d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 147d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff}; 148d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ; 149d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000; 150d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64]; 151d2fd9612SCédric Le Goater size_t page_sizes_prop_size; 152d2fd9612SCédric Le Goater const uint8_t pa_features[] = { 24, 0, 153d2fd9612SCédric Le Goater 0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0, 154d2fd9612SCédric Le Goater 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 155d2fd9612SCédric Le Goater 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 156d2fd9612SCédric Le Goater 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 157d2fd9612SCédric Le Goater int offset; 158d2fd9612SCédric Le Goater char *nodename; 159d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt); 160d2fd9612SCédric Le Goater 161d2fd9612SCédric Le Goater nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir); 162d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename); 163d2fd9612SCédric Le Goater _FDT(offset); 164d2fd9612SCédric Le Goater g_free(nodename); 165d2fd9612SCédric Le Goater 166d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id))); 167d2fd9612SCédric Le Goater 168d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir))); 169d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir))); 170d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 171d2fd9612SCédric Le Goater 172d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 173d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 174d2fd9612SCédric Le Goater env->dcache_line_size))); 175d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 176d2fd9612SCédric Le Goater env->dcache_line_size))); 177d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 178d2fd9612SCédric Le Goater env->icache_line_size))); 179d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 180d2fd9612SCédric Le Goater env->icache_line_size))); 181d2fd9612SCédric Le Goater 182d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) { 183d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 184d2fd9612SCédric Le Goater pcc->l1_dcache_size))); 185d2fd9612SCédric Le Goater } else { 1863dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu"); 187d2fd9612SCédric Le Goater } 188d2fd9612SCédric Le Goater if (pcc->l1_icache_size) { 189d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 190d2fd9612SCédric Le Goater pcc->l1_icache_size))); 191d2fd9612SCédric Le Goater } else { 1923dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu"); 193d2fd9612SCédric Le Goater } 194d2fd9612SCédric Le Goater 195d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 196d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 19759b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", 19859b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size))); 199d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 200d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 201d2fd9612SCédric Le Goater 20203282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) { 203d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 204d2fd9612SCédric Le Goater } 205d2fd9612SCédric Le Goater 20658969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) { 207d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 208d2fd9612SCédric Le Goater segs, sizeof(segs)))); 209d2fd9612SCédric Le Goater } 210d2fd9612SCédric Le Goater 21159b7c1c2SBalamuruhan S /* 21259b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available 213d2fd9612SCédric Le Goater * 0 / no property == no vector extensions 214d2fd9612SCédric Le Goater * 1 == VMX / Altivec available 21559b7c1c2SBalamuruhan S * 2 == VSX available 21659b7c1c2SBalamuruhan S */ 217d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) { 218d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 219d2fd9612SCédric Le Goater 220d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 221d2fd9612SCédric Le Goater } 222d2fd9612SCédric Le Goater 22359b7c1c2SBalamuruhan S /* 22459b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available 225d2fd9612SCédric Le Goater * 0 / no property == no DFP 22659b7c1c2SBalamuruhan S * 1 == DFP available 22759b7c1c2SBalamuruhan S */ 228d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) { 229d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 230d2fd9612SCédric Le Goater } 231d2fd9612SCédric Le Goater 232644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop, 233d2fd9612SCédric Le Goater sizeof(page_sizes_prop)); 234d2fd9612SCédric Le Goater if (page_sizes_prop_size) { 235d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 236d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size))); 237d2fd9612SCédric Le Goater } 238d2fd9612SCédric Le Goater 239d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", 240d2fd9612SCédric Le Goater pa_features, sizeof(pa_features)))); 241d2fd9612SCédric Le Goater 242d2fd9612SCédric Le Goater /* Build interrupt servers properties */ 243d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) { 244d2fd9612SCédric Le Goater servers_prop[i] = cpu_to_be32(pc->pir + i); 245d2fd9612SCédric Le Goater } 246d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 247a580fdcdSPhilippe Mathieu-Daudé servers_prop, sizeof(*servers_prop) * smt_threads))); 248d2fd9612SCédric Le Goater } 249d2fd9612SCédric Le Goater 250b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, 251bf5615e7SCédric Le Goater uint32_t nr_threads) 252bf5615e7SCédric Le Goater { 253bf5615e7SCédric Le Goater uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12); 254bf5615e7SCédric Le Goater char *name; 255bf5615e7SCédric Le Goater const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp"; 256bf5615e7SCédric Le Goater uint32_t irange[2], i, rsize; 257bf5615e7SCédric Le Goater uint64_t *reg; 258bf5615e7SCédric Le Goater int offset; 259bf5615e7SCédric Le Goater 260bf5615e7SCédric Le Goater irange[0] = cpu_to_be32(pir); 261bf5615e7SCédric Le Goater irange[1] = cpu_to_be32(nr_threads); 262bf5615e7SCédric Le Goater 263bf5615e7SCédric Le Goater rsize = sizeof(uint64_t) * 2 * nr_threads; 264bf5615e7SCédric Le Goater reg = g_malloc(rsize); 265bf5615e7SCédric Le Goater for (i = 0; i < nr_threads; i++) { 266bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000)); 267bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000); 268bf5615e7SCédric Le Goater } 269bf5615e7SCédric Le Goater 270bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr); 271bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name); 272bf5615e7SCédric Le Goater _FDT(offset); 273bf5615e7SCédric Le Goater g_free(name); 274bf5615e7SCédric Le Goater 275bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat)))); 276bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize))); 277bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", 278bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation"))); 279bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0))); 280bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges", 281bf5615e7SCédric Le Goater irange, sizeof(irange)))); 282bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1))); 283bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0))); 284bf5615e7SCédric Le Goater g_free(reg); 285bf5615e7SCédric Le Goater } 286bf5615e7SCédric Le Goater 287ba47c3a4SDaniel Henrique Barboza /* 288ddf0676fSFrederic Barrat * Adds a PnvPHB to the chip on P8. 289ddf0676fSFrederic Barrat * Implemented here, like for defaults PHBs 290ba47c3a4SDaniel Henrique Barboza */ 291ddf0676fSFrederic Barrat PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb) 292ba47c3a4SDaniel Henrique Barboza { 2930d512c71SDaniel Henrique Barboza Pnv8Chip *chip8 = PNV8_CHIP(chip); 2940d512c71SDaniel Henrique Barboza 2950d512c71SDaniel Henrique Barboza phb->chip = chip; 2960d512c71SDaniel Henrique Barboza 2970d512c71SDaniel Henrique Barboza chip8->phbs[chip8->num_phbs] = phb; 2980d512c71SDaniel Henrique Barboza chip8->num_phbs++; 299ddf0676fSFrederic Barrat return chip; 300ba47c3a4SDaniel Henrique Barboza } 301ba47c3a4SDaniel Henrique Barboza 302eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) 303e997040eSCédric Le Goater { 304c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; 305d2fd9612SCédric Le Goater int i; 306d2fd9612SCédric Le Goater 3073f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3083f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)), 309c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE), 310c396c58aSGreg Kurz compat, sizeof(compat)); 311967b7523SCédric Le Goater 312d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3134fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 314d2fd9612SCédric Le Goater 315b168a138SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 316bf5615e7SCédric Le Goater 317bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */ 318b168a138SCédric Le Goater pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads); 319d2fd9612SCédric Le Goater } 320d2fd9612SCédric Le Goater 321e997040eSCédric Le Goater if (chip->ram_size) { 322b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 323e997040eSCédric Le Goater } 324e997040eSCédric Le Goater } 325e997040eSCédric Le Goater 326eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt) 327eb859a27SCédric Le Goater { 328c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom"; 329eb859a27SCédric Le Goater int i; 330eb859a27SCédric Le Goater 3313f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3323f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)), 333c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE), 334c396c58aSGreg Kurz compat, sizeof(compat)); 335eb859a27SCédric Le Goater 336eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3374fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 338eb859a27SCédric Le Goater 339eb859a27SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 340eb859a27SCédric Le Goater } 341eb859a27SCédric Le Goater 342eb859a27SCédric Le Goater if (chip->ram_size) { 343eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 344eb859a27SCédric Le Goater } 34515376c66SCédric Le Goater 3462661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE); 347eb859a27SCédric Le Goater } 348eb859a27SCédric Le Goater 3492b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt) 3502b548a42SCédric Le Goater { 351c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom"; 3522b548a42SCédric Le Goater int i; 3532b548a42SCédric Le Goater 3543f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0, 3553f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)), 356c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE), 357c396c58aSGreg Kurz compat, sizeof(compat)); 3582b548a42SCédric Le Goater 3592b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 3602b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i]; 3612b548a42SCédric Le Goater 3622b548a42SCédric Le Goater pnv_dt_core(chip, pnv_core, fdt); 3632b548a42SCédric Le Goater } 3642b548a42SCédric Le Goater 3652b548a42SCédric Le Goater if (chip->ram_size) { 3662b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size); 3672b548a42SCédric Le Goater } 3682661f6abSCédric Le Goater 3692661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE); 3702b548a42SCédric Le Goater } 3712b548a42SCédric Le Goater 372b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off) 373c5ffdcaeSCédric Le Goater { 374c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id; 375c5ffdcaeSCédric Le Goater uint32_t io_regs[] = { 376c5ffdcaeSCédric Le Goater cpu_to_be32(1), 377c5ffdcaeSCédric Le Goater cpu_to_be32(io_base), 378c5ffdcaeSCédric Le Goater cpu_to_be32(2) 379c5ffdcaeSCédric Le Goater }; 380c5ffdcaeSCédric Le Goater char *name; 381c5ffdcaeSCédric Le Goater int node; 382c5ffdcaeSCédric Le Goater 383c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 384c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 385c5ffdcaeSCédric Le Goater _FDT(node); 386c5ffdcaeSCédric Le Goater g_free(name); 387c5ffdcaeSCédric Le Goater 388c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 389c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00"))); 390c5ffdcaeSCédric Le Goater } 391c5ffdcaeSCédric Le Goater 392b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off) 393cb228f5aSCédric Le Goater { 394cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501"; 395cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id; 396cb228f5aSCédric Le Goater uint32_t io_regs[] = { 397cb228f5aSCédric Le Goater cpu_to_be32(1), 398cb228f5aSCédric Le Goater cpu_to_be32(io_base), 399cb228f5aSCédric Le Goater cpu_to_be32(8) 400cb228f5aSCédric Le Goater }; 401632fc0b3SBernhard Beschow uint32_t irq; 402cb228f5aSCédric Le Goater char *name; 403cb228f5aSCédric Le Goater int node; 404cb228f5aSCédric Le Goater 405632fc0b3SBernhard Beschow irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal); 406632fc0b3SBernhard Beschow 407cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 408cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 409cb228f5aSCédric Le Goater _FDT(node); 410cb228f5aSCédric Le Goater g_free(name); 411cb228f5aSCédric Le Goater 412cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 413cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 414cb228f5aSCédric Le Goater sizeof(compatible)))); 415cb228f5aSCédric Le Goater 416cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200))); 417cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200))); 418632fc0b3SBernhard Beschow _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 419cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 420cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 421cb228f5aSCédric Le Goater 422cb228f5aSCédric Le Goater /* This is needed by Linux */ 423cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial"))); 424cb228f5aSCédric Le Goater } 425cb228f5aSCédric Le Goater 426b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) 42704f6c8b2SCédric Le Goater { 42804f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt"; 42904f6c8b2SCédric Le Goater uint32_t io_base; 43004f6c8b2SCédric Le Goater uint32_t io_regs[] = { 43104f6c8b2SCédric Le Goater cpu_to_be32(1), 43204f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */ 43304f6c8b2SCédric Le Goater cpu_to_be32(3) 43404f6c8b2SCédric Le Goater }; 43504f6c8b2SCédric Le Goater uint32_t irq; 43604f6c8b2SCédric Le Goater char *name; 43704f6c8b2SCédric Le Goater int node; 43804f6c8b2SCédric Le Goater 43904f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal); 44004f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base); 44104f6c8b2SCédric Le Goater 44204f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal); 44304f6c8b2SCédric Le Goater 44404f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base); 44504f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name); 44604f6c8b2SCédric Le Goater _FDT(node); 44704f6c8b2SCédric Le Goater g_free(name); 44804f6c8b2SCédric Le Goater 4497032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); 4507032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible, 4517032d92aSCédric Le Goater sizeof(compatible)))); 45204f6c8b2SCédric Le Goater 45304f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */ 45404f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); 45504f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq))); 45604f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent", 45704f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off)))); 45804f6c8b2SCédric Le Goater } 45904f6c8b2SCédric Le Goater 460e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs { 461e7a3fee3SCédric Le Goater void *fdt; 462e7a3fee3SCédric Le Goater int offset; 463e7a3fee3SCédric Le Goater } ForeachPopulateArgs; 464e7a3fee3SCédric Le Goater 465b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque) 466e7a3fee3SCédric Le Goater { 467c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque; 468c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev); 469c5ffdcaeSCédric Le Goater 470c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) { 471b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset); 472cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) { 473b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset); 47404f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) { 475b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset); 476c5ffdcaeSCédric Le Goater } else { 477c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev), 478c5ffdcaeSCédric Le Goater d->ioport_id); 479c5ffdcaeSCédric Le Goater } 480c5ffdcaeSCédric Le Goater 481e7a3fee3SCédric Le Goater return 0; 482e7a3fee3SCédric Le Goater } 483e7a3fee3SCédric Le Goater 48459b7c1c2SBalamuruhan S /* 48559b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's 486bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property. 487bb7ab95cSCédric Le Goater */ 488bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt) 489bb7ab95cSCédric Le Goater { 49064d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename); 491e7a3fee3SCédric Le Goater ForeachPopulateArgs args = { 492e7a3fee3SCédric Le Goater .fdt = fdt, 493bb7ab95cSCédric Le Goater .offset = isa_offset, 494e7a3fee3SCédric Le Goater }; 495f47a08d1SCédric Le Goater uint32_t phandle; 496e7a3fee3SCédric Le Goater 497bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0))); 498bb7ab95cSCédric Le Goater 499f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt); 500f47a08d1SCédric Le Goater assert(phandle > 0); 501f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle))); 502f47a08d1SCédric Le Goater 50359b7c1c2SBalamuruhan S /* 50459b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we 50559b7c1c2SBalamuruhan S * can not use object_child_foreach() 50659b7c1c2SBalamuruhan S */ 507bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL, 508bb7ab95cSCédric Le Goater &args); 509e7a3fee3SCédric Le Goater } 510e7a3fee3SCédric Le Goater 5117a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt) 512e5694793SCédric Le Goater { 513e5694793SCédric Le Goater int off; 514e5694793SCédric Le Goater 515e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal"); 516e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt"); 517e5694793SCédric Le Goater 518e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000)); 519e5694793SCédric Le Goater } 520e5694793SCédric Le Goater 521b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine) 5229e933f4aSBenjamin Herrenschmidt { 523d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine); 524b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 5259e933f4aSBenjamin Herrenschmidt void *fdt; 5269e933f4aSBenjamin Herrenschmidt char *buf; 5279e933f4aSBenjamin Herrenschmidt int off; 528e997040eSCédric Le Goater int i; 5299e933f4aSBenjamin Herrenschmidt 5309e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE); 5319e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 5329e933f4aSBenjamin Herrenschmidt 533ccb099b3SCédric Le Goater /* /qemu node */ 534ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu"))); 535ccb099b3SCédric Le Goater 5369e933f4aSBenjamin Herrenschmidt /* Root node */ 5379e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2))); 5389e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2))); 5399e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model", 5409e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)"))); 541d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size))); 5429e933f4aSBenjamin Herrenschmidt 5439e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid); 5449e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf))); 5459e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) { 546bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "system-id", buf))); 5479e933f4aSBenjamin Herrenschmidt } 5489e933f4aSBenjamin Herrenschmidt g_free(buf); 5499e933f4aSBenjamin Herrenschmidt 5509e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen"); 5519e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) { 5529e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs", 5539e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline))); 5549e933f4aSBenjamin Herrenschmidt } 5559e933f4aSBenjamin Herrenschmidt 5569e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) { 5579e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base); 5589e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size); 5599e933f4aSBenjamin Herrenschmidt 5609e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start", 5619e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop)))); 5629e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end", 5639e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop)))); 5649e933f4aSBenjamin Herrenschmidt } 5659e933f4aSBenjamin Herrenschmidt 566e997040eSCédric Le Goater /* Populate device tree for each chip */ 567e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 568eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt); 569e997040eSCédric Le Goater } 570e7a3fee3SCédric Le Goater 571e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */ 572bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt); 573aeaef83dSCédric Le Goater 574aeaef83dSCédric Le Goater if (pnv->bmc) { 575b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt); 576aeaef83dSCédric Le Goater } 577aeaef83dSCédric Le Goater 5787a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */ 5797a90c6a1SGreg Kurz if (pmc->dt_power_mgt) { 5807a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt); 581e5694793SCédric Le Goater } 582e5694793SCédric Le Goater 5839e933f4aSBenjamin Herrenschmidt return fdt; 5849e933f4aSBenjamin Herrenschmidt } 5859e933f4aSBenjamin Herrenschmidt 586bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque) 587bce0b691SCédric Le Goater { 5888f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier); 589bce0b691SCédric Le Goater 590bce0b691SCédric Le Goater if (pnv->bmc) { 591bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc); 592bce0b691SCédric Le Goater } 593bce0b691SCédric Le Goater } 594bce0b691SCédric Le Goater 5957966d70fSJason A. Donenfeld static void pnv_reset(MachineState *machine, ShutdownCause reason) 5969e933f4aSBenjamin Herrenschmidt { 59725f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 59825f3170bSCédric Le Goater IPMIBmc *bmc; 5999e933f4aSBenjamin Herrenschmidt void *fdt; 6009e933f4aSBenjamin Herrenschmidt 6017966d70fSJason A. Donenfeld qemu_devices_reset(reason); 6029e933f4aSBenjamin Herrenschmidt 60325f3170bSCédric Le Goater /* 60425f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator. 60525f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command 60625f3170bSCédric Le Goater * line. 60725f3170bSCédric Le Goater */ 60825f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal); 60925f3170bSCédric Le Goater if (!pnv->bmc) { 61025f3170bSCédric Le Goater if (!bmc) { 61138d2448aSGreg Kurz if (!qtest_enabled()) { 61225f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device " 61325f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' " 61425f3170bSCédric Le Goater "to define one"); 61538d2448aSGreg Kurz } 61625f3170bSCédric Le Goater } else { 61725f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor); 61825f3170bSCédric Le Goater pnv->bmc = bmc; 61925f3170bSCédric Le Goater } 62025f3170bSCédric Le Goater } 62125f3170bSCédric Le Goater 622b168a138SCédric Le Goater fdt = pnv_dt_create(machine); 6239e933f4aSBenjamin Herrenschmidt 6249e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */ 6259e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt))); 6269e933f4aSBenjamin Herrenschmidt 6278d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 6289e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt)); 629b2fb7a43SPan Nengyuan 630adb77996SDaniel Henrique Barboza /* 631adb77996SDaniel Henrique Barboza * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free 632adb77996SDaniel Henrique Barboza * the existing machine->fdt to avoid leaking it during 633adb77996SDaniel Henrique Barboza * a reset. 634adb77996SDaniel Henrique Barboza */ 635adb77996SDaniel Henrique Barboza g_free(machine->fdt); 636adb77996SDaniel Henrique Barboza machine->fdt = fdt; 6379e933f4aSBenjamin Herrenschmidt } 6389e933f4aSBenjamin Herrenschmidt 63904026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp) 6403495b6b6SCédric Le Goater { 64177864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 642c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL); 643c05aa140SCédric Le Goater 644c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 64577864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp); 64604026890SCédric Le Goater } 6473495b6b6SCédric Le Goater 64804026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp) 64904026890SCédric Le Goater { 65077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 651c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C); 652c05aa140SCédric Le Goater 653c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq); 65477864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp); 65504026890SCédric Le Goater } 6563495b6b6SCédric Le Goater 65704026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp) 65804026890SCédric Le Goater { 65915376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 660c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC); 661c05aa140SCédric Le Goater 662c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq); 66315376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp); 66404026890SCédric Le Goater } 6653495b6b6SCédric Le Goater 6662b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp) 6672b548a42SCédric Le Goater { 6682661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 669c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC); 670c05aa140SCédric Le Goater 671c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq); 6722661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp); 6732b548a42SCédric Le Goater } 6742b548a42SCédric Le Goater 67504026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp) 67604026890SCédric Le Goater { 67704026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp); 6783495b6b6SCédric Le Goater } 6793495b6b6SCédric Le Goater 680d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) 681d8e4aad5SCédric Le Goater { 682d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 6838a69bca7SDaniel Henrique Barboza int i; 684d8e4aad5SCédric Le Goater 685d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon); 6868a69bca7SDaniel Henrique Barboza 6878a69bca7SDaniel Henrique Barboza for (i = 0; i < chip8->num_phbs; i++) { 6880d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i]; 6891f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 6908a69bca7SDaniel Henrique Barboza 6918a69bca7SDaniel Henrique Barboza pnv_phb3_msi_pic_print_info(&phb3->msis, mon); 6928a69bca7SDaniel Henrique Barboza ics_pic_print_info(&phb3->lsis, mon); 6938a69bca7SDaniel Henrique Barboza } 694d8e4aad5SCédric Le Goater } 695d8e4aad5SCédric Le Goater 6960e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque) 6970e6232bcSCédric Le Goater { 6980e6232bcSCédric Le Goater Monitor *mon = opaque; 699210aacb3SDaniel Henrique Barboza PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB); 7000e6232bcSCédric Le Goater 701210aacb3SDaniel Henrique Barboza if (!phb) { 702210aacb3SDaniel Henrique Barboza return 0; 7030e6232bcSCédric Le Goater } 704210aacb3SDaniel Henrique Barboza 705210aacb3SDaniel Henrique Barboza pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon); 706210aacb3SDaniel Henrique Barboza 7070e6232bcSCédric Le Goater return 0; 7080e6232bcSCédric Le Goater } 7090e6232bcSCédric Le Goater 710d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon) 711d8e4aad5SCédric Le Goater { 712d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 713d8e4aad5SCédric Le Goater 714d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon); 715c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon); 7164f9924c4SBenjamin Herrenschmidt 7170e6232bcSCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 7180e6232bcSCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 719d8e4aad5SCédric Le Goater } 720d8e4aad5SCédric Le Goater 721c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip, 722c4b2c40cSGreg Kurz uint32_t core_id) 723c4b2c40cSGreg Kurz { 724c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id); 725c4b2c40cSGreg Kurz } 726c4b2c40cSGreg Kurz 727c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip, 728c4b2c40cSGreg Kurz uint32_t core_id) 729c4b2c40cSGreg Kurz { 730c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id); 731c4b2c40cSGreg Kurz } 732c4b2c40cSGreg Kurz 733c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip, 734c4b2c40cSGreg Kurz uint32_t core_id) 735c4b2c40cSGreg Kurz { 736c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id); 737c4b2c40cSGreg Kurz } 738c4b2c40cSGreg Kurz 739f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type) 740f30c843cSCédric Le Goater { 741f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default = 742f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type)); 743f30c843cSCédric Le Goater PowerPCCPUClass *ppc = 744f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); 745f30c843cSCédric Le Goater 74621d3a78eSNicholas Piggin return ppc_default->pvr_match(ppc_default, ppc->pvr, false); 747f30c843cSCédric Le Goater } 748f30c843cSCédric Le Goater 749e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) 750e2392d43SCédric Le Goater { 751c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt"); 752e2392d43SCédric Le Goater 7535325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal); 7545325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal); 755c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal); 756e2392d43SCédric Le Goater } 757e2392d43SCédric Le Goater 7582b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon) 7592b548a42SCédric Le Goater { 7608b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 7618b50ce85SCédric Le Goater 762da71b7e3SCédric Le Goater pnv_xive2_pic_print_info(&chip10->xive, mon); 7638b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon); 764623575e1SCédric Le Goater 765623575e1SCédric Le Goater object_child_foreach_recursive(OBJECT(chip), 766623575e1SCédric Le Goater pnv_chip_power9_pic_print_info_child, mon); 7672b548a42SCédric Le Goater } 7682b548a42SCédric Le Goater 769458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */ 770458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id) 771458c6f01SCédric Le Goater { 772458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv); 773458c6f01SCédric Le Goater uint64_t ram_per_chip; 774458c6f01SCédric Le Goater 775458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB); 776458c6f01SCédric Le Goater 777458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips; 778458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) { 779458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 780458c6f01SCédric Le Goater } 781458c6f01SCédric Le Goater 782f640afecSCédric Le Goater assert(pnv->num_chips > 1); 783f640afecSCédric Le Goater 784458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1); 785458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB); 786458c6f01SCédric Le Goater } 787458c6f01SCédric Le Goater 788b168a138SCédric Le Goater static void pnv_init(MachineState *machine) 7899e933f4aSBenjamin Herrenschmidt { 790cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME; 791b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine); 792f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine); 7939e933f4aSBenjamin Herrenschmidt char *fw_filename; 7949e933f4aSBenjamin Herrenschmidt long fw_size; 795458c6f01SCédric Le Goater uint64_t chip_ram_start = 0; 796e997040eSCédric Le Goater int i; 797e997040eSCédric Le Goater char *chip_typename; 79835dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0); 79935dde576SCédric Le Goater DeviceState *dev; 8009e933f4aSBenjamin Herrenschmidt 801ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) { 802518f72ecSCédric Le Goater error_report("machine %s does not support the KVM accelerator", 803518f72ecSCédric Le Goater mc->name); 804ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE); 805ebe6c3faSDaniel Henrique Barboza } 806ebe6c3faSDaniel Henrique Barboza 8079e933f4aSBenjamin Herrenschmidt /* allocate RAM */ 808dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) { 809dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size); 810dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz); 811dd7ef911SCédric Le Goater g_free(sz); 812dd7ef911SCédric Le Goater exit(EXIT_FAILURE); 8139e933f4aSBenjamin Herrenschmidt } 814173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram); 8159e933f4aSBenjamin Herrenschmidt 81635dde576SCédric Le Goater /* 81735dde576SCédric Le Goater * Create our simple PNOR device 81835dde576SCédric Le Goater */ 8193e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR); 82035dde576SCédric Le Goater if (pnor) { 821934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor)); 82235dde576SCédric Le Goater } 8233c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 82435dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev); 82535dde576SCédric Le Goater 8269e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */ 8279e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 82815fcedb2SCédric Le Goater if (!fw_filename) { 82915fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name); 83015fcedb2SCédric Le Goater exit(1); 83115fcedb2SCédric Le Goater } 8329e933f4aSBenjamin Herrenschmidt 83308c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE); 8349e933f4aSBenjamin Herrenschmidt if (fw_size < 0) { 83515fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename); 8369e933f4aSBenjamin Herrenschmidt exit(1); 8379e933f4aSBenjamin Herrenschmidt } 8389e933f4aSBenjamin Herrenschmidt g_free(fw_filename); 8399e933f4aSBenjamin Herrenschmidt 8409e933f4aSBenjamin Herrenschmidt /* load kernel */ 8419e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) { 8429e933f4aSBenjamin Herrenschmidt long kernel_size; 8439e933f4aSBenjamin Herrenschmidt 8449e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename, 845b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE); 8469e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) { 847802fc7abSThomas Huth error_report("Could not load kernel '%s'", 8489e933f4aSBenjamin Herrenschmidt machine->kernel_filename); 8499e933f4aSBenjamin Herrenschmidt exit(1); 8509e933f4aSBenjamin Herrenschmidt } 8519e933f4aSBenjamin Herrenschmidt } 8529e933f4aSBenjamin Herrenschmidt 8539e933f4aSBenjamin Herrenschmidt /* load initrd */ 8549e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) { 8559e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR; 8569e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename, 857584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE); 8589e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) { 859802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'", 8609e933f4aSBenjamin Herrenschmidt machine->initrd_filename); 8619e933f4aSBenjamin Herrenschmidt exit(1); 8629e933f4aSBenjamin Herrenschmidt } 8639e933f4aSBenjamin Herrenschmidt } 864e997040eSCédric Le Goater 8654f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */ 8664f9924c4SBenjamin Herrenschmidt msi_nonbroken = true; 8674f9924c4SBenjamin Herrenschmidt 868f30c843cSCédric Le Goater /* 869f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine 870f30c843cSCédric Le Goater * default. 871f30c843cSCédric Le Goater */ 872f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) { 873f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine", 874f30c843cSCédric Le Goater machine->cpu_type, mc->name); 875f30c843cSCédric Le Goater exit(1); 876f30c843cSCédric Le Goater } 877f30c843cSCédric Le Goater 878e997040eSCédric Le Goater /* Create the processor chips */ 8794a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX); 8807fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"), 8814a12c699SIgor Mammedov i, machine->cpu_type); 882e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) { 883f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine", 884f30c843cSCédric Le Goater i, machine->cpu_type, mc->name); 885e997040eSCédric Le Goater exit(1); 886e997040eSCédric Le Goater } 887e997040eSCédric Le Goater 888e44acde2SGreg Kurz pnv->num_chips = 889e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads); 890e44acde2SGreg Kurz /* 891e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based 892e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc..., 893e44acde2SGreg Kurz */ 894ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) { 895e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips); 896ab17a3feSCédric Le Goater error_printf( 897ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n"); 898e44acde2SGreg Kurz exit(1); 899e44acde2SGreg Kurz } 900e44acde2SGreg Kurz 901e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips); 902e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 903e997040eSCédric Le Goater char chip_name[32]; 904df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename)); 9050e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i); 906e997040eSCédric Le Goater 907e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip); 908e997040eSCédric Le Goater 909458c6f01SCédric Le Goater /* Distribute RAM among the chips */ 910458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start, 911e997040eSCédric Le Goater &error_fatal); 912458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size, 913458c6f01SCédric Le Goater &error_fatal); 914458c6f01SCédric Le Goater chip_ram_start += chip_ram_size; 915e997040eSCédric Le Goater 9160e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i); 917d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip); 9180e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal); 9195325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores, 9205325cc34SMarkus Armbruster &error_fatal); 9215325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads, 9225325cc34SMarkus Armbruster &error_fatal); 923245cdb7fSCédric Le Goater /* 924245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface. 925245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers. 926245cdb7fSCédric Le Goater */ 927245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) { 9285325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort); 929245cdb7fSCédric Le Goater } 930d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) { 9315325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv), 932d1214b81SGreg Kurz &error_abort); 933d1214b81SGreg Kurz } 9343c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal); 935e997040eSCédric Le Goater } 936e997040eSCédric Le Goater g_free(chip_typename); 9373495b6b6SCédric Le Goater 9383495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */ 93904026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal); 9403495b6b6SCédric Le Goater 9413495b6b6SCédric Le Goater /* Create serial port */ 942def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS); 9433495b6b6SCédric Le Goater 9443495b6b6SCédric Le Goater /* Create an RTC ISA device too */ 9456c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL); 946bce0b691SCédric Le Goater 94725f3170bSCédric Le Goater /* 94825f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for 94925f3170bSCédric Le Goater * communication with the BMC 95025f3170bSCédric Le Goater */ 95125f3170bSCédric Le Goater if (defaults_enabled()) { 95225f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor); 953e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10); 95425f3170bSCédric Le Goater } 955e2392d43SCédric Le Goater 95659b7c1c2SBalamuruhan S /* 957032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC. 958032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops, 959032c226bSCédric Le Goater * map it always for now. 960032c226bSCédric Le Goater */ 961032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET, 962032c226bSCédric Le Goater &pnv->pnor->mmio); 963032c226bSCédric Le Goater 964032c226bSCédric Le Goater /* 96559b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the 96659b7c1c2SBalamuruhan S * host to powerdown 96759b7c1c2SBalamuruhan S */ 968bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify; 969bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier); 970e997040eSCédric Le Goater } 971e997040eSCédric Le Goater 972631adaffSCédric Le Goater /* 973631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros 974631adaffSCédric Le Goater * 22:24 Chip ID 975631adaffSCédric Le Goater * 25:28 Core number 976631adaffSCédric Le Goater * 29:31 Thread ID 977631adaffSCédric Le Goater */ 978631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id) 979631adaffSCédric Le Goater { 980631adaffSCédric Le Goater return (chip->chip_id << 7) | (core_id << 3); 981631adaffSCédric Le Goater } 982631adaffSCédric Le Goater 9838fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu, 984d35aefa9SCédric Le Goater Error **errp) 985d35aefa9SCédric Le Goater { 986245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip); 9878fa1f4efSCédric Le Goater Error *local_err = NULL; 9888fa1f4efSCédric Le Goater Object *obj; 9898907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 9908fa1f4efSCédric Le Goater 991245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err); 9928fa1f4efSCédric Le Goater if (local_err) { 9938fa1f4efSCédric Le Goater error_propagate(errp, local_err); 9948fa1f4efSCédric Le Goater return; 9958fa1f4efSCédric Le Goater } 9968fa1f4efSCédric Le Goater 997956b8f46SCédric Le Goater pnv_cpu->intc = obj; 998d35aefa9SCédric Le Goater } 999d35aefa9SCédric Le Goater 10000990ce6aSGreg Kurz 1001d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1002d49e8a9bSCédric Le Goater { 1003d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1004d49e8a9bSCédric Le Goater 1005d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc)); 1006d49e8a9bSCédric Le Goater } 1007d49e8a9bSCédric Le Goater 10080990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10090990ce6aSGreg Kurz { 10100990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10110990ce6aSGreg Kurz 10120990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc)); 10130990ce6aSGreg Kurz pnv_cpu->intc = NULL; 10140990ce6aSGreg Kurz } 10150990ce6aSGreg Kurz 101685913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 101785913070SGreg Kurz Monitor *mon) 101885913070SGreg Kurz { 101985913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon); 102085913070SGreg Kurz } 102185913070SGreg Kurz 1022631adaffSCédric Le Goater /* 1023631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes 1024631adaffSCédric Le Goater * 49:52 Node ID 1025631adaffSCédric Le Goater * 53:55 Chip ID 1026631adaffSCédric Le Goater * 56 Reserved - Read as zero 1027631adaffSCédric Le Goater * 57:61 Core number 1028631adaffSCédric Le Goater * 62:63 Thread ID 1029631adaffSCédric Le Goater * 1030631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment. 1031631adaffSCédric Le Goater */ 1032631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id) 1033631adaffSCédric Le Goater { 1034631adaffSCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 1035631adaffSCédric Le Goater } 1036631adaffSCédric Le Goater 10372b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id) 10382b548a42SCédric Le Goater { 10392b548a42SCédric Le Goater return (chip->chip_id << 8) | (core_id << 2); 10402b548a42SCédric Le Goater } 10412b548a42SCédric Le Goater 10428fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu, 1043d35aefa9SCédric Le Goater Error **errp) 1044d35aefa9SCédric Le Goater { 10452dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip); 10462dfa91a2SCédric Le Goater Error *local_err = NULL; 10472dfa91a2SCédric Le Goater Object *obj; 10482dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10492dfa91a2SCédric Le Goater 10502dfa91a2SCédric Le Goater /* 10512dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt 10522dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 10532dfa91a2SCédric Le Goater * only used at runtime. 10542dfa91a2SCédric Le Goater */ 105547950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive), 105647950946SCédric Le Goater &local_err); 10572dfa91a2SCédric Le Goater if (local_err) { 10582dfa91a2SCédric Le Goater error_propagate(errp, local_err); 10598fa1f4efSCédric Le Goater return; 1060d35aefa9SCédric Le Goater } 1061d35aefa9SCédric Le Goater 10622dfa91a2SCédric Le Goater pnv_cpu->intc = obj; 10632dfa91a2SCédric Le Goater } 10642dfa91a2SCédric Le Goater 1065d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 1066d49e8a9bSCédric Le Goater { 1067d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1068d49e8a9bSCédric Le Goater 1069d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 1070d49e8a9bSCédric Le Goater } 1071d49e8a9bSCédric Le Goater 10720990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 10730990ce6aSGreg Kurz { 10740990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10750990ce6aSGreg Kurz 10760990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 10770990ce6aSGreg Kurz pnv_cpu->intc = NULL; 10780990ce6aSGreg Kurz } 10790990ce6aSGreg Kurz 108085913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 108185913070SGreg Kurz Monitor *mon) 108285913070SGreg Kurz { 108385913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 108485913070SGreg Kurz } 108585913070SGreg Kurz 10862b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu, 10872b548a42SCédric Le Goater Error **errp) 10882b548a42SCédric Le Goater { 1089da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1090da71b7e3SCédric Le Goater Error *local_err = NULL; 1091da71b7e3SCédric Le Goater Object *obj; 10922b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 10932b548a42SCédric Le Goater 1094da71b7e3SCédric Le Goater /* 1095da71b7e3SCédric Le Goater * The core creates its interrupt presenter but the XIVE2 interrupt 1096da71b7e3SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's 1097da71b7e3SCédric Le Goater * only used at runtime. 1098da71b7e3SCédric Le Goater */ 1099da71b7e3SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive), 1100da71b7e3SCédric Le Goater &local_err); 1101da71b7e3SCédric Le Goater if (local_err) { 1102da71b7e3SCédric Le Goater error_propagate(errp, local_err); 1103da71b7e3SCédric Le Goater return; 1104da71b7e3SCédric Le Goater } 1105da71b7e3SCédric Le Goater 1106da71b7e3SCédric Le Goater pnv_cpu->intc = obj; 11072b548a42SCédric Le Goater } 11082b548a42SCédric Le Goater 11092b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu) 11102b548a42SCédric Le Goater { 1111da71b7e3SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 1112da71b7e3SCédric Le Goater 1113da71b7e3SCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc)); 11142b548a42SCédric Le Goater } 11152b548a42SCédric Le Goater 11162b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu) 11172b548a42SCédric Le Goater { 11182b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu); 11192b548a42SCédric Le Goater 1120da71b7e3SCédric Le Goater xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc)); 11212b548a42SCédric Le Goater pnv_cpu->intc = NULL; 11222b548a42SCédric Le Goater } 11232b548a42SCédric Le Goater 112485913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu, 112585913070SGreg Kurz Monitor *mon) 112685913070SGreg Kurz { 1127da71b7e3SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon); 112885913070SGreg Kurz } 112985913070SGreg Kurz 113059b7c1c2SBalamuruhan S /* 113159b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip : 1132397a79e7SCédric Le Goater * 1133397a79e7SCédric Le Goater * <EX0 reserved> 1134397a79e7SCédric Le Goater * EX1 - Venice only 1135397a79e7SCédric Le Goater * EX2 - Venice only 1136397a79e7SCédric Le Goater * EX3 - Venice only 1137397a79e7SCédric Le Goater * EX4 1138397a79e7SCédric Le Goater * EX5 1139397a79e7SCédric Le Goater * EX6 1140397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved> 1141397a79e7SCédric Le Goater * EX9 - Venice only 1142397a79e7SCédric Le Goater * EX10 - Venice only 1143397a79e7SCédric Le Goater * EX11 - Venice only 1144397a79e7SCédric Le Goater * EX12 1145397a79e7SCédric Le Goater * EX13 1146397a79e7SCédric Le Goater * EX14 1147397a79e7SCédric Le Goater * <EX15 reserved> 1148397a79e7SCédric Le Goater */ 1149397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull) 1150397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull) 1151397a79e7SCédric Le Goater 1152397a79e7SCédric Le Goater /* 115309279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0 1154397a79e7SCédric Le Goater */ 115509279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull) 1156397a79e7SCédric Le Goater 11572b548a42SCédric Le Goater 11582b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull) 11592b548a42SCédric Le Goater 116077864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj) 116177864267SCédric Le Goater { 116277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj); 11639ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 11649ae1329eSCédric Le Goater int i; 116577864267SCédric Le Goater 1166245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC, 1167245cdb7fSCédric Le Goater (Object **)&chip8->xics, 1168245cdb7fSCédric Le Goater object_property_allow_set_link, 1169d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG); 1170245cdb7fSCédric Le Goater 11719fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI); 117277864267SCédric Le Goater 11739fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC); 117477864267SCédric Le Goater 11759fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC); 11763887d241SBalamuruhan S 11779fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); 11789ae1329eSCédric Le Goater 1179892c3ad0SDaniel Henrique Barboza if (defaults_enabled()) { 1180eb93c828SCédric Le Goater chip8->num_phbs = pcc->num_phbs; 11811f6a88ffSCédric Le Goater 1182eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 11830d512c71SDaniel Henrique Barboza Object *phb = object_new(TYPE_PNV_PHB); 11840d512c71SDaniel Henrique Barboza 11850d512c71SDaniel Henrique Barboza /* 11860d512c71SDaniel Henrique Barboza * We need the chip to parent the PHB to allow the DT 11870d512c71SDaniel Henrique Barboza * to build correctly (via pnv_xscom_dt()). 11880d512c71SDaniel Henrique Barboza * 11890d512c71SDaniel Henrique Barboza * TODO: the PHB should be parented by a PEC device that, at 11900d512c71SDaniel Henrique Barboza * this moment, is not modelled powernv8/phb3. 11910d512c71SDaniel Henrique Barboza */ 11920d512c71SDaniel Henrique Barboza object_property_add_child(obj, "phb[*]", phb); 11930d512c71SDaniel Henrique Barboza chip8->phbs[i] = PNV_PHB(phb); 11949ae1329eSCédric Le Goater } 1195892c3ad0SDaniel Henrique Barboza } 11969ae1329eSCédric Le Goater 119777864267SCédric Le Goater } 119877864267SCédric Le Goater 119977864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) 120077864267SCédric Le Goater { 120177864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8); 120277864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 120377864267SCédric Le Goater int i, j; 120477864267SCédric Le Goater char *name; 120577864267SCédric Le Goater 120677864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id); 120777864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE); 120877864267SCédric Le Goater sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio); 120977864267SCédric Le Goater g_free(name); 121077864267SCédric Le Goater 121177864267SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip)); 121277864267SCédric Le Goater 121377864267SCédric Le Goater /* Map the ICP registers for each thread */ 121477864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 12154fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i]; 121677864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id; 121777864267SCédric Le Goater 121877864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) { 121977864267SCédric Le Goater uint32_t pir = pcc->core_pir(chip, core_hwid) + j; 1220245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir)); 122177864267SCédric Le Goater 122277864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12, 122377864267SCédric Le Goater &icp->mmio); 122477864267SCédric Le Goater } 122577864267SCédric Le Goater } 122677864267SCédric Le Goater } 122777864267SCédric Le Goater 122877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) 122977864267SCédric Le Goater { 123077864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 123177864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 123277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev); 1233ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi; 123477864267SCédric Le Goater Error *local_err = NULL; 12359ae1329eSCédric Le Goater int i; 123677864267SCédric Le Goater 1237245cdb7fSCédric Le Goater assert(chip8->xics); 1238245cdb7fSCédric Le Goater 1239709044fdSCédric Le Goater /* XSCOM bridge is first */ 1240709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err); 1241709044fdSCédric Le Goater if (local_err) { 1242709044fdSCédric Le Goater error_propagate(errp, local_err); 1243709044fdSCédric Le Goater return; 1244709044fdSCédric Le Goater } 1245709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip)); 1246709044fdSCédric Le Goater 124777864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 124877864267SCédric Le Goater if (local_err) { 124977864267SCédric Le Goater error_propagate(errp, local_err); 125077864267SCédric Le Goater return; 125177864267SCédric Le Goater } 125277864267SCédric Le Goater 125377864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 12545325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip), 12555325cc34SMarkus Armbruster &error_fatal); 12565325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS, 12575325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort); 1258668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) { 125977864267SCédric Le Goater return; 126077864267SCédric Le Goater } 1261ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, 1262ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs); 126377864267SCédric Le Goater 126477864267SCédric Le Goater /* Create LPC controller */ 1265ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal); 126677864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs); 126777864267SCédric Le Goater 1268032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw; 126964d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x", 127064d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip), 127164d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE); 127264d011d5SCédric Le Goater 127359b7c1c2SBalamuruhan S /* 127459b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding 127559b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers 127659b7c1c2SBalamuruhan S */ 127777864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err); 127877864267SCédric Le Goater if (local_err) { 127977864267SCédric Le Goater error_propagate(errp, local_err); 128077864267SCédric Le Goater return; 128177864267SCédric Le Goater } 128277864267SCédric Le Goater 128377864267SCédric Le Goater /* Create the simplified OCC model */ 1284668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) { 128577864267SCédric Le Goater return; 128677864267SCédric Le Goater } 128777864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs); 1288b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->occ), 0, 1289b0ae5c69SCédric Le Goater qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC)); 1290f3db8266SBalamuruhan S 1291f3db8266SBalamuruhan S /* OCC SRAM model */ 12923a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip), 1293f3db8266SBalamuruhan S &chip8->occ.sram_regs); 12943887d241SBalamuruhan S 12953887d241SBalamuruhan S /* HOMER */ 12965325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip), 1297f2582acfSGreg Kurz &error_abort); 1298668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) { 12993887d241SBalamuruhan S return; 13003887d241SBalamuruhan S } 13018f092316SCédric Le Goater /* Homer Xscom region */ 13028f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs); 13038f092316SCédric Le Goater 13048f092316SCédric Le Goater /* Homer mmio region */ 13053887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), 13063887d241SBalamuruhan S &chip8->homer.regs); 13079ae1329eSCédric Le Goater 13081f5d6b2aSDaniel Henrique Barboza /* PHB controllers */ 1309eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) { 13100d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i]; 13119ae1329eSCédric Le Goater 13125325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal); 13135325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, 13149ae1329eSCédric Le Goater &error_fatal); 13152c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip), 13162c4d3a50SCédric Le Goater &error_fatal); 1317668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) { 13189ae1329eSCédric Le Goater return; 13199ae1329eSCédric Le Goater } 13209ae1329eSCédric Le Goater } 132177864267SCédric Le Goater } 132277864267SCédric Le Goater 132370c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr) 132470c059e9SGreg Kurz { 132570c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1); 132670c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf); 132770c059e9SGreg Kurz } 132870c059e9SGreg Kurz 1329e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) 1330e997040eSCédric Le Goater { 1331e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1332e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1333e997040eSCédric Le Goater 1334e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */ 1335397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK; 13369ae1329eSCédric Le Goater k->num_phbs = 3; 1337631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1338d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1339d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13400990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 134185913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 134204026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1343eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1344d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1345c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 134670c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1347e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E"; 134877864267SCédric Le Goater 134977864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 135077864267SCédric Le Goater &k->parent_realize); 1351e997040eSCédric Le Goater } 1352e997040eSCédric Le Goater 1353e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) 1354e997040eSCédric Le Goater { 1355e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1356e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1357e997040eSCédric Le Goater 1358e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */ 1359397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 13609ae1329eSCédric Le Goater k->num_phbs = 3; 1361631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1362d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1363d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13640990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 136585913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 136604026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create; 1367eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1368d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1369c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 137070c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1371e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8"; 137277864267SCédric Le Goater 137377864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 137477864267SCédric Le Goater &k->parent_realize); 1375e997040eSCédric Le Goater } 1376e997040eSCédric Le Goater 1377e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) 1378e997040eSCédric Le Goater { 1379e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1380e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1381e997040eSCédric Le Goater 1382e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */ 1383397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK; 1384316717feSCédric Le Goater k->num_phbs = 4; 1385631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p8; 1386d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create; 1387d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset; 13880990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy; 138985913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info; 139004026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create; 1391eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate; 1392d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info; 1393c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base; 139470c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba; 1395e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL"; 139677864267SCédric Le Goater 139777864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize, 139877864267SCédric Le Goater &k->parent_realize); 139977864267SCédric Le Goater } 140077864267SCédric Le Goater 140177864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj) 140277864267SCédric Le Goater { 14034f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj); 14042dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj); 14054f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 14064f9924c4SBenjamin Herrenschmidt int i; 14072dfa91a2SCédric Le Goater 1408db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE); 1409d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive), 1410d2623129SMarkus Armbruster "xive-fabric"); 1411c38536bcSCédric Le Goater 14129fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI); 141315376c66SCédric Le Goater 14149fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC); 14156598a70dSCédric Le Goater 14169fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); 14173887d241SBalamuruhan S 14180bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE); 14190bf4d77eSNicholas Piggin 14209fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); 14214f9924c4SBenjamin Herrenschmidt 1422422fd92eSCédric Le Goater /* Number of PECs is the chip default */ 1423422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs; 1424422fd92eSCédric Le Goater 1425422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14264f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i], 14279fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC); 14284f9924c4SBenjamin Herrenschmidt } 142977864267SCédric Le Goater } 143077864267SCédric Le Goater 1431ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq, 1432fdc2b46aSJoel Stanley PnvCore *pnv_core, 1433fdc2b46aSJoel Stanley const char *type) 14345dad902cSCédric Le Goater { 14355dad902cSCédric Le Goater char eq_name[32]; 14365dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id; 14375dad902cSCédric Le Goater 14385dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id); 14399fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq, 1440fdc2b46aSJoel Stanley sizeof(*eq), type, 14419fc7fc4dSMarkus Armbruster &error_fatal, NULL); 14425dad902cSCédric Le Goater 144392612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal); 1444ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal); 1445ae4c68e3SCédric Le Goater } 1446ae4c68e3SCédric Le Goater 1447ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp) 1448ae4c68e3SCédric Le Goater { 1449ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip9); 1450ae4c68e3SCédric Le Goater int i; 1451ae4c68e3SCédric Le Goater 1452ae4c68e3SCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1453ae4c68e3SCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads); 1454ae4c68e3SCédric Le Goater 1455ae4c68e3SCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) { 1456ae4c68e3SCédric Le Goater PnvQuad *eq = &chip9->quads[i]; 1457ae4c68e3SCédric Le Goater 1458fdc2b46aSJoel Stanley pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], 1459fdc2b46aSJoel Stanley PNV_QUAD_TYPE_NAME("power9")); 14605dad902cSCédric Le Goater 146192612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id), 14625dad902cSCédric Le Goater &eq->xscom_regs); 14635dad902cSCédric Le Goater } 14645dad902cSCédric Le Goater } 14655dad902cSCédric Le Goater 146613480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp) 14674f9924c4SBenjamin Herrenschmidt { 14684f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip); 146913480fc5SCédric Le Goater int i; 14704f9924c4SBenjamin Herrenschmidt 1471422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 14724f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i]; 14734f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 14744f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base; 14754f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base; 14764f9924c4SBenjamin Herrenschmidt 14775325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 14785325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 14794f9924c4SBenjamin Herrenschmidt &error_fatal); 14806f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 14816f43d255SCédric Le Goater &error_fatal); 1482668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) { 14834f9924c4SBenjamin Herrenschmidt return; 14844f9924c4SBenjamin Herrenschmidt } 14854f9924c4SBenjamin Herrenschmidt 14864f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec); 14874f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec); 14884f9924c4SBenjamin Herrenschmidt 14894f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 14904f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 14914f9924c4SBenjamin Herrenschmidt } 14924f9924c4SBenjamin Herrenschmidt } 14934f9924c4SBenjamin Herrenschmidt 149477864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) 149577864267SCédric Le Goater { 149677864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 14972dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev); 14982dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 1499c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi; 150077864267SCédric Le Goater Error *local_err = NULL; 150177864267SCédric Le Goater 1502709044fdSCédric Le Goater /* XSCOM bridge is first */ 1503709044fdSCédric Le Goater pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err); 1504709044fdSCédric Le Goater if (local_err) { 1505709044fdSCédric Le Goater error_propagate(errp, local_err); 1506709044fdSCédric Le Goater return; 1507709044fdSCédric Le Goater } 1508709044fdSCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip)); 1509709044fdSCédric Le Goater 151077864267SCédric Le Goater pcc->parent_realize(dev, &local_err); 151177864267SCédric Le Goater if (local_err) { 151277864267SCédric Le Goater error_propagate(errp, local_err); 151377864267SCédric Le Goater return; 151477864267SCédric Le Goater } 15152dfa91a2SCédric Le Goater 15165dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err); 15175dad902cSCédric Le Goater if (local_err) { 15185dad902cSCédric Le Goater error_propagate(errp, local_err); 15195dad902cSCédric Le Goater return; 15205dad902cSCédric Le Goater } 15215dad902cSCédric Le Goater 15222dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */ 15235325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar", 15245325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal); 15255325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar", 15265325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal); 15275325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar", 15285325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal); 15295325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar", 15305325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal); 15315325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip), 15327ae54cc3SGreg Kurz &error_abort); 1533668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) { 15342dfa91a2SCédric Le Goater return; 15352dfa91a2SCédric Le Goater } 15362dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE, 15372dfa91a2SCédric Le Goater &chip9->xive.xscom_regs); 1538c38536bcSCédric Le Goater 1539c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 15405325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip), 15415325cc34SMarkus Armbruster &error_fatal); 154224c8fa96SCédric Le Goater /* This is the only device with 4k ESB pages */ 154324c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K, 154424c8fa96SCédric Le Goater &error_fatal); 1545668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) { 1546c38536bcSCédric Le Goater return; 1547c38536bcSCédric Le Goater } 1548c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE, 1549c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs); 155015376c66SCédric Le Goater 155115376c66SCédric Le Goater /* LPC */ 1552668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) { 155315376c66SCédric Le Goater return; 155415376c66SCédric Le Goater } 155515376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip), 155615376c66SCédric Le Goater &chip9->lpc.xscom_regs); 155715376c66SCédric Le Goater 1558032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw; 155915376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 156015376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip)); 15616598a70dSCédric Le Goater 15626598a70dSCédric Le Goater /* Create the simplified OCC model */ 1563668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) { 15646598a70dSCédric Le Goater return; 15656598a70dSCédric Le Goater } 15666598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs); 1567b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in( 1568b0ae5c69SCédric Le Goater DEVICE(&chip9->psi), PSIHB9_IRQ_OCC)); 1569f3db8266SBalamuruhan S 1570f3db8266SBalamuruhan S /* OCC SRAM model */ 15713a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), 1572f3db8266SBalamuruhan S &chip9->occ.sram_regs); 15733887d241SBalamuruhan S 15740bf4d77eSNicholas Piggin /* SBE */ 15750bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) { 15760bf4d77eSNicholas Piggin return; 15770bf4d77eSNicholas Piggin } 15780bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE, 15790bf4d77eSNicholas Piggin &chip9->sbe.xscom_ctrl_regs); 15800bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE, 15810bf4d77eSNicholas Piggin &chip9->sbe.xscom_mbox_regs); 15820bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in( 15830bf4d77eSNicholas Piggin DEVICE(&chip9->psi), PSIHB9_IRQ_PSU)); 15840bf4d77eSNicholas Piggin 15853887d241SBalamuruhan S /* HOMER */ 15865325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), 1587f2582acfSGreg Kurz &error_abort); 1588668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) { 15893887d241SBalamuruhan S return; 15903887d241SBalamuruhan S } 15918f092316SCédric Le Goater /* Homer Xscom region */ 15928f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs); 15938f092316SCédric Le Goater 15948f092316SCédric Le Goater /* Homer mmio region */ 15953887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip), 15963887d241SBalamuruhan S &chip9->homer.regs); 15974f9924c4SBenjamin Herrenschmidt 159813480fc5SCédric Le Goater /* PEC PHBs */ 159913480fc5SCédric Le Goater pnv_chip_power9_pec_realize(chip, &local_err); 16004f9924c4SBenjamin Herrenschmidt if (local_err) { 16014f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err); 16024f9924c4SBenjamin Herrenschmidt return; 16034f9924c4SBenjamin Herrenschmidt } 1604e997040eSCédric Le Goater } 1605e997040eSCédric Le Goater 160670c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr) 160770c059e9SGreg Kurz { 160870c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1); 160970c059e9SGreg Kurz return addr >> 3; 161070c059e9SGreg Kurz } 161170c059e9SGreg Kurz 1612e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) 1613e997040eSCédric Le Goater { 1614e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1615e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 1616e997040eSCédric Le Goater 161783028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */ 1618397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK; 1619631adaffSCédric Le Goater k->core_pir = pnv_chip_core_pir_p9; 1620d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create; 1621d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset; 16220990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy; 162385913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info; 162404026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create; 1625eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate; 1626d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info; 1627c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base; 162870c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba; 1629e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9"; 1630422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC; 163177864267SCédric Le Goater 163277864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize, 163377864267SCédric Le Goater &k->parent_realize); 1634e997040eSCédric Le Goater } 1635e997040eSCédric Le Goater 16362b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj) 16372b548a42SCédric Le Goater { 1638623575e1SCédric Le Goater PnvChip *chip = PNV_CHIP(obj); 16398b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj); 1640623575e1SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj); 1641623575e1SCédric Le Goater int i; 16428b50ce85SCédric Le Goater 1643da71b7e3SCédric Le Goater object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2); 1644da71b7e3SCédric Le Goater object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive), 1645da71b7e3SCédric Le Goater "xive-fabric"); 16469fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); 16479fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); 16488bf682a3SCédric Le Goater object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); 16490bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE); 165092499676SCédric Le Goater object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); 1651623575e1SCédric Le Goater 1652623575e1SCédric Le Goater chip->num_pecs = pcc->num_pecs; 1653623575e1SCédric Le Goater 1654623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1655623575e1SCédric Le Goater object_initialize_child(obj, "pec[*]", &chip10->pecs[i], 1656623575e1SCédric Le Goater TYPE_PNV_PHB5_PEC); 1657623575e1SCédric Le Goater } 16582b548a42SCédric Le Goater } 16592b548a42SCédric Le Goater 1660ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp) 1661ae4c68e3SCédric Le Goater { 1662ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip10); 1663ae4c68e3SCédric Le Goater int i; 1664ae4c68e3SCédric Le Goater 1665ae4c68e3SCédric Le Goater chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4); 1666ae4c68e3SCédric Le Goater chip10->quads = g_new0(PnvQuad, chip10->nr_quads); 1667ae4c68e3SCédric Le Goater 1668ae4c68e3SCédric Le Goater for (i = 0; i < chip10->nr_quads; i++) { 1669ae4c68e3SCédric Le Goater PnvQuad *eq = &chip10->quads[i]; 1670ae4c68e3SCédric Le Goater 1671fdc2b46aSJoel Stanley pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4], 1672fdc2b46aSJoel Stanley PNV_QUAD_TYPE_NAME("power9")); 1673ae4c68e3SCédric Le Goater 1674ae4c68e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id), 1675ae4c68e3SCédric Le Goater &eq->xscom_regs); 1676ae4c68e3SCédric Le Goater } 1677ae4c68e3SCédric Le Goater } 1678ae4c68e3SCédric Le Goater 1679623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp) 1680623575e1SCédric Le Goater { 1681623575e1SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip); 1682623575e1SCédric Le Goater int i; 1683623575e1SCédric Le Goater 1684623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) { 1685623575e1SCédric Le Goater PnvPhb4PecState *pec = &chip10->pecs[i]; 1686623575e1SCédric Le Goater PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 1687623575e1SCédric Le Goater uint32_t pec_nest_base; 1688623575e1SCédric Le Goater uint32_t pec_pci_base; 1689623575e1SCédric Le Goater 1690623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "index", i, &error_fatal); 1691623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id, 1692623575e1SCédric Le Goater &error_fatal); 1693623575e1SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip), 1694623575e1SCédric Le Goater &error_fatal); 1695623575e1SCédric Le Goater if (!qdev_realize(DEVICE(pec), NULL, errp)) { 1696623575e1SCédric Le Goater return; 1697623575e1SCédric Le Goater } 1698623575e1SCédric Le Goater 1699623575e1SCédric Le Goater pec_nest_base = pecc->xscom_nest_base(pec); 1700623575e1SCédric Le Goater pec_pci_base = pecc->xscom_pci_base(pec); 1701623575e1SCédric Le Goater 1702623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr); 1703623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr); 1704623575e1SCédric Le Goater } 1705623575e1SCédric Le Goater } 1706623575e1SCédric Le Goater 17072b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) 17082b548a42SCédric Le Goater { 17092b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); 17102b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 17118b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev); 17122b548a42SCédric Le Goater Error *local_err = NULL; 17132b548a42SCédric Le Goater 17142b548a42SCédric Le Goater /* XSCOM bridge is first */ 17152b548a42SCédric Le Goater pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err); 17162b548a42SCédric Le Goater if (local_err) { 17172b548a42SCédric Le Goater error_propagate(errp, local_err); 17182b548a42SCédric Le Goater return; 17192b548a42SCédric Le Goater } 17202b548a42SCédric Le Goater sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip)); 17212b548a42SCédric Le Goater 17222b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err); 17232b548a42SCédric Le Goater if (local_err) { 17242b548a42SCédric Le Goater error_propagate(errp, local_err); 17252b548a42SCédric Le Goater return; 17262b548a42SCédric Le Goater } 17278b50ce85SCédric Le Goater 1728ae4c68e3SCédric Le Goater pnv_chip_power10_quad_realize(chip10, &local_err); 1729ae4c68e3SCédric Le Goater if (local_err) { 1730ae4c68e3SCédric Le Goater error_propagate(errp, local_err); 1731ae4c68e3SCédric Le Goater return; 1732ae4c68e3SCédric Le Goater } 1733ae4c68e3SCédric Le Goater 1734da71b7e3SCédric Le Goater /* XIVE2 interrupt controller (POWER10) */ 1735da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "ic-bar", 1736da71b7e3SCédric Le Goater PNV10_XIVE2_IC_BASE(chip), &error_fatal); 1737da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "esb-bar", 1738da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_BASE(chip), &error_fatal); 1739da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "end-bar", 1740da71b7e3SCédric Le Goater PNV10_XIVE2_END_BASE(chip), &error_fatal); 1741da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar", 1742da71b7e3SCédric Le Goater PNV10_XIVE2_NVPG_BASE(chip), &error_fatal); 1743da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvc-bar", 1744da71b7e3SCédric Le Goater PNV10_XIVE2_NVC_BASE(chip), &error_fatal); 1745da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "tm-bar", 1746da71b7e3SCédric Le Goater PNV10_XIVE2_TM_BASE(chip), &error_fatal); 1747da71b7e3SCédric Le Goater object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip), 1748da71b7e3SCédric Le Goater &error_abort); 1749da71b7e3SCédric Le Goater if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) { 1750da71b7e3SCédric Le Goater return; 1751da71b7e3SCédric Le Goater } 1752da71b7e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE, 1753da71b7e3SCédric Le Goater &chip10->xive.xscom_regs); 1754da71b7e3SCédric Le Goater 17558b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */ 17565325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar", 17575325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal); 175824c8fa96SCédric Le Goater /* PSI can now be configured to use 64k ESB pages on POWER10 */ 175924c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K, 176024c8fa96SCédric Le Goater &error_fatal); 1761668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) { 17628b50ce85SCédric Le Goater return; 17638b50ce85SCédric Le Goater } 17648b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE, 17658b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs); 17662661f6abSCédric Le Goater 17672661f6abSCédric Le Goater /* LPC */ 1768668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) { 17692661f6abSCédric Le Goater return; 17702661f6abSCédric Le Goater } 17712661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip), 17722661f6abSCédric Le Goater &chip10->lpc.xscom_regs); 17732661f6abSCédric Le Goater 1774032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw; 17752661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0", 17762661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip)); 17778bf682a3SCédric Le Goater 17788bf682a3SCédric Le Goater /* Create the simplified OCC model */ 17798bf682a3SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) { 17808bf682a3SCédric Le Goater return; 17818bf682a3SCédric Le Goater } 17828bf682a3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE, 17838bf682a3SCédric Le Goater &chip10->occ.xscom_regs); 1784b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in( 1785b0ae5c69SCédric Le Goater DEVICE(&chip10->psi), PSIHB9_IRQ_OCC)); 1786623575e1SCédric Le Goater 178792499676SCédric Le Goater /* OCC SRAM model */ 178892499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), 178992499676SCédric Le Goater PNV10_OCC_SENSOR_BASE(chip), 179092499676SCédric Le Goater &chip10->occ.sram_regs); 179192499676SCédric Le Goater 17920bf4d77eSNicholas Piggin /* SBE */ 17930bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) { 17940bf4d77eSNicholas Piggin return; 17950bf4d77eSNicholas Piggin } 17960bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE, 17970bf4d77eSNicholas Piggin &chip10->sbe.xscom_ctrl_regs); 17980bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE, 17990bf4d77eSNicholas Piggin &chip10->sbe.xscom_mbox_regs); 18000bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in( 18010bf4d77eSNicholas Piggin DEVICE(&chip10->psi), PSIHB9_IRQ_PSU)); 18020bf4d77eSNicholas Piggin 180392499676SCédric Le Goater /* HOMER */ 180492499676SCédric Le Goater object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip), 180592499676SCédric Le Goater &error_abort); 180692499676SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) { 180792499676SCédric Le Goater return; 180892499676SCédric Le Goater } 180992499676SCédric Le Goater /* Homer Xscom region */ 181092499676SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE, 181192499676SCédric Le Goater &chip10->homer.pba_regs); 181292499676SCédric Le Goater 181392499676SCédric Le Goater /* Homer mmio region */ 181492499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip), 181592499676SCédric Le Goater &chip10->homer.regs); 181692499676SCédric Le Goater 1817623575e1SCédric Le Goater /* PHBs */ 1818623575e1SCédric Le Goater pnv_chip_power10_phb_realize(chip, &local_err); 1819623575e1SCédric Le Goater if (local_err) { 1820623575e1SCédric Le Goater error_propagate(errp, local_err); 1821623575e1SCédric Le Goater return; 1822623575e1SCédric Le Goater } 18232b548a42SCédric Le Goater } 18242b548a42SCédric Le Goater 182570c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr) 182670c059e9SGreg Kurz { 182770c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1); 182870c059e9SGreg Kurz return addr >> 3; 182970c059e9SGreg Kurz } 183070c059e9SGreg Kurz 18312b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data) 18322b548a42SCédric Le Goater { 18332b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 18342b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass); 18352b548a42SCédric Le Goater 18362b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */ 18372b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK; 18382b548a42SCédric Le Goater k->core_pir = pnv_chip_core_pir_p10; 18392b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create; 18402b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset; 18412b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy; 184285913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info; 18432b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create; 18442b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate; 18452b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info; 1846c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base; 184770c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba; 18482b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10"; 1849623575e1SCédric Le Goater k->num_pecs = PNV10_CHIP_MAX_PEC; 18502b548a42SCédric Le Goater 18512b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize, 18522b548a42SCédric Le Goater &k->parent_realize); 18532b548a42SCédric Le Goater } 18542b548a42SCédric Le Goater 1855397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) 1856397a79e7SCédric Le Goater { 1857397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 1858397a79e7SCédric Le Goater int cores_max; 1859397a79e7SCédric Le Goater 1860397a79e7SCédric Le Goater /* 1861397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from * 1862397a79e7SCédric Le Goater * the chip class 1863397a79e7SCédric Le Goater */ 1864397a79e7SCédric Le Goater if (!chip->cores_mask) { 1865397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask; 1866397a79e7SCédric Le Goater } 1867397a79e7SCédric Le Goater 1868397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */ 1869397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) { 1870397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !", 1871397a79e7SCédric Le Goater chip->cores_mask); 1872397a79e7SCédric Le Goater return; 1873397a79e7SCédric Le Goater } 1874397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask; 1875397a79e7SCédric Le Goater 1876397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */ 187727d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask); 1878397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) { 1879397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d", 1880397a79e7SCédric Le Goater cores_max); 1881397a79e7SCédric Le Goater return; 1882397a79e7SCédric Le Goater } 1883397a79e7SCédric Le Goater } 1884397a79e7SCédric Le Goater 188551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp) 1886e997040eSCédric Le Goater { 1887397a79e7SCédric Le Goater Error *error = NULL; 1888d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip); 188940abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip); 1890d2fd9612SCédric Le Goater int i, core_hwid; 189108c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); 1892397a79e7SCédric Le Goater 1893d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) { 1894d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename); 1895d2fd9612SCédric Le Goater return; 1896d2fd9612SCédric Le Goater } 1897d2fd9612SCédric Le Goater 1898d2fd9612SCédric Le Goater /* Cores */ 1899397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error); 1900397a79e7SCédric Le Goater if (error) { 1901397a79e7SCédric Le Goater error_propagate(errp, error); 1902397a79e7SCédric Le Goater return; 1903397a79e7SCédric Le Goater } 1904d2fd9612SCédric Le Goater 19054fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores); 1906d2fd9612SCédric Le Goater 1907d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8) 1908d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) { 1909d2fd9612SCédric Le Goater char core_name[32]; 19104fa28f23SGreg Kurz PnvCore *pnv_core; 1911c035851aSCédric Le Goater uint64_t xscom_core_base; 1912d2fd9612SCédric Le Goater 1913d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) { 1914d2fd9612SCédric Le Goater continue; 1915d2fd9612SCédric Le Goater } 1916d2fd9612SCédric Le Goater 19174fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename)); 19184fa28f23SGreg Kurz 1919d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid); 1920d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core)); 19214fa28f23SGreg Kurz chip->cores[i] = pnv_core; 19225325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads", 19235325cc34SMarkus Armbruster chip->nr_threads, &error_fatal); 19245325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID, 19255325cc34SMarkus Armbruster core_hwid, &error_fatal); 19265325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "pir", 19275325cc34SMarkus Armbruster pcc->core_pir(chip, core_hwid), &error_fatal); 19285325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr, 19295325cc34SMarkus Armbruster &error_fatal); 19305325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip), 1931158e17a6SGreg Kurz &error_abort); 1932ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal); 193324ece072SCédric Le Goater 193424ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */ 1935c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid); 1936c035851aSCédric Le Goater 1937c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base, 19384fa28f23SGreg Kurz &pnv_core->xscom_regs); 1939d2fd9612SCédric Le Goater i++; 1940d2fd9612SCédric Le Goater } 194151c04728SCédric Le Goater } 194251c04728SCédric Le Goater 194351c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp) 194451c04728SCédric Le Goater { 194551c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev); 194651c04728SCédric Le Goater Error *error = NULL; 194751c04728SCédric Le Goater 194851c04728SCédric Le Goater /* Cores */ 194951c04728SCédric Le Goater pnv_chip_core_realize(chip, &error); 195051c04728SCédric Le Goater if (error) { 195151c04728SCédric Le Goater error_propagate(errp, error); 195251c04728SCédric Le Goater return; 195351c04728SCédric Le Goater } 1954e997040eSCédric Le Goater } 1955e997040eSCédric Le Goater 1956e997040eSCédric Le Goater static Property pnv_chip_properties[] = { 1957e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0), 1958e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0), 1959e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0), 1960397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1), 1961397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0), 1962764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1), 1963e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(), 1964e997040eSCédric Le Goater }; 1965e997040eSCédric Le Goater 1966e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data) 1967e997040eSCédric Le Goater { 1968e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 1969e997040eSCédric Le Goater 19709d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories); 1971e997040eSCédric Le Goater dc->realize = pnv_chip_realize; 19724f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties); 1973e997040eSCédric Le Goater dc->desc = "PowerNV Chip"; 1974e997040eSCédric Le Goater } 1975e997040eSCédric Le Goater 1976119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir) 1977119eaa9dSCédric Le Goater { 1978119eaa9dSCédric Le Goater int i, j; 1979119eaa9dSCédric Le Goater 1980119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) { 1981119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i]; 1982119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc); 1983119eaa9dSCédric Le Goater 1984119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) { 1985119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) { 1986119eaa9dSCédric Le Goater return pc->threads[j]; 1987119eaa9dSCédric Le Goater } 1988119eaa9dSCédric Le Goater } 1989119eaa9dSCédric Le Goater } 1990119eaa9dSCédric Le Goater return NULL; 1991119eaa9dSCédric Le Goater } 1992119eaa9dSCédric Le Goater 199354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq) 199454f59d78SCédric Le Goater { 1995b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 1996da6be501SDaniel Henrique Barboza int i, j; 199754f59d78SCédric Le Goater 199854f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 199977864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 200077864267SCédric Le Goater 200177864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) { 200277864267SCédric Le Goater return &chip8->psi.ics; 200354f59d78SCédric Le Goater } 20042ff73ddaSCédric Le Goater 2005da6be501SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 20060d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j]; 20071f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 2008da6be501SDaniel Henrique Barboza 2009da6be501SDaniel Henrique Barboza if (ics_valid_irq(&phb3->lsis, irq)) { 2010da6be501SDaniel Henrique Barboza return &phb3->lsis; 2011da6be501SDaniel Henrique Barboza } 2012da6be501SDaniel Henrique Barboza 2013da6be501SDaniel Henrique Barboza if (ics_valid_irq(ICS(&phb3->msis), irq)) { 2014da6be501SDaniel Henrique Barboza return ICS(&phb3->msis); 2015da6be501SDaniel Henrique Barboza } 20169ae1329eSCédric Le Goater } 201754f59d78SCédric Le Goater } 201854f59d78SCédric Le Goater return NULL; 201954f59d78SCédric Le Goater } 202054f59d78SCédric Le Goater 20211f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id) 20221f6a88ffSCédric Le Goater { 20231f6a88ffSCédric Le Goater int i; 20241f6a88ffSCédric Le Goater 20251f6a88ffSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 20261f6a88ffSCédric Le Goater PnvChip *chip = pnv->chips[i]; 20271f6a88ffSCédric Le Goater if (chip->chip_id == chip_id) { 20281f6a88ffSCédric Le Goater return chip; 20291f6a88ffSCédric Le Goater } 20301f6a88ffSCédric Le Goater } 20311f6a88ffSCédric Le Goater return NULL; 20321f6a88ffSCédric Le Goater } 20331f6a88ffSCédric Le Goater 203454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi) 203554f59d78SCédric Le Goater { 2036b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi); 2037ca459489SDaniel Henrique Barboza int i, j; 203854f59d78SCédric Le Goater 203954f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 204077864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]); 20419ae1329eSCédric Le Goater 204277864267SCédric Le Goater ics_resend(&chip8->psi.ics); 2043ca459489SDaniel Henrique Barboza 2044ca459489SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) { 20450d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j]; 20461f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend); 2047ca459489SDaniel Henrique Barboza 2048ca459489SDaniel Henrique Barboza ics_resend(&phb3->lsis); 2049ca459489SDaniel Henrique Barboza ics_resend(ICS(&phb3->msis)); 2050ca459489SDaniel Henrique Barboza } 205154f59d78SCédric Le Goater } 205254f59d78SCédric Le Goater } 205354f59d78SCédric Le Goater 205436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir) 205536fc6f08SCédric Le Goater { 205636fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); 205736fc6f08SCédric Le Goater 2058956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL; 205936fc6f08SCédric Le Goater } 206036fc6f08SCédric Le Goater 206147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj, 206247fea43aSCédric Le Goater Monitor *mon) 206347fea43aSCédric Le Goater { 2064b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 206554f59d78SCédric Le Goater int i; 206647fea43aSCédric Le Goater CPUState *cs; 206747fea43aSCédric Le Goater 206847fea43aSCédric Le Goater CPU_FOREACH(cs) { 206947fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 207047fea43aSCédric Le Goater 207185913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */ 207285913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu, 207385913070SGreg Kurz mon); 2074d8e4aad5SCédric Le Goater } 207554f59d78SCédric Le Goater 207654f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2077d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon); 207854f59d78SCédric Le Goater } 207947fea43aSCédric Le Goater } 208047fea43aSCédric Le Goater 2081c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format, 2082c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2083c722579eSCédric Le Goater bool cam_ignore, uint8_t priority, 2084c722579eSCédric Le Goater uint32_t logic_serv, 2085c722579eSCédric Le Goater XiveTCTXMatch *match) 2086c722579eSCédric Le Goater { 2087c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2088c722579eSCédric Le Goater int total_count = 0; 2089c722579eSCédric Le Goater int i; 2090c722579eSCédric Le Goater 2091c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2092c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]); 2093c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive); 2094c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2095c722579eSCédric Le Goater int count; 2096c722579eSCédric Le Goater 2097c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2098c722579eSCédric Le Goater priority, logic_serv, match); 2099c722579eSCédric Le Goater 2100c722579eSCédric Le Goater if (count < 0) { 2101c722579eSCédric Le Goater return count; 2102c722579eSCédric Le Goater } 2103c722579eSCédric Le Goater 2104c722579eSCédric Le Goater total_count += count; 2105c722579eSCédric Le Goater } 2106c722579eSCédric Le Goater 2107c722579eSCédric Le Goater return total_count; 2108c722579eSCédric Le Goater } 2109c722579eSCédric Le Goater 2110da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format, 2111da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx, 2112da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority, 2113da71b7e3SCédric Le Goater uint32_t logic_serv, 2114da71b7e3SCédric Le Goater XiveTCTXMatch *match) 2115da71b7e3SCédric Le Goater { 2116da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb); 2117da71b7e3SCédric Le Goater int total_count = 0; 2118da71b7e3SCédric Le Goater int i; 2119da71b7e3SCédric Le Goater 2120da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) { 2121da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]); 2122da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive); 2123da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr); 2124da71b7e3SCédric Le Goater int count; 2125da71b7e3SCédric Le Goater 2126da71b7e3SCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore, 2127da71b7e3SCédric Le Goater priority, logic_serv, match); 2128da71b7e3SCédric Le Goater 2129da71b7e3SCédric Le Goater if (count < 0) { 2130da71b7e3SCédric Le Goater return count; 2131da71b7e3SCédric Le Goater } 2132da71b7e3SCédric Le Goater 2133da71b7e3SCédric Le Goater total_count += count; 2134da71b7e3SCédric Le Goater } 2135da71b7e3SCédric Le Goater 2136da71b7e3SCédric Le Goater return total_count; 2137da71b7e3SCédric Le Goater } 2138da71b7e3SCédric Le Goater 2139f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) 21409e933f4aSBenjamin Herrenschmidt { 21419e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc); 214236fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 2143d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2144d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; 2145f30c843cSCédric Le Goater 21461f5d6b2aSDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 21471f5d6b2aSDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "3" }, 214880515061SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "3" }, 21491f5d6b2aSDaniel Henrique Barboza }; 21501f5d6b2aSDaniel Henrique Barboza 2151f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; 2152f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); 21531f5d6b2aSDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2154f30c843cSCédric Le Goater 2155f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get; 2156f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get; 2157f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend; 2158d76f2da7SGreg Kurz 2159d76f2da7SGreg Kurz pmc->compat = compat; 2160d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 2161892c3ad0SDaniel Henrique Barboza 2162892c3ad0SDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); 2163f30c843cSCédric Le Goater } 2164f30c843cSCédric Le Goater 2165f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) 2166f30c843cSCédric Le Goater { 2167f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2168c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2169d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2170d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv"; 2171f30c843cSCédric Le Goater 2172210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 2173210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "4" }, 2174c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "4" }, 2175210aacb3SDaniel Henrique Barboza }; 2176210aacb3SDaniel Henrique Barboza 2177f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; 2178277ee172SNicholas Piggin mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2"); 2179210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2180210aacb3SDaniel Henrique Barboza 2181c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt; 2182f30c843cSCédric Le Goater 2183f30c843cSCédric Le Goater mc->alias = "powernv"; 2184d76f2da7SGreg Kurz 2185d76f2da7SGreg Kurz pmc->compat = compat; 2186d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 21877a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2188d786be3fSDaniel Henrique Barboza 2189d786be3fSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); 2190f30c843cSCédric Le Goater } 2191f30c843cSCédric Le Goater 21922b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) 21932b548a42SCédric Le Goater { 21942b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 2195d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); 2196da71b7e3SCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); 2197d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv"; 21982b548a42SCédric Le Goater 2199210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = { 2200210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "5" }, 2201c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, 2202210aacb3SDaniel Henrique Barboza }; 2203210aacb3SDaniel Henrique Barboza 22042b548a42SCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; 22056bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); 2206210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); 2207d76f2da7SGreg Kurz 2208d76f2da7SGreg Kurz pmc->compat = compat; 2209d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat); 22107a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt; 2211da71b7e3SCédric Le Goater 2212da71b7e3SCédric Le Goater xfc->match_nvt = pnv10_xive_match_nvt; 2213f1327fdeSDaniel Henrique Barboza 2214f1327fdeSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); 22152b548a42SCédric Le Goater } 22162b548a42SCédric Le Goater 221708c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp) 221808c3f3a7SCédric Le Goater { 221908c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 222008c3f3a7SCédric Le Goater 222108c3f3a7SCédric Le Goater return !!pnv->fw_load_addr; 222208c3f3a7SCédric Le Goater } 222308c3f3a7SCédric Le Goater 222408c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp) 222508c3f3a7SCédric Le Goater { 222608c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj); 222708c3f3a7SCédric Le Goater 222808c3f3a7SCédric Le Goater if (value) { 222908c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000; 223008c3f3a7SCédric Le Goater } 223108c3f3a7SCédric Le Goater } 223208c3f3a7SCédric Le Goater 223301b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 223401b552b0SNicholas Piggin { 223501b552b0SNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 223601b552b0SNicholas Piggin CPUPPCState *env = &cpu->env; 223701b552b0SNicholas Piggin 223801b552b0SNicholas Piggin cpu_synchronize_state(cs); 223901b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs); 22400911a60cSLeonardo Bras if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) { 224101b552b0SNicholas Piggin /* 2242fe837714SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the 2243fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100 2244fe837714SNicholas Piggin * (PPC_BIT(43)). 224501b552b0SNicholas Piggin */ 22460911a60cSLeonardo Bras if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) { 2247fe837714SNicholas Piggin warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason"); 22480911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKERESET; 224901b552b0SNicholas Piggin } 2250fe837714SNicholas Piggin } else { 2251fe837714SNicholas Piggin /* 2252fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be 2253fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that 2254fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or 2255fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be 2256fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)). 2257fe837714SNicholas Piggin */ 22580911a60cSLeonardo Bras env->spr[SPR_SRR1] |= SRR1_WAKESCOM; 2259fe837714SNicholas Piggin } 2260fe837714SNicholas Piggin } 226101b552b0SNicholas Piggin 226201b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp) 226301b552b0SNicholas Piggin { 226401b552b0SNicholas Piggin CPUState *cs; 226501b552b0SNicholas Piggin 226601b552b0SNicholas Piggin CPU_FOREACH(cs) { 226701b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 226801b552b0SNicholas Piggin } 226901b552b0SNicholas Piggin } 227001b552b0SNicholas Piggin 2271f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data) 2272f30c843cSCédric Le Goater { 2273f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc); 227447fea43aSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 227501b552b0SNicholas Piggin NMIClass *nc = NMI_CLASS(oc); 22769e933f4aSBenjamin Herrenschmidt 22779e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)"; 2278b168a138SCédric Le Goater mc->init = pnv_init; 2279b168a138SCédric Le Goater mc->reset = pnv_reset; 22809e933f4aSBenjamin Herrenschmidt mc->max_cpus = MAX_CPUS; 228159b7c1c2SBalamuruhan S /* Pnv provides a AHCI device for storage */ 228259b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE; 22839e933f4aSBenjamin Herrenschmidt mc->no_parallel = 1; 22849e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL; 2285f1d18b0aSJoel Stanley /* 2286f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large 2287f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address 2288f1d18b0aSJoel Stanley */ 2289dd7ef911SCédric Le Goater mc->default_ram_size = 1 * GiB; 2290173a36d8SIgor Mammedov mc->default_ram_id = "pnv.ram"; 229147fea43aSCédric Le Goater ispc->print_info = pnv_pic_print_info; 229201b552b0SNicholas Piggin nc->nmi_monitor_handler = pnv_nmi; 229308c3f3a7SCédric Le Goater 229408c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode", 2295d2623129SMarkus Armbruster pnv_machine_get_hb, pnv_machine_set_hb); 229608c3f3a7SCédric Le Goater object_class_property_set_description(oc, "hb-mode", 22977eecec7dSMarkus Armbruster "Use a hostboot like boot loader"); 22989e933f4aSBenjamin Herrenschmidt } 22999e933f4aSBenjamin Herrenschmidt 230077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \ 2301beba5c0fSIgor Mammedov { \ 2302beba5c0fSIgor Mammedov .name = type, \ 2303beba5c0fSIgor Mammedov .class_init = class_initfn, \ 230477864267SCédric Le Goater .parent = TYPE_PNV8_CHIP, \ 230577864267SCédric Le Goater } 230677864267SCédric Le Goater 230777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \ 230877864267SCédric Le Goater { \ 230977864267SCédric Le Goater .name = type, \ 231077864267SCédric Le Goater .class_init = class_initfn, \ 231177864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \ 2312beba5c0fSIgor Mammedov } 2313beba5c0fSIgor Mammedov 23142b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \ 23152b548a42SCédric Le Goater { \ 23162b548a42SCédric Le Goater .name = type, \ 23172b548a42SCédric Le Goater .class_init = class_initfn, \ 23182b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \ 23192b548a42SCédric Le Goater } 23202b548a42SCédric Le Goater 2321beba5c0fSIgor Mammedov static const TypeInfo types[] = { 23221aba8716SCédric Le Goater { 23232b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10"), 23242b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23252b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init, 2326da71b7e3SCédric Le Goater .interfaces = (InterfaceInfo[]) { 2327da71b7e3SCédric Le Goater { TYPE_XIVE_FABRIC }, 2328da71b7e3SCédric Le Goater { }, 2329da71b7e3SCédric Le Goater }, 23302b548a42SCédric Le Goater }, 23312b548a42SCédric Le Goater { 23321aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"), 23331aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23341aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init, 2335c722579eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 2336c722579eSCédric Le Goater { TYPE_XIVE_FABRIC }, 2337c722579eSCédric Le Goater { }, 2338c722579eSCédric Le Goater }, 23391aba8716SCédric Le Goater }, 23401aba8716SCédric Le Goater { 23411aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"), 23421aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE, 23431aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init, 23441aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) { 23451aba8716SCédric Le Goater { TYPE_XICS_FABRIC }, 23461aba8716SCédric Le Goater { }, 23471aba8716SCédric Le Goater }, 23481aba8716SCédric Le Goater }, 2349beba5c0fSIgor Mammedov { 2350b168a138SCédric Le Goater .name = TYPE_PNV_MACHINE, 23519e933f4aSBenjamin Herrenschmidt .parent = TYPE_MACHINE, 2352f30c843cSCédric Le Goater .abstract = true, 23539e933f4aSBenjamin Herrenschmidt .instance_size = sizeof(PnvMachineState), 2354b168a138SCédric Le Goater .class_init = pnv_machine_class_init, 2355d76f2da7SGreg Kurz .class_size = sizeof(PnvMachineClass), 235636fc6f08SCédric Le Goater .interfaces = (InterfaceInfo[]) { 235747fea43aSCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 235801b552b0SNicholas Piggin { TYPE_NMI }, 235936fc6f08SCédric Le Goater { }, 236036fc6f08SCédric Le Goater }, 2361beba5c0fSIgor Mammedov }, 2362beba5c0fSIgor Mammedov { 2363beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP, 2364beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE, 2365beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init, 2366beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip), 2367beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass), 2368beba5c0fSIgor Mammedov .abstract = true, 2369beba5c0fSIgor Mammedov }, 237077864267SCédric Le Goater 237177864267SCédric Le Goater /* 23722b548a42SCédric Le Goater * P10 chip and variants 23732b548a42SCédric Le Goater */ 23742b548a42SCédric Le Goater { 23752b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP, 23762b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP, 23772b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init, 23782b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip), 23792b548a42SCédric Le Goater }, 23802b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init), 23812b548a42SCédric Le Goater 23822b548a42SCédric Le Goater /* 238377864267SCédric Le Goater * P9 chip and variants 238477864267SCédric Le Goater */ 238577864267SCédric Le Goater { 238677864267SCédric Le Goater .name = TYPE_PNV9_CHIP, 238777864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 238877864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init, 238977864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip), 239077864267SCédric Le Goater }, 239177864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init), 239277864267SCédric Le Goater 239377864267SCédric Le Goater /* 239477864267SCédric Le Goater * P8 chip and variants 239577864267SCédric Le Goater */ 239677864267SCédric Le Goater { 239777864267SCédric Le Goater .name = TYPE_PNV8_CHIP, 239877864267SCédric Le Goater .parent = TYPE_PNV_CHIP, 239977864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init, 240077864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip), 240177864267SCédric Le Goater }, 240277864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init), 240377864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init), 240477864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL, 2405beba5c0fSIgor Mammedov pnv_chip_power8nvl_class_init), 24069e933f4aSBenjamin Herrenschmidt }; 24079e933f4aSBenjamin Herrenschmidt 2408beba5c0fSIgor Mammedov DEFINE_TYPES(types) 2409