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
pnv_chip_core_typename(const PnvChip * o)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 */
pnv_dt_memory(void * fdt,int chip_id,hwaddr start,hwaddr size)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
get_cpus_node(void * fdt)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 */
pnv_dt_core(PnvChip * chip,PnvCore * pc,void * fdt)136ce2b8536SNicholas Piggin static int 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);
1449940412aSCaleb Schlossin PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
145a580fdcdSPhilippe Mathieu-Daudé g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
146d2fd9612SCédric Le Goater int i;
1479940412aSCaleb Schlossin uint32_t pir;
148d2fd9612SCédric Le Goater uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
149d2fd9612SCédric Le Goater 0xffffffff, 0xffffffff};
150d2fd9612SCédric Le Goater uint32_t tbfreq = PNV_TIMEBASE_FREQ;
151d2fd9612SCédric Le Goater uint32_t cpufreq = 1000000000;
152d2fd9612SCédric Le Goater uint32_t page_sizes_prop[64];
153d2fd9612SCédric Le Goater size_t page_sizes_prop_size;
154d2fd9612SCédric Le Goater int offset;
155d2fd9612SCédric Le Goater char *nodename;
156d2fd9612SCédric Le Goater int cpus_offset = get_cpus_node(fdt);
157d2fd9612SCédric Le Goater
1589940412aSCaleb Schlossin pir = pnv_cc->chip_pir(chip, pc->hwid, 0);
1599940412aSCaleb Schlossin
1609940412aSCaleb Schlossin nodename = g_strdup_printf("%s@%x", dc->fw_name, pir);
161d2fd9612SCédric Le Goater offset = fdt_add_subnode(fdt, cpus_offset, nodename);
162d2fd9612SCédric Le Goater _FDT(offset);
163d2fd9612SCédric Le Goater g_free(nodename);
164d2fd9612SCédric Le Goater
165d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
166d2fd9612SCédric Le Goater
1679940412aSCaleb Schlossin _FDT((fdt_setprop_cell(fdt, offset, "reg", pir)));
1689940412aSCaleb Schlossin _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pir)));
169d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
170d2fd9612SCédric Le Goater
171d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
172d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
173d2fd9612SCédric Le Goater env->dcache_line_size)));
174d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
175d2fd9612SCédric Le Goater env->dcache_line_size)));
176d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
177d2fd9612SCédric Le Goater env->icache_line_size)));
178d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
179d2fd9612SCédric Le Goater env->icache_line_size)));
180d2fd9612SCédric Le Goater
181d2fd9612SCédric Le Goater if (pcc->l1_dcache_size) {
182d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
183d2fd9612SCédric Le Goater pcc->l1_dcache_size)));
184d2fd9612SCédric Le Goater } else {
1853dc6f869SAlistair Francis warn_report("Unknown L1 dcache size for cpu");
186d2fd9612SCédric Le Goater }
187d2fd9612SCédric Le Goater if (pcc->l1_icache_size) {
188d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
189d2fd9612SCédric Le Goater pcc->l1_icache_size)));
190d2fd9612SCédric Le Goater } else {
1913dc6f869SAlistair Francis warn_report("Unknown L1 icache size for cpu");
192d2fd9612SCédric Le Goater }
193d2fd9612SCédric Le Goater
194d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
195d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19659b7c1c2SBalamuruhan S _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19759b7c1c2SBalamuruhan S cpu->hash64_opts->slb_size)));
198d2fd9612SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
199d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
200d2fd9612SCédric Le Goater
20103282a3aSLucas Mateus Castro (alqotel) if (ppc_has_spr(cpu, SPR_PURR)) {
202d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
203d2fd9612SCédric Le Goater }
204d2fd9612SCédric Le Goater
20558969eeeSDavid Gibson if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
206d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
207d2fd9612SCédric Le Goater segs, sizeof(segs))));
208d2fd9612SCédric Le Goater }
209d2fd9612SCédric Le Goater
21059b7c1c2SBalamuruhan S /*
21159b7c1c2SBalamuruhan S * Advertise VMX/VSX (vector extensions) if available
212d2fd9612SCédric Le Goater * 0 / no property == no vector extensions
213d2fd9612SCédric Le Goater * 1 == VMX / Altivec available
21459b7c1c2SBalamuruhan S * 2 == VSX available
21559b7c1c2SBalamuruhan S */
216d2fd9612SCédric Le Goater if (env->insns_flags & PPC_ALTIVEC) {
217d2fd9612SCédric Le Goater uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
218d2fd9612SCédric Le Goater
219d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
220d2fd9612SCédric Le Goater }
221d2fd9612SCédric Le Goater
22259b7c1c2SBalamuruhan S /*
22359b7c1c2SBalamuruhan S * Advertise DFP (Decimal Floating Point) if available
224d2fd9612SCédric Le Goater * 0 / no property == no DFP
22559b7c1c2SBalamuruhan S * 1 == DFP available
22659b7c1c2SBalamuruhan S */
227d2fd9612SCédric Le Goater if (env->insns_flags2 & PPC2_DFP) {
228d2fd9612SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
229d2fd9612SCédric Le Goater }
230d2fd9612SCédric Le Goater
231644a2c99SDavid Gibson page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
232d2fd9612SCédric Le Goater sizeof(page_sizes_prop));
233d2fd9612SCédric Le Goater if (page_sizes_prop_size) {
234d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
235d2fd9612SCédric Le Goater page_sizes_prop, page_sizes_prop_size)));
236d2fd9612SCédric Le Goater }
237d2fd9612SCédric Le Goater
238d2fd9612SCédric Le Goater /* Build interrupt servers properties */
239d2fd9612SCédric Le Goater for (i = 0; i < smt_threads; i++) {
2409940412aSCaleb Schlossin servers_prop[i] = cpu_to_be32(pnv_cc->chip_pir(chip, pc->hwid, i));
241d2fd9612SCédric Le Goater }
242d2fd9612SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
243a580fdcdSPhilippe Mathieu-Daudé servers_prop, sizeof(*servers_prop) * smt_threads)));
244ce2b8536SNicholas Piggin
245ce2b8536SNicholas Piggin return offset;
246d2fd9612SCédric Le Goater }
247d2fd9612SCédric Le Goater
pnv_dt_icp(PnvChip * chip,void * fdt,uint32_t hwid,uint32_t nr_threads)2489940412aSCaleb Schlossin static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t hwid,
249bf5615e7SCédric Le Goater uint32_t nr_threads)
250bf5615e7SCédric Le Goater {
2519940412aSCaleb Schlossin PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
2529940412aSCaleb Schlossin uint32_t pir = pcc->chip_pir(chip, hwid, 0);
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++) {
2669940412aSCaleb Schlossin /* We know P8 PIR is linear with thread id */
267bf5615e7SCédric Le Goater reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
268bf5615e7SCédric Le Goater reg[i * 2 + 1] = cpu_to_be64(0x1000);
269bf5615e7SCédric Le Goater }
270bf5615e7SCédric Le Goater
271bf5615e7SCédric Le Goater name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
272bf5615e7SCédric Le Goater offset = fdt_add_subnode(fdt, 0, name);
273bf5615e7SCédric Le Goater _FDT(offset);
274bf5615e7SCédric Le Goater g_free(name);
275bf5615e7SCédric Le Goater
276bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
277bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
278bf5615e7SCédric Le Goater _FDT((fdt_setprop_string(fdt, offset, "device_type",
279bf5615e7SCédric Le Goater "PowerPC-External-Interrupt-Presentation")));
280bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
281bf5615e7SCédric Le Goater _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
282bf5615e7SCédric Le Goater irange, sizeof(irange))));
283bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
284bf5615e7SCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
285bf5615e7SCédric Le Goater g_free(reg);
286bf5615e7SCédric Le Goater }
287bf5615e7SCédric Le Goater
288ba47c3a4SDaniel Henrique Barboza /*
289ddf0676fSFrederic Barrat * Adds a PnvPHB to the chip on P8.
290ddf0676fSFrederic Barrat * Implemented here, like for defaults PHBs
291ba47c3a4SDaniel Henrique Barboza */
pnv_chip_add_phb(PnvChip * chip,PnvPHB * phb)292ddf0676fSFrederic Barrat PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb)
293ba47c3a4SDaniel Henrique Barboza {
2940d512c71SDaniel Henrique Barboza Pnv8Chip *chip8 = PNV8_CHIP(chip);
2950d512c71SDaniel Henrique Barboza
2960d512c71SDaniel Henrique Barboza phb->chip = chip;
2970d512c71SDaniel Henrique Barboza
2980d512c71SDaniel Henrique Barboza chip8->phbs[chip8->num_phbs] = phb;
2990d512c71SDaniel Henrique Barboza chip8->num_phbs++;
300ddf0676fSFrederic Barrat return chip;
301ba47c3a4SDaniel Henrique Barboza }
302ba47c3a4SDaniel Henrique Barboza
303ce2b8536SNicholas Piggin /*
304ce2b8536SNicholas Piggin * Same as spapr pa_features_207 except pnv always enables CI largepages bit.
305ce2b8536SNicholas Piggin * HTM is always enabled because TCG does implement HTM, it's just a
306ce2b8536SNicholas Piggin * degenerate implementation.
307ce2b8536SNicholas Piggin */
308ce2b8536SNicholas Piggin static const uint8_t pa_features_207[] = { 24, 0,
309ce2b8536SNicholas Piggin 0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0,
310ce2b8536SNicholas Piggin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
311ce2b8536SNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
312ce2b8536SNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
313ce2b8536SNicholas Piggin
pnv_chip_power8_dt_populate(PnvChip * chip,void * fdt)314eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
315e997040eSCédric Le Goater {
316c396c58aSGreg Kurz static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
317d2fd9612SCédric Le Goater int i;
318d2fd9612SCédric Le Goater
3193f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0,
3203f5b45caSGreg Kurz cpu_to_be64(PNV_XSCOM_BASE(chip)),
321c396c58aSGreg Kurz cpu_to_be64(PNV_XSCOM_SIZE),
322c396c58aSGreg Kurz compat, sizeof(compat));
323967b7523SCédric Le Goater
324d2fd9612SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
3254fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i];
326ce2b8536SNicholas Piggin int offset;
327d2fd9612SCédric Le Goater
328ce2b8536SNicholas Piggin offset = pnv_dt_core(chip, pnv_core, fdt);
329ce2b8536SNicholas Piggin
330ce2b8536SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
331ce2b8536SNicholas Piggin pa_features_207, sizeof(pa_features_207))));
332bf5615e7SCédric Le Goater
333bf5615e7SCédric Le Goater /* Interrupt Control Presenters (ICP). One per core. */
3349940412aSCaleb Schlossin pnv_dt_icp(chip, fdt, pnv_core->hwid, CPU_CORE(pnv_core)->nr_threads);
335d2fd9612SCédric Le Goater }
336d2fd9612SCédric Le Goater
337e997040eSCédric Le Goater if (chip->ram_size) {
338b168a138SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
339e997040eSCédric Le Goater }
340e997040eSCédric Le Goater }
341e997040eSCédric Le Goater
34224a9d20cSNicholas Piggin /*
34324a9d20cSNicholas Piggin * Same as spapr pa_features_300 except pnv always enables CI largepages bit.
34424a9d20cSNicholas Piggin */
34524a9d20cSNicholas Piggin static const uint8_t pa_features_300[] = { 66, 0,
34624a9d20cSNicholas Piggin /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: CILRG|fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
34724a9d20cSNicholas Piggin /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
34824a9d20cSNicholas Piggin 0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
34924a9d20cSNicholas Piggin /* 6: DS207 */
35024a9d20cSNicholas Piggin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
35124a9d20cSNicholas Piggin /* 16: Vector */
35224a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
35324a9d20cSNicholas Piggin /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */
35424a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 18 - 23 */
35524a9d20cSNicholas Piggin /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
35624a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
35724a9d20cSNicholas Piggin /* 32: LE atomic, 34: EBB + ext EBB */
35824a9d20cSNicholas Piggin 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
35924a9d20cSNicholas Piggin /* 40: Radix MMU */
36024a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
36124a9d20cSNicholas Piggin /* 42: PM, 44: PC RA, 46: SC vec'd */
36224a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
36324a9d20cSNicholas Piggin /* 48: SIMD, 50: QP BFP, 52: String */
36424a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
36524a9d20cSNicholas Piggin /* 54: DecFP, 56: DecI, 58: SHA */
36624a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
36724a9d20cSNicholas Piggin /* 60: NM atomic, 62: RNG */
36824a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
36924a9d20cSNicholas Piggin };
37024a9d20cSNicholas Piggin
pnv_chip_power9_dt_populate(PnvChip * chip,void * fdt)371eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
372eb859a27SCédric Le Goater {
373c396c58aSGreg Kurz static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
374eb859a27SCédric Le Goater int i;
375eb859a27SCédric Le Goater
3763f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0,
3773f5b45caSGreg Kurz cpu_to_be64(PNV9_XSCOM_BASE(chip)),
378c396c58aSGreg Kurz cpu_to_be64(PNV9_XSCOM_SIZE),
379c396c58aSGreg Kurz compat, sizeof(compat));
380eb859a27SCédric Le Goater
381eb859a27SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
3824fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i];
383ce2b8536SNicholas Piggin int offset;
384eb859a27SCédric Le Goater
385ce2b8536SNicholas Piggin offset = pnv_dt_core(chip, pnv_core, fdt);
386ce2b8536SNicholas Piggin
387ce2b8536SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
38824a9d20cSNicholas Piggin pa_features_300, sizeof(pa_features_300))));
389eb859a27SCédric Le Goater }
390eb859a27SCédric Le Goater
391eb859a27SCédric Le Goater if (chip->ram_size) {
392eb859a27SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
393eb859a27SCédric Le Goater }
39415376c66SCédric Le Goater
3952661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
396eb859a27SCédric Le Goater }
397eb859a27SCédric Le Goater
39824a9d20cSNicholas Piggin /*
39924a9d20cSNicholas Piggin * Same as spapr pa_features_31 except pnv always enables CI largepages bit,
40024a9d20cSNicholas Piggin * always disables copy/paste.
40124a9d20cSNicholas Piggin */
40224a9d20cSNicholas Piggin static const uint8_t pa_features_31[] = { 74, 0,
40324a9d20cSNicholas Piggin /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: CILRG|fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
40424a9d20cSNicholas Piggin /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
40524a9d20cSNicholas Piggin 0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
40624a9d20cSNicholas Piggin /* 6: DS207 */
40724a9d20cSNicholas Piggin 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
40824a9d20cSNicholas Piggin /* 16: Vector */
40924a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
41024a9d20cSNicholas Piggin /* 18: Vec. Scalar, 20: Vec. XOR */
41124a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
41224a9d20cSNicholas Piggin /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
41324a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
41424a9d20cSNicholas Piggin /* 32: LE atomic, 34: EBB + ext EBB */
41524a9d20cSNicholas Piggin 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
41624a9d20cSNicholas Piggin /* 40: Radix MMU */
41724a9d20cSNicholas Piggin 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
41824a9d20cSNicholas Piggin /* 42: PM, 44: PC RA, 46: SC vec'd */
41924a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
42024a9d20cSNicholas Piggin /* 48: SIMD, 50: QP BFP, 52: String */
42124a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
42224a9d20cSNicholas Piggin /* 54: DecFP, 56: DecI, 58: SHA */
42324a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
42424a9d20cSNicholas Piggin /* 60: NM atomic, 62: RNG */
42524a9d20cSNicholas Piggin 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
42624a9d20cSNicholas Piggin /* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */
42724a9d20cSNicholas Piggin 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */
42824a9d20cSNicholas Piggin /* 72: [P]HASHST/[P]HASHCHK */
42924a9d20cSNicholas Piggin 0x80, 0x00, /* 72 - 73 */
43024a9d20cSNicholas Piggin };
43124a9d20cSNicholas Piggin
pnv_chip_power10_dt_populate(PnvChip * chip,void * fdt)4322b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
4332b548a42SCédric Le Goater {
434c396c58aSGreg Kurz static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
4352b548a42SCédric Le Goater int i;
4362b548a42SCédric Le Goater
4373f5b45caSGreg Kurz pnv_dt_xscom(chip, fdt, 0,
4383f5b45caSGreg Kurz cpu_to_be64(PNV10_XSCOM_BASE(chip)),
439c396c58aSGreg Kurz cpu_to_be64(PNV10_XSCOM_SIZE),
440c396c58aSGreg Kurz compat, sizeof(compat));
4412b548a42SCédric Le Goater
4422b548a42SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
4432b548a42SCédric Le Goater PnvCore *pnv_core = chip->cores[i];
444ce2b8536SNicholas Piggin int offset;
4452b548a42SCédric Le Goater
446ce2b8536SNicholas Piggin offset = pnv_dt_core(chip, pnv_core, fdt);
447ce2b8536SNicholas Piggin
448ce2b8536SNicholas Piggin _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
44924a9d20cSNicholas Piggin pa_features_31, sizeof(pa_features_31))));
4502b548a42SCédric Le Goater }
4512b548a42SCédric Le Goater
4522b548a42SCédric Le Goater if (chip->ram_size) {
4532b548a42SCédric Le Goater pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
4542b548a42SCédric Le Goater }
4552661f6abSCédric Le Goater
4562661f6abSCédric Le Goater pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
4572b548a42SCédric Le Goater }
4582b548a42SCédric Le Goater
pnv_dt_rtc(ISADevice * d,void * fdt,int lpc_off)459b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
460c5ffdcaeSCédric Le Goater {
461c5ffdcaeSCédric Le Goater uint32_t io_base = d->ioport_id;
462c5ffdcaeSCédric Le Goater uint32_t io_regs[] = {
463c5ffdcaeSCédric Le Goater cpu_to_be32(1),
464c5ffdcaeSCédric Le Goater cpu_to_be32(io_base),
465c5ffdcaeSCédric Le Goater cpu_to_be32(2)
466c5ffdcaeSCédric Le Goater };
467c5ffdcaeSCédric Le Goater char *name;
468c5ffdcaeSCédric Le Goater int node;
469c5ffdcaeSCédric Le Goater
470c5ffdcaeSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
471c5ffdcaeSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name);
472c5ffdcaeSCédric Le Goater _FDT(node);
473c5ffdcaeSCédric Le Goater g_free(name);
474c5ffdcaeSCédric Le Goater
475c5ffdcaeSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
476c5ffdcaeSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
477c5ffdcaeSCédric Le Goater }
478c5ffdcaeSCédric Le Goater
pnv_dt_serial(ISADevice * d,void * fdt,int lpc_off)479b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
480cb228f5aSCédric Le Goater {
481cb228f5aSCédric Le Goater const char compatible[] = "ns16550\0pnpPNP,501";
482cb228f5aSCédric Le Goater uint32_t io_base = d->ioport_id;
483cb228f5aSCédric Le Goater uint32_t io_regs[] = {
484cb228f5aSCédric Le Goater cpu_to_be32(1),
485cb228f5aSCédric Le Goater cpu_to_be32(io_base),
486cb228f5aSCédric Le Goater cpu_to_be32(8)
487cb228f5aSCédric Le Goater };
488632fc0b3SBernhard Beschow uint32_t irq;
489cb228f5aSCédric Le Goater char *name;
490cb228f5aSCédric Le Goater int node;
491cb228f5aSCédric Le Goater
492632fc0b3SBernhard Beschow irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
493632fc0b3SBernhard Beschow
494cb228f5aSCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
495cb228f5aSCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name);
496cb228f5aSCédric Le Goater _FDT(node);
497cb228f5aSCédric Le Goater g_free(name);
498cb228f5aSCédric Le Goater
499cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
500cb228f5aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible,
501cb228f5aSCédric Le Goater sizeof(compatible))));
502cb228f5aSCédric Le Goater
503cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
504cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
505632fc0b3SBernhard Beschow _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
506cb228f5aSCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
507cb228f5aSCédric Le Goater fdt_get_phandle(fdt, lpc_off))));
508cb228f5aSCédric Le Goater
509cb228f5aSCédric Le Goater /* This is needed by Linux */
510cb228f5aSCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
511cb228f5aSCédric Le Goater }
512cb228f5aSCédric Le Goater
pnv_dt_ipmi_bt(ISADevice * d,void * fdt,int lpc_off)513b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
51404f6c8b2SCédric Le Goater {
51504f6c8b2SCédric Le Goater const char compatible[] = "bt\0ipmi-bt";
51604f6c8b2SCédric Le Goater uint32_t io_base;
51704f6c8b2SCédric Le Goater uint32_t io_regs[] = {
51804f6c8b2SCédric Le Goater cpu_to_be32(1),
51904f6c8b2SCédric Le Goater 0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
52004f6c8b2SCédric Le Goater cpu_to_be32(3)
52104f6c8b2SCédric Le Goater };
52204f6c8b2SCédric Le Goater uint32_t irq;
52304f6c8b2SCédric Le Goater char *name;
52404f6c8b2SCédric Le Goater int node;
52504f6c8b2SCédric Le Goater
52604f6c8b2SCédric Le Goater io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
52704f6c8b2SCédric Le Goater io_regs[1] = cpu_to_be32(io_base);
52804f6c8b2SCédric Le Goater
52904f6c8b2SCédric Le Goater irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
53004f6c8b2SCédric Le Goater
53104f6c8b2SCédric Le Goater name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
53204f6c8b2SCédric Le Goater node = fdt_add_subnode(fdt, lpc_off, name);
53304f6c8b2SCédric Le Goater _FDT(node);
53404f6c8b2SCédric Le Goater g_free(name);
53504f6c8b2SCédric Le Goater
5367032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
5377032d92aSCédric Le Goater _FDT((fdt_setprop(fdt, node, "compatible", compatible,
5387032d92aSCédric Le Goater sizeof(compatible))));
53904f6c8b2SCédric Le Goater
54004f6c8b2SCédric Le Goater /* Mark it as reserved to avoid Linux trying to claim it */
54104f6c8b2SCédric Le Goater _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
54204f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
54304f6c8b2SCédric Le Goater _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
54404f6c8b2SCédric Le Goater fdt_get_phandle(fdt, lpc_off))));
54504f6c8b2SCédric Le Goater }
54604f6c8b2SCédric Le Goater
547e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
548e7a3fee3SCédric Le Goater void *fdt;
549e7a3fee3SCédric Le Goater int offset;
550e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
551e7a3fee3SCédric Le Goater
pnv_dt_isa_device(DeviceState * dev,void * opaque)552b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
553e7a3fee3SCédric Le Goater {
554c5ffdcaeSCédric Le Goater ForeachPopulateArgs *args = opaque;
555c5ffdcaeSCédric Le Goater ISADevice *d = ISA_DEVICE(dev);
556c5ffdcaeSCédric Le Goater
557c5ffdcaeSCédric Le Goater if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
558b168a138SCédric Le Goater pnv_dt_rtc(d, args->fdt, args->offset);
559cb228f5aSCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
560b168a138SCédric Le Goater pnv_dt_serial(d, args->fdt, args->offset);
56104f6c8b2SCédric Le Goater } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
562b168a138SCédric Le Goater pnv_dt_ipmi_bt(d, args->fdt, args->offset);
563c5ffdcaeSCédric Le Goater } else {
564c5ffdcaeSCédric Le Goater error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
565c5ffdcaeSCédric Le Goater d->ioport_id);
566c5ffdcaeSCédric Le Goater }
567c5ffdcaeSCédric Le Goater
568e7a3fee3SCédric Le Goater return 0;
569e7a3fee3SCédric Le Goater }
570e7a3fee3SCédric Le Goater
57159b7c1c2SBalamuruhan S /*
57259b7c1c2SBalamuruhan S * The default LPC bus of a multichip system is on chip 0. It's
573bb7ab95cSCédric Le Goater * recognized by the firmware (skiboot) using a "primary" property.
574bb7ab95cSCédric Le Goater */
pnv_dt_isa(PnvMachineState * pnv,void * fdt)575bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
576bb7ab95cSCédric Le Goater {
57764d011d5SCédric Le Goater int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
578e7a3fee3SCédric Le Goater ForeachPopulateArgs args = {
579e7a3fee3SCédric Le Goater .fdt = fdt,
580bb7ab95cSCédric Le Goater .offset = isa_offset,
581e7a3fee3SCédric Le Goater };
582f47a08d1SCédric Le Goater uint32_t phandle;
583e7a3fee3SCédric Le Goater
584bb7ab95cSCédric Le Goater _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
585bb7ab95cSCédric Le Goater
586f47a08d1SCédric Le Goater phandle = qemu_fdt_alloc_phandle(fdt);
587f47a08d1SCédric Le Goater assert(phandle > 0);
588f47a08d1SCédric Le Goater _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
589f47a08d1SCédric Le Goater
59059b7c1c2SBalamuruhan S /*
59159b7c1c2SBalamuruhan S * ISA devices are not necessarily parented to the ISA bus so we
59259b7c1c2SBalamuruhan S * can not use object_child_foreach()
59359b7c1c2SBalamuruhan S */
594bb7ab95cSCédric Le Goater qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
595bb7ab95cSCédric Le Goater &args);
596e7a3fee3SCédric Le Goater }
597e7a3fee3SCédric Le Goater
pnv_dt_power_mgt(PnvMachineState * pnv,void * fdt)5987a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
599e5694793SCédric Le Goater {
600e5694793SCédric Le Goater int off;
601e5694793SCédric Le Goater
602e5694793SCédric Le Goater off = fdt_add_subnode(fdt, 0, "ibm,opal");
603e5694793SCédric Le Goater off = fdt_add_subnode(fdt, off, "power-mgt");
604e5694793SCédric Le Goater
605e5694793SCédric Le Goater _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
606e5694793SCédric Le Goater }
607e5694793SCédric Le Goater
pnv_dt_create(MachineState * machine)608b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
6099e933f4aSBenjamin Herrenschmidt {
610d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
611b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine);
6129e933f4aSBenjamin Herrenschmidt void *fdt;
6139e933f4aSBenjamin Herrenschmidt char *buf;
6149e933f4aSBenjamin Herrenschmidt int off;
615e997040eSCédric Le Goater int i;
6169e933f4aSBenjamin Herrenschmidt
6179e933f4aSBenjamin Herrenschmidt fdt = g_malloc0(FDT_MAX_SIZE);
6189e933f4aSBenjamin Herrenschmidt _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
6199e933f4aSBenjamin Herrenschmidt
620ccb099b3SCédric Le Goater /* /qemu node */
621ccb099b3SCédric Le Goater _FDT((fdt_add_subnode(fdt, 0, "qemu")));
622ccb099b3SCédric Le Goater
6239e933f4aSBenjamin Herrenschmidt /* Root node */
6249e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
6259e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
6269e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "model",
6279e933f4aSBenjamin Herrenschmidt "IBM PowerNV (emulated by qemu)")));
628d76f2da7SGreg Kurz _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
6299e933f4aSBenjamin Herrenschmidt
6309e933f4aSBenjamin Herrenschmidt buf = qemu_uuid_unparse_strdup(&qemu_uuid);
6319e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
6329e933f4aSBenjamin Herrenschmidt if (qemu_uuid_set) {
633bbfbbff5SDaniel Henrique Barboza _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
6349e933f4aSBenjamin Herrenschmidt }
6359e933f4aSBenjamin Herrenschmidt g_free(buf);
6369e933f4aSBenjamin Herrenschmidt
6379e933f4aSBenjamin Herrenschmidt off = fdt_add_subnode(fdt, 0, "chosen");
6389e933f4aSBenjamin Herrenschmidt if (machine->kernel_cmdline) {
6399e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop_string(fdt, off, "bootargs",
6409e933f4aSBenjamin Herrenschmidt machine->kernel_cmdline)));
6419e933f4aSBenjamin Herrenschmidt }
6429e933f4aSBenjamin Herrenschmidt
6439e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size) {
6449e933f4aSBenjamin Herrenschmidt uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
6459e933f4aSBenjamin Herrenschmidt uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
6469e933f4aSBenjamin Herrenschmidt
6479e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
6489e933f4aSBenjamin Herrenschmidt &start_prop, sizeof(start_prop))));
6499e933f4aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
6509e933f4aSBenjamin Herrenschmidt &end_prop, sizeof(end_prop))));
6519e933f4aSBenjamin Herrenschmidt }
6529e933f4aSBenjamin Herrenschmidt
653e997040eSCédric Le Goater /* Populate device tree for each chip */
654e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
655eb859a27SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
656e997040eSCédric Le Goater }
657e7a3fee3SCédric Le Goater
658e7a3fee3SCédric Le Goater /* Populate ISA devices on chip 0 */
659bb7ab95cSCédric Le Goater pnv_dt_isa(pnv, fdt);
660aeaef83dSCédric Le Goater
661aeaef83dSCédric Le Goater if (pnv->bmc) {
662b168a138SCédric Le Goater pnv_dt_bmc_sensors(pnv->bmc, fdt);
663aeaef83dSCédric Le Goater }
664aeaef83dSCédric Le Goater
6657a90c6a1SGreg Kurz /* Create an extra node for power management on machines that support it */
6667a90c6a1SGreg Kurz if (pmc->dt_power_mgt) {
6677a90c6a1SGreg Kurz pmc->dt_power_mgt(pnv, fdt);
668e5694793SCédric Le Goater }
669e5694793SCédric Le Goater
6709e933f4aSBenjamin Herrenschmidt return fdt;
6719e933f4aSBenjamin Herrenschmidt }
6729e933f4aSBenjamin Herrenschmidt
pnv_powerdown_notify(Notifier * n,void * opaque)673bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
674bce0b691SCédric Le Goater {
6758f06e370SCédric Le Goater PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
676bce0b691SCédric Le Goater
677bce0b691SCédric Le Goater if (pnv->bmc) {
678bce0b691SCédric Le Goater pnv_bmc_powerdown(pnv->bmc);
679bce0b691SCédric Le Goater }
680bce0b691SCédric Le Goater }
681bce0b691SCédric Le Goater
pnv_reset(MachineState * machine,ShutdownCause reason)6827966d70fSJason A. Donenfeld static void pnv_reset(MachineState *machine, ShutdownCause reason)
6839e933f4aSBenjamin Herrenschmidt {
68425f3170bSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine);
68525f3170bSCédric Le Goater IPMIBmc *bmc;
6869e933f4aSBenjamin Herrenschmidt void *fdt;
6879e933f4aSBenjamin Herrenschmidt
6887966d70fSJason A. Donenfeld qemu_devices_reset(reason);
6899e933f4aSBenjamin Herrenschmidt
69025f3170bSCédric Le Goater /*
69125f3170bSCédric Le Goater * The machine should provide by default an internal BMC simulator.
69225f3170bSCédric Le Goater * If not, try to use the BMC device that was provided on the command
69325f3170bSCédric Le Goater * line.
69425f3170bSCédric Le Goater */
69525f3170bSCédric Le Goater bmc = pnv_bmc_find(&error_fatal);
69625f3170bSCédric Le Goater if (!pnv->bmc) {
69725f3170bSCédric Le Goater if (!bmc) {
69838d2448aSGreg Kurz if (!qtest_enabled()) {
69925f3170bSCédric Le Goater warn_report("machine has no BMC device. Use '-device "
70025f3170bSCédric Le Goater "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
70125f3170bSCédric Le Goater "to define one");
70238d2448aSGreg Kurz }
70325f3170bSCédric Le Goater } else {
70425f3170bSCédric Le Goater pnv_bmc_set_pnor(bmc, pnv->pnor);
70525f3170bSCédric Le Goater pnv->bmc = bmc;
70625f3170bSCédric Le Goater }
70725f3170bSCédric Le Goater }
70825f3170bSCédric Le Goater
709b168a138SCédric Le Goater fdt = pnv_dt_create(machine);
7109e933f4aSBenjamin Herrenschmidt
7119e933f4aSBenjamin Herrenschmidt /* Pack resulting tree */
7129e933f4aSBenjamin Herrenschmidt _FDT((fdt_pack(fdt)));
7139e933f4aSBenjamin Herrenschmidt
7148d409261SCédric Le Goater qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
7159e933f4aSBenjamin Herrenschmidt cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
716b2fb7a43SPan Nengyuan
717adb77996SDaniel Henrique Barboza /*
718adb77996SDaniel Henrique Barboza * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
719adb77996SDaniel Henrique Barboza * the existing machine->fdt to avoid leaking it during
720adb77996SDaniel Henrique Barboza * a reset.
721adb77996SDaniel Henrique Barboza */
722adb77996SDaniel Henrique Barboza g_free(machine->fdt);
723adb77996SDaniel Henrique Barboza machine->fdt = fdt;
7249e933f4aSBenjamin Herrenschmidt }
7259e933f4aSBenjamin Herrenschmidt
pnv_chip_power8_isa_create(PnvChip * chip,Error ** errp)72604026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
7273495b6b6SCédric Le Goater {
72877864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
729c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
730c05aa140SCédric Le Goater
731c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
73277864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, true, errp);
73304026890SCédric Le Goater }
7343495b6b6SCédric Le Goater
pnv_chip_power8nvl_isa_create(PnvChip * chip,Error ** errp)73504026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
73604026890SCédric Le Goater {
73777864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
738c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
739c05aa140SCédric Le Goater
740c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
74177864267SCédric Le Goater return pnv_lpc_isa_create(&chip8->lpc, false, errp);
74204026890SCédric Le Goater }
7433495b6b6SCédric Le Goater
pnv_chip_power9_isa_create(PnvChip * chip,Error ** errp)74404026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
74504026890SCédric Le Goater {
74615376c66SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip);
747c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
748c05aa140SCédric Le Goater
749c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq);
75015376c66SCédric Le Goater return pnv_lpc_isa_create(&chip9->lpc, false, errp);
75104026890SCédric Le Goater }
7523495b6b6SCédric Le Goater
pnv_chip_power10_isa_create(PnvChip * chip,Error ** errp)7532b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
7542b548a42SCédric Le Goater {
7552661f6abSCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
756c05aa140SCédric Le Goater qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
757c05aa140SCédric Le Goater
758c05aa140SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq);
7592661f6abSCédric Le Goater return pnv_lpc_isa_create(&chip10->lpc, false, errp);
7602b548a42SCédric Le Goater }
7612b548a42SCédric Le Goater
pnv_isa_create(PnvChip * chip,Error ** errp)76204026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
76304026890SCédric Le Goater {
76404026890SCédric Le Goater return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
7653495b6b6SCédric Le Goater }
7663495b6b6SCédric Le Goater
pnv_chip_power8_pic_print_info(PnvChip * chip,Monitor * mon)767d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
768d8e4aad5SCédric Le Goater {
769d8e4aad5SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
7708a69bca7SDaniel Henrique Barboza int i;
771d8e4aad5SCédric Le Goater
772d8e4aad5SCédric Le Goater ics_pic_print_info(&chip8->psi.ics, mon);
7738a69bca7SDaniel Henrique Barboza
7748a69bca7SDaniel Henrique Barboza for (i = 0; i < chip8->num_phbs; i++) {
7750d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i];
7761f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
7778a69bca7SDaniel Henrique Barboza
7788a69bca7SDaniel Henrique Barboza pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
7798a69bca7SDaniel Henrique Barboza ics_pic_print_info(&phb3->lsis, mon);
7808a69bca7SDaniel Henrique Barboza }
781d8e4aad5SCédric Le Goater }
782d8e4aad5SCédric Le Goater
pnv_chip_power9_pic_print_info_child(Object * child,void * opaque)7830e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
7840e6232bcSCédric Le Goater {
7850e6232bcSCédric Le Goater Monitor *mon = opaque;
786210aacb3SDaniel Henrique Barboza PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
7870e6232bcSCédric Le Goater
788210aacb3SDaniel Henrique Barboza if (!phb) {
789210aacb3SDaniel Henrique Barboza return 0;
7900e6232bcSCédric Le Goater }
791210aacb3SDaniel Henrique Barboza
792210aacb3SDaniel Henrique Barboza pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon);
793210aacb3SDaniel Henrique Barboza
7940e6232bcSCédric Le Goater return 0;
7950e6232bcSCédric Le Goater }
7960e6232bcSCédric Le Goater
pnv_chip_power9_pic_print_info(PnvChip * chip,Monitor * mon)797d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
798d8e4aad5SCédric Le Goater {
799d8e4aad5SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip);
800d8e4aad5SCédric Le Goater
801d8e4aad5SCédric Le Goater pnv_xive_pic_print_info(&chip9->xive, mon);
802c38536bcSCédric Le Goater pnv_psi_pic_print_info(&chip9->psi, mon);
8034f9924c4SBenjamin Herrenschmidt
8040e6232bcSCédric Le Goater object_child_foreach_recursive(OBJECT(chip),
8050e6232bcSCédric Le Goater pnv_chip_power9_pic_print_info_child, mon);
806d8e4aad5SCédric Le Goater }
807d8e4aad5SCédric Le Goater
pnv_chip_power8_xscom_core_base(PnvChip * chip,uint32_t core_id)808c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
809c4b2c40cSGreg Kurz uint32_t core_id)
810c4b2c40cSGreg Kurz {
811c4b2c40cSGreg Kurz return PNV_XSCOM_EX_BASE(core_id);
812c4b2c40cSGreg Kurz }
813c4b2c40cSGreg Kurz
pnv_chip_power9_xscom_core_base(PnvChip * chip,uint32_t core_id)814c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
815c4b2c40cSGreg Kurz uint32_t core_id)
816c4b2c40cSGreg Kurz {
817c4b2c40cSGreg Kurz return PNV9_XSCOM_EC_BASE(core_id);
818c4b2c40cSGreg Kurz }
819c4b2c40cSGreg Kurz
pnv_chip_power10_xscom_core_base(PnvChip * chip,uint32_t core_id)820c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
821c4b2c40cSGreg Kurz uint32_t core_id)
822c4b2c40cSGreg Kurz {
823c4b2c40cSGreg Kurz return PNV10_XSCOM_EC_BASE(core_id);
824c4b2c40cSGreg Kurz }
825c4b2c40cSGreg Kurz
pnv_match_cpu(const char * default_type,const char * cpu_type)826f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
827f30c843cSCédric Le Goater {
828f30c843cSCédric Le Goater PowerPCCPUClass *ppc_default =
829f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(default_type));
830f30c843cSCédric Le Goater PowerPCCPUClass *ppc =
831f30c843cSCédric Le Goater POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
832f30c843cSCédric Le Goater
83321d3a78eSNicholas Piggin return ppc_default->pvr_match(ppc_default, ppc->pvr, false);
834f30c843cSCédric Le Goater }
835f30c843cSCédric Le Goater
pnv_ipmi_bt_init(ISABus * bus,IPMIBmc * bmc,uint32_t irq)836e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
837e2392d43SCédric Le Goater {
838c23e0561SMarkus Armbruster ISADevice *dev = isa_new("isa-ipmi-bt");
839e2392d43SCédric Le Goater
8405325cc34SMarkus Armbruster object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
8415325cc34SMarkus Armbruster object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
842c23e0561SMarkus Armbruster isa_realize_and_unref(dev, bus, &error_fatal);
843e2392d43SCédric Le Goater }
844e2392d43SCédric Le Goater
pnv_chip_power10_pic_print_info(PnvChip * chip,Monitor * mon)8452b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
8462b548a42SCédric Le Goater {
8478b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
8488b50ce85SCédric Le Goater
849da71b7e3SCédric Le Goater pnv_xive2_pic_print_info(&chip10->xive, mon);
8508b50ce85SCédric Le Goater pnv_psi_pic_print_info(&chip10->psi, mon);
851623575e1SCédric Le Goater
852623575e1SCédric Le Goater object_child_foreach_recursive(OBJECT(chip),
853623575e1SCédric Le Goater pnv_chip_power9_pic_print_info_child, mon);
8542b548a42SCédric Le Goater }
8552b548a42SCédric Le Goater
856458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
pnv_chip_get_ram_size(PnvMachineState * pnv,int chip_id)857458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
858458c6f01SCédric Le Goater {
859458c6f01SCédric Le Goater MachineState *machine = MACHINE(pnv);
860458c6f01SCédric Le Goater uint64_t ram_per_chip;
861458c6f01SCédric Le Goater
862458c6f01SCédric Le Goater assert(machine->ram_size >= 1 * GiB);
863458c6f01SCédric Le Goater
864458c6f01SCédric Le Goater ram_per_chip = machine->ram_size / pnv->num_chips;
865458c6f01SCédric Le Goater if (ram_per_chip >= 1 * GiB) {
866458c6f01SCédric Le Goater return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
867458c6f01SCédric Le Goater }
868458c6f01SCédric Le Goater
869f640afecSCédric Le Goater assert(pnv->num_chips > 1);
870f640afecSCédric Le Goater
871458c6f01SCédric Le Goater ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
872458c6f01SCédric Le Goater return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
873458c6f01SCédric Le Goater }
874458c6f01SCédric Le Goater
pnv_init(MachineState * machine)875b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
8769e933f4aSBenjamin Herrenschmidt {
877cd7b9498SPaolo Bonzini const char *bios_name = machine->firmware ?: FW_FILE_NAME;
878b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(machine);
879f30c843cSCédric Le Goater MachineClass *mc = MACHINE_GET_CLASS(machine);
88033467ecbSGlenn Miles PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
8819e933f4aSBenjamin Herrenschmidt char *fw_filename;
8829e933f4aSBenjamin Herrenschmidt long fw_size;
883458c6f01SCédric Le Goater uint64_t chip_ram_start = 0;
884e997040eSCédric Le Goater int i;
885e997040eSCédric Le Goater char *chip_typename;
88635dde576SCédric Le Goater DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
88735dde576SCédric Le Goater DeviceState *dev;
8889e933f4aSBenjamin Herrenschmidt
889ebe6c3faSDaniel Henrique Barboza if (kvm_enabled()) {
890518f72ecSCédric Le Goater error_report("machine %s does not support the KVM accelerator",
891518f72ecSCédric Le Goater mc->name);
892ebe6c3faSDaniel Henrique Barboza exit(EXIT_FAILURE);
893ebe6c3faSDaniel Henrique Barboza }
894ebe6c3faSDaniel Henrique Barboza
8959e933f4aSBenjamin Herrenschmidt /* allocate RAM */
896dd7ef911SCédric Le Goater if (machine->ram_size < mc->default_ram_size) {
897dd7ef911SCédric Le Goater char *sz = size_to_str(mc->default_ram_size);
898dd7ef911SCédric Le Goater error_report("Invalid RAM size, should be bigger than %s", sz);
899dd7ef911SCédric Le Goater g_free(sz);
900dd7ef911SCédric Le Goater exit(EXIT_FAILURE);
9019e933f4aSBenjamin Herrenschmidt }
902173a36d8SIgor Mammedov memory_region_add_subregion(get_system_memory(), 0, machine->ram);
9039e933f4aSBenjamin Herrenschmidt
90435dde576SCédric Le Goater /*
90535dde576SCédric Le Goater * Create our simple PNOR device
90635dde576SCédric Le Goater */
9073e80f690SMarkus Armbruster dev = qdev_new(TYPE_PNV_PNOR);
90835dde576SCédric Le Goater if (pnor) {
909934df912SMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
91035dde576SCédric Le Goater }
9113c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
91235dde576SCédric Le Goater pnv->pnor = PNV_PNOR(dev);
91335dde576SCédric Le Goater
9149e933f4aSBenjamin Herrenschmidt /* load skiboot firmware */
9159e933f4aSBenjamin Herrenschmidt fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
91615fcedb2SCédric Le Goater if (!fw_filename) {
91715fcedb2SCédric Le Goater error_report("Could not find OPAL firmware '%s'", bios_name);
91815fcedb2SCédric Le Goater exit(1);
91915fcedb2SCédric Le Goater }
9209e933f4aSBenjamin Herrenschmidt
92108c3f3a7SCédric Le Goater fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
9229e933f4aSBenjamin Herrenschmidt if (fw_size < 0) {
92315fcedb2SCédric Le Goater error_report("Could not load OPAL firmware '%s'", fw_filename);
9249e933f4aSBenjamin Herrenschmidt exit(1);
9259e933f4aSBenjamin Herrenschmidt }
9269e933f4aSBenjamin Herrenschmidt g_free(fw_filename);
9279e933f4aSBenjamin Herrenschmidt
9289e933f4aSBenjamin Herrenschmidt /* load kernel */
9299e933f4aSBenjamin Herrenschmidt if (machine->kernel_filename) {
9309e933f4aSBenjamin Herrenschmidt long kernel_size;
9319e933f4aSBenjamin Herrenschmidt
9329e933f4aSBenjamin Herrenschmidt kernel_size = load_image_targphys(machine->kernel_filename,
933b45b56baSMurilo Opsfelder Araujo KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
9349e933f4aSBenjamin Herrenschmidt if (kernel_size < 0) {
935802fc7abSThomas Huth error_report("Could not load kernel '%s'",
9369e933f4aSBenjamin Herrenschmidt machine->kernel_filename);
9379e933f4aSBenjamin Herrenschmidt exit(1);
9389e933f4aSBenjamin Herrenschmidt }
9399e933f4aSBenjamin Herrenschmidt }
9409e933f4aSBenjamin Herrenschmidt
9419e933f4aSBenjamin Herrenschmidt /* load initrd */
9429e933f4aSBenjamin Herrenschmidt if (machine->initrd_filename) {
9439e933f4aSBenjamin Herrenschmidt pnv->initrd_base = INITRD_LOAD_ADDR;
9449e933f4aSBenjamin Herrenschmidt pnv->initrd_size = load_image_targphys(machine->initrd_filename,
945584ea7e7SMurilo Opsfelder Araujo pnv->initrd_base, INITRD_MAX_SIZE);
9469e933f4aSBenjamin Herrenschmidt if (pnv->initrd_size < 0) {
947802fc7abSThomas Huth error_report("Could not load initial ram disk '%s'",
9489e933f4aSBenjamin Herrenschmidt machine->initrd_filename);
9499e933f4aSBenjamin Herrenschmidt exit(1);
9509e933f4aSBenjamin Herrenschmidt }
9519e933f4aSBenjamin Herrenschmidt }
952e997040eSCédric Le Goater
9534f9924c4SBenjamin Herrenschmidt /* MSIs are supported on this platform */
9544f9924c4SBenjamin Herrenschmidt msi_nonbroken = true;
9554f9924c4SBenjamin Herrenschmidt
956f30c843cSCédric Le Goater /*
957f30c843cSCédric Le Goater * Check compatibility of the specified CPU with the machine
958f30c843cSCédric Le Goater * default.
959f30c843cSCédric Le Goater */
960f30c843cSCédric Le Goater if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
961f30c843cSCédric Le Goater error_report("invalid CPU model '%s' for %s machine",
962f30c843cSCédric Le Goater machine->cpu_type, mc->name);
963f30c843cSCédric Le Goater exit(1);
964f30c843cSCédric Le Goater }
965f30c843cSCédric Le Goater
966e997040eSCédric Le Goater /* Create the processor chips */
9674a12c699SIgor Mammedov i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
9687fd544d8SIgor Mammedov chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
9694a12c699SIgor Mammedov i, machine->cpu_type);
970e997040eSCédric Le Goater if (!object_class_by_name(chip_typename)) {
971f30c843cSCédric Le Goater error_report("invalid chip model '%.*s' for %s machine",
972f30c843cSCédric Le Goater i, machine->cpu_type, mc->name);
973e997040eSCédric Le Goater exit(1);
974e997040eSCédric Le Goater }
975e997040eSCédric Le Goater
976e44acde2SGreg Kurz pnv->num_chips =
977e44acde2SGreg Kurz machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
978934676c7SNicholas Piggin
979934676c7SNicholas Piggin if (machine->smp.threads > 8) {
980934676c7SNicholas Piggin error_report("Cannot support more than 8 threads/core "
981934676c7SNicholas Piggin "on a powernv machine");
982934676c7SNicholas Piggin exit(1);
983934676c7SNicholas Piggin }
984934676c7SNicholas Piggin if (!is_power_of_2(machine->smp.threads)) {
985934676c7SNicholas Piggin error_report("Cannot support %d threads/core on a powernv"
986934676c7SNicholas Piggin "machine because it must be a power of 2",
987934676c7SNicholas Piggin machine->smp.threads);
988934676c7SNicholas Piggin exit(1);
989934676c7SNicholas Piggin }
990e44acde2SGreg Kurz /*
991e44acde2SGreg Kurz * TODO: should we decide on how many chips we can create based
992e44acde2SGreg Kurz * on #cores and Venice vs. Murano vs. Naples chip type etc...,
993e44acde2SGreg Kurz */
994ab17a3feSCédric Le Goater if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
995e44acde2SGreg Kurz error_report("invalid number of chips: '%d'", pnv->num_chips);
996ab17a3feSCédric Le Goater error_printf(
997ab17a3feSCédric Le Goater "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
998e44acde2SGreg Kurz exit(1);
999e44acde2SGreg Kurz }
1000e44acde2SGreg Kurz
1001e997040eSCédric Le Goater pnv->chips = g_new0(PnvChip *, pnv->num_chips);
1002e997040eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
1003e997040eSCédric Le Goater char chip_name[32];
1004df707969SMarkus Armbruster Object *chip = OBJECT(qdev_new(chip_typename));
10050e5e9ff4SCédric Le Goater uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, i);
1006e997040eSCédric Le Goater
1007e997040eSCédric Le Goater pnv->chips[i] = PNV_CHIP(chip);
1008e997040eSCédric Le Goater
1009458c6f01SCédric Le Goater /* Distribute RAM among the chips */
1010458c6f01SCédric Le Goater object_property_set_int(chip, "ram-start", chip_ram_start,
1011e997040eSCédric Le Goater &error_fatal);
1012458c6f01SCédric Le Goater object_property_set_int(chip, "ram-size", chip_ram_size,
1013458c6f01SCédric Le Goater &error_fatal);
1014458c6f01SCédric Le Goater chip_ram_start += chip_ram_size;
1015e997040eSCédric Le Goater
10160e5e9ff4SCédric Le Goater snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
1017d2623129SMarkus Armbruster object_property_add_child(OBJECT(pnv), chip_name, chip);
10180e5e9ff4SCédric Le Goater object_property_set_int(chip, "chip-id", i, &error_fatal);
10195325cc34SMarkus Armbruster object_property_set_int(chip, "nr-cores", machine->smp.cores,
10205325cc34SMarkus Armbruster &error_fatal);
10215325cc34SMarkus Armbruster object_property_set_int(chip, "nr-threads", machine->smp.threads,
10225325cc34SMarkus Armbruster &error_fatal);
1023245cdb7fSCédric Le Goater /*
1024245cdb7fSCédric Le Goater * The POWER8 machine use the XICS interrupt interface.
1025245cdb7fSCédric Le Goater * Propagate the XICS fabric to the chip and its controllers.
1026245cdb7fSCédric Le Goater */
1027245cdb7fSCédric Le Goater if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
10285325cc34SMarkus Armbruster object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
1029245cdb7fSCédric Le Goater }
1030d1214b81SGreg Kurz if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
10315325cc34SMarkus Armbruster object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
1032d1214b81SGreg Kurz &error_abort);
1033d1214b81SGreg Kurz }
10343c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
1035e997040eSCédric Le Goater }
1036e997040eSCédric Le Goater g_free(chip_typename);
10373495b6b6SCédric Le Goater
10383495b6b6SCédric Le Goater /* Instantiate ISA bus on chip 0 */
103904026890SCédric Le Goater pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
10403495b6b6SCédric Le Goater
10413495b6b6SCédric Le Goater /* Create serial port */
1042def337ffSPeter Maydell serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
10433495b6b6SCédric Le Goater
10443495b6b6SCédric Le Goater /* Create an RTC ISA device too */
10456c646a11SPhilippe Mathieu-Daudé mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
1046bce0b691SCédric Le Goater
104725f3170bSCédric Le Goater /*
104825f3170bSCédric Le Goater * Create the machine BMC simulator and the IPMI BT device for
104925f3170bSCédric Le Goater * communication with the BMC
105025f3170bSCédric Le Goater */
105125f3170bSCédric Le Goater if (defaults_enabled()) {
105225f3170bSCédric Le Goater pnv->bmc = pnv_bmc_create(pnv->pnor);
1053e2392d43SCédric Le Goater pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
105425f3170bSCédric Le Goater }
1055e2392d43SCédric Le Goater
105659b7c1c2SBalamuruhan S /*
1057032c226bSCédric Le Goater * The PNOR is mapped on the LPC FW address space by the BMC.
1058032c226bSCédric Le Goater * Since we can not reach the remote BMC machine with LPC memops,
1059032c226bSCédric Le Goater * map it always for now.
1060032c226bSCédric Le Goater */
1061032c226bSCédric Le Goater memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
1062032c226bSCédric Le Goater &pnv->pnor->mmio);
1063032c226bSCédric Le Goater
1064032c226bSCédric Le Goater /*
106559b7c1c2SBalamuruhan S * OpenPOWER systems use a IPMI SEL Event message to notify the
106659b7c1c2SBalamuruhan S * host to powerdown
106759b7c1c2SBalamuruhan S */
1068bce0b691SCédric Le Goater pnv->powerdown_notifier.notify = pnv_powerdown_notify;
1069bce0b691SCédric Le Goater qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
107033467ecbSGlenn Miles
107133467ecbSGlenn Miles /*
107233467ecbSGlenn Miles * Create/Connect any machine-specific I2C devices
107333467ecbSGlenn Miles */
107433467ecbSGlenn Miles if (pmc->i2c_init) {
107533467ecbSGlenn Miles pmc->i2c_init(pnv);
107633467ecbSGlenn Miles }
1077e997040eSCédric Le Goater }
1078e997040eSCédric Le Goater
1079631adaffSCédric Le Goater /*
1080631adaffSCédric Le Goater * 0:21 Reserved - Read as zeros
1081631adaffSCédric Le Goater * 22:24 Chip ID
1082631adaffSCédric Le Goater * 25:28 Core number
1083631adaffSCédric Le Goater * 29:31 Thread ID
1084631adaffSCédric Le Goater */
pnv_chip_pir_p8(PnvChip * chip,uint32_t core_id,uint32_t thread_id)10859940412aSCaleb Schlossin static uint32_t pnv_chip_pir_p8(PnvChip *chip, uint32_t core_id,
10869940412aSCaleb Schlossin uint32_t thread_id)
1087631adaffSCédric Le Goater {
10889940412aSCaleb Schlossin return (chip->chip_id << 7) | (core_id << 3) | thread_id;
1089631adaffSCédric Le Goater }
1090631adaffSCédric Le Goater
pnv_chip_power8_intc_create(PnvChip * chip,PowerPCCPU * cpu,Error ** errp)10918fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1092d35aefa9SCédric Le Goater Error **errp)
1093d35aefa9SCédric Le Goater {
1094245cdb7fSCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(chip);
10958fa1f4efSCédric Le Goater Error *local_err = NULL;
10968fa1f4efSCédric Le Goater Object *obj;
10978907fc25SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10988fa1f4efSCédric Le Goater
1099245cdb7fSCédric Le Goater obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
11008fa1f4efSCédric Le Goater if (local_err) {
11018fa1f4efSCédric Le Goater error_propagate(errp, local_err);
11028fa1f4efSCédric Le Goater return;
11038fa1f4efSCédric Le Goater }
11048fa1f4efSCédric Le Goater
1105956b8f46SCédric Le Goater pnv_cpu->intc = obj;
1106d35aefa9SCédric Le Goater }
1107d35aefa9SCédric Le Goater
11080990ce6aSGreg Kurz
pnv_chip_power8_intc_reset(PnvChip * chip,PowerPCCPU * cpu)1109d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1110d49e8a9bSCédric Le Goater {
1111d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1112d49e8a9bSCédric Le Goater
1113d49e8a9bSCédric Le Goater icp_reset(ICP(pnv_cpu->intc));
1114d49e8a9bSCédric Le Goater }
1115d49e8a9bSCédric Le Goater
pnv_chip_power8_intc_destroy(PnvChip * chip,PowerPCCPU * cpu)11160990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11170990ce6aSGreg Kurz {
11180990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11190990ce6aSGreg Kurz
11200990ce6aSGreg Kurz icp_destroy(ICP(pnv_cpu->intc));
11210990ce6aSGreg Kurz pnv_cpu->intc = NULL;
11220990ce6aSGreg Kurz }
11230990ce6aSGreg Kurz
pnv_chip_power8_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,Monitor * mon)112485913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
112585913070SGreg Kurz Monitor *mon)
112685913070SGreg Kurz {
112785913070SGreg Kurz icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
112885913070SGreg Kurz }
112985913070SGreg Kurz
1130631adaffSCédric Le Goater /*
1131631adaffSCédric Le Goater * 0:48 Reserved - Read as zeroes
1132631adaffSCédric Le Goater * 49:52 Node ID
1133631adaffSCédric Le Goater * 53:55 Chip ID
1134631adaffSCédric Le Goater * 56 Reserved - Read as zero
1135631adaffSCédric Le Goater * 57:61 Core number
1136631adaffSCédric Le Goater * 62:63 Thread ID
1137631adaffSCédric Le Goater *
1138631adaffSCédric Le Goater * We only care about the lower bits. uint32_t is fine for the moment.
1139631adaffSCédric Le Goater */
pnv_chip_pir_p9(PnvChip * chip,uint32_t core_id,uint32_t thread_id)11409940412aSCaleb Schlossin static uint32_t pnv_chip_pir_p9(PnvChip *chip, uint32_t core_id,
11419940412aSCaleb Schlossin uint32_t thread_id)
1142631adaffSCédric Le Goater {
11439940412aSCaleb Schlossin if (chip->nr_threads == 8) {
11449940412aSCaleb Schlossin return (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) |
11459940412aSCaleb Schlossin (thread_id >> 1);
11469940412aSCaleb Schlossin } else {
11479940412aSCaleb Schlossin return (chip->chip_id << 8) | (core_id << 2) | thread_id;
11489940412aSCaleb Schlossin }
1149631adaffSCédric Le Goater }
1150631adaffSCédric Le Goater
11519940412aSCaleb Schlossin /*
11529940412aSCaleb Schlossin * 0:48 Reserved - Read as zeroes
11539940412aSCaleb Schlossin * 49:52 Node ID
11549940412aSCaleb Schlossin * 53:55 Chip ID
11559940412aSCaleb Schlossin * 56 Reserved - Read as zero
11569940412aSCaleb Schlossin * 57:59 Quad ID
11579940412aSCaleb Schlossin * 60 Core Chiplet Pair ID
11589940412aSCaleb Schlossin * 61:63 Thread/Core Chiplet ID t0-t2
11599940412aSCaleb Schlossin *
11609940412aSCaleb Schlossin * We only care about the lower bits. uint32_t is fine for the moment.
11619940412aSCaleb Schlossin */
pnv_chip_pir_p10(PnvChip * chip,uint32_t core_id,uint32_t thread_id)11629940412aSCaleb Schlossin static uint32_t pnv_chip_pir_p10(PnvChip *chip, uint32_t core_id,
11639940412aSCaleb Schlossin uint32_t thread_id)
11642b548a42SCédric Le Goater {
11659940412aSCaleb Schlossin if (chip->nr_threads == 8) {
11669940412aSCaleb Schlossin return (chip->chip_id << 8) | ((core_id / 4) << 4) |
11679940412aSCaleb Schlossin ((core_id % 2) << 3) | thread_id;
11689940412aSCaleb Schlossin } else {
11699940412aSCaleb Schlossin return (chip->chip_id << 8) | (core_id << 2) | thread_id;
11709940412aSCaleb Schlossin }
11712b548a42SCédric Le Goater }
11722b548a42SCédric Le Goater
pnv_chip_power9_intc_create(PnvChip * chip,PowerPCCPU * cpu,Error ** errp)11738fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1174d35aefa9SCédric Le Goater Error **errp)
1175d35aefa9SCédric Le Goater {
11762dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(chip);
11772dfa91a2SCédric Le Goater Error *local_err = NULL;
11782dfa91a2SCédric Le Goater Object *obj;
11792dfa91a2SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11802dfa91a2SCédric Le Goater
11812dfa91a2SCédric Le Goater /*
11822dfa91a2SCédric Le Goater * The core creates its interrupt presenter but the XIVE interrupt
11832dfa91a2SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's
11842dfa91a2SCédric Le Goater * only used at runtime.
11852dfa91a2SCédric Le Goater */
118647950946SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
118747950946SCédric Le Goater &local_err);
11882dfa91a2SCédric Le Goater if (local_err) {
11892dfa91a2SCédric Le Goater error_propagate(errp, local_err);
11908fa1f4efSCédric Le Goater return;
1191d35aefa9SCédric Le Goater }
1192d35aefa9SCédric Le Goater
11932dfa91a2SCédric Le Goater pnv_cpu->intc = obj;
11942dfa91a2SCédric Le Goater }
11952dfa91a2SCédric Le Goater
pnv_chip_power9_intc_reset(PnvChip * chip,PowerPCCPU * cpu)1196d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1197d49e8a9bSCédric Le Goater {
1198d49e8a9bSCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1199d49e8a9bSCédric Le Goater
1200d49e8a9bSCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1201d49e8a9bSCédric Le Goater }
1202d49e8a9bSCédric Le Goater
pnv_chip_power9_intc_destroy(PnvChip * chip,PowerPCCPU * cpu)12030990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
12040990ce6aSGreg Kurz {
12050990ce6aSGreg Kurz PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
12060990ce6aSGreg Kurz
12070990ce6aSGreg Kurz xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
12080990ce6aSGreg Kurz pnv_cpu->intc = NULL;
12090990ce6aSGreg Kurz }
12100990ce6aSGreg Kurz
pnv_chip_power9_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,Monitor * mon)121185913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
121285913070SGreg Kurz Monitor *mon)
121385913070SGreg Kurz {
121485913070SGreg Kurz xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
121585913070SGreg Kurz }
121685913070SGreg Kurz
pnv_chip_power10_intc_create(PnvChip * chip,PowerPCCPU * cpu,Error ** errp)12172b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
12182b548a42SCédric Le Goater Error **errp)
12192b548a42SCédric Le Goater {
1220da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
1221da71b7e3SCédric Le Goater Error *local_err = NULL;
1222da71b7e3SCédric Le Goater Object *obj;
12232b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
12242b548a42SCédric Le Goater
1225da71b7e3SCédric Le Goater /*
1226da71b7e3SCédric Le Goater * The core creates its interrupt presenter but the XIVE2 interrupt
1227da71b7e3SCédric Le Goater * controller object is initialized afterwards. Hopefully, it's
1228da71b7e3SCédric Le Goater * only used at runtime.
1229da71b7e3SCédric Le Goater */
1230da71b7e3SCédric Le Goater obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1231da71b7e3SCédric Le Goater &local_err);
1232da71b7e3SCédric Le Goater if (local_err) {
1233da71b7e3SCédric Le Goater error_propagate(errp, local_err);
1234da71b7e3SCédric Le Goater return;
1235da71b7e3SCédric Le Goater }
1236da71b7e3SCédric Le Goater
1237da71b7e3SCédric Le Goater pnv_cpu->intc = obj;
12382b548a42SCédric Le Goater }
12392b548a42SCédric Le Goater
pnv_chip_power10_intc_reset(PnvChip * chip,PowerPCCPU * cpu)12402b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
12412b548a42SCédric Le Goater {
1242da71b7e3SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1243da71b7e3SCédric Le Goater
1244da71b7e3SCédric Le Goater xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
12452b548a42SCédric Le Goater }
12462b548a42SCédric Le Goater
pnv_chip_power10_intc_destroy(PnvChip * chip,PowerPCCPU * cpu)12472b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
12482b548a42SCédric Le Goater {
12492b548a42SCédric Le Goater PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
12502b548a42SCédric Le Goater
1251da71b7e3SCédric Le Goater xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
12522b548a42SCédric Le Goater pnv_cpu->intc = NULL;
12532b548a42SCédric Le Goater }
12542b548a42SCédric Le Goater
pnv_chip_power10_intc_print_info(PnvChip * chip,PowerPCCPU * cpu,Monitor * mon)125585913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
125685913070SGreg Kurz Monitor *mon)
125785913070SGreg Kurz {
1258da71b7e3SCédric Le Goater xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
125985913070SGreg Kurz }
126085913070SGreg Kurz
126159b7c1c2SBalamuruhan S /*
126259b7c1c2SBalamuruhan S * Allowed core identifiers on a POWER8 Processor Chip :
1263397a79e7SCédric Le Goater *
1264397a79e7SCédric Le Goater * <EX0 reserved>
1265397a79e7SCédric Le Goater * EX1 - Venice only
1266397a79e7SCédric Le Goater * EX2 - Venice only
1267397a79e7SCédric Le Goater * EX3 - Venice only
1268397a79e7SCédric Le Goater * EX4
1269397a79e7SCédric Le Goater * EX5
1270397a79e7SCédric Le Goater * EX6
1271397a79e7SCédric Le Goater * <EX7,8 reserved> <reserved>
1272397a79e7SCédric Le Goater * EX9 - Venice only
1273397a79e7SCédric Le Goater * EX10 - Venice only
1274397a79e7SCédric Le Goater * EX11 - Venice only
1275397a79e7SCédric Le Goater * EX12
1276397a79e7SCédric Le Goater * EX13
1277397a79e7SCédric Le Goater * EX14
1278397a79e7SCédric Le Goater * <EX15 reserved>
1279397a79e7SCédric Le Goater */
1280397a79e7SCédric Le Goater #define POWER8E_CORE_MASK (0x7070ull)
1281397a79e7SCédric Le Goater #define POWER8_CORE_MASK (0x7e7eull)
1282397a79e7SCédric Le Goater
1283397a79e7SCédric Le Goater /*
128409279d7eSCédric Le Goater * POWER9 has 24 cores, ids starting at 0x0
1285397a79e7SCédric Le Goater */
128609279d7eSCédric Le Goater #define POWER9_CORE_MASK (0xffffffffffffffull)
1287397a79e7SCédric Le Goater
12882b548a42SCédric Le Goater
12892b548a42SCédric Le Goater #define POWER10_CORE_MASK (0xffffffffffffffull)
12902b548a42SCédric Le Goater
pnv_chip_power8_instance_init(Object * obj)129177864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
129277864267SCédric Le Goater {
129377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(obj);
12949ae1329eSCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
12959ae1329eSCédric Le Goater int i;
129677864267SCédric Le Goater
1297245cdb7fSCédric Le Goater object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1298245cdb7fSCédric Le Goater (Object **)&chip8->xics,
1299245cdb7fSCédric Le Goater object_property_allow_set_link,
1300d2623129SMarkus Armbruster OBJ_PROP_LINK_STRONG);
1301245cdb7fSCédric Le Goater
13029fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
130377864267SCédric Le Goater
13049fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
130577864267SCédric Le Goater
13069fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
13073887d241SBalamuruhan S
13089fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
13099ae1329eSCédric Le Goater
1310892c3ad0SDaniel Henrique Barboza if (defaults_enabled()) {
1311eb93c828SCédric Le Goater chip8->num_phbs = pcc->num_phbs;
13121f6a88ffSCédric Le Goater
1313eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) {
13140d512c71SDaniel Henrique Barboza Object *phb = object_new(TYPE_PNV_PHB);
13150d512c71SDaniel Henrique Barboza
13160d512c71SDaniel Henrique Barboza /*
13170d512c71SDaniel Henrique Barboza * We need the chip to parent the PHB to allow the DT
13180d512c71SDaniel Henrique Barboza * to build correctly (via pnv_xscom_dt()).
13190d512c71SDaniel Henrique Barboza *
13200d512c71SDaniel Henrique Barboza * TODO: the PHB should be parented by a PEC device that, at
13210d512c71SDaniel Henrique Barboza * this moment, is not modelled powernv8/phb3.
13220d512c71SDaniel Henrique Barboza */
13230d512c71SDaniel Henrique Barboza object_property_add_child(obj, "phb[*]", phb);
13240d512c71SDaniel Henrique Barboza chip8->phbs[i] = PNV_PHB(phb);
13259ae1329eSCédric Le Goater }
1326892c3ad0SDaniel Henrique Barboza }
13279ae1329eSCédric Le Goater
132877864267SCédric Le Goater }
132977864267SCédric Le Goater
pnv_chip_icp_realize(Pnv8Chip * chip8,Error ** errp)133077864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
133177864267SCédric Le Goater {
133277864267SCédric Le Goater PnvChip *chip = PNV_CHIP(chip8);
133377864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
133477864267SCédric Le Goater int i, j;
133577864267SCédric Le Goater char *name;
133677864267SCédric Le Goater
133777864267SCédric Le Goater name = g_strdup_printf("icp-%x", chip->chip_id);
133877864267SCédric Le Goater memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
133977864267SCédric Le Goater g_free(name);
1340bf3b9754SPhilippe Mathieu-Daudé memory_region_add_subregion(get_system_memory(), PNV_ICP_BASE(chip),
1341bf3b9754SPhilippe Mathieu-Daudé &chip8->icp_mmio);
134277864267SCédric Le Goater
134377864267SCédric Le Goater /* Map the ICP registers for each thread */
134477864267SCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
13454fa28f23SGreg Kurz PnvCore *pnv_core = chip->cores[i];
134677864267SCédric Le Goater int core_hwid = CPU_CORE(pnv_core)->core_id;
134777864267SCédric Le Goater
134877864267SCédric Le Goater for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
13499940412aSCaleb Schlossin uint32_t pir = pcc->chip_pir(chip, core_hwid, j);
1350245cdb7fSCédric Le Goater PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
135177864267SCédric Le Goater
135277864267SCédric Le Goater memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
135377864267SCédric Le Goater &icp->mmio);
135477864267SCédric Le Goater }
135577864267SCédric Le Goater }
135677864267SCédric Le Goater }
135777864267SCédric Le Goater
pnv_chip_power8_realize(DeviceState * dev,Error ** errp)135877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
135977864267SCédric Le Goater {
136077864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
136177864267SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
136277864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(dev);
1363ae856055SCédric Le Goater Pnv8Psi *psi8 = &chip8->psi;
136477864267SCédric Le Goater Error *local_err = NULL;
13659ae1329eSCédric Le Goater int i;
136677864267SCédric Le Goater
1367245cdb7fSCédric Le Goater assert(chip8->xics);
1368245cdb7fSCédric Le Goater
1369709044fdSCédric Le Goater /* XSCOM bridge is first */
1370326f7acbSPhilippe Mathieu-Daudé pnv_xscom_init(chip, PNV_XSCOM_SIZE, PNV_XSCOM_BASE(chip));
1371709044fdSCédric Le Goater
137277864267SCédric Le Goater pcc->parent_realize(dev, &local_err);
137377864267SCédric Le Goater if (local_err) {
137477864267SCédric Le Goater error_propagate(errp, local_err);
137577864267SCédric Le Goater return;
137677864267SCédric Le Goater }
137777864267SCédric Le Goater
137877864267SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */
13795325cc34SMarkus Armbruster object_property_set_int(OBJECT(psi8), "bar", PNV_PSIHB_BASE(chip),
13805325cc34SMarkus Armbruster &error_fatal);
13815325cc34SMarkus Armbruster object_property_set_link(OBJECT(psi8), ICS_PROP_XICS,
13825325cc34SMarkus Armbruster OBJECT(chip8->xics), &error_abort);
1383668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(psi8), NULL, errp)) {
138477864267SCédric Le Goater return;
138577864267SCédric Le Goater }
1386ae856055SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1387ae856055SCédric Le Goater &PNV_PSI(psi8)->xscom_regs);
138877864267SCédric Le Goater
138977864267SCédric Le Goater /* Create LPC controller */
1390ce189ab2SMarkus Armbruster qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
139177864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
139277864267SCédric Le Goater
1393032c226bSCédric Le Goater chip->fw_mr = &chip8->lpc.isa_fw;
139464d011d5SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
139564d011d5SCédric Le Goater (uint64_t) PNV_XSCOM_BASE(chip),
139664d011d5SCédric Le Goater PNV_XSCOM_LPC_BASE);
139764d011d5SCédric Le Goater
139859b7c1c2SBalamuruhan S /*
139959b7c1c2SBalamuruhan S * Interrupt Management Area. This is the memory region holding
140059b7c1c2SBalamuruhan S * all the Interrupt Control Presenter (ICP) registers
140159b7c1c2SBalamuruhan S */
140277864267SCédric Le Goater pnv_chip_icp_realize(chip8, &local_err);
140377864267SCédric Le Goater if (local_err) {
140477864267SCédric Le Goater error_propagate(errp, local_err);
140577864267SCédric Le Goater return;
140677864267SCédric Le Goater }
140777864267SCédric Le Goater
140877864267SCédric Le Goater /* Create the simplified OCC model */
1409668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
141077864267SCédric Le Goater return;
141177864267SCédric Le Goater }
141277864267SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1413b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1414b0ae5c69SCédric Le Goater qdev_get_gpio_in(DEVICE(psi8), PSIHB_IRQ_OCC));
1415f3db8266SBalamuruhan S
1416f3db8266SBalamuruhan S /* OCC SRAM model */
14173a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1418f3db8266SBalamuruhan S &chip8->occ.sram_regs);
14193887d241SBalamuruhan S
14203887d241SBalamuruhan S /* HOMER */
14215325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1422f2582acfSGreg Kurz &error_abort);
1423668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
14243887d241SBalamuruhan S return;
14253887d241SBalamuruhan S }
14268f092316SCédric Le Goater /* Homer Xscom region */
14278f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
14288f092316SCédric Le Goater
14298f092316SCédric Le Goater /* Homer mmio region */
14303887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
14313887d241SBalamuruhan S &chip8->homer.regs);
14329ae1329eSCédric Le Goater
14331f5d6b2aSDaniel Henrique Barboza /* PHB controllers */
1434eb93c828SCédric Le Goater for (i = 0; i < chip8->num_phbs; i++) {
14350d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[i];
14369ae1329eSCédric Le Goater
14375325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
14385325cc34SMarkus Armbruster object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
14399ae1329eSCédric Le Goater &error_fatal);
14402c4d3a50SCédric Le Goater object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
14412c4d3a50SCédric Le Goater &error_fatal);
1442668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
14439ae1329eSCédric Le Goater return;
14449ae1329eSCédric Le Goater }
14459ae1329eSCédric Le Goater }
144677864267SCédric Le Goater }
144777864267SCédric Le Goater
pnv_chip_power8_xscom_pcba(PnvChip * chip,uint64_t addr)144870c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
144970c059e9SGreg Kurz {
145070c059e9SGreg Kurz addr &= (PNV_XSCOM_SIZE - 1);
145170c059e9SGreg Kurz return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
145270c059e9SGreg Kurz }
145370c059e9SGreg Kurz
pnv_chip_power8e_class_init(ObjectClass * klass,void * data)1454e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1455e997040eSCédric Le Goater {
1456e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1457e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
1458e997040eSCédric Le Goater
1459e997040eSCédric Le Goater k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
1460397a79e7SCédric Le Goater k->cores_mask = POWER8E_CORE_MASK;
14619ae1329eSCédric Le Goater k->num_phbs = 3;
14629940412aSCaleb Schlossin k->chip_pir = pnv_chip_pir_p8;
1463d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create;
1464d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset;
14650990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy;
146685913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info;
146704026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create;
1468eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate;
1469d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info;
1470c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base;
147170c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1472e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8E";
147377864267SCédric Le Goater
147477864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize,
147577864267SCédric Le Goater &k->parent_realize);
1476e997040eSCédric Le Goater }
1477e997040eSCédric Le Goater
pnv_chip_power8_class_init(ObjectClass * klass,void * data)1478e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1479e997040eSCédric Le Goater {
1480e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1481e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
1482e997040eSCédric Le Goater
1483e997040eSCédric Le Goater k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1484397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK;
14859ae1329eSCédric Le Goater k->num_phbs = 3;
14869940412aSCaleb Schlossin k->chip_pir = pnv_chip_pir_p8;
1487d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create;
1488d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset;
14890990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy;
149085913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info;
149104026890SCédric Le Goater k->isa_create = pnv_chip_power8_isa_create;
1492eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate;
1493d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info;
1494c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base;
149570c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1496e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8";
149777864267SCédric Le Goater
149877864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize,
149977864267SCédric Le Goater &k->parent_realize);
1500e997040eSCédric Le Goater }
1501e997040eSCédric Le Goater
pnv_chip_power8nvl_class_init(ObjectClass * klass,void * data)1502e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1503e997040eSCédric Le Goater {
1504e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1505e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
1506e997040eSCédric Le Goater
1507e997040eSCédric Le Goater k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
1508397a79e7SCédric Le Goater k->cores_mask = POWER8_CORE_MASK;
1509316717feSCédric Le Goater k->num_phbs = 4;
15109940412aSCaleb Schlossin k->chip_pir = pnv_chip_pir_p8;
1511d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power8_intc_create;
1512d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power8_intc_reset;
15130990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power8_intc_destroy;
151485913070SGreg Kurz k->intc_print_info = pnv_chip_power8_intc_print_info;
151504026890SCédric Le Goater k->isa_create = pnv_chip_power8nvl_isa_create;
1516eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power8_dt_populate;
1517d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power8_pic_print_info;
1518c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power8_xscom_core_base;
151970c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1520e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER8NVL";
152177864267SCédric Le Goater
152277864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power8_realize,
152377864267SCédric Le Goater &k->parent_realize);
152477864267SCédric Le Goater }
152577864267SCédric Le Goater
pnv_chip_power9_instance_init(Object * obj)152677864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
152777864267SCédric Le Goater {
15284f9924c4SBenjamin Herrenschmidt PnvChip *chip = PNV_CHIP(obj);
15292dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(obj);
15304f9924c4SBenjamin Herrenschmidt PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
15314f9924c4SBenjamin Herrenschmidt int i;
15322dfa91a2SCédric Le Goater
1533db873cc5SMarkus Armbruster object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1534d1214b81SGreg Kurz object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1535d2623129SMarkus Armbruster "xive-fabric");
1536c38536bcSCédric Le Goater
15379fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
153815376c66SCédric Le Goater
15399fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
15406598a70dSCédric Le Goater
1541de3ba0ccSNicholas Piggin object_initialize_child(obj, "chiptod", &chip9->chiptod, TYPE_PNV9_CHIPTOD);
1542de3ba0ccSNicholas Piggin
15439fc7fc4dSMarkus Armbruster object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
15443887d241SBalamuruhan S
15450bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
15460bf4d77eSNicholas Piggin
15479fc7fc4dSMarkus Armbruster object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
15484f9924c4SBenjamin Herrenschmidt
1549422fd92eSCédric Le Goater /* Number of PECs is the chip default */
1550422fd92eSCédric Le Goater chip->num_pecs = pcc->num_pecs;
1551422fd92eSCédric Le Goater
1552422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
15534f9924c4SBenjamin Herrenschmidt object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
15549fc7fc4dSMarkus Armbruster TYPE_PNV_PHB4_PEC);
15554f9924c4SBenjamin Herrenschmidt }
15565f066121SCédric Le Goater
15575f066121SCédric Le Goater for (i = 0; i < pcc->i2c_num_engines; i++) {
15585f066121SCédric Le Goater object_initialize_child(obj, "i2c[*]", &chip9->i2c[i], TYPE_PNV_I2C);
15595f066121SCédric Le Goater }
156077864267SCédric Le Goater }
156177864267SCédric Le Goater
pnv_chip_quad_realize_one(PnvChip * chip,PnvQuad * eq,PnvCore * pnv_core,const char * type)1562ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1563fdc2b46aSJoel Stanley PnvCore *pnv_core,
1564fdc2b46aSJoel Stanley const char *type)
15655dad902cSCédric Le Goater {
15665dad902cSCédric Le Goater char eq_name[32];
15675dad902cSCédric Le Goater int core_id = CPU_CORE(pnv_core)->core_id;
15685dad902cSCédric Le Goater
15695dad902cSCédric Le Goater snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
15709fc7fc4dSMarkus Armbruster object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
1571fdc2b46aSJoel Stanley sizeof(*eq), type,
15729fc7fc4dSMarkus Armbruster &error_fatal, NULL);
15735dad902cSCédric Le Goater
157492612f15SCédric Le Goater object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1575ce189ab2SMarkus Armbruster qdev_realize(DEVICE(eq), NULL, &error_fatal);
1576ae4c68e3SCédric Le Goater }
1577ae4c68e3SCédric Le Goater
pnv_chip_quad_realize(Pnv9Chip * chip9,Error ** errp)1578ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1579ae4c68e3SCédric Le Goater {
1580ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip9);
1581ae4c68e3SCédric Le Goater int i;
1582ae4c68e3SCédric Le Goater
1583ae4c68e3SCédric Le Goater chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1584ae4c68e3SCédric Le Goater chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1585ae4c68e3SCédric Le Goater
1586ae4c68e3SCédric Le Goater for (i = 0; i < chip9->nr_quads; i++) {
1587ae4c68e3SCédric Le Goater PnvQuad *eq = &chip9->quads[i];
1588ae4c68e3SCédric Le Goater
1589fdc2b46aSJoel Stanley pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
1590fdc2b46aSJoel Stanley PNV_QUAD_TYPE_NAME("power9"));
15915dad902cSCédric Le Goater
159292612f15SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
15935dad902cSCédric Le Goater &eq->xscom_regs);
15945dad902cSCédric Le Goater }
15955dad902cSCédric Le Goater }
15965dad902cSCédric Le Goater
pnv_chip_power9_pec_realize(PnvChip * chip,Error ** errp)159713480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
15984f9924c4SBenjamin Herrenschmidt {
15994f9924c4SBenjamin Herrenschmidt Pnv9Chip *chip9 = PNV9_CHIP(chip);
160013480fc5SCédric Le Goater int i;
16014f9924c4SBenjamin Herrenschmidt
1602422fd92eSCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
16034f9924c4SBenjamin Herrenschmidt PnvPhb4PecState *pec = &chip9->pecs[i];
16044f9924c4SBenjamin Herrenschmidt PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
16054f9924c4SBenjamin Herrenschmidt uint32_t pec_nest_base;
16064f9924c4SBenjamin Herrenschmidt uint32_t pec_pci_base;
16074f9924c4SBenjamin Herrenschmidt
16085325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
16095325cc34SMarkus Armbruster object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
16104f9924c4SBenjamin Herrenschmidt &error_fatal);
16116f43d255SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
16126f43d255SCédric Le Goater &error_fatal);
1613668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(pec), NULL, errp)) {
16144f9924c4SBenjamin Herrenschmidt return;
16154f9924c4SBenjamin Herrenschmidt }
16164f9924c4SBenjamin Herrenschmidt
16174f9924c4SBenjamin Herrenschmidt pec_nest_base = pecc->xscom_nest_base(pec);
16184f9924c4SBenjamin Herrenschmidt pec_pci_base = pecc->xscom_pci_base(pec);
16194f9924c4SBenjamin Herrenschmidt
16204f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
16214f9924c4SBenjamin Herrenschmidt pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
16224f9924c4SBenjamin Herrenschmidt }
16234f9924c4SBenjamin Herrenschmidt }
16244f9924c4SBenjamin Herrenschmidt
pnv_chip_power9_realize(DeviceState * dev,Error ** errp)162577864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
162677864267SCédric Le Goater {
162777864267SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
16282dfa91a2SCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(dev);
16292dfa91a2SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
1630c38536bcSCédric Le Goater Pnv9Psi *psi9 = &chip9->psi;
163177864267SCédric Le Goater Error *local_err = NULL;
16325f066121SCédric Le Goater int i;
163377864267SCédric Le Goater
1634709044fdSCédric Le Goater /* XSCOM bridge is first */
1635326f7acbSPhilippe Mathieu-Daudé pnv_xscom_init(chip, PNV9_XSCOM_SIZE, PNV9_XSCOM_BASE(chip));
1636709044fdSCédric Le Goater
163777864267SCédric Le Goater pcc->parent_realize(dev, &local_err);
163877864267SCédric Le Goater if (local_err) {
163977864267SCédric Le Goater error_propagate(errp, local_err);
164077864267SCédric Le Goater return;
164177864267SCédric Le Goater }
16422dfa91a2SCédric Le Goater
16435dad902cSCédric Le Goater pnv_chip_quad_realize(chip9, &local_err);
16445dad902cSCédric Le Goater if (local_err) {
16455dad902cSCédric Le Goater error_propagate(errp, local_err);
16465dad902cSCédric Le Goater return;
16475dad902cSCédric Le Goater }
16485dad902cSCédric Le Goater
16492dfa91a2SCédric Le Goater /* XIVE interrupt controller (POWER9) */
16505325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
16515325cc34SMarkus Armbruster PNV9_XIVE_IC_BASE(chip), &error_fatal);
16525325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
16535325cc34SMarkus Armbruster PNV9_XIVE_VC_BASE(chip), &error_fatal);
16545325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
16555325cc34SMarkus Armbruster PNV9_XIVE_PC_BASE(chip), &error_fatal);
16565325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
16575325cc34SMarkus Armbruster PNV9_XIVE_TM_BASE(chip), &error_fatal);
16585325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
16597ae54cc3SGreg Kurz &error_abort);
1660668f62ecSMarkus Armbruster if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
16612dfa91a2SCédric Le Goater return;
16622dfa91a2SCédric Le Goater }
16632dfa91a2SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
16642dfa91a2SCédric Le Goater &chip9->xive.xscom_regs);
1665c38536bcSCédric Le Goater
1666c38536bcSCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */
16675325cc34SMarkus Armbruster object_property_set_int(OBJECT(psi9), "bar", PNV9_PSIHB_BASE(chip),
16685325cc34SMarkus Armbruster &error_fatal);
166924c8fa96SCédric Le Goater /* This is the only device with 4k ESB pages */
167024c8fa96SCédric Le Goater object_property_set_int(OBJECT(psi9), "shift", XIVE_ESB_4K,
167124c8fa96SCédric Le Goater &error_fatal);
1672668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(psi9), NULL, errp)) {
1673c38536bcSCédric Le Goater return;
1674c38536bcSCédric Le Goater }
1675c38536bcSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1676c38536bcSCédric Le Goater &PNV_PSI(psi9)->xscom_regs);
167715376c66SCédric Le Goater
167815376c66SCédric Le Goater /* LPC */
1679668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
168015376c66SCédric Le Goater return;
168115376c66SCédric Le Goater }
168215376c66SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
168315376c66SCédric Le Goater &chip9->lpc.xscom_regs);
168415376c66SCédric Le Goater
1685032c226bSCédric Le Goater chip->fw_mr = &chip9->lpc.isa_fw;
168615376c66SCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
168715376c66SCédric Le Goater (uint64_t) PNV9_LPCM_BASE(chip));
16886598a70dSCédric Le Goater
1689de3ba0ccSNicholas Piggin /* ChipTOD */
1690de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip9->chiptod), "primary",
1691de3ba0ccSNicholas Piggin chip->chip_id == 0, &error_abort);
1692de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip9->chiptod), "secondary",
1693de3ba0ccSNicholas Piggin chip->chip_id == 1, &error_abort);
1694de3ba0ccSNicholas Piggin object_property_set_link(OBJECT(&chip9->chiptod), "chip", OBJECT(chip),
1695de3ba0ccSNicholas Piggin &error_abort);
1696de3ba0ccSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->chiptod), NULL, errp)) {
1697de3ba0ccSNicholas Piggin return;
1698de3ba0ccSNicholas Piggin }
1699de3ba0ccSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_CHIPTOD_BASE,
1700de3ba0ccSNicholas Piggin &chip9->chiptod.xscom_regs);
1701de3ba0ccSNicholas Piggin
17026598a70dSCédric Le Goater /* Create the simplified OCC model */
1703668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
17046598a70dSCédric Le Goater return;
17056598a70dSCédric Le Goater }
17066598a70dSCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1707b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1708b0ae5c69SCédric Le Goater DEVICE(psi9), PSIHB9_IRQ_OCC));
1709f3db8266SBalamuruhan S
1710f3db8266SBalamuruhan S /* OCC SRAM model */
17113a1b70b6SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1712f3db8266SBalamuruhan S &chip9->occ.sram_regs);
17133887d241SBalamuruhan S
17140bf4d77eSNicholas Piggin /* SBE */
17150bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
17160bf4d77eSNicholas Piggin return;
17170bf4d77eSNicholas Piggin }
17180bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
17190bf4d77eSNicholas Piggin &chip9->sbe.xscom_ctrl_regs);
17200bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
17210bf4d77eSNicholas Piggin &chip9->sbe.xscom_mbox_regs);
17220bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
17230bf4d77eSNicholas Piggin DEVICE(psi9), PSIHB9_IRQ_PSU));
17240bf4d77eSNicholas Piggin
17253887d241SBalamuruhan S /* HOMER */
17265325cc34SMarkus Armbruster object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1727f2582acfSGreg Kurz &error_abort);
1728668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
17293887d241SBalamuruhan S return;
17303887d241SBalamuruhan S }
17318f092316SCédric Le Goater /* Homer Xscom region */
17328f092316SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
17338f092316SCédric Le Goater
17348f092316SCédric Le Goater /* Homer mmio region */
17353887d241SBalamuruhan S memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
17363887d241SBalamuruhan S &chip9->homer.regs);
17374f9924c4SBenjamin Herrenschmidt
173813480fc5SCédric Le Goater /* PEC PHBs */
173913480fc5SCédric Le Goater pnv_chip_power9_pec_realize(chip, &local_err);
17404f9924c4SBenjamin Herrenschmidt if (local_err) {
17414f9924c4SBenjamin Herrenschmidt error_propagate(errp, local_err);
17424f9924c4SBenjamin Herrenschmidt return;
17434f9924c4SBenjamin Herrenschmidt }
17445f066121SCédric Le Goater
17455f066121SCédric Le Goater /*
17465f066121SCédric Le Goater * I2C
17475f066121SCédric Le Goater */
17485f066121SCédric Le Goater for (i = 0; i < pcc->i2c_num_engines; i++) {
17495f066121SCédric Le Goater Object *obj = OBJECT(&chip9->i2c[i]);
17505f066121SCédric Le Goater
17515f066121SCédric Le Goater object_property_set_int(obj, "engine", i + 1, &error_fatal);
17520d1dcb0bSGlenn Miles object_property_set_int(obj, "num-busses",
17530d1dcb0bSGlenn Miles pcc->i2c_ports_per_engine[i],
17545f066121SCédric Le Goater &error_fatal);
17555f066121SCédric Le Goater object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
17565f066121SCédric Le Goater if (!qdev_realize(DEVICE(obj), NULL, errp)) {
17575f066121SCédric Le Goater return;
17585f066121SCédric Le Goater }
17595f066121SCédric Le Goater pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE +
176047dfdd23SGlenn Miles (chip9->i2c[i].engine - 1) *
176147dfdd23SGlenn Miles PNV9_XSCOM_I2CM_SIZE,
17625f066121SCédric Le Goater &chip9->i2c[i].xscom_regs);
17635f066121SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0,
17645f066121SCédric Le Goater qdev_get_gpio_in(DEVICE(psi9),
17655f066121SCédric Le Goater PSIHB9_IRQ_SBE_I2C));
17665f066121SCédric Le Goater }
1767e997040eSCédric Le Goater }
1768e997040eSCédric Le Goater
pnv_chip_power9_xscom_pcba(PnvChip * chip,uint64_t addr)176970c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
177070c059e9SGreg Kurz {
177170c059e9SGreg Kurz addr &= (PNV9_XSCOM_SIZE - 1);
177270c059e9SGreg Kurz return addr >> 3;
177370c059e9SGreg Kurz }
177470c059e9SGreg Kurz
pnv_chip_power9_class_init(ObjectClass * klass,void * data)1775e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1776e997040eSCédric Le Goater {
1777e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
1778e997040eSCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
17790d1dcb0bSGlenn Miles static const int i2c_ports_per_engine[PNV9_CHIP_MAX_I2C] = {2, 13, 2, 2};
1780e997040eSCédric Le Goater
178183028a2bSCédric Le Goater k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1782397a79e7SCédric Le Goater k->cores_mask = POWER9_CORE_MASK;
17839940412aSCaleb Schlossin k->chip_pir = pnv_chip_pir_p9;
1784d35aefa9SCédric Le Goater k->intc_create = pnv_chip_power9_intc_create;
1785d49e8a9bSCédric Le Goater k->intc_reset = pnv_chip_power9_intc_reset;
17860990ce6aSGreg Kurz k->intc_destroy = pnv_chip_power9_intc_destroy;
178785913070SGreg Kurz k->intc_print_info = pnv_chip_power9_intc_print_info;
178804026890SCédric Le Goater k->isa_create = pnv_chip_power9_isa_create;
1789eb859a27SCédric Le Goater k->dt_populate = pnv_chip_power9_dt_populate;
1790d8e4aad5SCédric Le Goater k->pic_print_info = pnv_chip_power9_pic_print_info;
1791c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power9_xscom_core_base;
179270c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1793e997040eSCédric Le Goater dc->desc = "PowerNV Chip POWER9";
1794422fd92eSCédric Le Goater k->num_pecs = PNV9_CHIP_MAX_PEC;
17955f066121SCédric Le Goater k->i2c_num_engines = PNV9_CHIP_MAX_I2C;
17960d1dcb0bSGlenn Miles k->i2c_ports_per_engine = i2c_ports_per_engine;
179777864267SCédric Le Goater
179877864267SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power9_realize,
179977864267SCédric Le Goater &k->parent_realize);
1800e997040eSCédric Le Goater }
1801e997040eSCédric Le Goater
pnv_chip_power10_instance_init(Object * obj)18022b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
18032b548a42SCédric Le Goater {
1804623575e1SCédric Le Goater PnvChip *chip = PNV_CHIP(obj);
18058b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(obj);
1806623575e1SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1807623575e1SCédric Le Goater int i;
18088b50ce85SCédric Le Goater
1809da71b7e3SCédric Le Goater object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1810da71b7e3SCédric Le Goater object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1811da71b7e3SCédric Le Goater "xive-fabric");
18129fc7fc4dSMarkus Armbruster object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
18139fc7fc4dSMarkus Armbruster object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
1814de3ba0ccSNicholas Piggin object_initialize_child(obj, "chiptod", &chip10->chiptod,
1815de3ba0ccSNicholas Piggin TYPE_PNV10_CHIPTOD);
18168bf682a3SCédric Le Goater object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC);
18170bf4d77eSNicholas Piggin object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE);
181892499676SCédric Le Goater object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1819c295d3b0SChalapathi V object_initialize_child(obj, "n1-chiplet", &chip10->n1_chiplet,
1820c295d3b0SChalapathi V TYPE_PNV_N1_CHIPLET);
1821623575e1SCédric Le Goater
1822623575e1SCédric Le Goater chip->num_pecs = pcc->num_pecs;
1823623575e1SCédric Le Goater
1824623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
1825623575e1SCédric Le Goater object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1826623575e1SCédric Le Goater TYPE_PNV_PHB5_PEC);
1827623575e1SCédric Le Goater }
18281ceda19cSGlenn Miles
18291ceda19cSGlenn Miles for (i = 0; i < pcc->i2c_num_engines; i++) {
18301ceda19cSGlenn Miles object_initialize_child(obj, "i2c[*]", &chip10->i2c[i], TYPE_PNV_I2C);
18311ceda19cSGlenn Miles }
18322b548a42SCédric Le Goater }
18332b548a42SCédric Le Goater
pnv_chip_power10_quad_realize(Pnv10Chip * chip10,Error ** errp)1834ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1835ae4c68e3SCédric Le Goater {
1836ae4c68e3SCédric Le Goater PnvChip *chip = PNV_CHIP(chip10);
1837ae4c68e3SCédric Le Goater int i;
1838ae4c68e3SCédric Le Goater
1839ae4c68e3SCédric Le Goater chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1840ae4c68e3SCédric Le Goater chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1841ae4c68e3SCédric Le Goater
1842ae4c68e3SCédric Le Goater for (i = 0; i < chip10->nr_quads; i++) {
1843ae4c68e3SCédric Le Goater PnvQuad *eq = &chip10->quads[i];
1844ae4c68e3SCédric Le Goater
1845fdc2b46aSJoel Stanley pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
1846a1d64b9eSJoel Stanley PNV_QUAD_TYPE_NAME("power10"));
1847ae4c68e3SCédric Le Goater
1848ae4c68e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1849ae4c68e3SCédric Le Goater &eq->xscom_regs);
1850bdb97596SJoel Stanley
1851bdb97596SJoel Stanley pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id),
1852bdb97596SJoel Stanley &eq->xscom_qme_regs);
1853ae4c68e3SCédric Le Goater }
1854ae4c68e3SCédric Le Goater }
1855ae4c68e3SCédric Le Goater
pnv_chip_power10_phb_realize(PnvChip * chip,Error ** errp)1856623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1857623575e1SCédric Le Goater {
1858623575e1SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(chip);
1859623575e1SCédric Le Goater int i;
1860623575e1SCédric Le Goater
1861623575e1SCédric Le Goater for (i = 0; i < chip->num_pecs; i++) {
1862623575e1SCédric Le Goater PnvPhb4PecState *pec = &chip10->pecs[i];
1863623575e1SCédric Le Goater PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1864623575e1SCédric Le Goater uint32_t pec_nest_base;
1865623575e1SCédric Le Goater uint32_t pec_pci_base;
1866623575e1SCédric Le Goater
1867623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1868623575e1SCédric Le Goater object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1869623575e1SCédric Le Goater &error_fatal);
1870623575e1SCédric Le Goater object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1871623575e1SCédric Le Goater &error_fatal);
1872623575e1SCédric Le Goater if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1873623575e1SCédric Le Goater return;
1874623575e1SCédric Le Goater }
1875623575e1SCédric Le Goater
1876623575e1SCédric Le Goater pec_nest_base = pecc->xscom_nest_base(pec);
1877623575e1SCédric Le Goater pec_pci_base = pecc->xscom_pci_base(pec);
1878623575e1SCédric Le Goater
1879623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1880623575e1SCédric Le Goater pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1881623575e1SCédric Le Goater }
1882623575e1SCédric Le Goater }
1883623575e1SCédric Le Goater
pnv_chip_power10_realize(DeviceState * dev,Error ** errp)18842b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
18852b548a42SCédric Le Goater {
18862b548a42SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
18872b548a42SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
18888b50ce85SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(dev);
18892b548a42SCédric Le Goater Error *local_err = NULL;
18901ceda19cSGlenn Miles int i;
18912b548a42SCédric Le Goater
18922b548a42SCédric Le Goater /* XSCOM bridge is first */
1893326f7acbSPhilippe Mathieu-Daudé pnv_xscom_init(chip, PNV10_XSCOM_SIZE, PNV10_XSCOM_BASE(chip));
18942b548a42SCédric Le Goater
18952b548a42SCédric Le Goater pcc->parent_realize(dev, &local_err);
18962b548a42SCédric Le Goater if (local_err) {
18972b548a42SCédric Le Goater error_propagate(errp, local_err);
18982b548a42SCédric Le Goater return;
18992b548a42SCédric Le Goater }
19008b50ce85SCédric Le Goater
1901ae4c68e3SCédric Le Goater pnv_chip_power10_quad_realize(chip10, &local_err);
1902ae4c68e3SCédric Le Goater if (local_err) {
1903ae4c68e3SCédric Le Goater error_propagate(errp, local_err);
1904ae4c68e3SCédric Le Goater return;
1905ae4c68e3SCédric Le Goater }
1906ae4c68e3SCédric Le Goater
1907da71b7e3SCédric Le Goater /* XIVE2 interrupt controller (POWER10) */
1908da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1909da71b7e3SCédric Le Goater PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1910da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1911da71b7e3SCédric Le Goater PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1912da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1913da71b7e3SCédric Le Goater PNV10_XIVE2_END_BASE(chip), &error_fatal);
1914da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1915da71b7e3SCédric Le Goater PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1916da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1917da71b7e3SCédric Le Goater PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1918da71b7e3SCédric Le Goater object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1919da71b7e3SCédric Le Goater PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1920da71b7e3SCédric Le Goater object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1921da71b7e3SCédric Le Goater &error_abort);
1922da71b7e3SCédric Le Goater if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1923da71b7e3SCédric Le Goater return;
1924da71b7e3SCédric Le Goater }
1925da71b7e3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1926da71b7e3SCédric Le Goater &chip10->xive.xscom_regs);
1927da71b7e3SCédric Le Goater
19288b50ce85SCédric Le Goater /* Processor Service Interface (PSI) Host Bridge */
19295325cc34SMarkus Armbruster object_property_set_int(OBJECT(&chip10->psi), "bar",
19305325cc34SMarkus Armbruster PNV10_PSIHB_BASE(chip), &error_fatal);
193124c8fa96SCédric Le Goater /* PSI can now be configured to use 64k ESB pages on POWER10 */
193224c8fa96SCédric Le Goater object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
193324c8fa96SCédric Le Goater &error_fatal);
1934668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
19358b50ce85SCédric Le Goater return;
19368b50ce85SCédric Le Goater }
19378b50ce85SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
19388b50ce85SCédric Le Goater &PNV_PSI(&chip10->psi)->xscom_regs);
19392661f6abSCédric Le Goater
19402661f6abSCédric Le Goater /* LPC */
1941668f62ecSMarkus Armbruster if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
19422661f6abSCédric Le Goater return;
19432661f6abSCédric Le Goater }
19442661f6abSCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
19452661f6abSCédric Le Goater &chip10->lpc.xscom_regs);
19462661f6abSCédric Le Goater
1947032c226bSCédric Le Goater chip->fw_mr = &chip10->lpc.isa_fw;
19482661f6abSCédric Le Goater chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
19492661f6abSCédric Le Goater (uint64_t) PNV10_LPCM_BASE(chip));
19508bf682a3SCédric Le Goater
1951de3ba0ccSNicholas Piggin /* ChipTOD */
1952de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip10->chiptod), "primary",
1953de3ba0ccSNicholas Piggin chip->chip_id == 0, &error_abort);
1954de3ba0ccSNicholas Piggin object_property_set_bool(OBJECT(&chip10->chiptod), "secondary",
1955de3ba0ccSNicholas Piggin chip->chip_id == 1, &error_abort);
1956de3ba0ccSNicholas Piggin object_property_set_link(OBJECT(&chip10->chiptod), "chip", OBJECT(chip),
1957de3ba0ccSNicholas Piggin &error_abort);
1958de3ba0ccSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->chiptod), NULL, errp)) {
1959de3ba0ccSNicholas Piggin return;
1960de3ba0ccSNicholas Piggin }
1961de3ba0ccSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_CHIPTOD_BASE,
1962de3ba0ccSNicholas Piggin &chip10->chiptod.xscom_regs);
1963de3ba0ccSNicholas Piggin
19648bf682a3SCédric Le Goater /* Create the simplified OCC model */
19658bf682a3SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
19668bf682a3SCédric Le Goater return;
19678bf682a3SCédric Le Goater }
19688bf682a3SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
19698bf682a3SCédric Le Goater &chip10->occ.xscom_regs);
1970b0ae5c69SCédric Le Goater qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1971b0ae5c69SCédric Le Goater DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1972623575e1SCédric Le Goater
197392499676SCédric Le Goater /* OCC SRAM model */
197492499676SCédric Le Goater memory_region_add_subregion(get_system_memory(),
197592499676SCédric Le Goater PNV10_OCC_SENSOR_BASE(chip),
197692499676SCédric Le Goater &chip10->occ.sram_regs);
197792499676SCédric Le Goater
19780bf4d77eSNicholas Piggin /* SBE */
19790bf4d77eSNicholas Piggin if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
19800bf4d77eSNicholas Piggin return;
19810bf4d77eSNicholas Piggin }
19820bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
19830bf4d77eSNicholas Piggin &chip10->sbe.xscom_ctrl_regs);
19840bf4d77eSNicholas Piggin pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
19850bf4d77eSNicholas Piggin &chip10->sbe.xscom_mbox_regs);
19860bf4d77eSNicholas Piggin qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
19870bf4d77eSNicholas Piggin DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
19880bf4d77eSNicholas Piggin
198992499676SCédric Le Goater /* HOMER */
199092499676SCédric Le Goater object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
199192499676SCédric Le Goater &error_abort);
199292499676SCédric Le Goater if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
199392499676SCédric Le Goater return;
199492499676SCédric Le Goater }
199592499676SCédric Le Goater /* Homer Xscom region */
199692499676SCédric Le Goater pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
199792499676SCédric Le Goater &chip10->homer.pba_regs);
199892499676SCédric Le Goater
199992499676SCédric Le Goater /* Homer mmio region */
200092499676SCédric Le Goater memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
200192499676SCédric Le Goater &chip10->homer.regs);
200292499676SCédric Le Goater
2003c295d3b0SChalapathi V /* N1 chiplet */
2004c295d3b0SChalapathi V if (!qdev_realize(DEVICE(&chip10->n1_chiplet), NULL, errp)) {
2005c295d3b0SChalapathi V return;
2006c295d3b0SChalapathi V }
2007c295d3b0SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_CHIPLET_CTRL_REGS_BASE,
2008c295d3b0SChalapathi V &chip10->n1_chiplet.nest_pervasive.xscom_ctrl_regs_mr);
2009c295d3b0SChalapathi V
2010c295d3b0SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_EQ_BASE,
2011c295d3b0SChalapathi V &chip10->n1_chiplet.xscom_pb_eq_mr);
2012c295d3b0SChalapathi V
2013c295d3b0SChalapathi V pnv_xscom_add_subregion(chip, PNV10_XSCOM_N1_PB_SCOM_ES_BASE,
2014c295d3b0SChalapathi V &chip10->n1_chiplet.xscom_pb_es_mr);
2015c295d3b0SChalapathi V
2016623575e1SCédric Le Goater /* PHBs */
2017623575e1SCédric Le Goater pnv_chip_power10_phb_realize(chip, &local_err);
2018623575e1SCédric Le Goater if (local_err) {
2019623575e1SCédric Le Goater error_propagate(errp, local_err);
2020623575e1SCédric Le Goater return;
2021623575e1SCédric Le Goater }
20221ceda19cSGlenn Miles
20231ceda19cSGlenn Miles
20241ceda19cSGlenn Miles /*
20251ceda19cSGlenn Miles * I2C
20261ceda19cSGlenn Miles */
20271ceda19cSGlenn Miles for (i = 0; i < pcc->i2c_num_engines; i++) {
20281ceda19cSGlenn Miles Object *obj = OBJECT(&chip10->i2c[i]);
20291ceda19cSGlenn Miles
20301ceda19cSGlenn Miles object_property_set_int(obj, "engine", i + 1, &error_fatal);
20310d1dcb0bSGlenn Miles object_property_set_int(obj, "num-busses",
20320d1dcb0bSGlenn Miles pcc->i2c_ports_per_engine[i],
20331ceda19cSGlenn Miles &error_fatal);
20341ceda19cSGlenn Miles object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
20351ceda19cSGlenn Miles if (!qdev_realize(DEVICE(obj), NULL, errp)) {
20361ceda19cSGlenn Miles return;
20371ceda19cSGlenn Miles }
20381ceda19cSGlenn Miles pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE +
203947dfdd23SGlenn Miles (chip10->i2c[i].engine - 1) *
204047dfdd23SGlenn Miles PNV10_XSCOM_I2CM_SIZE,
20411ceda19cSGlenn Miles &chip10->i2c[i].xscom_regs);
20421ceda19cSGlenn Miles qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0,
20431ceda19cSGlenn Miles qdev_get_gpio_in(DEVICE(&chip10->psi),
20441ceda19cSGlenn Miles PSIHB9_IRQ_SBE_I2C));
20451ceda19cSGlenn Miles }
204633467ecbSGlenn Miles
204733467ecbSGlenn Miles }
204833467ecbSGlenn Miles
pnv_rainier_i2c_init(PnvMachineState * pnv)204933467ecbSGlenn Miles static void pnv_rainier_i2c_init(PnvMachineState *pnv)
205033467ecbSGlenn Miles {
205133467ecbSGlenn Miles int i;
205233467ecbSGlenn Miles for (i = 0; i < pnv->num_chips; i++) {
205333467ecbSGlenn Miles Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
205433467ecbSGlenn Miles
205533467ecbSGlenn Miles /*
205633467ecbSGlenn Miles * Add a PCA9552 I2C device for PCIe hotplug control
205733467ecbSGlenn Miles * to engine 2, bus 1, address 0x63
205833467ecbSGlenn Miles */
20596f86885aSGlenn Miles I2CSlave *dev = i2c_slave_create_simple(chip10->i2c[2].busses[1],
20606f86885aSGlenn Miles "pca9552", 0x63);
20616f86885aSGlenn Miles
20626f86885aSGlenn Miles /*
20636f86885aSGlenn Miles * Connect PCA9552 GPIO pins 0-4 (SLOTx_EN) outputs to GPIO pins 5-9
20646f86885aSGlenn Miles * (SLOTx_PG) inputs in order to fake the pgood state of PCIe slots
20656f86885aSGlenn Miles * after hypervisor code sets a SLOTx_EN pin high.
20666f86885aSGlenn Miles */
20676f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 0, qdev_get_gpio_in(DEVICE(dev), 5));
20686f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 1, qdev_get_gpio_in(DEVICE(dev), 6));
20696f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 2, qdev_get_gpio_in(DEVICE(dev), 7));
20706f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 3, qdev_get_gpio_in(DEVICE(dev), 8));
20716f86885aSGlenn Miles qdev_connect_gpio_out(DEVICE(dev), 4, qdev_get_gpio_in(DEVICE(dev), 9));
20726aa4ef32SGlenn Miles
20736aa4ef32SGlenn Miles /*
20746aa4ef32SGlenn Miles * Add a PCA9554 I2C device for cable card presence detection
20756aa4ef32SGlenn Miles * to engine 2, bus 1, address 0x25
20766aa4ef32SGlenn Miles */
20776aa4ef32SGlenn Miles i2c_slave_create_simple(chip10->i2c[2].busses[1], "pca9554", 0x25);
207833467ecbSGlenn Miles }
20792b548a42SCédric Le Goater }
20802b548a42SCédric Le Goater
pnv_chip_power10_xscom_pcba(PnvChip * chip,uint64_t addr)208170c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
208270c059e9SGreg Kurz {
208370c059e9SGreg Kurz addr &= (PNV10_XSCOM_SIZE - 1);
208470c059e9SGreg Kurz return addr >> 3;
208570c059e9SGreg Kurz }
208670c059e9SGreg Kurz
pnv_chip_power10_class_init(ObjectClass * klass,void * data)20872b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
20882b548a42SCédric Le Goater {
20892b548a42SCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
20902b548a42SCédric Le Goater PnvChipClass *k = PNV_CHIP_CLASS(klass);
20910d1dcb0bSGlenn Miles static const int i2c_ports_per_engine[PNV10_CHIP_MAX_I2C] = {14, 14, 2, 16};
20922b548a42SCédric Le Goater
20932b548a42SCédric Le Goater k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
20942b548a42SCédric Le Goater k->cores_mask = POWER10_CORE_MASK;
20959940412aSCaleb Schlossin k->chip_pir = pnv_chip_pir_p10;
20962b548a42SCédric Le Goater k->intc_create = pnv_chip_power10_intc_create;
20972b548a42SCédric Le Goater k->intc_reset = pnv_chip_power10_intc_reset;
20982b548a42SCédric Le Goater k->intc_destroy = pnv_chip_power10_intc_destroy;
209985913070SGreg Kurz k->intc_print_info = pnv_chip_power10_intc_print_info;
21002b548a42SCédric Le Goater k->isa_create = pnv_chip_power10_isa_create;
21012b548a42SCédric Le Goater k->dt_populate = pnv_chip_power10_dt_populate;
21022b548a42SCédric Le Goater k->pic_print_info = pnv_chip_power10_pic_print_info;
2103c4b2c40cSGreg Kurz k->xscom_core_base = pnv_chip_power10_xscom_core_base;
210470c059e9SGreg Kurz k->xscom_pcba = pnv_chip_power10_xscom_pcba;
21052b548a42SCédric Le Goater dc->desc = "PowerNV Chip POWER10";
2106623575e1SCédric Le Goater k->num_pecs = PNV10_CHIP_MAX_PEC;
21071ceda19cSGlenn Miles k->i2c_num_engines = PNV10_CHIP_MAX_I2C;
21080d1dcb0bSGlenn Miles k->i2c_ports_per_engine = i2c_ports_per_engine;
21092b548a42SCédric Le Goater
21102b548a42SCédric Le Goater device_class_set_parent_realize(dc, pnv_chip_power10_realize,
21112b548a42SCédric Le Goater &k->parent_realize);
21122b548a42SCédric Le Goater }
21132b548a42SCédric Le Goater
pnv_chip_core_sanitize(PnvChip * chip,Error ** errp)2114397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
2115397a79e7SCédric Le Goater {
2116397a79e7SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
2117397a79e7SCédric Le Goater int cores_max;
2118397a79e7SCédric Le Goater
2119397a79e7SCédric Le Goater /*
2120397a79e7SCédric Le Goater * No custom mask for this chip, let's use the default one from *
2121397a79e7SCédric Le Goater * the chip class
2122397a79e7SCédric Le Goater */
2123397a79e7SCédric Le Goater if (!chip->cores_mask) {
2124397a79e7SCédric Le Goater chip->cores_mask = pcc->cores_mask;
2125397a79e7SCédric Le Goater }
2126397a79e7SCédric Le Goater
2127397a79e7SCédric Le Goater /* filter alien core ids ! some are reserved */
2128397a79e7SCédric Le Goater if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
2129397a79e7SCédric Le Goater error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
2130397a79e7SCédric Le Goater chip->cores_mask);
2131397a79e7SCédric Le Goater return;
2132397a79e7SCédric Le Goater }
2133397a79e7SCédric Le Goater chip->cores_mask &= pcc->cores_mask;
2134397a79e7SCédric Le Goater
2135397a79e7SCédric Le Goater /* now that we have a sane layout, let check the number of cores */
213627d9ffd4SDavid Gibson cores_max = ctpop64(chip->cores_mask);
2137397a79e7SCédric Le Goater if (chip->nr_cores > cores_max) {
2138397a79e7SCédric Le Goater error_setg(errp, "warning: too many cores for chip ! Limit is %d",
2139397a79e7SCédric Le Goater cores_max);
2140397a79e7SCédric Le Goater return;
2141397a79e7SCédric Le Goater }
2142397a79e7SCédric Le Goater }
2143397a79e7SCédric Le Goater
pnv_chip_core_realize(PnvChip * chip,Error ** errp)214451c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
2145e997040eSCédric Le Goater {
2146397a79e7SCédric Le Goater Error *error = NULL;
2147d2fd9612SCédric Le Goater PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
214840abf43fSIgor Mammedov const char *typename = pnv_chip_core_typename(chip);
2149d2fd9612SCédric Le Goater int i, core_hwid;
215008c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
2151397a79e7SCédric Le Goater
2152d2fd9612SCédric Le Goater if (!object_class_by_name(typename)) {
2153d2fd9612SCédric Le Goater error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
2154d2fd9612SCédric Le Goater return;
2155d2fd9612SCédric Le Goater }
2156d2fd9612SCédric Le Goater
2157d2fd9612SCédric Le Goater /* Cores */
2158397a79e7SCédric Le Goater pnv_chip_core_sanitize(chip, &error);
2159397a79e7SCédric Le Goater if (error) {
2160397a79e7SCédric Le Goater error_propagate(errp, error);
2161397a79e7SCédric Le Goater return;
2162397a79e7SCédric Le Goater }
2163d2fd9612SCédric Le Goater
21644fa28f23SGreg Kurz chip->cores = g_new0(PnvCore *, chip->nr_cores);
2165d2fd9612SCédric Le Goater
2166d2fd9612SCédric Le Goater for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
2167d2fd9612SCédric Le Goater && (i < chip->nr_cores); core_hwid++) {
2168d2fd9612SCédric Le Goater char core_name[32];
21694fa28f23SGreg Kurz PnvCore *pnv_core;
2170c035851aSCédric Le Goater uint64_t xscom_core_base;
2171d2fd9612SCédric Le Goater
2172d2fd9612SCédric Le Goater if (!(chip->cores_mask & (1ull << core_hwid))) {
2173d2fd9612SCédric Le Goater continue;
2174d2fd9612SCédric Le Goater }
2175d2fd9612SCédric Le Goater
21764fa28f23SGreg Kurz pnv_core = PNV_CORE(object_new(typename));
21774fa28f23SGreg Kurz
2178d2fd9612SCédric Le Goater snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
2179d2623129SMarkus Armbruster object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
21804fa28f23SGreg Kurz chip->cores[i] = pnv_core;
21815325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "nr-threads",
21825325cc34SMarkus Armbruster chip->nr_threads, &error_fatal);
21835325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
21845325cc34SMarkus Armbruster core_hwid, &error_fatal);
21859940412aSCaleb Schlossin object_property_set_int(OBJECT(pnv_core), "hwid", core_hwid,
21869940412aSCaleb Schlossin &error_fatal);
21875325cc34SMarkus Armbruster object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
21885325cc34SMarkus Armbruster &error_fatal);
21895325cc34SMarkus Armbruster object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
2190158e17a6SGreg Kurz &error_abort);
2191ce189ab2SMarkus Armbruster qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
219224ece072SCédric Le Goater
219324ece072SCédric Le Goater /* Each core has an XSCOM MMIO region */
2194c4b2c40cSGreg Kurz xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
2195c035851aSCédric Le Goater
2196c035851aSCédric Le Goater pnv_xscom_add_subregion(chip, xscom_core_base,
21974fa28f23SGreg Kurz &pnv_core->xscom_regs);
2198d2fd9612SCédric Le Goater i++;
2199d2fd9612SCédric Le Goater }
220051c04728SCédric Le Goater }
220151c04728SCédric Le Goater
pnv_chip_realize(DeviceState * dev,Error ** errp)220251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
220351c04728SCédric Le Goater {
220451c04728SCédric Le Goater PnvChip *chip = PNV_CHIP(dev);
220551c04728SCédric Le Goater Error *error = NULL;
220651c04728SCédric Le Goater
220751c04728SCédric Le Goater /* Cores */
220851c04728SCédric Le Goater pnv_chip_core_realize(chip, &error);
220951c04728SCédric Le Goater if (error) {
221051c04728SCédric Le Goater error_propagate(errp, error);
221151c04728SCédric Le Goater return;
221251c04728SCédric Le Goater }
2213e997040eSCédric Le Goater }
2214e997040eSCédric Le Goater
2215e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
2216e997040eSCédric Le Goater DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
2217e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
2218e997040eSCédric Le Goater DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
2219397a79e7SCédric Le Goater DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
2220397a79e7SCédric Le Goater DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
2221764f9b25SGreg Kurz DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
2222e997040eSCédric Le Goater DEFINE_PROP_END_OF_LIST(),
2223e997040eSCédric Le Goater };
2224e997040eSCédric Le Goater
pnv_chip_class_init(ObjectClass * klass,void * data)2225e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
2226e997040eSCédric Le Goater {
2227e997040eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass);
2228e997040eSCédric Le Goater
22299d169fb3SThomas Huth set_bit(DEVICE_CATEGORY_CPU, dc->categories);
2230e997040eSCédric Le Goater dc->realize = pnv_chip_realize;
22314f67d30bSMarc-André Lureau device_class_set_props(dc, pnv_chip_properties);
2232e997040eSCédric Le Goater dc->desc = "PowerNV Chip";
2233e997040eSCédric Le Goater }
2234e997040eSCédric Le Goater
pnv_chip_find_core(PnvChip * chip,uint32_t core_id)2235cde2ba34SNicholas Piggin PnvCore *pnv_chip_find_core(PnvChip *chip, uint32_t core_id)
2236cde2ba34SNicholas Piggin {
2237cde2ba34SNicholas Piggin int i;
2238cde2ba34SNicholas Piggin
2239cde2ba34SNicholas Piggin for (i = 0; i < chip->nr_cores; i++) {
2240cde2ba34SNicholas Piggin PnvCore *pc = chip->cores[i];
2241cde2ba34SNicholas Piggin CPUCore *cc = CPU_CORE(pc);
2242cde2ba34SNicholas Piggin
2243cde2ba34SNicholas Piggin if (cc->core_id == core_id) {
2244cde2ba34SNicholas Piggin return pc;
2245cde2ba34SNicholas Piggin }
2246cde2ba34SNicholas Piggin }
2247cde2ba34SNicholas Piggin return NULL;
2248cde2ba34SNicholas Piggin }
2249cde2ba34SNicholas Piggin
pnv_chip_find_cpu(PnvChip * chip,uint32_t pir)2250119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
2251119eaa9dSCédric Le Goater {
2252119eaa9dSCédric Le Goater int i, j;
2253119eaa9dSCédric Le Goater
2254119eaa9dSCédric Le Goater for (i = 0; i < chip->nr_cores; i++) {
2255119eaa9dSCédric Le Goater PnvCore *pc = chip->cores[i];
2256119eaa9dSCédric Le Goater CPUCore *cc = CPU_CORE(pc);
2257119eaa9dSCédric Le Goater
2258119eaa9dSCédric Le Goater for (j = 0; j < cc->nr_threads; j++) {
2259119eaa9dSCédric Le Goater if (ppc_cpu_pir(pc->threads[j]) == pir) {
2260119eaa9dSCédric Le Goater return pc->threads[j];
2261119eaa9dSCédric Le Goater }
2262119eaa9dSCédric Le Goater }
2263119eaa9dSCédric Le Goater }
2264119eaa9dSCédric Le Goater return NULL;
2265119eaa9dSCédric Le Goater }
2266119eaa9dSCédric Le Goater
pnv_ics_get(XICSFabric * xi,int irq)226754f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
226854f59d78SCédric Le Goater {
2269b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi);
2270da6be501SDaniel Henrique Barboza int i, j;
227154f59d78SCédric Le Goater
227254f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
227377864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
227477864267SCédric Le Goater
227577864267SCédric Le Goater if (ics_valid_irq(&chip8->psi.ics, irq)) {
227677864267SCédric Le Goater return &chip8->psi.ics;
227754f59d78SCédric Le Goater }
22782ff73ddaSCédric Le Goater
2279da6be501SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) {
22800d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j];
22811f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2282da6be501SDaniel Henrique Barboza
2283da6be501SDaniel Henrique Barboza if (ics_valid_irq(&phb3->lsis, irq)) {
2284da6be501SDaniel Henrique Barboza return &phb3->lsis;
2285da6be501SDaniel Henrique Barboza }
2286da6be501SDaniel Henrique Barboza
2287da6be501SDaniel Henrique Barboza if (ics_valid_irq(ICS(&phb3->msis), irq)) {
2288da6be501SDaniel Henrique Barboza return ICS(&phb3->msis);
2289da6be501SDaniel Henrique Barboza }
22909ae1329eSCédric Le Goater }
229154f59d78SCédric Le Goater }
229254f59d78SCédric Le Goater return NULL;
229354f59d78SCédric Le Goater }
229454f59d78SCédric Le Goater
pnv_get_chip(PnvMachineState * pnv,uint32_t chip_id)22951f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
22961f6a88ffSCédric Le Goater {
22971f6a88ffSCédric Le Goater int i;
22981f6a88ffSCédric Le Goater
22991f6a88ffSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
23001f6a88ffSCédric Le Goater PnvChip *chip = pnv->chips[i];
23011f6a88ffSCédric Le Goater if (chip->chip_id == chip_id) {
23021f6a88ffSCédric Le Goater return chip;
23031f6a88ffSCédric Le Goater }
23041f6a88ffSCédric Le Goater }
23051f6a88ffSCédric Le Goater return NULL;
23061f6a88ffSCédric Le Goater }
23071f6a88ffSCédric Le Goater
pnv_ics_resend(XICSFabric * xi)230854f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
230954f59d78SCédric Le Goater {
2310b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xi);
2311ca459489SDaniel Henrique Barboza int i, j;
231254f59d78SCédric Le Goater
231354f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
231477864267SCédric Le Goater Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
23159ae1329eSCédric Le Goater
231677864267SCédric Le Goater ics_resend(&chip8->psi.ics);
2317ca459489SDaniel Henrique Barboza
2318ca459489SDaniel Henrique Barboza for (j = 0; j < chip8->num_phbs; j++) {
23190d512c71SDaniel Henrique Barboza PnvPHB *phb = chip8->phbs[j];
23201f5d6b2aSDaniel Henrique Barboza PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2321ca459489SDaniel Henrique Barboza
2322ca459489SDaniel Henrique Barboza ics_resend(&phb3->lsis);
2323ca459489SDaniel Henrique Barboza ics_resend(ICS(&phb3->msis));
2324ca459489SDaniel Henrique Barboza }
232554f59d78SCédric Le Goater }
232654f59d78SCédric Le Goater }
232754f59d78SCédric Le Goater
pnv_icp_get(XICSFabric * xi,int pir)232836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
232936fc6f08SCédric Le Goater {
233036fc6f08SCédric Le Goater PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
233136fc6f08SCédric Le Goater
2332956b8f46SCédric Le Goater return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
233336fc6f08SCédric Le Goater }
233436fc6f08SCédric Le Goater
pnv_pic_print_info(InterruptStatsProvider * obj,Monitor * mon)233547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
233647fea43aSCédric Le Goater Monitor *mon)
233747fea43aSCédric Le Goater {
2338b168a138SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj);
233954f59d78SCédric Le Goater int i;
234047fea43aSCédric Le Goater CPUState *cs;
234147fea43aSCédric Le Goater
234247fea43aSCédric Le Goater CPU_FOREACH(cs) {
234347fea43aSCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs);
234447fea43aSCédric Le Goater
234585913070SGreg Kurz /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
234685913070SGreg Kurz PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
234785913070SGreg Kurz mon);
2348d8e4aad5SCédric Le Goater }
234954f59d78SCédric Le Goater
235054f59d78SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
2351d8e4aad5SCédric Le Goater PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
235254f59d78SCédric Le Goater }
235347fea43aSCédric Le Goater }
235447fea43aSCédric Le Goater
pnv_match_nvt(XiveFabric * xfb,uint8_t format,uint8_t nvt_blk,uint32_t nvt_idx,bool cam_ignore,uint8_t priority,uint32_t logic_serv,XiveTCTXMatch * match)2355c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2356c722579eSCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx,
2357c722579eSCédric Le Goater bool cam_ignore, uint8_t priority,
2358c722579eSCédric Le Goater uint32_t logic_serv,
2359c722579eSCédric Le Goater XiveTCTXMatch *match)
2360c722579eSCédric Le Goater {
2361c722579eSCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb);
2362c722579eSCédric Le Goater int total_count = 0;
2363c722579eSCédric Le Goater int i;
2364c722579eSCédric Le Goater
2365c722579eSCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
2366c722579eSCédric Le Goater Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2367c722579eSCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2368c722579eSCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2369c722579eSCédric Le Goater int count;
2370c722579eSCédric Le Goater
2371c722579eSCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2372c722579eSCédric Le Goater priority, logic_serv, match);
2373c722579eSCédric Le Goater
2374c722579eSCédric Le Goater if (count < 0) {
2375c722579eSCédric Le Goater return count;
2376c722579eSCédric Le Goater }
2377c722579eSCédric Le Goater
2378c722579eSCédric Le Goater total_count += count;
2379c722579eSCédric Le Goater }
2380c722579eSCédric Le Goater
2381c722579eSCédric Le Goater return total_count;
2382c722579eSCédric Le Goater }
2383c722579eSCédric Le Goater
pnv10_xive_match_nvt(XiveFabric * xfb,uint8_t format,uint8_t nvt_blk,uint32_t nvt_idx,bool cam_ignore,uint8_t priority,uint32_t logic_serv,XiveTCTXMatch * match)2384da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2385da71b7e3SCédric Le Goater uint8_t nvt_blk, uint32_t nvt_idx,
2386da71b7e3SCédric Le Goater bool cam_ignore, uint8_t priority,
2387da71b7e3SCédric Le Goater uint32_t logic_serv,
2388da71b7e3SCédric Le Goater XiveTCTXMatch *match)
2389da71b7e3SCédric Le Goater {
2390da71b7e3SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(xfb);
2391da71b7e3SCédric Le Goater int total_count = 0;
2392da71b7e3SCédric Le Goater int i;
2393da71b7e3SCédric Le Goater
2394da71b7e3SCédric Le Goater for (i = 0; i < pnv->num_chips; i++) {
2395da71b7e3SCédric Le Goater Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2396da71b7e3SCédric Le Goater XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2397da71b7e3SCédric Le Goater XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2398da71b7e3SCédric Le Goater int count;
2399da71b7e3SCédric Le Goater
2400da71b7e3SCédric Le Goater count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2401da71b7e3SCédric Le Goater priority, logic_serv, match);
2402da71b7e3SCédric Le Goater
2403da71b7e3SCédric Le Goater if (count < 0) {
2404da71b7e3SCédric Le Goater return count;
2405da71b7e3SCédric Le Goater }
2406da71b7e3SCédric Le Goater
2407da71b7e3SCédric Le Goater total_count += count;
2408da71b7e3SCédric Le Goater }
2409da71b7e3SCédric Le Goater
2410da71b7e3SCédric Le Goater return total_count;
2411da71b7e3SCédric Le Goater }
2412da71b7e3SCédric Le Goater
pnv_machine_power8_class_init(ObjectClass * oc,void * data)2413f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
24149e933f4aSBenjamin Herrenschmidt {
24159e933f4aSBenjamin Herrenschmidt MachineClass *mc = MACHINE_CLASS(oc);
241636fc6f08SCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2417d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2418d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2419f30c843cSCédric Le Goater
24201f5d6b2aSDaniel Henrique Barboza static GlobalProperty phb_compat[] = {
24211f5d6b2aSDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "3" },
242280515061SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
24231f5d6b2aSDaniel Henrique Barboza };
24241f5d6b2aSDaniel Henrique Barboza
2425f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2426f30c843cSCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
24271f5d6b2aSDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2428f30c843cSCédric Le Goater
2429f30c843cSCédric Le Goater xic->icp_get = pnv_icp_get;
2430f30c843cSCédric Le Goater xic->ics_get = pnv_ics_get;
2431f30c843cSCédric Le Goater xic->ics_resend = pnv_ics_resend;
2432d76f2da7SGreg Kurz
2433d76f2da7SGreg Kurz pmc->compat = compat;
2434d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat);
2435892c3ad0SDaniel Henrique Barboza
2436892c3ad0SDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2437f30c843cSCédric Le Goater }
2438f30c843cSCédric Le Goater
pnv_machine_power9_class_init(ObjectClass * oc,void * data)2439f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2440f30c843cSCédric Le Goater {
2441f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc);
2442c722579eSCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2443d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2444d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv9\0ibm,powernv";
2445f30c843cSCédric Le Goater
2446210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = {
2447210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "4" },
2448c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "4" },
2449210aacb3SDaniel Henrique Barboza };
2450210aacb3SDaniel Henrique Barboza
2451f30c843cSCédric Le Goater mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2452277ee172SNicholas Piggin mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
2453210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2454210aacb3SDaniel Henrique Barboza
2455c722579eSCédric Le Goater xfc->match_nvt = pnv_match_nvt;
2456f30c843cSCédric Le Goater
2457d76f2da7SGreg Kurz pmc->compat = compat;
2458d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat);
24597a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt;
2460d786be3fSDaniel Henrique Barboza
2461d786be3fSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2462f30c843cSCédric Le Goater }
2463f30c843cSCédric Le Goater
pnv_machine_p10_common_class_init(ObjectClass * oc,void * data)2464ab874668SGlenn Miles static void pnv_machine_p10_common_class_init(ObjectClass *oc, void *data)
24652b548a42SCédric Le Goater {
24662b548a42SCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc);
2467d76f2da7SGreg Kurz PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2468da71b7e3SCédric Le Goater XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2469d76f2da7SGreg Kurz static const char compat[] = "qemu,powernv10\0ibm,powernv";
24702b548a42SCédric Le Goater
2471210aacb3SDaniel Henrique Barboza static GlobalProperty phb_compat[] = {
2472210aacb3SDaniel Henrique Barboza { TYPE_PNV_PHB, "version", "5" },
2473c8d14603SDaniel Henrique Barboza { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
2474210aacb3SDaniel Henrique Barboza };
2475210aacb3SDaniel Henrique Barboza
24766bc8c046SCédric Le Goater mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2477210aacb3SDaniel Henrique Barboza compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2478d76f2da7SGreg Kurz
247921465adeSNicholas Piggin mc->alias = "powernv";
248021465adeSNicholas Piggin
2481d76f2da7SGreg Kurz pmc->compat = compat;
2482d76f2da7SGreg Kurz pmc->compat_size = sizeof(compat);
24837a90c6a1SGreg Kurz pmc->dt_power_mgt = pnv_dt_power_mgt;
2484da71b7e3SCédric Le Goater
2485da71b7e3SCédric Le Goater xfc->match_nvt = pnv10_xive_match_nvt;
2486f1327fdeSDaniel Henrique Barboza
2487f1327fdeSDaniel Henrique Barboza machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
24882b548a42SCédric Le Goater }
24892b548a42SCédric Le Goater
pnv_machine_power10_class_init(ObjectClass * oc,void * data)2490ab874668SGlenn Miles static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
2491ab874668SGlenn Miles {
2492ab874668SGlenn Miles MachineClass *mc = MACHINE_CLASS(oc);
2493ab874668SGlenn Miles
2494ab874668SGlenn Miles pnv_machine_p10_common_class_init(oc, data);
2495ab874668SGlenn Miles mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
2496ab874668SGlenn Miles }
2497ab874668SGlenn Miles
pnv_machine_p10_rainier_class_init(ObjectClass * oc,void * data)2498ab874668SGlenn Miles static void pnv_machine_p10_rainier_class_init(ObjectClass *oc, void *data)
2499ab874668SGlenn Miles {
2500ab874668SGlenn Miles MachineClass *mc = MACHINE_CLASS(oc);
250133467ecbSGlenn Miles PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2502ab874668SGlenn Miles
2503ab874668SGlenn Miles pnv_machine_p10_common_class_init(oc, data);
2504ab874668SGlenn Miles mc->desc = "IBM PowerNV (Non-Virtualized) POWER10 Rainier";
250533467ecbSGlenn Miles pmc->i2c_init = pnv_rainier_i2c_init;
2506ab874668SGlenn Miles }
2507ab874668SGlenn Miles
pnv_machine_get_hb(Object * obj,Error ** errp)250808c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
250908c3f3a7SCédric Le Goater {
251008c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj);
251108c3f3a7SCédric Le Goater
251208c3f3a7SCédric Le Goater return !!pnv->fw_load_addr;
251308c3f3a7SCédric Le Goater }
251408c3f3a7SCédric Le Goater
pnv_machine_set_hb(Object * obj,bool value,Error ** errp)251508c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
251608c3f3a7SCédric Le Goater {
251708c3f3a7SCédric Le Goater PnvMachineState *pnv = PNV_MACHINE(obj);
251808c3f3a7SCédric Le Goater
251908c3f3a7SCédric Le Goater if (value) {
252008c3f3a7SCédric Le Goater pnv->fw_load_addr = 0x8000000;
252108c3f3a7SCédric Le Goater }
252208c3f3a7SCédric Le Goater }
252308c3f3a7SCédric Le Goater
pnv_cpu_do_nmi_on_cpu(CPUState * cs,run_on_cpu_data arg)252401b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
252501b552b0SNicholas Piggin {
252601b552b0SNicholas Piggin CPUPPCState *env = cpu_env(cs);
252701b552b0SNicholas Piggin
252801b552b0SNicholas Piggin cpu_synchronize_state(cs);
252901b552b0SNicholas Piggin ppc_cpu_do_system_reset(cs);
253001b552b0SNicholas Piggin if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
25310911a60cSLeonardo Bras /*
253201b552b0SNicholas Piggin * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2533fe837714SNicholas Piggin * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2534fe837714SNicholas Piggin * (PPC_BIT(43)).
2535fe837714SNicholas Piggin */
253601b552b0SNicholas Piggin if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
25370911a60cSLeonardo Bras warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
2538fe837714SNicholas Piggin env->spr[SPR_SRR1] |= SRR1_WAKERESET;
25390911a60cSLeonardo Bras }
254001b552b0SNicholas Piggin } else {
2541fe837714SNicholas Piggin /*
2542fe837714SNicholas Piggin * For non-powersave system resets, SRR1[42:45] are defined to be
2543fe837714SNicholas Piggin * implementation-dependent. The POWER9 User Manual specifies that
2544fe837714SNicholas Piggin * an external (SCOM driven, which may come from a BMC nmi command or
2545fe837714SNicholas Piggin * another CPU requesting a NMI IPI) system reset exception should be
2546fe837714SNicholas Piggin * 0b0010 (PPC_BIT(44)).
2547fe837714SNicholas Piggin */
2548fe837714SNicholas Piggin env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
25490911a60cSLeonardo Bras }
2550fe837714SNicholas Piggin }
2551fe837714SNicholas Piggin
pnv_nmi(NMIState * n,int cpu_index,Error ** errp)255201b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
255301b552b0SNicholas Piggin {
255401b552b0SNicholas Piggin CPUState *cs;
255501b552b0SNicholas Piggin
255601b552b0SNicholas Piggin CPU_FOREACH(cs) {
255701b552b0SNicholas Piggin async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
255801b552b0SNicholas Piggin }
255901b552b0SNicholas Piggin }
256001b552b0SNicholas Piggin
pnv_machine_class_init(ObjectClass * oc,void * data)256101b552b0SNicholas Piggin static void pnv_machine_class_init(ObjectClass *oc, void *data)
2562f30c843cSCédric Le Goater {
2563f30c843cSCédric Le Goater MachineClass *mc = MACHINE_CLASS(oc);
2564f30c843cSCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
256547fea43aSCédric Le Goater NMIClass *nc = NMI_CLASS(oc);
256601b552b0SNicholas Piggin
25679e933f4aSBenjamin Herrenschmidt mc->desc = "IBM PowerNV (Non-Virtualized)";
25689e933f4aSBenjamin Herrenschmidt mc->init = pnv_init;
2569b168a138SCédric Le Goater mc->reset = pnv_reset;
2570b168a138SCédric Le Goater mc->max_cpus = MAX_CPUS;
25719e933f4aSBenjamin Herrenschmidt /* Pnv provides a AHCI device for storage */
257259b7c1c2SBalamuruhan S mc->block_default_type = IF_IDE;
257359b7c1c2SBalamuruhan S mc->no_parallel = 1;
25749e933f4aSBenjamin Herrenschmidt mc->default_boot_order = NULL;
25759e933f4aSBenjamin Herrenschmidt /*
2576f1d18b0aSJoel Stanley * RAM defaults to less than 2048 for 32-bit hosts, and large
2577f1d18b0aSJoel Stanley * enough to fit the maximum initrd size at it's load address
2578f1d18b0aSJoel Stanley */
2579f1d18b0aSJoel Stanley mc->default_ram_size = 1 * GiB;
2580dd7ef911SCédric Le Goater mc->default_ram_id = "pnv.ram";
2581173a36d8SIgor Mammedov ispc->print_info = pnv_pic_print_info;
258247fea43aSCédric Le Goater nc->nmi_monitor_handler = pnv_nmi;
258301b552b0SNicholas Piggin
258408c3f3a7SCédric Le Goater object_class_property_add_bool(oc, "hb-mode",
258508c3f3a7SCédric Le Goater pnv_machine_get_hb, pnv_machine_set_hb);
2586d2623129SMarkus Armbruster object_class_property_set_description(oc, "hb-mode",
258708c3f3a7SCédric Le Goater "Use a hostboot like boot loader");
25887eecec7dSMarkus Armbruster }
25899e933f4aSBenjamin Herrenschmidt
25909e933f4aSBenjamin Herrenschmidt #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
259177864267SCédric Le Goater { \
2592beba5c0fSIgor Mammedov .name = type, \
2593beba5c0fSIgor Mammedov .class_init = class_initfn, \
2594beba5c0fSIgor Mammedov .parent = TYPE_PNV8_CHIP, \
259577864267SCédric Le Goater }
259677864267SCédric Le Goater
259777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
259877864267SCédric Le Goater { \
259977864267SCédric Le Goater .name = type, \
260077864267SCédric Le Goater .class_init = class_initfn, \
260177864267SCédric Le Goater .parent = TYPE_PNV9_CHIP, \
260277864267SCédric Le Goater }
2603beba5c0fSIgor Mammedov
2604beba5c0fSIgor Mammedov #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
26052b548a42SCédric Le Goater { \
26062b548a42SCédric Le Goater .name = type, \
26072b548a42SCédric Le Goater .class_init = class_initfn, \
26082b548a42SCédric Le Goater .parent = TYPE_PNV10_CHIP, \
26092b548a42SCédric Le Goater }
26102b548a42SCédric Le Goater
26112b548a42SCédric Le Goater static const TypeInfo types[] = {
2612beba5c0fSIgor Mammedov {
26131aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv10-rainier"),
2614ab874668SGlenn Miles .parent = MACHINE_TYPE_NAME("powernv10"),
2615ab874668SGlenn Miles .class_init = pnv_machine_p10_rainier_class_init,
2616ab874668SGlenn Miles },
2617ab874668SGlenn Miles {
2618ab874668SGlenn Miles .name = MACHINE_TYPE_NAME("powernv10"),
26192b548a42SCédric Le Goater .parent = TYPE_PNV_MACHINE,
26202b548a42SCédric Le Goater .class_init = pnv_machine_power10_class_init,
26212b548a42SCédric Le Goater .interfaces = (InterfaceInfo[]) {
2622da71b7e3SCédric Le Goater { TYPE_XIVE_FABRIC },
2623da71b7e3SCédric Le Goater { },
2624da71b7e3SCédric Le Goater },
2625da71b7e3SCédric Le Goater },
26262b548a42SCédric Le Goater {
26272b548a42SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv9"),
26281aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE,
26291aba8716SCédric Le Goater .class_init = pnv_machine_power9_class_init,
26301aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) {
2631c722579eSCédric Le Goater { TYPE_XIVE_FABRIC },
2632c722579eSCédric Le Goater { },
2633c722579eSCédric Le Goater },
2634c722579eSCédric Le Goater },
26351aba8716SCédric Le Goater {
26361aba8716SCédric Le Goater .name = MACHINE_TYPE_NAME("powernv8"),
26371aba8716SCédric Le Goater .parent = TYPE_PNV_MACHINE,
26381aba8716SCédric Le Goater .class_init = pnv_machine_power8_class_init,
26391aba8716SCédric Le Goater .interfaces = (InterfaceInfo[]) {
26401aba8716SCédric Le Goater { TYPE_XICS_FABRIC },
26411aba8716SCédric Le Goater { },
26421aba8716SCédric Le Goater },
26431aba8716SCédric Le Goater },
26441aba8716SCédric Le Goater {
2645beba5c0fSIgor Mammedov .name = TYPE_PNV_MACHINE,
2646b168a138SCédric Le Goater .parent = TYPE_MACHINE,
26479e933f4aSBenjamin Herrenschmidt .abstract = true,
2648f30c843cSCédric Le Goater .instance_size = sizeof(PnvMachineState),
26499e933f4aSBenjamin Herrenschmidt .class_init = pnv_machine_class_init,
2650b168a138SCédric Le Goater .class_size = sizeof(PnvMachineClass),
2651d76f2da7SGreg Kurz .interfaces = (InterfaceInfo[]) {
265236fc6f08SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER },
265347fea43aSCédric Le Goater { TYPE_NMI },
265401b552b0SNicholas Piggin { },
265536fc6f08SCédric Le Goater },
265636fc6f08SCédric Le Goater },
2657beba5c0fSIgor Mammedov {
2658beba5c0fSIgor Mammedov .name = TYPE_PNV_CHIP,
2659beba5c0fSIgor Mammedov .parent = TYPE_SYS_BUS_DEVICE,
2660beba5c0fSIgor Mammedov .class_init = pnv_chip_class_init,
2661beba5c0fSIgor Mammedov .instance_size = sizeof(PnvChip),
2662beba5c0fSIgor Mammedov .class_size = sizeof(PnvChipClass),
2663beba5c0fSIgor Mammedov .abstract = true,
2664beba5c0fSIgor Mammedov },
2665beba5c0fSIgor Mammedov
266677864267SCédric Le Goater /*
266777864267SCédric Le Goater * P10 chip and variants
26682b548a42SCédric Le Goater */
26692b548a42SCédric Le Goater {
26702b548a42SCédric Le Goater .name = TYPE_PNV10_CHIP,
26712b548a42SCédric Le Goater .parent = TYPE_PNV_CHIP,
26722b548a42SCédric Le Goater .instance_init = pnv_chip_power10_instance_init,
26732b548a42SCédric Le Goater .instance_size = sizeof(Pnv10Chip),
26742b548a42SCédric Le Goater },
26752b548a42SCédric Le Goater DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
26762b548a42SCédric Le Goater
26772b548a42SCédric Le Goater /*
26782b548a42SCédric Le Goater * P9 chip and variants
267977864267SCédric Le Goater */
268077864267SCédric Le Goater {
268177864267SCédric Le Goater .name = TYPE_PNV9_CHIP,
268277864267SCédric Le Goater .parent = TYPE_PNV_CHIP,
268377864267SCédric Le Goater .instance_init = pnv_chip_power9_instance_init,
268477864267SCédric Le Goater .instance_size = sizeof(Pnv9Chip),
268577864267SCédric Le Goater },
268677864267SCédric Le Goater DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
268777864267SCédric Le Goater
268877864267SCédric Le Goater /*
268977864267SCédric Le Goater * P8 chip and variants
269077864267SCédric Le Goater */
269177864267SCédric Le Goater {
269277864267SCédric Le Goater .name = TYPE_PNV8_CHIP,
269377864267SCédric Le Goater .parent = TYPE_PNV_CHIP,
269477864267SCédric Le Goater .instance_init = pnv_chip_power8_instance_init,
269577864267SCédric Le Goater .instance_size = sizeof(Pnv8Chip),
269677864267SCédric Le Goater },
269777864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
269877864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
269977864267SCédric Le Goater DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
270077864267SCédric Le Goater pnv_chip_power8nvl_class_init),
2701beba5c0fSIgor Mammedov };
27029e933f4aSBenjamin Herrenschmidt
27039e933f4aSBenjamin Herrenschmidt DEFINE_TYPES(types)
2704beba5c0fSIgor Mammedov