xref: /qemu/hw/ppc/pnv.c (revision adb77996)
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"
479e933f4aSBenjamin Herrenschmidt 
4836fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
49a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
50967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5135dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
52967b7523SCédric Le Goater 
533495b6b6SCédric Le Goater #include "hw/isa/isa.h"
543495b6b6SCédric Le Goater #include "hw/char/serial.h"
55bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
563495b6b6SCédric Le Goater 
579e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
589e933f4aSBenjamin Herrenschmidt 
59b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
609e933f4aSBenjamin Herrenschmidt 
619e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
629e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
6383fa6e2aSCédric Le Goater #define FW_MAX_SIZE             (16 * MiB)
649e933f4aSBenjamin Herrenschmidt 
659e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
6605ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE         (128 * MiB)
6705ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR        0x28000000
6805ce9b73SCédric Le Goater #define INITRD_MAX_SIZE         (128 * MiB)
699e933f4aSBenjamin Herrenschmidt 
7040abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7140abf43fSIgor Mammedov {
7240abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7340abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7440abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7540abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7640abf43fSIgor Mammedov     g_free(s);
7740abf43fSIgor Mammedov     return core_type;
7840abf43fSIgor Mammedov }
7940abf43fSIgor Mammedov 
809e933f4aSBenjamin Herrenschmidt /*
819e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
829e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
839e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
849e933f4aSBenjamin Herrenschmidt  */
859e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
869e933f4aSBenjamin Herrenschmidt 
879e933f4aSBenjamin Herrenschmidt /*
889e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
899e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
909e933f4aSBenjamin Herrenschmidt  * per chip.
919e933f4aSBenjamin Herrenschmidt  */
92b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
939e933f4aSBenjamin Herrenschmidt {
949e933f4aSBenjamin Herrenschmidt     char *mem_name;
959e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
969e933f4aSBenjamin Herrenschmidt     int off;
979e933f4aSBenjamin Herrenschmidt 
989e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
999e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
1009e933f4aSBenjamin Herrenschmidt 
1019e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1029e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1039e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1049e933f4aSBenjamin Herrenschmidt 
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1069e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1079e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1089e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1099e933f4aSBenjamin Herrenschmidt }
1109e933f4aSBenjamin Herrenschmidt 
111d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
112d2fd9612SCédric Le Goater {
113d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
114d2fd9612SCédric Le Goater 
115d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
116a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
117d2fd9612SCédric Le Goater         if (cpus_offset) {
118d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
119d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
120d2fd9612SCédric Le Goater         }
121d2fd9612SCédric Le Goater     }
122d2fd9612SCédric Le Goater     _FDT(cpus_offset);
123d2fd9612SCédric Le Goater     return cpus_offset;
124d2fd9612SCédric Le Goater }
125d2fd9612SCédric Le Goater 
126d2fd9612SCédric Le Goater /*
127d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
128d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
129d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
130d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
131d2fd9612SCédric Le Goater  * servers.
132d2fd9612SCédric Le Goater  */
133b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
134d2fd9612SCédric Le Goater {
13508304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13608304a86SDavid Gibson     CPUState *cs = CPU(cpu);
137d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1388bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
139d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
140d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
141a580fdcdSPhilippe Mathieu-Daudé     g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
142d2fd9612SCédric Le Goater     int i;
143d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
144d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
145d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
146d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
147d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
148d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
149d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
150d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
151d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
152d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
153d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
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 
158d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
159d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
160d2fd9612SCédric Le Goater     _FDT(offset);
161d2fd9612SCédric Le Goater     g_free(nodename);
162d2fd9612SCédric Le Goater 
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
164d2fd9612SCédric Le Goater 
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
168d2fd9612SCédric Le Goater 
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
171d2fd9612SCédric Le Goater                             env->dcache_line_size)));
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
173d2fd9612SCédric Le Goater                             env->dcache_line_size)));
174d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
175d2fd9612SCédric Le Goater                             env->icache_line_size)));
176d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
177d2fd9612SCédric Le Goater                             env->icache_line_size)));
178d2fd9612SCédric Le Goater 
179d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
180d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
181d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
182d2fd9612SCédric Le Goater     } else {
1833dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
184d2fd9612SCédric Le Goater     }
185d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
186d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
187d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
188d2fd9612SCédric Le Goater     } else {
1893dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
190d2fd9612SCédric Le Goater     }
191d2fd9612SCédric Le Goater 
192d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19459b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19559b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
196d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
197d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
198d2fd9612SCédric Le Goater 
19903282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
200d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
201d2fd9612SCédric Le Goater     }
202d2fd9612SCédric Le Goater 
20358969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
204d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
205d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
206d2fd9612SCédric Le Goater     }
207d2fd9612SCédric Le Goater 
20859b7c1c2SBalamuruhan S     /*
20959b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
210d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
211d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21259b7c1c2SBalamuruhan S      *   2               == VSX available
21359b7c1c2SBalamuruhan S      */
214d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
215d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
216d2fd9612SCédric Le Goater 
217d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
218d2fd9612SCédric Le Goater     }
219d2fd9612SCédric Le Goater 
22059b7c1c2SBalamuruhan S     /*
22159b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
222d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22359b7c1c2SBalamuruhan S      *   1               == DFP available
22459b7c1c2SBalamuruhan S      */
225d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
226d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
227d2fd9612SCédric Le Goater     }
228d2fd9612SCédric Le Goater 
229644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
230d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
231d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
232d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
233d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
234d2fd9612SCédric Le Goater     }
235d2fd9612SCédric Le Goater 
236d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
237d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
238d2fd9612SCédric Le Goater 
239d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
240d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
241d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
242d2fd9612SCédric Le Goater     }
243d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
244a580fdcdSPhilippe Mathieu-Daudé                        servers_prop, sizeof(*servers_prop) * smt_threads)));
245d2fd9612SCédric Le Goater }
246d2fd9612SCédric Le Goater 
247b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
248bf5615e7SCédric Le Goater                        uint32_t nr_threads)
249bf5615e7SCédric Le Goater {
250bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
251bf5615e7SCédric Le Goater     char *name;
252bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
253bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
254bf5615e7SCédric Le Goater     uint64_t *reg;
255bf5615e7SCédric Le Goater     int offset;
256bf5615e7SCédric Le Goater 
257bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
258bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
259bf5615e7SCédric Le Goater 
260bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
261bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
262bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
263bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
264bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
265bf5615e7SCédric Le Goater     }
266bf5615e7SCédric Le Goater 
267bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
268bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
269bf5615e7SCédric Le Goater     _FDT(offset);
270bf5615e7SCédric Le Goater     g_free(name);
271bf5615e7SCédric Le Goater 
272bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
275bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
278bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
279bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
280bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
281bf5615e7SCédric Le Goater     g_free(reg);
282bf5615e7SCédric Le Goater }
283bf5615e7SCédric Le Goater 
284c1471772SDaniel Henrique Barboza static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb,
285c1471772SDaniel Henrique Barboza                                          Error **errp)
286c1471772SDaniel Henrique Barboza {
287607e9316SDaniel Henrique Barboza     PnvPHB *phb_base = phb->phb_base;
288607e9316SDaniel Henrique Barboza     PnvPhb4PecState *pecs = NULL;
289c1471772SDaniel Henrique Barboza     int chip_id = phb->chip_id;
290c1471772SDaniel Henrique Barboza     int index = phb->phb_id;
291c1471772SDaniel Henrique Barboza     int i, j;
292c1471772SDaniel Henrique Barboza 
293607e9316SDaniel Henrique Barboza     if (phb_base->version == 4) {
294607e9316SDaniel Henrique Barboza         Pnv9Chip *chip9 = PNV9_CHIP(chip);
295607e9316SDaniel Henrique Barboza 
296607e9316SDaniel Henrique Barboza         pecs = chip9->pecs;
297607e9316SDaniel Henrique Barboza     } else if (phb_base->version == 5) {
298607e9316SDaniel Henrique Barboza         Pnv10Chip *chip10 = PNV10_CHIP(chip);
299607e9316SDaniel Henrique Barboza 
300607e9316SDaniel Henrique Barboza         pecs = chip10->pecs;
301607e9316SDaniel Henrique Barboza     } else {
302607e9316SDaniel Henrique Barboza         g_assert_not_reached();
303607e9316SDaniel Henrique Barboza     }
304607e9316SDaniel Henrique Barboza 
305c1471772SDaniel Henrique Barboza     for (i = 0; i < chip->num_pecs; i++) {
306c1471772SDaniel Henrique Barboza         /*
307c1471772SDaniel Henrique Barboza          * For each PEC, check the amount of phbs it supports
308c1471772SDaniel Henrique Barboza          * and see if the given phb4 index matches an index.
309c1471772SDaniel Henrique Barboza          */
310607e9316SDaniel Henrique Barboza         PnvPhb4PecState *pec = &pecs[i];
311c1471772SDaniel Henrique Barboza 
312c1471772SDaniel Henrique Barboza         for (j = 0; j < pec->num_phbs; j++) {
313c1471772SDaniel Henrique Barboza             if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
314c1471772SDaniel Henrique Barboza                 return pec;
315c1471772SDaniel Henrique Barboza             }
316c1471772SDaniel Henrique Barboza         }
317c1471772SDaniel Henrique Barboza     }
318c1471772SDaniel Henrique Barboza     error_setg(errp,
319c1471772SDaniel Henrique Barboza                "pnv-phb4 chip-id %d index %d didn't match any existing PEC",
320c1471772SDaniel Henrique Barboza                chip_id, index);
321c1471772SDaniel Henrique Barboza 
322c1471772SDaniel Henrique Barboza     return NULL;
323c1471772SDaniel Henrique Barboza }
324c1471772SDaniel Henrique Barboza 
325ba47c3a4SDaniel Henrique Barboza /*
326ba47c3a4SDaniel Henrique Barboza  * Adds a PnvPHB to the chip. Returns the parent obj of the
327ba47c3a4SDaniel Henrique Barboza  * PHB which varies with each version (phb version 3 is parented
328ba47c3a4SDaniel Henrique Barboza  * by the chip, version 4 and 5 are parented by the PEC
329ba47c3a4SDaniel Henrique Barboza  * device).
330ba47c3a4SDaniel Henrique Barboza  *
331ba47c3a4SDaniel Henrique Barboza  * TODO: for version 3 we're still parenting the PHB with the
332ba47c3a4SDaniel Henrique Barboza  * chip. We should parent with a (so far not implemented)
333ba47c3a4SDaniel Henrique Barboza  * PHB3 PEC device.
334ba47c3a4SDaniel Henrique Barboza  */
335ba47c3a4SDaniel Henrique Barboza Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp)
336ba47c3a4SDaniel Henrique Barboza {
337ba47c3a4SDaniel Henrique Barboza     if (phb->version == 3) {
3380d512c71SDaniel Henrique Barboza         Pnv8Chip *chip8 = PNV8_CHIP(chip);
3390d512c71SDaniel Henrique Barboza 
3400d512c71SDaniel Henrique Barboza         phb->chip = chip;
3410d512c71SDaniel Henrique Barboza 
3420d512c71SDaniel Henrique Barboza         chip8->phbs[chip8->num_phbs] = phb;
3430d512c71SDaniel Henrique Barboza         chip8->num_phbs++;
3440d512c71SDaniel Henrique Barboza 
345ba47c3a4SDaniel Henrique Barboza         return OBJECT(chip);
346ba47c3a4SDaniel Henrique Barboza     }
347c1471772SDaniel Henrique Barboza 
348c1471772SDaniel Henrique Barboza     phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp);
349c1471772SDaniel Henrique Barboza 
350c1471772SDaniel Henrique Barboza     return OBJECT(phb->pec);
351ba47c3a4SDaniel Henrique Barboza }
352ba47c3a4SDaniel Henrique Barboza 
353eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
354e997040eSCédric Le Goater {
355c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
356d2fd9612SCédric Le Goater     int i;
357d2fd9612SCédric Le Goater 
3583f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3593f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
360c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
361c396c58aSGreg Kurz                  compat, sizeof(compat));
362967b7523SCédric Le Goater 
363d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3644fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
365d2fd9612SCédric Le Goater 
366b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
367bf5615e7SCédric Le Goater 
368bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
369b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
370d2fd9612SCédric Le Goater     }
371d2fd9612SCédric Le Goater 
372e997040eSCédric Le Goater     if (chip->ram_size) {
373b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
374e997040eSCédric Le Goater     }
375e997040eSCédric Le Goater }
376e997040eSCédric Le Goater 
377eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
378eb859a27SCédric Le Goater {
379c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
380eb859a27SCédric Le Goater     int i;
381eb859a27SCédric Le Goater 
3823f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3833f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
384c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
385c396c58aSGreg Kurz                  compat, sizeof(compat));
386eb859a27SCédric Le Goater 
387eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3884fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
389eb859a27SCédric Le Goater 
390eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
391eb859a27SCédric Le Goater     }
392eb859a27SCédric Le Goater 
393eb859a27SCédric Le Goater     if (chip->ram_size) {
394eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
395eb859a27SCédric Le Goater     }
39615376c66SCédric Le Goater 
3972661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
398eb859a27SCédric Le Goater }
399eb859a27SCédric Le Goater 
4002b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
4012b548a42SCédric Le Goater {
402c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
4032b548a42SCédric Le Goater     int i;
4042b548a42SCédric Le Goater 
4053f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
4063f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
407c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
408c396c58aSGreg Kurz                  compat, sizeof(compat));
4092b548a42SCédric Le Goater 
4102b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
4112b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
4122b548a42SCédric Le Goater 
4132b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
4142b548a42SCédric Le Goater     }
4152b548a42SCédric Le Goater 
4162b548a42SCédric Le Goater     if (chip->ram_size) {
4172b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
4182b548a42SCédric Le Goater     }
4192661f6abSCédric Le Goater 
4202661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
4212b548a42SCédric Le Goater }
4222b548a42SCédric Le Goater 
423b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
424c5ffdcaeSCédric Le Goater {
425c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
426c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
427c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
428c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
429c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
430c5ffdcaeSCédric Le Goater     };
431c5ffdcaeSCédric Le Goater     char *name;
432c5ffdcaeSCédric Le Goater     int node;
433c5ffdcaeSCédric Le Goater 
434c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
435c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
436c5ffdcaeSCédric Le Goater     _FDT(node);
437c5ffdcaeSCédric Le Goater     g_free(name);
438c5ffdcaeSCédric Le Goater 
439c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
440c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
441c5ffdcaeSCédric Le Goater }
442c5ffdcaeSCédric Le Goater 
443b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
444cb228f5aSCédric Le Goater {
445cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
446cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
447cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
448cb228f5aSCédric Le Goater         cpu_to_be32(1),
449cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
450cb228f5aSCédric Le Goater         cpu_to_be32(8)
451cb228f5aSCédric Le Goater     };
452632fc0b3SBernhard Beschow     uint32_t irq;
453cb228f5aSCédric Le Goater     char *name;
454cb228f5aSCédric Le Goater     int node;
455cb228f5aSCédric Le Goater 
456632fc0b3SBernhard Beschow     irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
457632fc0b3SBernhard Beschow 
458cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
459cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
460cb228f5aSCédric Le Goater     _FDT(node);
461cb228f5aSCédric Le Goater     g_free(name);
462cb228f5aSCédric Le Goater 
463cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
464cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
465cb228f5aSCédric Le Goater                       sizeof(compatible))));
466cb228f5aSCédric Le Goater 
467cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
468cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
469632fc0b3SBernhard Beschow     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
470cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
471cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
472cb228f5aSCédric Le Goater 
473cb228f5aSCédric Le Goater     /* This is needed by Linux */
474cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
475cb228f5aSCédric Le Goater }
476cb228f5aSCédric Le Goater 
477b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
47804f6c8b2SCédric Le Goater {
47904f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
48004f6c8b2SCédric Le Goater     uint32_t io_base;
48104f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
48204f6c8b2SCédric Le Goater         cpu_to_be32(1),
48304f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
48404f6c8b2SCédric Le Goater         cpu_to_be32(3)
48504f6c8b2SCédric Le Goater     };
48604f6c8b2SCédric Le Goater     uint32_t irq;
48704f6c8b2SCédric Le Goater     char *name;
48804f6c8b2SCédric Le Goater     int node;
48904f6c8b2SCédric Le Goater 
49004f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
49104f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
49204f6c8b2SCédric Le Goater 
49304f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
49404f6c8b2SCédric Le Goater 
49504f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
49604f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
49704f6c8b2SCédric Le Goater     _FDT(node);
49804f6c8b2SCédric Le Goater     g_free(name);
49904f6c8b2SCédric Le Goater 
5007032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
5017032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
5027032d92aSCédric Le Goater                       sizeof(compatible))));
50304f6c8b2SCédric Le Goater 
50404f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
50504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
50604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
50704f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
50804f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
50904f6c8b2SCédric Le Goater }
51004f6c8b2SCédric Le Goater 
511e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
512e7a3fee3SCédric Le Goater     void *fdt;
513e7a3fee3SCédric Le Goater     int offset;
514e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
515e7a3fee3SCédric Le Goater 
516b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
517e7a3fee3SCédric Le Goater {
518c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
519c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
520c5ffdcaeSCédric Le Goater 
521c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
522b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
523cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
524b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
52504f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
526b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
527c5ffdcaeSCédric Le Goater     } else {
528c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
529c5ffdcaeSCédric Le Goater                      d->ioport_id);
530c5ffdcaeSCédric Le Goater     }
531c5ffdcaeSCédric Le Goater 
532e7a3fee3SCédric Le Goater     return 0;
533e7a3fee3SCédric Le Goater }
534e7a3fee3SCédric Le Goater 
53559b7c1c2SBalamuruhan S /*
53659b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
537bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
538bb7ab95cSCédric Le Goater  */
539bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
540bb7ab95cSCédric Le Goater {
54164d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
542e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
543e7a3fee3SCédric Le Goater         .fdt = fdt,
544bb7ab95cSCédric Le Goater         .offset = isa_offset,
545e7a3fee3SCédric Le Goater     };
546f47a08d1SCédric Le Goater     uint32_t phandle;
547e7a3fee3SCédric Le Goater 
548bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
549bb7ab95cSCédric Le Goater 
550f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
551f47a08d1SCédric Le Goater     assert(phandle > 0);
552f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
553f47a08d1SCédric Le Goater 
55459b7c1c2SBalamuruhan S     /*
55559b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
55659b7c1c2SBalamuruhan S      * can not use object_child_foreach()
55759b7c1c2SBalamuruhan S      */
558bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
559bb7ab95cSCédric Le Goater                        &args);
560e7a3fee3SCédric Le Goater }
561e7a3fee3SCédric Le Goater 
5627a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
563e5694793SCédric Le Goater {
564e5694793SCédric Le Goater     int off;
565e5694793SCédric Le Goater 
566e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
567e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
568e5694793SCédric Le Goater 
569e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
570e5694793SCédric Le Goater }
571e5694793SCédric Le Goater 
572b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5739e933f4aSBenjamin Herrenschmidt {
574d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
575b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5769e933f4aSBenjamin Herrenschmidt     void *fdt;
5779e933f4aSBenjamin Herrenschmidt     char *buf;
5789e933f4aSBenjamin Herrenschmidt     int off;
579e997040eSCédric Le Goater     int i;
5809e933f4aSBenjamin Herrenschmidt 
5819e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5829e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5839e933f4aSBenjamin Herrenschmidt 
584ccb099b3SCédric Le Goater     /* /qemu node */
585ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
586ccb099b3SCédric Le Goater 
5879e933f4aSBenjamin Herrenschmidt     /* Root node */
5889e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5899e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5909e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5919e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
592d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5939e933f4aSBenjamin Herrenschmidt 
5949e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5959e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5969e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
597bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
5989e933f4aSBenjamin Herrenschmidt     }
5999e933f4aSBenjamin Herrenschmidt     g_free(buf);
6009e933f4aSBenjamin Herrenschmidt 
6019e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
6029e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
6039e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
6049e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
6059e933f4aSBenjamin Herrenschmidt     }
6069e933f4aSBenjamin Herrenschmidt 
6079e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
6089e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
6099e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
6109e933f4aSBenjamin Herrenschmidt 
6119e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
6129e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
6139e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
6149e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
6159e933f4aSBenjamin Herrenschmidt     }
6169e933f4aSBenjamin Herrenschmidt 
617e997040eSCédric Le Goater     /* Populate device tree for each chip */
618e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
619eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
620e997040eSCédric Le Goater     }
621e7a3fee3SCédric Le Goater 
622e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
623bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
624aeaef83dSCédric Le Goater 
625aeaef83dSCédric Le Goater     if (pnv->bmc) {
626b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
627aeaef83dSCédric Le Goater     }
628aeaef83dSCédric Le Goater 
6297a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
6307a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
6317a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
632e5694793SCédric Le Goater     }
633e5694793SCédric Le Goater 
6349e933f4aSBenjamin Herrenschmidt     return fdt;
6359e933f4aSBenjamin Herrenschmidt }
6369e933f4aSBenjamin Herrenschmidt 
637bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
638bce0b691SCédric Le Goater {
6398f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
640bce0b691SCédric Le Goater 
641bce0b691SCédric Le Goater     if (pnv->bmc) {
642bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
643bce0b691SCédric Le Goater     }
644bce0b691SCédric Le Goater }
645bce0b691SCédric Le Goater 
646a0628599SLike Xu static void pnv_reset(MachineState *machine)
6479e933f4aSBenjamin Herrenschmidt {
64825f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
64925f3170bSCédric Le Goater     IPMIBmc *bmc;
6509e933f4aSBenjamin Herrenschmidt     void *fdt;
6519e933f4aSBenjamin Herrenschmidt 
6529e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
6539e933f4aSBenjamin Herrenschmidt 
65425f3170bSCédric Le Goater     /*
65525f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
65625f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
65725f3170bSCédric Le Goater      * line.
65825f3170bSCédric Le Goater      */
65925f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
66025f3170bSCédric Le Goater     if (!pnv->bmc) {
66125f3170bSCédric Le Goater         if (!bmc) {
66238d2448aSGreg Kurz             if (!qtest_enabled()) {
66325f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
66425f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
66525f3170bSCédric Le Goater                             "to define one");
66638d2448aSGreg Kurz             }
66725f3170bSCédric Le Goater         } else {
66825f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
66925f3170bSCédric Le Goater             pnv->bmc = bmc;
67025f3170bSCédric Le Goater         }
67125f3170bSCédric Le Goater     }
67225f3170bSCédric Le Goater 
673b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6749e933f4aSBenjamin Herrenschmidt 
6759e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6769e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6779e933f4aSBenjamin Herrenschmidt 
6788d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6799e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
680b2fb7a43SPan Nengyuan 
681adb77996SDaniel Henrique Barboza     /*
682adb77996SDaniel Henrique Barboza      * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
683adb77996SDaniel Henrique Barboza      * the existing machine->fdt to avoid leaking it during
684adb77996SDaniel Henrique Barboza      * a reset.
685adb77996SDaniel Henrique Barboza      */
686adb77996SDaniel Henrique Barboza     g_free(machine->fdt);
687adb77996SDaniel Henrique Barboza     machine->fdt = fdt;
6889e933f4aSBenjamin Herrenschmidt }
6899e933f4aSBenjamin Herrenschmidt 
69004026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6913495b6b6SCédric Le Goater {
69277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
693c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
694c05aa140SCédric Le Goater 
695c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
69677864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
69704026890SCédric Le Goater }
6983495b6b6SCédric Le Goater 
69904026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
70004026890SCédric Le Goater {
70177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
702c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
703c05aa140SCédric Le Goater 
704c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
70577864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
70604026890SCédric Le Goater }
7073495b6b6SCédric Le Goater 
70804026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
70904026890SCédric Le Goater {
71015376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
711c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
712c05aa140SCédric Le Goater 
713c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq);
71415376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
71504026890SCédric Le Goater }
7163495b6b6SCédric Le Goater 
7172b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
7182b548a42SCédric Le Goater {
7192661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
720c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
721c05aa140SCédric Le Goater 
722c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq);
7232661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
7242b548a42SCédric Le Goater }
7252b548a42SCédric Le Goater 
72604026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
72704026890SCédric Le Goater {
72804026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
7293495b6b6SCédric Le Goater }
7303495b6b6SCédric Le Goater 
731d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
732d8e4aad5SCédric Le Goater {
733d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
7348a69bca7SDaniel Henrique Barboza     int i;
735d8e4aad5SCédric Le Goater 
736d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
7378a69bca7SDaniel Henrique Barboza 
7388a69bca7SDaniel Henrique Barboza     for (i = 0; i < chip8->num_phbs; i++) {
7390d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
7401f5d6b2aSDaniel Henrique Barboza         PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
7418a69bca7SDaniel Henrique Barboza 
7428a69bca7SDaniel Henrique Barboza         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
7438a69bca7SDaniel Henrique Barboza         ics_pic_print_info(&phb3->lsis, mon);
7448a69bca7SDaniel Henrique Barboza     }
745d8e4aad5SCédric Le Goater }
746d8e4aad5SCédric Le Goater 
7470e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
7480e6232bcSCédric Le Goater {
7490e6232bcSCédric Le Goater     Monitor *mon = opaque;
750210aacb3SDaniel Henrique Barboza     PnvPHB *phb =  (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
7510e6232bcSCédric Le Goater 
752210aacb3SDaniel Henrique Barboza     if (!phb) {
753210aacb3SDaniel Henrique Barboza         return 0;
7540e6232bcSCédric Le Goater     }
755210aacb3SDaniel Henrique Barboza 
756210aacb3SDaniel Henrique Barboza     pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon);
757210aacb3SDaniel Henrique Barboza 
7580e6232bcSCédric Le Goater     return 0;
7590e6232bcSCédric Le Goater }
7600e6232bcSCédric Le Goater 
761d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
762d8e4aad5SCédric Le Goater {
763d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
764d8e4aad5SCédric Le Goater 
765d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
766c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
7674f9924c4SBenjamin Herrenschmidt 
7680e6232bcSCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
7690e6232bcSCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
770d8e4aad5SCédric Le Goater }
771d8e4aad5SCédric Le Goater 
772c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
773c4b2c40cSGreg Kurz                                                 uint32_t core_id)
774c4b2c40cSGreg Kurz {
775c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
776c4b2c40cSGreg Kurz }
777c4b2c40cSGreg Kurz 
778c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
779c4b2c40cSGreg Kurz                                                 uint32_t core_id)
780c4b2c40cSGreg Kurz {
781c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
782c4b2c40cSGreg Kurz }
783c4b2c40cSGreg Kurz 
784c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
785c4b2c40cSGreg Kurz                                                  uint32_t core_id)
786c4b2c40cSGreg Kurz {
787c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
788c4b2c40cSGreg Kurz }
789c4b2c40cSGreg Kurz 
790f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
791f30c843cSCédric Le Goater {
792f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
793f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
794f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
795f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
796f30c843cSCédric Le Goater 
79721d3a78eSNicholas Piggin     return ppc_default->pvr_match(ppc_default, ppc->pvr, false);
798f30c843cSCédric Le Goater }
799f30c843cSCédric Le Goater 
800e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
801e2392d43SCédric Le Goater {
802c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
803e2392d43SCédric Le Goater 
8045325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
8055325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
806c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
807e2392d43SCédric Le Goater }
808e2392d43SCédric Le Goater 
8092b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
8102b548a42SCédric Le Goater {
8118b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
8128b50ce85SCédric Le Goater 
813da71b7e3SCédric Le Goater     pnv_xive2_pic_print_info(&chip10->xive, mon);
8148b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
815623575e1SCédric Le Goater 
816623575e1SCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
817623575e1SCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
8182b548a42SCédric Le Goater }
8192b548a42SCédric Le Goater 
820458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
821458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
822458c6f01SCédric Le Goater {
823458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
824458c6f01SCédric Le Goater     uint64_t ram_per_chip;
825458c6f01SCédric Le Goater 
826458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
827458c6f01SCédric Le Goater 
828458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
829458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
830458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
831458c6f01SCédric Le Goater     }
832458c6f01SCédric Le Goater 
833f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
834f640afecSCédric Le Goater 
835458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
836458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
837458c6f01SCédric Le Goater }
838458c6f01SCédric Le Goater 
839b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
8409e933f4aSBenjamin Herrenschmidt {
841cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
842b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
843f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
8449e933f4aSBenjamin Herrenschmidt     char *fw_filename;
8459e933f4aSBenjamin Herrenschmidt     long fw_size;
846458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
847e997040eSCédric Le Goater     int i;
848e997040eSCédric Le Goater     char *chip_typename;
84935dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
85035dde576SCédric Le Goater     DeviceState *dev;
8519e933f4aSBenjamin Herrenschmidt 
852ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
853ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
854ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
855ebe6c3faSDaniel Henrique Barboza     }
856ebe6c3faSDaniel Henrique Barboza 
8579e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
858dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
859dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
860dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
861dd7ef911SCédric Le Goater         g_free(sz);
862dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
8639e933f4aSBenjamin Herrenschmidt     }
864173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
8659e933f4aSBenjamin Herrenschmidt 
86635dde576SCédric Le Goater     /*
86735dde576SCédric Le Goater      * Create our simple PNOR device
86835dde576SCédric Le Goater      */
8693e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
87035dde576SCédric Le Goater     if (pnor) {
871934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
87235dde576SCédric Le Goater     }
8733c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
87435dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
87535dde576SCédric Le Goater 
8769e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
8779e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
87815fcedb2SCédric Le Goater     if (!fw_filename) {
87915fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
88015fcedb2SCédric Le Goater         exit(1);
88115fcedb2SCédric Le Goater     }
8829e933f4aSBenjamin Herrenschmidt 
88308c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
8849e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
88515fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
8869e933f4aSBenjamin Herrenschmidt         exit(1);
8879e933f4aSBenjamin Herrenschmidt     }
8889e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8899e933f4aSBenjamin Herrenschmidt 
8909e933f4aSBenjamin Herrenschmidt     /* load kernel */
8919e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8929e933f4aSBenjamin Herrenschmidt         long kernel_size;
8939e933f4aSBenjamin Herrenschmidt 
8949e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
895b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8969e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
897802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8989e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8999e933f4aSBenjamin Herrenschmidt             exit(1);
9009e933f4aSBenjamin Herrenschmidt         }
9019e933f4aSBenjamin Herrenschmidt     }
9029e933f4aSBenjamin Herrenschmidt 
9039e933f4aSBenjamin Herrenschmidt     /* load initrd */
9049e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
9059e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
9069e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
907584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
9089e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
909802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
9109e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
9119e933f4aSBenjamin Herrenschmidt             exit(1);
9129e933f4aSBenjamin Herrenschmidt         }
9139e933f4aSBenjamin Herrenschmidt     }
914e997040eSCédric Le Goater 
9154f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
9164f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
9174f9924c4SBenjamin Herrenschmidt 
918f30c843cSCédric Le Goater     /*
919f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
920f30c843cSCédric Le Goater      * default.
921f30c843cSCédric Le Goater      */
922f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
923f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
924f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
925f30c843cSCédric Le Goater         exit(1);
926f30c843cSCédric Le Goater     }
927f30c843cSCédric Le Goater 
928e997040eSCédric Le Goater     /* Create the processor chips */
9294a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
9307fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
9314a12c699SIgor Mammedov                                     i, machine->cpu_type);
932e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
933f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
934f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
935e997040eSCédric Le Goater         exit(1);
936e997040eSCédric Le Goater     }
937e997040eSCédric Le Goater 
938e44acde2SGreg Kurz     pnv->num_chips =
939e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
940e44acde2SGreg Kurz     /*
941e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
942e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
943e44acde2SGreg Kurz      */
944ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
945e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
946ab17a3feSCédric Le Goater         error_printf(
947ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
948e44acde2SGreg Kurz         exit(1);
949e44acde2SGreg Kurz     }
950e44acde2SGreg Kurz 
951e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
952e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
953e997040eSCédric Le Goater         char chip_name[32];
954df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
9550e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
956e997040eSCédric Le Goater 
957e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
958e997040eSCédric Le Goater 
959458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
960458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
961e997040eSCédric Le Goater                                 &error_fatal);
962458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
963458c6f01SCédric Le Goater                                 &error_fatal);
964458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
965e997040eSCédric Le Goater 
9660e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
967d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
9680e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
9695325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
9705325cc34SMarkus Armbruster                                 &error_fatal);
9715325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
9725325cc34SMarkus Armbruster                                 &error_fatal);
973245cdb7fSCédric Le Goater         /*
974245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
975245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
976245cdb7fSCédric Le Goater          */
977245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
9785325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
979245cdb7fSCédric Le Goater         }
980d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
9815325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
982d1214b81SGreg Kurz                                      &error_abort);
983d1214b81SGreg Kurz         }
9843c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
985e997040eSCédric Le Goater     }
986e997040eSCédric Le Goater     g_free(chip_typename);
9873495b6b6SCédric Le Goater 
9883495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
98904026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9903495b6b6SCédric Le Goater 
9913495b6b6SCédric Le Goater     /* Create serial port */
992def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9933495b6b6SCédric Le Goater 
9943495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9956c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
996bce0b691SCédric Le Goater 
99725f3170bSCédric Le Goater     /*
99825f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
99925f3170bSCédric Le Goater      * communication with the BMC
100025f3170bSCédric Le Goater      */
100125f3170bSCédric Le Goater     if (defaults_enabled()) {
100225f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
1003e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
100425f3170bSCédric Le Goater     }
1005e2392d43SCédric Le Goater 
100659b7c1c2SBalamuruhan S     /*
1007032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
1008032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
1009032c226bSCédric Le Goater      * map it always for now.
1010032c226bSCédric Le Goater      */
1011032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
1012032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
1013032c226bSCédric Le Goater 
1014032c226bSCédric Le Goater     /*
101559b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
101659b7c1c2SBalamuruhan S      * host to powerdown
101759b7c1c2SBalamuruhan S      */
1018bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
1019bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
1020e997040eSCédric Le Goater }
1021e997040eSCédric Le Goater 
1022631adaffSCédric Le Goater /*
1023631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
1024631adaffSCédric Le Goater  *   22:24  Chip ID
1025631adaffSCédric Le Goater  *   25:28  Core number
1026631adaffSCédric Le Goater  *   29:31  Thread ID
1027631adaffSCédric Le Goater  */
1028631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
1029631adaffSCédric Le Goater {
1030631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
1031631adaffSCédric Le Goater }
1032631adaffSCédric Le Goater 
10338fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1034d35aefa9SCédric Le Goater                                         Error **errp)
1035d35aefa9SCédric Le Goater {
1036245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
10378fa1f4efSCédric Le Goater     Error *local_err = NULL;
10388fa1f4efSCédric Le Goater     Object *obj;
10398907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10408fa1f4efSCédric Le Goater 
1041245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
10428fa1f4efSCédric Le Goater     if (local_err) {
10438fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
10448fa1f4efSCédric Le Goater         return;
10458fa1f4efSCédric Le Goater     }
10468fa1f4efSCédric Le Goater 
1047956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
1048d35aefa9SCédric Le Goater }
1049d35aefa9SCédric Le Goater 
10500990ce6aSGreg Kurz 
1051d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1052d49e8a9bSCédric Le Goater {
1053d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1054d49e8a9bSCédric Le Goater 
1055d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
1056d49e8a9bSCédric Le Goater }
1057d49e8a9bSCédric Le Goater 
10580990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10590990ce6aSGreg Kurz {
10600990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10610990ce6aSGreg Kurz 
10620990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
10630990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10640990ce6aSGreg Kurz }
10650990ce6aSGreg Kurz 
106685913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
106785913070SGreg Kurz                                             Monitor *mon)
106885913070SGreg Kurz {
106985913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
107085913070SGreg Kurz }
107185913070SGreg Kurz 
1072631adaffSCédric Le Goater /*
1073631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
1074631adaffSCédric Le Goater  *   49:52  Node ID
1075631adaffSCédric Le Goater  *   53:55  Chip ID
1076631adaffSCédric Le Goater  *   56     Reserved - Read as zero
1077631adaffSCédric Le Goater  *   57:61  Core number
1078631adaffSCédric Le Goater  *   62:63  Thread ID
1079631adaffSCédric Le Goater  *
1080631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
1081631adaffSCédric Le Goater  */
1082631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
1083631adaffSCédric Le Goater {
1084631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
1085631adaffSCédric Le Goater }
1086631adaffSCédric Le Goater 
10872b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10882b548a42SCédric Le Goater {
10892b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10902b548a42SCédric Le Goater }
10912b548a42SCédric Le Goater 
10928fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1093d35aefa9SCédric Le Goater                                         Error **errp)
1094d35aefa9SCédric Le Goater {
10952dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10962dfa91a2SCédric Le Goater     Error *local_err = NULL;
10972dfa91a2SCédric Le Goater     Object *obj;
10982dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10992dfa91a2SCédric Le Goater 
11002dfa91a2SCédric Le Goater     /*
11012dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
11022dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
11032dfa91a2SCédric Le Goater      * only used at runtime.
11042dfa91a2SCédric Le Goater      */
110547950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
110647950946SCédric Le Goater                            &local_err);
11072dfa91a2SCédric Le Goater     if (local_err) {
11082dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
11098fa1f4efSCédric Le Goater         return;
1110d35aefa9SCédric Le Goater     }
1111d35aefa9SCédric Le Goater 
11122dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
11132dfa91a2SCédric Le Goater }
11142dfa91a2SCédric Le Goater 
1115d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1116d49e8a9bSCédric Le Goater {
1117d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1118d49e8a9bSCédric Le Goater 
1119d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1120d49e8a9bSCédric Le Goater }
1121d49e8a9bSCédric Le Goater 
11220990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11230990ce6aSGreg Kurz {
11240990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11250990ce6aSGreg Kurz 
11260990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
11270990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
11280990ce6aSGreg Kurz }
11290990ce6aSGreg Kurz 
113085913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
113185913070SGreg Kurz                                             Monitor *mon)
113285913070SGreg Kurz {
113385913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
113485913070SGreg Kurz }
113585913070SGreg Kurz 
11362b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
11372b548a42SCédric Le Goater                                         Error **errp)
11382b548a42SCédric Le Goater {
1139da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1140da71b7e3SCédric Le Goater     Error *local_err = NULL;
1141da71b7e3SCédric Le Goater     Object *obj;
11422b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11432b548a42SCédric Le Goater 
1144da71b7e3SCédric Le Goater     /*
1145da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1146da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1147da71b7e3SCédric Le Goater      * only used at runtime.
1148da71b7e3SCédric Le Goater      */
1149da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1150da71b7e3SCédric Le Goater                            &local_err);
1151da71b7e3SCédric Le Goater     if (local_err) {
1152da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1153da71b7e3SCédric Le Goater         return;
1154da71b7e3SCédric Le Goater     }
1155da71b7e3SCédric Le Goater 
1156da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
11572b548a42SCédric Le Goater }
11582b548a42SCédric Le Goater 
11592b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
11602b548a42SCédric Le Goater {
1161da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1162da71b7e3SCédric Le Goater 
1163da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
11642b548a42SCédric Le Goater }
11652b548a42SCédric Le Goater 
11662b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11672b548a42SCédric Le Goater {
11682b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11692b548a42SCédric Le Goater 
1170da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
11712b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
11722b548a42SCédric Le Goater }
11732b548a42SCédric Le Goater 
117485913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
117585913070SGreg Kurz                                              Monitor *mon)
117685913070SGreg Kurz {
1177da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
117885913070SGreg Kurz }
117985913070SGreg Kurz 
118059b7c1c2SBalamuruhan S /*
118159b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1182397a79e7SCédric Le Goater  *
1183397a79e7SCédric Le Goater  * <EX0 reserved>
1184397a79e7SCédric Le Goater  *  EX1  - Venice only
1185397a79e7SCédric Le Goater  *  EX2  - Venice only
1186397a79e7SCédric Le Goater  *  EX3  - Venice only
1187397a79e7SCédric Le Goater  *  EX4
1188397a79e7SCédric Le Goater  *  EX5
1189397a79e7SCédric Le Goater  *  EX6
1190397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1191397a79e7SCédric Le Goater  *  EX9  - Venice only
1192397a79e7SCédric Le Goater  *  EX10 - Venice only
1193397a79e7SCédric Le Goater  *  EX11 - Venice only
1194397a79e7SCédric Le Goater  *  EX12
1195397a79e7SCédric Le Goater  *  EX13
1196397a79e7SCédric Le Goater  *  EX14
1197397a79e7SCédric Le Goater  * <EX15 reserved>
1198397a79e7SCédric Le Goater  */
1199397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1200397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1201397a79e7SCédric Le Goater 
1202397a79e7SCédric Le Goater /*
120309279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1204397a79e7SCédric Le Goater  */
120509279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1206397a79e7SCédric Le Goater 
12072b548a42SCédric Le Goater 
12082b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
12092b548a42SCédric Le Goater 
121077864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
121177864267SCédric Le Goater {
121277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
12139ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
12149ae1329eSCédric Le Goater     int i;
121577864267SCédric Le Goater 
1216245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1217245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1218245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1219d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1220245cdb7fSCédric Le Goater 
12219fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
122277864267SCédric Le Goater 
12239fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
122477864267SCédric Le Goater 
12259fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
12263887d241SBalamuruhan S 
12279fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
12289ae1329eSCédric Le Goater 
1229892c3ad0SDaniel Henrique Barboza     if (defaults_enabled()) {
1230eb93c828SCédric Le Goater         chip8->num_phbs = pcc->num_phbs;
12311f6a88ffSCédric Le Goater 
1232eb93c828SCédric Le Goater         for (i = 0; i < chip8->num_phbs; i++) {
12330d512c71SDaniel Henrique Barboza             Object *phb = object_new(TYPE_PNV_PHB);
12340d512c71SDaniel Henrique Barboza 
12350d512c71SDaniel Henrique Barboza             /*
12360d512c71SDaniel Henrique Barboza              * We need the chip to parent the PHB to allow the DT
12370d512c71SDaniel Henrique Barboza              * to build correctly (via pnv_xscom_dt()).
12380d512c71SDaniel Henrique Barboza              *
12390d512c71SDaniel Henrique Barboza              * TODO: the PHB should be parented by a PEC device that, at
12400d512c71SDaniel Henrique Barboza              * this moment, is not modelled powernv8/phb3.
12410d512c71SDaniel Henrique Barboza              */
12420d512c71SDaniel Henrique Barboza             object_property_add_child(obj, "phb[*]", phb);
12430d512c71SDaniel Henrique Barboza             chip8->phbs[i] = PNV_PHB(phb);
12449ae1329eSCédric Le Goater         }
1245892c3ad0SDaniel Henrique Barboza     }
12469ae1329eSCédric Le Goater 
124777864267SCédric Le Goater }
124877864267SCédric Le Goater 
124977864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
125077864267SCédric Le Goater  {
125177864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
125277864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
125377864267SCédric Le Goater     int i, j;
125477864267SCédric Le Goater     char *name;
125577864267SCédric Le Goater 
125677864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
125777864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
125877864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
125977864267SCédric Le Goater     g_free(name);
126077864267SCédric Le Goater 
126177864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
126277864267SCédric Le Goater 
126377864267SCédric Le Goater     /* Map the ICP registers for each thread */
126477864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
12654fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
126677864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
126777864267SCédric Le Goater 
126877864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
126977864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1270245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
127177864267SCédric Le Goater 
127277864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
127377864267SCédric Le Goater                                         &icp->mmio);
127477864267SCédric Le Goater         }
127577864267SCédric Le Goater     }
127677864267SCédric Le Goater }
127777864267SCédric Le Goater 
127877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
127977864267SCédric Le Goater {
128077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
128177864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
128277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1283ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
128477864267SCédric Le Goater     Error *local_err = NULL;
12859ae1329eSCédric Le Goater     int i;
128677864267SCédric Le Goater 
1287245cdb7fSCédric Le Goater     assert(chip8->xics);
1288245cdb7fSCédric Le Goater 
1289709044fdSCédric Le Goater     /* XSCOM bridge is first */
1290709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1291709044fdSCédric Le Goater     if (local_err) {
1292709044fdSCédric Le Goater         error_propagate(errp, local_err);
1293709044fdSCédric Le Goater         return;
1294709044fdSCédric Le Goater     }
1295709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1296709044fdSCédric Le Goater 
129777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
129877864267SCédric Le Goater     if (local_err) {
129977864267SCédric Le Goater         error_propagate(errp, local_err);
130077864267SCédric Le Goater         return;
130177864267SCédric Le Goater     }
130277864267SCédric Le Goater 
130377864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
13045325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
13055325cc34SMarkus Armbruster                             &error_fatal);
13065325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
13075325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1308668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
130977864267SCédric Le Goater         return;
131077864267SCédric Le Goater     }
1311ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1312ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
131377864267SCédric Le Goater 
131477864267SCédric Le Goater     /* Create LPC controller */
1315ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
131677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
131777864267SCédric Le Goater 
1318032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
131964d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
132064d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
132164d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
132264d011d5SCédric Le Goater 
132359b7c1c2SBalamuruhan S     /*
132459b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
132559b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
132659b7c1c2SBalamuruhan S      */
132777864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
132877864267SCédric Le Goater     if (local_err) {
132977864267SCédric Le Goater         error_propagate(errp, local_err);
133077864267SCédric Le Goater         return;
133177864267SCédric Le Goater     }
133277864267SCédric Le Goater 
133377864267SCédric Le Goater     /* Create the simplified OCC model */
1334668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
133577864267SCédric Le Goater         return;
133677864267SCédric Le Goater     }
133777864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1338b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1339b0ae5c69SCédric Le Goater                           qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC));
1340f3db8266SBalamuruhan S 
1341f3db8266SBalamuruhan S     /* OCC SRAM model */
13423a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1343f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
13443887d241SBalamuruhan S 
13453887d241SBalamuruhan S     /* HOMER */
13465325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1347f2582acfSGreg Kurz                              &error_abort);
1348668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
13493887d241SBalamuruhan S         return;
13503887d241SBalamuruhan S     }
13518f092316SCédric Le Goater     /* Homer Xscom region */
13528f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
13538f092316SCédric Le Goater 
13548f092316SCédric Le Goater     /* Homer mmio region */
13553887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
13563887d241SBalamuruhan S                                 &chip8->homer.regs);
13579ae1329eSCédric Le Goater 
13581f5d6b2aSDaniel Henrique Barboza     /* PHB controllers */
1359eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
13600d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
13619ae1329eSCédric Le Goater 
13625325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
13635325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
13649ae1329eSCédric Le Goater                                 &error_fatal);
13652c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
13662c4d3a50SCédric Le Goater                                  &error_fatal);
1367668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
13689ae1329eSCédric Le Goater             return;
13699ae1329eSCédric Le Goater         }
13709ae1329eSCédric Le Goater     }
137177864267SCédric Le Goater }
137277864267SCédric Le Goater 
137370c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
137470c059e9SGreg Kurz {
137570c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
137670c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
137770c059e9SGreg Kurz }
137870c059e9SGreg Kurz 
1379e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1380e997040eSCédric Le Goater {
1381e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1382e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1383e997040eSCédric Le Goater 
1384e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1385397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
13869ae1329eSCédric Le Goater     k->num_phbs = 3;
1387631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1388d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1389d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13900990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
139185913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
139204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1393eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1394d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1395c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
139670c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1397e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
139877864267SCédric Le Goater 
139977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
140077864267SCédric Le Goater                                     &k->parent_realize);
1401e997040eSCédric Le Goater }
1402e997040eSCédric Le Goater 
1403e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1404e997040eSCédric Le Goater {
1405e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1406e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1407e997040eSCédric Le Goater 
1408e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1409397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
14109ae1329eSCédric Le Goater     k->num_phbs = 3;
1411631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1412d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1413d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
14140990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
141585913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
141604026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1417eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1418d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1419c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
142070c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1421e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
142277864267SCédric Le Goater 
142377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
142477864267SCédric Le Goater                                     &k->parent_realize);
1425e997040eSCédric Le Goater }
1426e997040eSCédric Le Goater 
1427e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1428e997040eSCédric Le Goater {
1429e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1430e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1431e997040eSCédric Le Goater 
1432e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1433397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1434316717feSCédric Le Goater     k->num_phbs = 4;
1435631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1436d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1437d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
14380990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
143985913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
144004026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1441eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1442d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1443c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
144470c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1445e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
144677864267SCédric Le Goater 
144777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
144877864267SCédric Le Goater                                     &k->parent_realize);
144977864267SCédric Le Goater }
145077864267SCédric Le Goater 
145177864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
145277864267SCédric Le Goater {
14534f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
14542dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
14554f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
14564f9924c4SBenjamin Herrenschmidt     int i;
14572dfa91a2SCédric Le Goater 
1458db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1459d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1460d2623129SMarkus Armbruster                               "xive-fabric");
1461c38536bcSCédric Le Goater 
14629fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
146315376c66SCédric Le Goater 
14649fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
14656598a70dSCédric Le Goater 
14669fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
14673887d241SBalamuruhan S 
14680bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
14690bf4d77eSNicholas Piggin 
14709fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
14714f9924c4SBenjamin Herrenschmidt 
1472422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1473422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1474422fd92eSCédric Le Goater 
1475422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14764f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
14779fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
14784f9924c4SBenjamin Herrenschmidt     }
147977864267SCédric Le Goater }
148077864267SCédric Le Goater 
1481ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1482ae4c68e3SCédric Le Goater                                       PnvCore *pnv_core)
14835dad902cSCédric Le Goater {
14845dad902cSCédric Le Goater     char eq_name[32];
14855dad902cSCédric Le Goater     int core_id = CPU_CORE(pnv_core)->core_id;
14865dad902cSCédric Le Goater 
14875dad902cSCédric Le Goater     snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14889fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
14899fc7fc4dSMarkus Armbruster                                        sizeof(*eq), TYPE_PNV_QUAD,
14909fc7fc4dSMarkus Armbruster                                        &error_fatal, NULL);
14915dad902cSCédric Le Goater 
149292612f15SCédric Le Goater     object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1493ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(eq), NULL, &error_fatal);
1494ae4c68e3SCédric Le Goater }
1495ae4c68e3SCédric Le Goater 
1496ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1497ae4c68e3SCédric Le Goater {
1498ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
1499ae4c68e3SCédric Le Goater     int i;
1500ae4c68e3SCédric Le Goater 
1501ae4c68e3SCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1502ae4c68e3SCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1503ae4c68e3SCédric Le Goater 
1504ae4c68e3SCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
1505ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
1506ae4c68e3SCédric Le Goater 
1507ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
15085dad902cSCédric Le Goater 
150992612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
15105dad902cSCédric Le Goater                                 &eq->xscom_regs);
15115dad902cSCédric Le Goater     }
15125dad902cSCédric Le Goater }
15135dad902cSCédric Le Goater 
151413480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
15154f9924c4SBenjamin Herrenschmidt {
15164f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
151713480fc5SCédric Le Goater     int i;
15184f9924c4SBenjamin Herrenschmidt 
1519422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
15204f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
15214f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
15224f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
15234f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
15244f9924c4SBenjamin Herrenschmidt 
15255325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
15265325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
15274f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
15286f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
15296f43d255SCédric Le Goater                                  &error_fatal);
1530668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
15314f9924c4SBenjamin Herrenschmidt             return;
15324f9924c4SBenjamin Herrenschmidt         }
15334f9924c4SBenjamin Herrenschmidt 
15344f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
15354f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
15364f9924c4SBenjamin Herrenschmidt 
15374f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
15384f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
15394f9924c4SBenjamin Herrenschmidt     }
15404f9924c4SBenjamin Herrenschmidt }
15414f9924c4SBenjamin Herrenschmidt 
154277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
154377864267SCédric Le Goater {
154477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15452dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
15462dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1547c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
154877864267SCédric Le Goater     Error *local_err = NULL;
154977864267SCédric Le Goater 
1550709044fdSCédric Le Goater     /* XSCOM bridge is first */
1551709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1552709044fdSCédric Le Goater     if (local_err) {
1553709044fdSCédric Le Goater         error_propagate(errp, local_err);
1554709044fdSCédric Le Goater         return;
1555709044fdSCédric Le Goater     }
1556709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1557709044fdSCédric Le Goater 
155877864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
155977864267SCédric Le Goater     if (local_err) {
156077864267SCédric Le Goater         error_propagate(errp, local_err);
156177864267SCédric Le Goater         return;
156277864267SCédric Le Goater     }
15632dfa91a2SCédric Le Goater 
15645dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
15655dad902cSCédric Le Goater     if (local_err) {
15665dad902cSCédric Le Goater         error_propagate(errp, local_err);
15675dad902cSCédric Le Goater         return;
15685dad902cSCédric Le Goater     }
15695dad902cSCédric Le Goater 
15702dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
15715325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
15725325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
15735325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
15745325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
15755325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
15765325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
15775325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
15785325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
15795325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
15807ae54cc3SGreg Kurz                              &error_abort);
1581668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
15822dfa91a2SCédric Le Goater         return;
15832dfa91a2SCédric Le Goater     }
15842dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
15852dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1586c38536bcSCédric Le Goater 
1587c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15885325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
15895325cc34SMarkus Armbruster                             &error_fatal);
159024c8fa96SCédric Le Goater     /* This is the only device with 4k ESB pages */
159124c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
159224c8fa96SCédric Le Goater                             &error_fatal);
1593668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1594c38536bcSCédric Le Goater         return;
1595c38536bcSCédric Le Goater     }
1596c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1597c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
159815376c66SCédric Le Goater 
159915376c66SCédric Le Goater     /* LPC */
1600668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
160115376c66SCédric Le Goater         return;
160215376c66SCédric Le Goater     }
160315376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
160415376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
160515376c66SCédric Le Goater 
1606032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
160715376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
160815376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
16096598a70dSCédric Le Goater 
16106598a70dSCédric Le Goater     /* Create the simplified OCC model */
1611668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
16126598a70dSCédric Le Goater         return;
16136598a70dSCédric Le Goater     }
16146598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1615b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1616b0ae5c69SCédric Le Goater                               DEVICE(&chip9->psi), PSIHB9_IRQ_OCC));
1617f3db8266SBalamuruhan S 
1618f3db8266SBalamuruhan S     /* OCC SRAM model */
16193a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1620f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
16213887d241SBalamuruhan S 
16220bf4d77eSNicholas Piggin     /* SBE */
16230bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
16240bf4d77eSNicholas Piggin         return;
16250bf4d77eSNicholas Piggin     }
16260bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
16270bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_ctrl_regs);
16280bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
16290bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_mbox_regs);
16300bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
16310bf4d77eSNicholas Piggin                               DEVICE(&chip9->psi), PSIHB9_IRQ_PSU));
16320bf4d77eSNicholas Piggin 
16333887d241SBalamuruhan S     /* HOMER */
16345325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1635f2582acfSGreg Kurz                              &error_abort);
1636668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
16373887d241SBalamuruhan S         return;
16383887d241SBalamuruhan S     }
16398f092316SCédric Le Goater     /* Homer Xscom region */
16408f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
16418f092316SCédric Le Goater 
16428f092316SCédric Le Goater     /* Homer mmio region */
16433887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
16443887d241SBalamuruhan S                                 &chip9->homer.regs);
16454f9924c4SBenjamin Herrenschmidt 
164613480fc5SCédric Le Goater     /* PEC PHBs */
164713480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
16484f9924c4SBenjamin Herrenschmidt     if (local_err) {
16494f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
16504f9924c4SBenjamin Herrenschmidt         return;
16514f9924c4SBenjamin Herrenschmidt     }
1652e997040eSCédric Le Goater }
1653e997040eSCédric Le Goater 
165470c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
165570c059e9SGreg Kurz {
165670c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
165770c059e9SGreg Kurz     return addr >> 3;
165870c059e9SGreg Kurz }
165970c059e9SGreg Kurz 
1660e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1661e997040eSCédric Le Goater {
1662e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1663e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1664e997040eSCédric Le Goater 
166583028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1666397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1667631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1668d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1669d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
16700990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
167185913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
167204026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1673eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1674d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1675c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
167670c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1677e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1678422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
167977864267SCédric Le Goater 
168077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
168177864267SCédric Le Goater                                     &k->parent_realize);
1682e997040eSCédric Le Goater }
1683e997040eSCédric Le Goater 
16842b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
16852b548a42SCédric Le Goater {
1686623575e1SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
16878b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1688623575e1SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1689623575e1SCédric Le Goater     int i;
16908b50ce85SCédric Le Goater 
1691da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1692da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1693da71b7e3SCédric Le Goater                               "xive-fabric");
16949fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
16959fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
16968bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
16970bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe",  &chip10->sbe, TYPE_PNV10_SBE);
169892499676SCédric Le Goater     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1699623575e1SCédric Le Goater 
1700623575e1SCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1701623575e1SCédric Le Goater 
1702623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1703623575e1SCédric Le Goater         object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1704623575e1SCédric Le Goater                                 TYPE_PNV_PHB5_PEC);
1705623575e1SCédric Le Goater     }
17062b548a42SCédric Le Goater }
17072b548a42SCédric Le Goater 
1708ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1709ae4c68e3SCédric Le Goater {
1710ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip10);
1711ae4c68e3SCédric Le Goater     int i;
1712ae4c68e3SCédric Le Goater 
1713ae4c68e3SCédric Le Goater     chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1714ae4c68e3SCédric Le Goater     chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1715ae4c68e3SCédric Le Goater 
1716ae4c68e3SCédric Le Goater     for (i = 0; i < chip10->nr_quads; i++) {
1717ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip10->quads[i];
1718ae4c68e3SCédric Le Goater 
1719ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
1720ae4c68e3SCédric Le Goater 
1721ae4c68e3SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1722ae4c68e3SCédric Le Goater                                 &eq->xscom_regs);
1723ae4c68e3SCédric Le Goater     }
1724ae4c68e3SCédric Le Goater }
1725ae4c68e3SCédric Le Goater 
1726623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1727623575e1SCédric Le Goater {
1728623575e1SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1729623575e1SCédric Le Goater     int i;
1730623575e1SCédric Le Goater 
1731623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1732623575e1SCédric Le Goater         PnvPhb4PecState *pec = &chip10->pecs[i];
1733623575e1SCédric Le Goater         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1734623575e1SCédric Le Goater         uint32_t pec_nest_base;
1735623575e1SCédric Le Goater         uint32_t pec_pci_base;
1736623575e1SCédric Le Goater 
1737623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1738623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1739623575e1SCédric Le Goater                                 &error_fatal);
1740623575e1SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1741623575e1SCédric Le Goater                                  &error_fatal);
1742623575e1SCédric Le Goater         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1743623575e1SCédric Le Goater             return;
1744623575e1SCédric Le Goater         }
1745623575e1SCédric Le Goater 
1746623575e1SCédric Le Goater         pec_nest_base = pecc->xscom_nest_base(pec);
1747623575e1SCédric Le Goater         pec_pci_base = pecc->xscom_pci_base(pec);
1748623575e1SCédric Le Goater 
1749623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1750623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1751623575e1SCédric Le Goater     }
1752623575e1SCédric Le Goater }
1753623575e1SCédric Le Goater 
17542b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
17552b548a42SCédric Le Goater {
17562b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
17572b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
17588b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
17592b548a42SCédric Le Goater     Error *local_err = NULL;
17602b548a42SCédric Le Goater 
17612b548a42SCédric Le Goater     /* XSCOM bridge is first */
17622b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
17632b548a42SCédric Le Goater     if (local_err) {
17642b548a42SCédric Le Goater         error_propagate(errp, local_err);
17652b548a42SCédric Le Goater         return;
17662b548a42SCédric Le Goater     }
17672b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
17682b548a42SCédric Le Goater 
17692b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
17702b548a42SCédric Le Goater     if (local_err) {
17712b548a42SCédric Le Goater         error_propagate(errp, local_err);
17722b548a42SCédric Le Goater         return;
17732b548a42SCédric Le Goater     }
17748b50ce85SCédric Le Goater 
1775ae4c68e3SCédric Le Goater     pnv_chip_power10_quad_realize(chip10, &local_err);
1776ae4c68e3SCédric Le Goater     if (local_err) {
1777ae4c68e3SCédric Le Goater         error_propagate(errp, local_err);
1778ae4c68e3SCédric Le Goater         return;
1779ae4c68e3SCédric Le Goater     }
1780ae4c68e3SCédric Le Goater 
1781da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1782da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1783da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1784da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1785da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1786da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1787da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1788da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1789da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1790da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1791da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1792da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1793da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1794da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1795da71b7e3SCédric Le Goater                              &error_abort);
1796da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1797da71b7e3SCédric Le Goater         return;
1798da71b7e3SCédric Le Goater     }
1799da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1800da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1801da71b7e3SCédric Le Goater 
18028b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
18035325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
18045325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
180524c8fa96SCédric Le Goater     /* PSI can now be configured to use 64k ESB pages on POWER10 */
180624c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
180724c8fa96SCédric Le Goater                             &error_fatal);
1808668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
18098b50ce85SCédric Le Goater         return;
18108b50ce85SCédric Le Goater     }
18118b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
18128b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
18132661f6abSCédric Le Goater 
18142661f6abSCédric Le Goater     /* LPC */
1815668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
18162661f6abSCédric Le Goater         return;
18172661f6abSCédric Le Goater     }
18182661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
18192661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
18202661f6abSCédric Le Goater 
1821032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
18222661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
18232661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
18248bf682a3SCédric Le Goater 
18258bf682a3SCédric Le Goater     /* Create the simplified OCC model */
18268bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
18278bf682a3SCédric Le Goater         return;
18288bf682a3SCédric Le Goater     }
18298bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
18308bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
1831b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1832b0ae5c69SCédric Le Goater                               DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1833623575e1SCédric Le Goater 
183492499676SCédric Le Goater     /* OCC SRAM model */
183592499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(),
183692499676SCédric Le Goater                                 PNV10_OCC_SENSOR_BASE(chip),
183792499676SCédric Le Goater                                 &chip10->occ.sram_regs);
183892499676SCédric Le Goater 
18390bf4d77eSNicholas Piggin     /* SBE */
18400bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
18410bf4d77eSNicholas Piggin         return;
18420bf4d77eSNicholas Piggin     }
18430bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
18440bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_ctrl_regs);
18450bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
18460bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_mbox_regs);
18470bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
18480bf4d77eSNicholas Piggin                               DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
18490bf4d77eSNicholas Piggin 
185092499676SCédric Le Goater     /* HOMER */
185192499676SCédric Le Goater     object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
185292499676SCédric Le Goater                              &error_abort);
185392499676SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
185492499676SCédric Le Goater         return;
185592499676SCédric Le Goater     }
185692499676SCédric Le Goater     /* Homer Xscom region */
185792499676SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
185892499676SCédric Le Goater                             &chip10->homer.pba_regs);
185992499676SCédric Le Goater 
186092499676SCédric Le Goater     /* Homer mmio region */
186192499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
186292499676SCédric Le Goater                                 &chip10->homer.regs);
186392499676SCédric Le Goater 
1864623575e1SCédric Le Goater     /* PHBs */
1865623575e1SCédric Le Goater     pnv_chip_power10_phb_realize(chip, &local_err);
1866623575e1SCédric Le Goater     if (local_err) {
1867623575e1SCédric Le Goater         error_propagate(errp, local_err);
1868623575e1SCédric Le Goater         return;
1869623575e1SCédric Le Goater     }
18702b548a42SCédric Le Goater }
18712b548a42SCédric Le Goater 
187270c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
187370c059e9SGreg Kurz {
187470c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
187570c059e9SGreg Kurz     return addr >> 3;
187670c059e9SGreg Kurz }
187770c059e9SGreg Kurz 
18782b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
18792b548a42SCédric Le Goater {
18802b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
18812b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
18822b548a42SCédric Le Goater 
18832b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
18842b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
18852b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
18862b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
18872b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
18882b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
188985913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
18902b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
18912b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
18922b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1893c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
189470c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
18952b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
1896623575e1SCédric Le Goater     k->num_pecs = PNV10_CHIP_MAX_PEC;
18972b548a42SCédric Le Goater 
18982b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
18992b548a42SCédric Le Goater                                     &k->parent_realize);
19002b548a42SCédric Le Goater }
19012b548a42SCédric Le Goater 
1902397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1903397a79e7SCédric Le Goater {
1904397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1905397a79e7SCédric Le Goater     int cores_max;
1906397a79e7SCédric Le Goater 
1907397a79e7SCédric Le Goater     /*
1908397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1909397a79e7SCédric Le Goater      * the chip class
1910397a79e7SCédric Le Goater      */
1911397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1912397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1913397a79e7SCédric Le Goater     }
1914397a79e7SCédric Le Goater 
1915397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1916397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1917397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1918397a79e7SCédric Le Goater                    chip->cores_mask);
1919397a79e7SCédric Le Goater         return;
1920397a79e7SCédric Le Goater     }
1921397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1922397a79e7SCédric Le Goater 
1923397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
192427d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1925397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1926397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1927397a79e7SCédric Le Goater                    cores_max);
1928397a79e7SCédric Le Goater         return;
1929397a79e7SCédric Le Goater     }
1930397a79e7SCédric Le Goater }
1931397a79e7SCédric Le Goater 
193251c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1933e997040eSCédric Le Goater {
1934397a79e7SCédric Le Goater     Error *error = NULL;
1935d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
193640abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1937d2fd9612SCédric Le Goater     int i, core_hwid;
193808c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1939397a79e7SCédric Le Goater 
1940d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1941d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1942d2fd9612SCédric Le Goater         return;
1943d2fd9612SCédric Le Goater     }
1944d2fd9612SCédric Le Goater 
1945d2fd9612SCédric Le Goater     /* Cores */
1946397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1947397a79e7SCédric Le Goater     if (error) {
1948397a79e7SCédric Le Goater         error_propagate(errp, error);
1949397a79e7SCédric Le Goater         return;
1950397a79e7SCédric Le Goater     }
1951d2fd9612SCédric Le Goater 
19524fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1953d2fd9612SCédric Le Goater 
1954d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1955d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1956d2fd9612SCédric Le Goater         char core_name[32];
19574fa28f23SGreg Kurz         PnvCore *pnv_core;
1958c035851aSCédric Le Goater         uint64_t xscom_core_base;
1959d2fd9612SCédric Le Goater 
1960d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1961d2fd9612SCédric Le Goater             continue;
1962d2fd9612SCédric Le Goater         }
1963d2fd9612SCédric Le Goater 
19644fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
19654fa28f23SGreg Kurz 
1966d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1967d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
19684fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
19695325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
19705325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
19715325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
19725325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
19735325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
19745325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
19755325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
19765325cc34SMarkus Armbruster                                 &error_fatal);
19775325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1978158e17a6SGreg Kurz                                  &error_abort);
1979ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
198024ece072SCédric Le Goater 
198124ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1982c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1983c035851aSCédric Le Goater 
1984c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
19854fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1986d2fd9612SCédric Le Goater         i++;
1987d2fd9612SCédric Le Goater     }
198851c04728SCédric Le Goater }
198951c04728SCédric Le Goater 
199051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
199151c04728SCédric Le Goater {
199251c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
199351c04728SCédric Le Goater     Error *error = NULL;
199451c04728SCédric Le Goater 
199551c04728SCédric Le Goater     /* Cores */
199651c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
199751c04728SCédric Le Goater     if (error) {
199851c04728SCédric Le Goater         error_propagate(errp, error);
199951c04728SCédric Le Goater         return;
200051c04728SCédric Le Goater     }
2001e997040eSCédric Le Goater }
2002e997040eSCédric Le Goater 
2003e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
2004e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
2005e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
2006e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
2007397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
2008397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
2009764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
2010e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
2011e997040eSCédric Le Goater };
2012e997040eSCédric Le Goater 
2013e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
2014e997040eSCédric Le Goater {
2015e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
2016e997040eSCédric Le Goater 
20179d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
2018e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
20194f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
2020e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
2021e997040eSCédric Le Goater }
2022e997040eSCédric Le Goater 
2023119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
2024119eaa9dSCédric Le Goater {
2025119eaa9dSCédric Le Goater     int i, j;
2026119eaa9dSCédric Le Goater 
2027119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2028119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
2029119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
2030119eaa9dSCédric Le Goater 
2031119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
2032119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
2033119eaa9dSCédric Le Goater                 return pc->threads[j];
2034119eaa9dSCédric Le Goater             }
2035119eaa9dSCédric Le Goater         }
2036119eaa9dSCédric Le Goater     }
2037119eaa9dSCédric Le Goater     return NULL;
2038119eaa9dSCédric Le Goater }
2039119eaa9dSCédric Le Goater 
204054f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
204154f59d78SCédric Le Goater {
2042b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2043da6be501SDaniel Henrique Barboza     int i, j;
204454f59d78SCédric Le Goater 
204554f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
204677864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
204777864267SCédric Le Goater 
204877864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
204977864267SCédric Le Goater             return &chip8->psi.ics;
205054f59d78SCédric Le Goater         }
20512ff73ddaSCédric Le Goater 
2052da6be501SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20530d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20541f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2055da6be501SDaniel Henrique Barboza 
2056da6be501SDaniel Henrique Barboza             if (ics_valid_irq(&phb3->lsis, irq)) {
2057da6be501SDaniel Henrique Barboza                 return &phb3->lsis;
2058da6be501SDaniel Henrique Barboza             }
2059da6be501SDaniel Henrique Barboza 
2060da6be501SDaniel Henrique Barboza             if (ics_valid_irq(ICS(&phb3->msis), irq)) {
2061da6be501SDaniel Henrique Barboza                 return ICS(&phb3->msis);
2062da6be501SDaniel Henrique Barboza             }
20639ae1329eSCédric Le Goater         }
206454f59d78SCédric Le Goater     }
206554f59d78SCédric Le Goater     return NULL;
206654f59d78SCédric Le Goater }
206754f59d78SCédric Le Goater 
20681f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
20691f6a88ffSCédric Le Goater {
20701f6a88ffSCédric Le Goater     int i;
20711f6a88ffSCédric Le Goater 
20721f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
20731f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
20741f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
20751f6a88ffSCédric Le Goater             return chip;
20761f6a88ffSCédric Le Goater         }
20771f6a88ffSCédric Le Goater     }
20781f6a88ffSCédric Le Goater     return NULL;
20791f6a88ffSCédric Le Goater }
20801f6a88ffSCédric Le Goater 
208154f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
208254f59d78SCédric Le Goater {
2083b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2084ca459489SDaniel Henrique Barboza     int i, j;
208554f59d78SCédric Le Goater 
208654f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
208777864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
20889ae1329eSCédric Le Goater 
208977864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
2090ca459489SDaniel Henrique Barboza 
2091ca459489SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20920d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20931f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2094ca459489SDaniel Henrique Barboza 
2095ca459489SDaniel Henrique Barboza             ics_resend(&phb3->lsis);
2096ca459489SDaniel Henrique Barboza             ics_resend(ICS(&phb3->msis));
2097ca459489SDaniel Henrique Barboza         }
209854f59d78SCédric Le Goater     }
209954f59d78SCédric Le Goater }
210054f59d78SCédric Le Goater 
210136fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
210236fc6f08SCédric Le Goater {
210336fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
210436fc6f08SCédric Le Goater 
2105956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
210636fc6f08SCédric Le Goater }
210736fc6f08SCédric Le Goater 
210847fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
210947fea43aSCédric Le Goater                                Monitor *mon)
211047fea43aSCédric Le Goater {
2111b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
211254f59d78SCédric Le Goater     int i;
211347fea43aSCédric Le Goater     CPUState *cs;
211447fea43aSCédric Le Goater 
211547fea43aSCédric Le Goater     CPU_FOREACH(cs) {
211647fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
211747fea43aSCédric Le Goater 
211885913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
211985913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
212085913070SGreg Kurz                                                            mon);
2121d8e4aad5SCédric Le Goater     }
212254f59d78SCédric Le Goater 
212354f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2124d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
212554f59d78SCédric Le Goater     }
212647fea43aSCédric Le Goater }
212747fea43aSCédric Le Goater 
2128c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2129c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
2130c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
2131c722579eSCédric Le Goater                          uint32_t logic_serv,
2132c722579eSCédric Le Goater                          XiveTCTXMatch *match)
2133c722579eSCédric Le Goater {
2134c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2135c722579eSCédric Le Goater     int total_count = 0;
2136c722579eSCédric Le Goater     int i;
2137c722579eSCédric Le Goater 
2138c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2139c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2140c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2141c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2142c722579eSCédric Le Goater         int count;
2143c722579eSCédric Le Goater 
2144c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2145c722579eSCédric Le Goater                                priority, logic_serv, match);
2146c722579eSCédric Le Goater 
2147c722579eSCédric Le Goater         if (count < 0) {
2148c722579eSCédric Le Goater             return count;
2149c722579eSCédric Le Goater         }
2150c722579eSCédric Le Goater 
2151c722579eSCédric Le Goater         total_count += count;
2152c722579eSCédric Le Goater     }
2153c722579eSCédric Le Goater 
2154c722579eSCédric Le Goater     return total_count;
2155c722579eSCédric Le Goater }
2156c722579eSCédric Le Goater 
2157da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2158da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
2159da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
2160da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
2161da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
2162da71b7e3SCédric Le Goater {
2163da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2164da71b7e3SCédric Le Goater     int total_count = 0;
2165da71b7e3SCédric Le Goater     int i;
2166da71b7e3SCédric Le Goater 
2167da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2168da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2169da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2170da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2171da71b7e3SCédric Le Goater         int count;
2172da71b7e3SCédric Le Goater 
2173da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2174da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2175da71b7e3SCédric Le Goater 
2176da71b7e3SCédric Le Goater         if (count < 0) {
2177da71b7e3SCédric Le Goater             return count;
2178da71b7e3SCédric Le Goater         }
2179da71b7e3SCédric Le Goater 
2180da71b7e3SCédric Le Goater         total_count += count;
2181da71b7e3SCédric Le Goater     }
2182da71b7e3SCédric Le Goater 
2183da71b7e3SCédric Le Goater     return total_count;
2184da71b7e3SCédric Le Goater }
2185da71b7e3SCédric Le Goater 
2186f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
21879e933f4aSBenjamin Herrenschmidt {
21889e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
218936fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2190d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2191d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2192f30c843cSCédric Le Goater 
21931f5d6b2aSDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
21941f5d6b2aSDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "3" },
219580515061SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
21961f5d6b2aSDaniel Henrique Barboza     };
21971f5d6b2aSDaniel Henrique Barboza 
2198f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2199f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
22001f5d6b2aSDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2201f30c843cSCédric Le Goater 
2202f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2203f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2204f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2205d76f2da7SGreg Kurz 
2206d76f2da7SGreg Kurz     pmc->compat = compat;
2207d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2208892c3ad0SDaniel Henrique Barboza 
2209892c3ad0SDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2210f30c843cSCédric Le Goater }
2211f30c843cSCédric Le Goater 
2212f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2213f30c843cSCédric Le Goater {
2214f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2215c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2216d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2217d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2218f30c843cSCédric Le Goater 
2219210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2220210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "4" },
2221c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "4" },
2222210aacb3SDaniel Henrique Barboza     };
2223210aacb3SDaniel Henrique Barboza 
2224f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2225f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
2226210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2227210aacb3SDaniel Henrique Barboza 
2228c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2229f30c843cSCédric Le Goater 
2230f30c843cSCédric Le Goater     mc->alias = "powernv";
2231d76f2da7SGreg Kurz 
2232d76f2da7SGreg Kurz     pmc->compat = compat;
2233d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22347a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2235d786be3fSDaniel Henrique Barboza 
2236d786be3fSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2237f30c843cSCédric Le Goater }
2238f30c843cSCédric Le Goater 
22392b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
22402b548a42SCédric Le Goater {
22412b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2242d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2243da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2244d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
22452b548a42SCédric Le Goater 
2246210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2247210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "5" },
2248c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
2249210aacb3SDaniel Henrique Barboza     };
2250210aacb3SDaniel Henrique Barboza 
22512b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
22526bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2253210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2254d76f2da7SGreg Kurz 
2255d76f2da7SGreg Kurz     pmc->compat = compat;
2256d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22577a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2258da71b7e3SCédric Le Goater 
2259da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
2260f1327fdeSDaniel Henrique Barboza 
2261f1327fdeSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
22622b548a42SCédric Le Goater }
22632b548a42SCédric Le Goater 
226408c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
226508c3f3a7SCédric Le Goater {
226608c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
226708c3f3a7SCédric Le Goater 
226808c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
226908c3f3a7SCédric Le Goater }
227008c3f3a7SCédric Le Goater 
227108c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
227208c3f3a7SCédric Le Goater {
227308c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
227408c3f3a7SCédric Le Goater 
227508c3f3a7SCédric Le Goater     if (value) {
227608c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
227708c3f3a7SCédric Le Goater     }
227808c3f3a7SCédric Le Goater }
227908c3f3a7SCédric Le Goater 
228001b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
228101b552b0SNicholas Piggin {
228201b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
228301b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
228401b552b0SNicholas Piggin 
228501b552b0SNicholas Piggin     cpu_synchronize_state(cs);
228601b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
22870911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
228801b552b0SNicholas Piggin         /*
2289fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2290fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2291fe837714SNicholas Piggin          * (PPC_BIT(43)).
229201b552b0SNicholas Piggin          */
22930911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2294fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
22950911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
229601b552b0SNicholas Piggin         }
2297fe837714SNicholas Piggin     } else {
2298fe837714SNicholas Piggin         /*
2299fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2300fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2301fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2302fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2303fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2304fe837714SNicholas Piggin          */
23050911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2306fe837714SNicholas Piggin     }
2307fe837714SNicholas Piggin }
230801b552b0SNicholas Piggin 
230901b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
231001b552b0SNicholas Piggin {
231101b552b0SNicholas Piggin     CPUState *cs;
231201b552b0SNicholas Piggin 
231301b552b0SNicholas Piggin     CPU_FOREACH(cs) {
231401b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
231501b552b0SNicholas Piggin     }
231601b552b0SNicholas Piggin }
231701b552b0SNicholas Piggin 
2318f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2319f30c843cSCédric Le Goater {
2320f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
232147fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
232201b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
23239e933f4aSBenjamin Herrenschmidt 
23249e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2325b168a138SCédric Le Goater     mc->init = pnv_init;
2326b168a138SCédric Le Goater     mc->reset = pnv_reset;
23279e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
232859b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
232959b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
23309e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
23319e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2332f1d18b0aSJoel Stanley     /*
2333f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2334f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2335f1d18b0aSJoel Stanley      */
2336dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2337173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
233847fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
233901b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
234008c3f3a7SCédric Le Goater 
234108c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2342d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
234308c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
23447eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
23459e933f4aSBenjamin Herrenschmidt }
23469e933f4aSBenjamin Herrenschmidt 
234777864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2348beba5c0fSIgor Mammedov     {                                             \
2349beba5c0fSIgor Mammedov         .name          = type,                    \
2350beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
235177864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
235277864267SCédric Le Goater     }
235377864267SCédric Le Goater 
235477864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
235577864267SCédric Le Goater     {                                             \
235677864267SCédric Le Goater         .name          = type,                    \
235777864267SCédric Le Goater         .class_init    = class_initfn,            \
235877864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2359beba5c0fSIgor Mammedov     }
2360beba5c0fSIgor Mammedov 
23612b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
23622b548a42SCédric Le Goater     {                                              \
23632b548a42SCédric Le Goater         .name          = type,                     \
23642b548a42SCédric Le Goater         .class_init    = class_initfn,             \
23652b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
23662b548a42SCédric Le Goater     }
23672b548a42SCédric Le Goater 
2368beba5c0fSIgor Mammedov static const TypeInfo types[] = {
23691aba8716SCédric Le Goater     {
23702b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
23712b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23722b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2373da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2374da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2375da71b7e3SCédric Le Goater             { },
2376da71b7e3SCédric Le Goater         },
23772b548a42SCédric Le Goater     },
23782b548a42SCédric Le Goater     {
23791aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
23801aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23811aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2382c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2383c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2384c722579eSCédric Le Goater             { },
2385c722579eSCédric Le Goater         },
23861aba8716SCédric Le Goater     },
23871aba8716SCédric Le Goater     {
23881aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
23891aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23901aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
23911aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
23921aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
23931aba8716SCédric Le Goater             { },
23941aba8716SCédric Le Goater         },
23951aba8716SCédric Le Goater     },
2396beba5c0fSIgor Mammedov     {
2397b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
23989e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2399f30c843cSCédric Le Goater         .abstract       = true,
24009e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2401b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2402d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
240336fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
240447fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
240501b552b0SNicholas Piggin             { TYPE_NMI },
240636fc6f08SCédric Le Goater             { },
240736fc6f08SCédric Le Goater         },
2408beba5c0fSIgor Mammedov     },
2409beba5c0fSIgor Mammedov     {
2410beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2411beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2412beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2413beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2414beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2415beba5c0fSIgor Mammedov         .abstract      = true,
2416beba5c0fSIgor Mammedov     },
241777864267SCédric Le Goater 
241877864267SCédric Le Goater     /*
24192b548a42SCédric Le Goater      * P10 chip and variants
24202b548a42SCédric Le Goater      */
24212b548a42SCédric Le Goater     {
24222b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
24232b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
24242b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
24252b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
24262b548a42SCédric Le Goater     },
24272b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
24282b548a42SCédric Le Goater 
24292b548a42SCédric Le Goater     /*
243077864267SCédric Le Goater      * P9 chip and variants
243177864267SCédric Le Goater      */
243277864267SCédric Le Goater     {
243377864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
243477864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
243577864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
243677864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
243777864267SCédric Le Goater     },
243877864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
243977864267SCédric Le Goater 
244077864267SCédric Le Goater     /*
244177864267SCédric Le Goater      * P8 chip and variants
244277864267SCédric Le Goater      */
244377864267SCédric Le Goater     {
244477864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
244577864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
244677864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
244777864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
244877864267SCédric Le Goater     },
244977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
245077864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
245177864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2452beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
24539e933f4aSBenjamin Herrenschmidt };
24549e933f4aSBenjamin Herrenschmidt 
2455beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2456