xref: /qemu/hw/ppc/pnv.c (revision 8bf682a3)
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"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
222c65db5eSPaolo Bonzini #include "qemu/datadir.h"
23fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
24dd7ef911SCédric Le Goater #include "qemu/cutils.h"
259e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
2638d2448aSGreg Kurz #include "sysemu/qtest.h"
279e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
289e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2971e8a915SMarkus Armbruster #include "sysemu/reset.h"
3054d31236SMarkus Armbruster #include "sysemu/runstate.h"
31d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
328d409261SCédric Le Goater #include "sysemu/device_tree.h"
3301b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
34fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
379e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
38d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
399e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
4001b552b0SNicholas Piggin #include "hw/nmi.h"
41e997040eSCédric Le Goater #include "qapi/visitor.h"
4247fea43aSCédric Le Goater #include "monitor/monitor.h"
4347fea43aSCédric Le Goater #include "hw/intc/intc.h"
44aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4558969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
464f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.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);
141d2fd9612SCédric Le Goater     uint32_t servers_prop[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",
244d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
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 
284eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
285e997040eSCédric Le Goater {
286c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
287d2fd9612SCédric Le Goater     int i;
288d2fd9612SCédric Le Goater 
2893f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2903f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
291c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
292c396c58aSGreg Kurz                  compat, sizeof(compat));
293967b7523SCédric Le Goater 
294d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2954fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
296d2fd9612SCédric Le Goater 
297b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
298bf5615e7SCédric Le Goater 
299bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
300b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
301d2fd9612SCédric Le Goater     }
302d2fd9612SCédric Le Goater 
303e997040eSCédric Le Goater     if (chip->ram_size) {
304b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
305e997040eSCédric Le Goater     }
306e997040eSCédric Le Goater }
307e997040eSCédric Le Goater 
308eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
309eb859a27SCédric Le Goater {
310c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
311eb859a27SCédric Le Goater     int i;
312eb859a27SCédric Le Goater 
3133f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3143f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
315c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
316c396c58aSGreg Kurz                  compat, sizeof(compat));
317eb859a27SCédric Le Goater 
318eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3194fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
320eb859a27SCédric Le Goater 
321eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
322eb859a27SCédric Le Goater     }
323eb859a27SCédric Le Goater 
324eb859a27SCédric Le Goater     if (chip->ram_size) {
325eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
326eb859a27SCédric Le Goater     }
32715376c66SCédric Le Goater 
3282661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
329eb859a27SCédric Le Goater }
330eb859a27SCédric Le Goater 
3312b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3322b548a42SCédric Le Goater {
333c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3342b548a42SCédric Le Goater     int i;
3352b548a42SCédric Le Goater 
3363f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3373f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
338c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
339c396c58aSGreg Kurz                  compat, sizeof(compat));
3402b548a42SCédric Le Goater 
3412b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3422b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3432b548a42SCédric Le Goater 
3442b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3452b548a42SCédric Le Goater     }
3462b548a42SCédric Le Goater 
3472b548a42SCédric Le Goater     if (chip->ram_size) {
3482b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3492b548a42SCédric Le Goater     }
3502661f6abSCédric Le Goater 
3512661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3522b548a42SCédric Le Goater }
3532b548a42SCédric Le Goater 
354b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
355c5ffdcaeSCédric Le Goater {
356c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
357c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
358c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
359c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
360c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
361c5ffdcaeSCédric Le Goater     };
362c5ffdcaeSCédric Le Goater     char *name;
363c5ffdcaeSCédric Le Goater     int node;
364c5ffdcaeSCédric Le Goater 
365c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
366c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
367c5ffdcaeSCédric Le Goater     _FDT(node);
368c5ffdcaeSCédric Le Goater     g_free(name);
369c5ffdcaeSCédric Le Goater 
370c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
371c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
372c5ffdcaeSCédric Le Goater }
373c5ffdcaeSCédric Le Goater 
374b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
375cb228f5aSCédric Le Goater {
376cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
377cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
378cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
379cb228f5aSCédric Le Goater         cpu_to_be32(1),
380cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
381cb228f5aSCédric Le Goater         cpu_to_be32(8)
382cb228f5aSCédric Le Goater     };
383632fc0b3SBernhard Beschow     uint32_t irq;
384cb228f5aSCédric Le Goater     char *name;
385cb228f5aSCédric Le Goater     int node;
386cb228f5aSCédric Le Goater 
387632fc0b3SBernhard Beschow     irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
388632fc0b3SBernhard Beschow 
389cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
390cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
391cb228f5aSCédric Le Goater     _FDT(node);
392cb228f5aSCédric Le Goater     g_free(name);
393cb228f5aSCédric Le Goater 
394cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
395cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
396cb228f5aSCédric Le Goater                       sizeof(compatible))));
397cb228f5aSCédric Le Goater 
398cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
399cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
400632fc0b3SBernhard Beschow     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
401cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
402cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
403cb228f5aSCédric Le Goater 
404cb228f5aSCédric Le Goater     /* This is needed by Linux */
405cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
406cb228f5aSCédric Le Goater }
407cb228f5aSCédric Le Goater 
408b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40904f6c8b2SCédric Le Goater {
41004f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
41104f6c8b2SCédric Le Goater     uint32_t io_base;
41204f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
41304f6c8b2SCédric Le Goater         cpu_to_be32(1),
41404f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41504f6c8b2SCédric Le Goater         cpu_to_be32(3)
41604f6c8b2SCédric Le Goater     };
41704f6c8b2SCédric Le Goater     uint32_t irq;
41804f6c8b2SCédric Le Goater     char *name;
41904f6c8b2SCédric Le Goater     int node;
42004f6c8b2SCédric Le Goater 
42104f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
42204f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
42304f6c8b2SCédric Le Goater 
42404f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42504f6c8b2SCédric Le Goater 
42604f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42704f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42804f6c8b2SCédric Le Goater     _FDT(node);
42904f6c8b2SCédric Le Goater     g_free(name);
43004f6c8b2SCédric Le Goater 
4317032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4327032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4337032d92aSCédric Le Goater                       sizeof(compatible))));
43404f6c8b2SCédric Le Goater 
43504f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43704f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43804f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43904f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
44004f6c8b2SCédric Le Goater }
44104f6c8b2SCédric Le Goater 
442e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
443e7a3fee3SCédric Le Goater     void *fdt;
444e7a3fee3SCédric Le Goater     int offset;
445e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
446e7a3fee3SCédric Le Goater 
447b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
448e7a3fee3SCédric Le Goater {
449c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
450c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
451c5ffdcaeSCédric Le Goater 
452c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
453b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
454cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
455b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45604f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
457b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
458c5ffdcaeSCédric Le Goater     } else {
459c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
460c5ffdcaeSCédric Le Goater                      d->ioport_id);
461c5ffdcaeSCédric Le Goater     }
462c5ffdcaeSCédric Le Goater 
463e7a3fee3SCédric Le Goater     return 0;
464e7a3fee3SCédric Le Goater }
465e7a3fee3SCédric Le Goater 
46659b7c1c2SBalamuruhan S /*
46759b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
468bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
469bb7ab95cSCédric Le Goater  */
470bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
471bb7ab95cSCédric Le Goater {
47264d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
473e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
474e7a3fee3SCédric Le Goater         .fdt = fdt,
475bb7ab95cSCédric Le Goater         .offset = isa_offset,
476e7a3fee3SCédric Le Goater     };
477f47a08d1SCédric Le Goater     uint32_t phandle;
478e7a3fee3SCédric Le Goater 
479bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
480bb7ab95cSCédric Le Goater 
481f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
482f47a08d1SCédric Le Goater     assert(phandle > 0);
483f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
484f47a08d1SCédric Le Goater 
48559b7c1c2SBalamuruhan S     /*
48659b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48759b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48859b7c1c2SBalamuruhan S      */
489bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
490bb7ab95cSCédric Le Goater                        &args);
491e7a3fee3SCédric Le Goater }
492e7a3fee3SCédric Le Goater 
4937a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
494e5694793SCédric Le Goater {
495e5694793SCédric Le Goater     int off;
496e5694793SCédric Le Goater 
497e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
498e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
499e5694793SCédric Le Goater 
500e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
501e5694793SCédric Le Goater }
502e5694793SCédric Le Goater 
503b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5049e933f4aSBenjamin Herrenschmidt {
505d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
506b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5079e933f4aSBenjamin Herrenschmidt     void *fdt;
5089e933f4aSBenjamin Herrenschmidt     char *buf;
5099e933f4aSBenjamin Herrenschmidt     int off;
510e997040eSCédric Le Goater     int i;
5119e933f4aSBenjamin Herrenschmidt 
5129e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5139e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5149e933f4aSBenjamin Herrenschmidt 
515ccb099b3SCédric Le Goater     /* /qemu node */
516ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
517ccb099b3SCédric Le Goater 
5189e933f4aSBenjamin Herrenschmidt     /* Root node */
5199e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5209e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5219e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5229e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
523d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5249e933f4aSBenjamin Herrenschmidt 
5259e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5269e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5279e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
528bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
5299e933f4aSBenjamin Herrenschmidt     }
5309e933f4aSBenjamin Herrenschmidt     g_free(buf);
5319e933f4aSBenjamin Herrenschmidt 
5329e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5339e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5349e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5359e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5369e933f4aSBenjamin Herrenschmidt     }
5379e933f4aSBenjamin Herrenschmidt 
5389e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5399e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5409e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5419e933f4aSBenjamin Herrenschmidt 
5429e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5439e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5449e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5459e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5469e933f4aSBenjamin Herrenschmidt     }
5479e933f4aSBenjamin Herrenschmidt 
548e997040eSCédric Le Goater     /* Populate device tree for each chip */
549e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
550eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
551e997040eSCédric Le Goater     }
552e7a3fee3SCédric Le Goater 
553e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
554bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
555aeaef83dSCédric Le Goater 
556aeaef83dSCédric Le Goater     if (pnv->bmc) {
557b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
558aeaef83dSCédric Le Goater     }
559aeaef83dSCédric Le Goater 
5607a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5617a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5627a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
563e5694793SCédric Le Goater     }
564e5694793SCédric Le Goater 
5659e933f4aSBenjamin Herrenschmidt     return fdt;
5669e933f4aSBenjamin Herrenschmidt }
5679e933f4aSBenjamin Herrenschmidt 
568bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
569bce0b691SCédric Le Goater {
5708f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
571bce0b691SCédric Le Goater 
572bce0b691SCédric Le Goater     if (pnv->bmc) {
573bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
574bce0b691SCédric Le Goater     }
575bce0b691SCédric Le Goater }
576bce0b691SCédric Le Goater 
577a0628599SLike Xu static void pnv_reset(MachineState *machine)
5789e933f4aSBenjamin Herrenschmidt {
57925f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
58025f3170bSCédric Le Goater     IPMIBmc *bmc;
5819e933f4aSBenjamin Herrenschmidt     void *fdt;
5829e933f4aSBenjamin Herrenschmidt 
5839e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5849e933f4aSBenjamin Herrenschmidt 
58525f3170bSCédric Le Goater     /*
58625f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
58725f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
58825f3170bSCédric Le Goater      * line.
58925f3170bSCédric Le Goater      */
59025f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
59125f3170bSCédric Le Goater     if (!pnv->bmc) {
59225f3170bSCédric Le Goater         if (!bmc) {
59338d2448aSGreg Kurz             if (!qtest_enabled()) {
59425f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
59525f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59625f3170bSCédric Le Goater                             "to define one");
59738d2448aSGreg Kurz             }
59825f3170bSCédric Le Goater         } else {
59925f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
60025f3170bSCédric Le Goater             pnv->bmc = bmc;
60125f3170bSCédric Le Goater         }
60225f3170bSCédric Le Goater     }
60325f3170bSCédric Le Goater 
604b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6059e933f4aSBenjamin Herrenschmidt 
6069e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6079e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6089e933f4aSBenjamin Herrenschmidt 
6098d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6109e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
611b2fb7a43SPan Nengyuan 
612b2fb7a43SPan Nengyuan     g_free(fdt);
6139e933f4aSBenjamin Herrenschmidt }
6149e933f4aSBenjamin Herrenschmidt 
61504026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6163495b6b6SCédric Le Goater {
61777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
61877864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
61904026890SCédric Le Goater }
6203495b6b6SCédric Le Goater 
62104026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
62204026890SCédric Le Goater {
62377864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
62477864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
62504026890SCédric Le Goater }
6263495b6b6SCédric Le Goater 
62704026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
62804026890SCédric Le Goater {
62915376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
63015376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
63104026890SCédric Le Goater }
6323495b6b6SCédric Le Goater 
6332b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6342b548a42SCédric Le Goater {
6352661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6362661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6372b548a42SCédric Le Goater }
6382b548a42SCédric Le Goater 
63904026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
64004026890SCédric Le Goater {
64104026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6423495b6b6SCédric Le Goater }
6433495b6b6SCédric Le Goater 
6442ff73ddaSCédric Le Goater static int pnv_chip_power8_pic_print_info_child(Object *child, void *opaque)
6452ff73ddaSCédric Le Goater {
6462ff73ddaSCédric Le Goater     Monitor *mon = opaque;
6472ff73ddaSCédric Le Goater     PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
6482ff73ddaSCédric Le Goater 
6492ff73ddaSCédric Le Goater     if (phb3) {
6502ff73ddaSCédric Le Goater         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
6512ff73ddaSCédric Le Goater         ics_pic_print_info(&phb3->lsis, mon);
6522ff73ddaSCédric Le Goater     }
6532ff73ddaSCédric Le Goater     return 0;
6542ff73ddaSCédric Le Goater }
6552ff73ddaSCédric Le Goater 
656d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
657d8e4aad5SCédric Le Goater {
658d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
659d8e4aad5SCédric Le Goater 
660d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6612ff73ddaSCédric Le Goater     object_child_foreach(OBJECT(chip),
6622ff73ddaSCédric Le Goater                          pnv_chip_power8_pic_print_info_child, mon);
663d8e4aad5SCédric Le Goater }
664d8e4aad5SCédric Le Goater 
6650e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
6660e6232bcSCédric Le Goater {
6670e6232bcSCédric Le Goater     Monitor *mon = opaque;
6680e6232bcSCédric Le Goater     PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4);
6690e6232bcSCédric Le Goater 
6700e6232bcSCédric Le Goater     if (phb4) {
6710e6232bcSCédric Le Goater         pnv_phb4_pic_print_info(phb4, mon);
6720e6232bcSCédric Le Goater     }
6730e6232bcSCédric Le Goater     return 0;
6740e6232bcSCédric Le Goater }
6750e6232bcSCédric Le Goater 
676d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
677d8e4aad5SCédric Le Goater {
678d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
679d8e4aad5SCédric Le Goater 
680d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
681c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6824f9924c4SBenjamin Herrenschmidt 
6830e6232bcSCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
6840e6232bcSCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
685d8e4aad5SCédric Le Goater }
686d8e4aad5SCédric Le Goater 
687c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
688c4b2c40cSGreg Kurz                                                 uint32_t core_id)
689c4b2c40cSGreg Kurz {
690c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
691c4b2c40cSGreg Kurz }
692c4b2c40cSGreg Kurz 
693c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
694c4b2c40cSGreg Kurz                                                 uint32_t core_id)
695c4b2c40cSGreg Kurz {
696c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
697c4b2c40cSGreg Kurz }
698c4b2c40cSGreg Kurz 
699c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
700c4b2c40cSGreg Kurz                                                  uint32_t core_id)
701c4b2c40cSGreg Kurz {
702c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
703c4b2c40cSGreg Kurz }
704c4b2c40cSGreg Kurz 
705f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
706f30c843cSCédric Le Goater {
707f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
708f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
709f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
710f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
711f30c843cSCédric Le Goater 
712f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
713f30c843cSCédric Le Goater }
714f30c843cSCédric Le Goater 
715e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
716e2392d43SCédric Le Goater {
717c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
718e2392d43SCédric Le Goater 
7195325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7205325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
721c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
722e2392d43SCédric Le Goater }
723e2392d43SCédric Le Goater 
7242b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7252b548a42SCédric Le Goater {
7268b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7278b50ce85SCédric Le Goater 
728da71b7e3SCédric Le Goater     pnv_xive2_pic_print_info(&chip10->xive, mon);
7298b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
7302b548a42SCédric Le Goater }
7312b548a42SCédric Le Goater 
732458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
733458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
734458c6f01SCédric Le Goater {
735458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
736458c6f01SCédric Le Goater     uint64_t ram_per_chip;
737458c6f01SCédric Le Goater 
738458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
739458c6f01SCédric Le Goater 
740458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
741458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
742458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
743458c6f01SCédric Le Goater     }
744458c6f01SCédric Le Goater 
745f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
746f640afecSCédric Le Goater 
747458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
748458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
749458c6f01SCédric Le Goater }
750458c6f01SCédric Le Goater 
751b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7529e933f4aSBenjamin Herrenschmidt {
753cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
754b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
755f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7569e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7579e933f4aSBenjamin Herrenschmidt     long fw_size;
758458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
759e997040eSCédric Le Goater     int i;
760e997040eSCédric Le Goater     char *chip_typename;
76135dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
76235dde576SCédric Le Goater     DeviceState *dev;
7639e933f4aSBenjamin Herrenschmidt 
764ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
765ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
766ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
767ebe6c3faSDaniel Henrique Barboza     }
768ebe6c3faSDaniel Henrique Barboza 
7699e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
770dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
771dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
772dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
773dd7ef911SCédric Le Goater         g_free(sz);
774dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
7759e933f4aSBenjamin Herrenschmidt     }
776173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7779e933f4aSBenjamin Herrenschmidt 
77835dde576SCédric Le Goater     /*
77935dde576SCédric Le Goater      * Create our simple PNOR device
78035dde576SCédric Le Goater      */
7813e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
78235dde576SCédric Le Goater     if (pnor) {
783934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
78435dde576SCédric Le Goater     }
7853c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
78635dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
78735dde576SCédric Le Goater 
7889e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7899e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
79015fcedb2SCédric Le Goater     if (!fw_filename) {
79115fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
79215fcedb2SCédric Le Goater         exit(1);
79315fcedb2SCédric Le Goater     }
7949e933f4aSBenjamin Herrenschmidt 
79508c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
7969e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
79715fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7989e933f4aSBenjamin Herrenschmidt         exit(1);
7999e933f4aSBenjamin Herrenschmidt     }
8009e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8019e933f4aSBenjamin Herrenschmidt 
8029e933f4aSBenjamin Herrenschmidt     /* load kernel */
8039e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8049e933f4aSBenjamin Herrenschmidt         long kernel_size;
8059e933f4aSBenjamin Herrenschmidt 
8069e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
807b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8089e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
809802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8109e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8119e933f4aSBenjamin Herrenschmidt             exit(1);
8129e933f4aSBenjamin Herrenschmidt         }
8139e933f4aSBenjamin Herrenschmidt     }
8149e933f4aSBenjamin Herrenschmidt 
8159e933f4aSBenjamin Herrenschmidt     /* load initrd */
8169e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
8179e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
8189e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
819584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
8209e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
821802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
8229e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
8239e933f4aSBenjamin Herrenschmidt             exit(1);
8249e933f4aSBenjamin Herrenschmidt         }
8259e933f4aSBenjamin Herrenschmidt     }
826e997040eSCédric Le Goater 
8274f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8284f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8294f9924c4SBenjamin Herrenschmidt 
830f30c843cSCédric Le Goater     /*
831f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
832f30c843cSCédric Le Goater      * default.
833f30c843cSCédric Le Goater      */
834f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
835f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
836f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
837f30c843cSCédric Le Goater         exit(1);
838f30c843cSCédric Le Goater     }
839f30c843cSCédric Le Goater 
840e997040eSCédric Le Goater     /* Create the processor chips */
8414a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8427fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8434a12c699SIgor Mammedov                                     i, machine->cpu_type);
844e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
845f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
846f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
847e997040eSCédric Le Goater         exit(1);
848e997040eSCédric Le Goater     }
849e997040eSCédric Le Goater 
850e44acde2SGreg Kurz     pnv->num_chips =
851e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
852e44acde2SGreg Kurz     /*
853e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
854e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
855e44acde2SGreg Kurz      */
856ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
857e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
858ab17a3feSCédric Le Goater         error_printf(
859ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
860e44acde2SGreg Kurz         exit(1);
861e44acde2SGreg Kurz     }
862e44acde2SGreg Kurz 
863e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
864e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
865e997040eSCédric Le Goater         char chip_name[32];
866df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
8670e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
868e997040eSCédric Le Goater 
869e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
870e997040eSCédric Le Goater 
871458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
872458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
873e997040eSCédric Le Goater                                 &error_fatal);
874458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
875458c6f01SCédric Le Goater                                 &error_fatal);
876458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
877e997040eSCédric Le Goater 
8780e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
879d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
8800e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
8815325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
8825325cc34SMarkus Armbruster                                 &error_fatal);
8835325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
8845325cc34SMarkus Armbruster                                 &error_fatal);
885245cdb7fSCédric Le Goater         /*
886245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
887245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
888245cdb7fSCédric Le Goater          */
889245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
8905325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
891245cdb7fSCédric Le Goater         }
892d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
8935325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
894d1214b81SGreg Kurz                                      &error_abort);
895d1214b81SGreg Kurz         }
8963c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
897e997040eSCédric Le Goater     }
898e997040eSCédric Le Goater     g_free(chip_typename);
8993495b6b6SCédric Le Goater 
9003495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
90104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9023495b6b6SCédric Le Goater 
9033495b6b6SCédric Le Goater     /* Create serial port */
904def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9053495b6b6SCédric Le Goater 
9063495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9076c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
908bce0b691SCédric Le Goater 
90925f3170bSCédric Le Goater     /*
91025f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
91125f3170bSCédric Le Goater      * communication with the BMC
91225f3170bSCédric Le Goater      */
91325f3170bSCédric Le Goater     if (defaults_enabled()) {
91425f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
915e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
91625f3170bSCédric Le Goater     }
917e2392d43SCédric Le Goater 
91859b7c1c2SBalamuruhan S     /*
919032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
920032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
921032c226bSCédric Le Goater      * map it always for now.
922032c226bSCédric Le Goater      */
923032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
924032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
925032c226bSCédric Le Goater 
926032c226bSCédric Le Goater     /*
92759b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
92859b7c1c2SBalamuruhan S      * host to powerdown
92959b7c1c2SBalamuruhan S      */
930bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
931bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
932e997040eSCédric Le Goater }
933e997040eSCédric Le Goater 
934631adaffSCédric Le Goater /*
935631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
936631adaffSCédric Le Goater  *   22:24  Chip ID
937631adaffSCédric Le Goater  *   25:28  Core number
938631adaffSCédric Le Goater  *   29:31  Thread ID
939631adaffSCédric Le Goater  */
940631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
941631adaffSCédric Le Goater {
942631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
943631adaffSCédric Le Goater }
944631adaffSCédric Le Goater 
9458fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
946d35aefa9SCédric Le Goater                                         Error **errp)
947d35aefa9SCédric Le Goater {
948245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9498fa1f4efSCédric Le Goater     Error *local_err = NULL;
9508fa1f4efSCédric Le Goater     Object *obj;
9518907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9528fa1f4efSCédric Le Goater 
953245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9548fa1f4efSCédric Le Goater     if (local_err) {
9558fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9568fa1f4efSCédric Le Goater         return;
9578fa1f4efSCédric Le Goater     }
9588fa1f4efSCédric Le Goater 
959956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
960d35aefa9SCédric Le Goater }
961d35aefa9SCédric Le Goater 
9620990ce6aSGreg Kurz 
963d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
964d49e8a9bSCédric Le Goater {
965d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
966d49e8a9bSCédric Le Goater 
967d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
968d49e8a9bSCédric Le Goater }
969d49e8a9bSCédric Le Goater 
9700990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9710990ce6aSGreg Kurz {
9720990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9730990ce6aSGreg Kurz 
9740990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9750990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9760990ce6aSGreg Kurz }
9770990ce6aSGreg Kurz 
97885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
97985913070SGreg Kurz                                             Monitor *mon)
98085913070SGreg Kurz {
98185913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
98285913070SGreg Kurz }
98385913070SGreg Kurz 
984631adaffSCédric Le Goater /*
985631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
986631adaffSCédric Le Goater  *   49:52  Node ID
987631adaffSCédric Le Goater  *   53:55  Chip ID
988631adaffSCédric Le Goater  *   56     Reserved - Read as zero
989631adaffSCédric Le Goater  *   57:61  Core number
990631adaffSCédric Le Goater  *   62:63  Thread ID
991631adaffSCédric Le Goater  *
992631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
993631adaffSCédric Le Goater  */
994631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
995631adaffSCédric Le Goater {
996631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
997631adaffSCédric Le Goater }
998631adaffSCédric Le Goater 
9992b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10002b548a42SCédric Le Goater {
10012b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10022b548a42SCédric Le Goater }
10032b548a42SCédric Le Goater 
10048fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1005d35aefa9SCédric Le Goater                                         Error **errp)
1006d35aefa9SCédric Le Goater {
10072dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10082dfa91a2SCédric Le Goater     Error *local_err = NULL;
10092dfa91a2SCédric Le Goater     Object *obj;
10102dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10112dfa91a2SCédric Le Goater 
10122dfa91a2SCédric Le Goater     /*
10132dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
10142dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
10152dfa91a2SCédric Le Goater      * only used at runtime.
10162dfa91a2SCédric Le Goater      */
101747950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
101847950946SCédric Le Goater                            &local_err);
10192dfa91a2SCédric Le Goater     if (local_err) {
10202dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
10218fa1f4efSCédric Le Goater         return;
1022d35aefa9SCédric Le Goater     }
1023d35aefa9SCédric Le Goater 
10242dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10252dfa91a2SCédric Le Goater }
10262dfa91a2SCédric Le Goater 
1027d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1028d49e8a9bSCédric Le Goater {
1029d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1030d49e8a9bSCédric Le Goater 
1031d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1032d49e8a9bSCédric Le Goater }
1033d49e8a9bSCédric Le Goater 
10340990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10350990ce6aSGreg Kurz {
10360990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10370990ce6aSGreg Kurz 
10380990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10390990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10400990ce6aSGreg Kurz }
10410990ce6aSGreg Kurz 
104285913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
104385913070SGreg Kurz                                             Monitor *mon)
104485913070SGreg Kurz {
104585913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
104685913070SGreg Kurz }
104785913070SGreg Kurz 
10482b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10492b548a42SCédric Le Goater                                         Error **errp)
10502b548a42SCédric Le Goater {
1051da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1052da71b7e3SCédric Le Goater     Error *local_err = NULL;
1053da71b7e3SCédric Le Goater     Object *obj;
10542b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10552b548a42SCédric Le Goater 
1056da71b7e3SCédric Le Goater     /*
1057da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1058da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1059da71b7e3SCédric Le Goater      * only used at runtime.
1060da71b7e3SCédric Le Goater      */
1061da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1062da71b7e3SCédric Le Goater                            &local_err);
1063da71b7e3SCédric Le Goater     if (local_err) {
1064da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1065da71b7e3SCédric Le Goater         return;
1066da71b7e3SCédric Le Goater     }
1067da71b7e3SCédric Le Goater 
1068da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
10692b548a42SCédric Le Goater }
10702b548a42SCédric Le Goater 
10712b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10722b548a42SCédric Le Goater {
1073da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1074da71b7e3SCédric Le Goater 
1075da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
10762b548a42SCédric Le Goater }
10772b548a42SCédric Le Goater 
10782b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10792b548a42SCédric Le Goater {
10802b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10812b548a42SCédric Le Goater 
1082da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10832b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10842b548a42SCédric Le Goater }
10852b548a42SCédric Le Goater 
108685913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
108785913070SGreg Kurz                                              Monitor *mon)
108885913070SGreg Kurz {
1089da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
109085913070SGreg Kurz }
109185913070SGreg Kurz 
109259b7c1c2SBalamuruhan S /*
109359b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1094397a79e7SCédric Le Goater  *
1095397a79e7SCédric Le Goater  * <EX0 reserved>
1096397a79e7SCédric Le Goater  *  EX1  - Venice only
1097397a79e7SCédric Le Goater  *  EX2  - Venice only
1098397a79e7SCédric Le Goater  *  EX3  - Venice only
1099397a79e7SCédric Le Goater  *  EX4
1100397a79e7SCédric Le Goater  *  EX5
1101397a79e7SCédric Le Goater  *  EX6
1102397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1103397a79e7SCédric Le Goater  *  EX9  - Venice only
1104397a79e7SCédric Le Goater  *  EX10 - Venice only
1105397a79e7SCédric Le Goater  *  EX11 - Venice only
1106397a79e7SCédric Le Goater  *  EX12
1107397a79e7SCédric Le Goater  *  EX13
1108397a79e7SCédric Le Goater  *  EX14
1109397a79e7SCédric Le Goater  * <EX15 reserved>
1110397a79e7SCédric Le Goater  */
1111397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1112397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1113397a79e7SCédric Le Goater 
1114397a79e7SCédric Le Goater /*
111509279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1116397a79e7SCédric Le Goater  */
111709279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1118397a79e7SCédric Le Goater 
11192b548a42SCédric Le Goater 
11202b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
11212b548a42SCédric Le Goater 
112277864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
112377864267SCédric Le Goater {
112477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
11259ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
11269ae1329eSCédric Le Goater     int i;
112777864267SCédric Le Goater 
1128245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1129245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1130245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1131d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1132245cdb7fSCédric Le Goater 
11339fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
113477864267SCédric Le Goater 
11359fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
113677864267SCédric Le Goater 
11379fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
11383887d241SBalamuruhan S 
11399fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
11409ae1329eSCédric Le Goater 
11411f6a88ffSCédric Le Goater     if (defaults_enabled()) {
1142eb93c828SCédric Le Goater         chip8->num_phbs = pcc->num_phbs;
11431f6a88ffSCédric Le Goater     }
11441f6a88ffSCédric Le Goater 
1145eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
11469fc7fc4dSMarkus Armbruster         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
11479ae1329eSCédric Le Goater     }
11489ae1329eSCédric Le Goater 
114977864267SCédric Le Goater }
115077864267SCédric Le Goater 
115177864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
115277864267SCédric Le Goater  {
115377864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
115477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
115577864267SCédric Le Goater     int i, j;
115677864267SCédric Le Goater     char *name;
115777864267SCédric Le Goater 
115877864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
115977864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
116077864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
116177864267SCédric Le Goater     g_free(name);
116277864267SCédric Le Goater 
116377864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
116477864267SCédric Le Goater 
116577864267SCédric Le Goater     /* Map the ICP registers for each thread */
116677864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
11674fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
116877864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
116977864267SCédric Le Goater 
117077864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
117177864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1172245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
117377864267SCédric Le Goater 
117477864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
117577864267SCédric Le Goater                                         &icp->mmio);
117677864267SCédric Le Goater         }
117777864267SCédric Le Goater     }
117877864267SCédric Le Goater }
117977864267SCédric Le Goater 
1180a71cd51eSCédric Le Goater /* Attach a root port device */
1181a71cd51eSCédric Le Goater void pnv_phb_attach_root_port(PCIHostState *pci, const char *name)
1182a71cd51eSCédric Le Goater {
1183a71cd51eSCédric Le Goater     PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
1184a71cd51eSCédric Le Goater 
1185a71cd51eSCédric Le Goater     pci_realize_and_unref(root, pci->bus, &error_fatal);
1186a71cd51eSCédric Le Goater }
1187a71cd51eSCédric Le Goater 
118877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
118977864267SCédric Le Goater {
119077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
119177864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
119277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1193ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
119477864267SCédric Le Goater     Error *local_err = NULL;
11959ae1329eSCédric Le Goater     int i;
119677864267SCédric Le Goater 
1197245cdb7fSCédric Le Goater     assert(chip8->xics);
1198245cdb7fSCédric Le Goater 
1199709044fdSCédric Le Goater     /* XSCOM bridge is first */
1200709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1201709044fdSCédric Le Goater     if (local_err) {
1202709044fdSCédric Le Goater         error_propagate(errp, local_err);
1203709044fdSCédric Le Goater         return;
1204709044fdSCédric Le Goater     }
1205709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1206709044fdSCédric Le Goater 
120777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
120877864267SCédric Le Goater     if (local_err) {
120977864267SCédric Le Goater         error_propagate(errp, local_err);
121077864267SCédric Le Goater         return;
121177864267SCédric Le Goater     }
121277864267SCédric Le Goater 
121377864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
12145325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
12155325cc34SMarkus Armbruster                             &error_fatal);
12165325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
12175325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1218668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
121977864267SCédric Le Goater         return;
122077864267SCédric Le Goater     }
1221ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1222ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
122377864267SCédric Le Goater 
122477864267SCédric Le Goater     /* Create LPC controller */
12255325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi),
1226b63f3893SGreg Kurz                              &error_abort);
1227ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
122877864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
122977864267SCédric Le Goater 
1230032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
123164d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
123264d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
123364d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
123464d011d5SCédric Le Goater 
123559b7c1c2SBalamuruhan S     /*
123659b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
123759b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
123859b7c1c2SBalamuruhan S      */
123977864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
124077864267SCédric Le Goater     if (local_err) {
124177864267SCédric Le Goater         error_propagate(errp, local_err);
124277864267SCédric Le Goater         return;
124377864267SCédric Le Goater     }
124477864267SCédric Le Goater 
124577864267SCédric Le Goater     /* Create the simplified OCC model */
12465325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi),
1247ee3d2713SGreg Kurz                              &error_abort);
1248668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
124977864267SCédric Le Goater         return;
125077864267SCédric Le Goater     }
125177864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1252f3db8266SBalamuruhan S 
1253f3db8266SBalamuruhan S     /* OCC SRAM model */
12543a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1255f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
12563887d241SBalamuruhan S 
12573887d241SBalamuruhan S     /* HOMER */
12585325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1259f2582acfSGreg Kurz                              &error_abort);
1260668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
12613887d241SBalamuruhan S         return;
12623887d241SBalamuruhan S     }
12638f092316SCédric Le Goater     /* Homer Xscom region */
12648f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
12658f092316SCédric Le Goater 
12668f092316SCédric Le Goater     /* Homer mmio region */
12673887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
12683887d241SBalamuruhan S                                 &chip8->homer.regs);
12699ae1329eSCédric Le Goater 
12709ae1329eSCédric Le Goater     /* PHB3 controllers */
1271eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
12729ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
12739ae1329eSCédric Le Goater 
12745325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
12755325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
12769ae1329eSCédric Le Goater                                 &error_fatal);
12772c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
12782c4d3a50SCédric Le Goater                                  &error_fatal);
1279668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
12809ae1329eSCédric Le Goater             return;
12819ae1329eSCédric Le Goater         }
12829ae1329eSCédric Le Goater     }
128377864267SCédric Le Goater }
128477864267SCédric Le Goater 
128570c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
128670c059e9SGreg Kurz {
128770c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
128870c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
128970c059e9SGreg Kurz }
129070c059e9SGreg Kurz 
1291e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1292e997040eSCédric Le Goater {
1293e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1294e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1295e997040eSCédric Le Goater 
1296e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1297397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
12989ae1329eSCédric Le Goater     k->num_phbs = 3;
1299631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1300d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1301d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13020990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
130385913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
130404026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1305eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1306d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1307c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
130870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1309e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
131077864267SCédric Le Goater 
131177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
131277864267SCédric Le Goater                                     &k->parent_realize);
1313e997040eSCédric Le Goater }
1314e997040eSCédric Le Goater 
1315e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1316e997040eSCédric Le Goater {
1317e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1318e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1319e997040eSCédric Le Goater 
1320e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1321397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13229ae1329eSCédric Le Goater     k->num_phbs = 3;
1323631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1324d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1325d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13260990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
132785913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
132804026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1329eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1330d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1331c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
133270c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1333e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
133477864267SCédric Le Goater 
133577864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
133677864267SCédric Le Goater                                     &k->parent_realize);
1337e997040eSCédric Le Goater }
1338e997040eSCédric Le Goater 
1339e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1340e997040eSCédric Le Goater {
1341e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1342e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1343e997040eSCédric Le Goater 
1344e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1345397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1346316717feSCédric Le Goater     k->num_phbs = 4;
1347631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1348d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1349d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13500990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
135185913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
135204026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1353eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1354d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1355c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
135670c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1357e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
135877864267SCédric Le Goater 
135977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
136077864267SCédric Le Goater                                     &k->parent_realize);
136177864267SCédric Le Goater }
136277864267SCédric Le Goater 
136377864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
136477864267SCédric Le Goater {
13654f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13662dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13674f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13684f9924c4SBenjamin Herrenschmidt     int i;
13692dfa91a2SCédric Le Goater 
1370db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1371d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1372d2623129SMarkus Armbruster                               "xive-fabric");
1373c38536bcSCédric Le Goater 
13749fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
137515376c66SCédric Le Goater 
13769fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
13776598a70dSCédric Le Goater 
13789fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
13793887d241SBalamuruhan S 
13809fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
13814f9924c4SBenjamin Herrenschmidt 
1382422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1383422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1384422fd92eSCédric Le Goater 
1385422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
13864f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
13879fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
13884f9924c4SBenjamin Herrenschmidt     }
138977864267SCédric Le Goater }
139077864267SCédric Le Goater 
13915dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
13925dad902cSCédric Le Goater {
13935dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
13945dad902cSCédric Le Goater     int i;
13955dad902cSCédric Le Goater 
13965dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
13975dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
13985dad902cSCédric Le Goater 
13995dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
14005dad902cSCédric Le Goater         char eq_name[32];
14015dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
14024fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
14035dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
14045dad902cSCédric Le Goater 
14055dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14069fc7fc4dSMarkus Armbruster         object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
14079fc7fc4dSMarkus Armbruster                                            sizeof(*eq), TYPE_PNV_QUAD,
14089fc7fc4dSMarkus Armbruster                                            &error_fatal, NULL);
14095dad902cSCédric Le Goater 
141092612f15SCédric Le Goater         object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1411ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(eq), NULL, &error_fatal);
14125dad902cSCédric Le Goater 
141392612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
14145dad902cSCédric Le Goater                                 &eq->xscom_regs);
14155dad902cSCédric Le Goater     }
14165dad902cSCédric Le Goater }
14175dad902cSCédric Le Goater 
141813480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
14194f9924c4SBenjamin Herrenschmidt {
14204f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
142113480fc5SCédric Le Goater     int i;
14224f9924c4SBenjamin Herrenschmidt 
1423422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14244f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
14254f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
14264f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
14274f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
14284f9924c4SBenjamin Herrenschmidt 
14295325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
14305325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
14314f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14326f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
14336f43d255SCédric Le Goater                                  &error_fatal);
1434668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14354f9924c4SBenjamin Herrenschmidt             return;
14364f9924c4SBenjamin Herrenschmidt         }
14374f9924c4SBenjamin Herrenschmidt 
14384f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14394f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14404f9924c4SBenjamin Herrenschmidt 
14414f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
14424f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
14434f9924c4SBenjamin Herrenschmidt     }
14444f9924c4SBenjamin Herrenschmidt }
14454f9924c4SBenjamin Herrenschmidt 
144677864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
144777864267SCédric Le Goater {
144877864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14492dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14502dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1451c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
145277864267SCédric Le Goater     Error *local_err = NULL;
145377864267SCédric Le Goater 
1454709044fdSCédric Le Goater     /* XSCOM bridge is first */
1455709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1456709044fdSCédric Le Goater     if (local_err) {
1457709044fdSCédric Le Goater         error_propagate(errp, local_err);
1458709044fdSCédric Le Goater         return;
1459709044fdSCédric Le Goater     }
1460709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1461709044fdSCédric Le Goater 
146277864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
146377864267SCédric Le Goater     if (local_err) {
146477864267SCédric Le Goater         error_propagate(errp, local_err);
146577864267SCédric Le Goater         return;
146677864267SCédric Le Goater     }
14672dfa91a2SCédric Le Goater 
14685dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14695dad902cSCédric Le Goater     if (local_err) {
14705dad902cSCédric Le Goater         error_propagate(errp, local_err);
14715dad902cSCédric Le Goater         return;
14725dad902cSCédric Le Goater     }
14735dad902cSCédric Le Goater 
14742dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
14755325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
14765325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
14775325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
14785325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
14795325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
14805325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
14815325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
14825325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
14835325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
14847ae54cc3SGreg Kurz                              &error_abort);
1485668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
14862dfa91a2SCédric Le Goater         return;
14872dfa91a2SCédric Le Goater     }
14882dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
14892dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1490c38536bcSCédric Le Goater 
1491c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
14925325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
14935325cc34SMarkus Armbruster                             &error_fatal);
1494668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1495c38536bcSCédric Le Goater         return;
1496c38536bcSCédric Le Goater     }
1497c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1498c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
149915376c66SCédric Le Goater 
150015376c66SCédric Le Goater     /* LPC */
15015325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi),
1502b63f3893SGreg Kurz                              &error_abort);
1503668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
150415376c66SCédric Le Goater         return;
150515376c66SCédric Le Goater     }
150615376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
150715376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
150815376c66SCédric Le Goater 
1509032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
151015376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
151115376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15126598a70dSCédric Le Goater 
15136598a70dSCédric Le Goater     /* Create the simplified OCC model */
15145325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi),
1515ee3d2713SGreg Kurz                              &error_abort);
1516668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
15176598a70dSCédric Le Goater         return;
15186598a70dSCédric Le Goater     }
15196598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1520f3db8266SBalamuruhan S 
1521f3db8266SBalamuruhan S     /* OCC SRAM model */
15223a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1523f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15243887d241SBalamuruhan S 
15253887d241SBalamuruhan S     /* HOMER */
15265325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1527f2582acfSGreg Kurz                              &error_abort);
1528668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15293887d241SBalamuruhan S         return;
15303887d241SBalamuruhan S     }
15318f092316SCédric Le Goater     /* Homer Xscom region */
15328f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15338f092316SCédric Le Goater 
15348f092316SCédric Le Goater     /* Homer mmio region */
15353887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15363887d241SBalamuruhan S                                 &chip9->homer.regs);
15374f9924c4SBenjamin Herrenschmidt 
153813480fc5SCédric Le Goater     /* PEC PHBs */
153913480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
15404f9924c4SBenjamin Herrenschmidt     if (local_err) {
15414f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15424f9924c4SBenjamin Herrenschmidt         return;
15434f9924c4SBenjamin Herrenschmidt     }
1544e997040eSCédric Le Goater }
1545e997040eSCédric Le Goater 
154670c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
154770c059e9SGreg Kurz {
154870c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
154970c059e9SGreg Kurz     return addr >> 3;
155070c059e9SGreg Kurz }
155170c059e9SGreg Kurz 
1552e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1553e997040eSCédric Le Goater {
1554e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1555e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1556e997040eSCédric Le Goater 
155783028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1558397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1559631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1560d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1561d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15620990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
156385913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
156404026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1565eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1566d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1567c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
156870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1569e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1570422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
157177864267SCédric Le Goater 
157277864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
157377864267SCédric Le Goater                                     &k->parent_realize);
1574e997040eSCédric Le Goater }
1575e997040eSCédric Le Goater 
15762b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
15772b548a42SCédric Le Goater {
15788b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
15798b50ce85SCédric Le Goater 
1580da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1581da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1582da71b7e3SCédric Le Goater                               "xive-fabric");
15839fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
15849fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
1585*8bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
15862b548a42SCédric Le Goater }
15872b548a42SCédric Le Goater 
15882b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
15892b548a42SCédric Le Goater {
15902b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15912b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
15928b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
15932b548a42SCédric Le Goater     Error *local_err = NULL;
15942b548a42SCédric Le Goater 
15952b548a42SCédric Le Goater     /* XSCOM bridge is first */
15962b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
15972b548a42SCédric Le Goater     if (local_err) {
15982b548a42SCédric Le Goater         error_propagate(errp, local_err);
15992b548a42SCédric Le Goater         return;
16002b548a42SCédric Le Goater     }
16012b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
16022b548a42SCédric Le Goater 
16032b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
16042b548a42SCédric Le Goater     if (local_err) {
16052b548a42SCédric Le Goater         error_propagate(errp, local_err);
16062b548a42SCédric Le Goater         return;
16072b548a42SCédric Le Goater     }
16088b50ce85SCédric Le Goater 
1609da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1610da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1611da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1612da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1613da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1614da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1615da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1616da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1617da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1618da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1619da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1620da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1621da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1622da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1623da71b7e3SCédric Le Goater                              &error_abort);
1624da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1625da71b7e3SCédric Le Goater         return;
1626da71b7e3SCédric Le Goater     }
1627da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1628da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1629da71b7e3SCédric Le Goater 
16308b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
16315325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
16325325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
1633668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
16348b50ce85SCédric Le Goater         return;
16358b50ce85SCédric Le Goater     }
16368b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
16378b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
16382661f6abSCédric Le Goater 
16392661f6abSCédric Le Goater     /* LPC */
16405325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip10->lpc), "psi",
16415325cc34SMarkus Armbruster                              OBJECT(&chip10->psi), &error_abort);
1642668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
16432661f6abSCédric Le Goater         return;
16442661f6abSCédric Le Goater     }
16452661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
16462661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
16472661f6abSCédric Le Goater 
1648032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
16492661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
16502661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
1651*8bf682a3SCédric Le Goater 
1652*8bf682a3SCédric Le Goater     /* Create the simplified OCC model */
1653*8bf682a3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->occ), "psi", OBJECT(&chip10->psi),
1654*8bf682a3SCédric Le Goater                              &error_abort);
1655*8bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
1656*8bf682a3SCédric Le Goater         return;
1657*8bf682a3SCédric Le Goater     }
1658*8bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
1659*8bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
16602b548a42SCédric Le Goater }
16612b548a42SCédric Le Goater 
166270c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
166370c059e9SGreg Kurz {
166470c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
166570c059e9SGreg Kurz     return addr >> 3;
166670c059e9SGreg Kurz }
166770c059e9SGreg Kurz 
16682b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
16692b548a42SCédric Le Goater {
16702b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
16712b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16722b548a42SCédric Le Goater 
16732b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
16742b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
16752b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
16762b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
16772b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
16782b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
167985913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
16802b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
16812b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
16822b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1683c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
168470c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
16852b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
16862b548a42SCédric Le Goater 
16872b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
16882b548a42SCédric Le Goater                                     &k->parent_realize);
16892b548a42SCédric Le Goater }
16902b548a42SCédric Le Goater 
1691397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1692397a79e7SCédric Le Goater {
1693397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1694397a79e7SCédric Le Goater     int cores_max;
1695397a79e7SCédric Le Goater 
1696397a79e7SCédric Le Goater     /*
1697397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1698397a79e7SCédric Le Goater      * the chip class
1699397a79e7SCédric Le Goater      */
1700397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1701397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1702397a79e7SCédric Le Goater     }
1703397a79e7SCédric Le Goater 
1704397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1705397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1706397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1707397a79e7SCédric Le Goater                    chip->cores_mask);
1708397a79e7SCédric Le Goater         return;
1709397a79e7SCédric Le Goater     }
1710397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1711397a79e7SCédric Le Goater 
1712397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
171327d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1714397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1715397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1716397a79e7SCédric Le Goater                    cores_max);
1717397a79e7SCédric Le Goater         return;
1718397a79e7SCédric Le Goater     }
1719397a79e7SCédric Le Goater }
1720397a79e7SCédric Le Goater 
172151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1722e997040eSCédric Le Goater {
1723397a79e7SCédric Le Goater     Error *error = NULL;
1724d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
172540abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1726d2fd9612SCédric Le Goater     int i, core_hwid;
172708c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1728397a79e7SCédric Le Goater 
1729d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1730d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1731d2fd9612SCédric Le Goater         return;
1732d2fd9612SCédric Le Goater     }
1733d2fd9612SCédric Le Goater 
1734d2fd9612SCédric Le Goater     /* Cores */
1735397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1736397a79e7SCédric Le Goater     if (error) {
1737397a79e7SCédric Le Goater         error_propagate(errp, error);
1738397a79e7SCédric Le Goater         return;
1739397a79e7SCédric Le Goater     }
1740d2fd9612SCédric Le Goater 
17414fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1742d2fd9612SCédric Le Goater 
1743d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1744d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1745d2fd9612SCédric Le Goater         char core_name[32];
17464fa28f23SGreg Kurz         PnvCore *pnv_core;
1747c035851aSCédric Le Goater         uint64_t xscom_core_base;
1748d2fd9612SCédric Le Goater 
1749d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1750d2fd9612SCédric Le Goater             continue;
1751d2fd9612SCédric Le Goater         }
1752d2fd9612SCédric Le Goater 
17534fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
17544fa28f23SGreg Kurz 
1755d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1756d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
17574fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
17585325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
17595325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
17605325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
17615325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
17625325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
17635325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
17645325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
17655325cc34SMarkus Armbruster                                 &error_fatal);
17665325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1767158e17a6SGreg Kurz                                  &error_abort);
1768ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
176924ece072SCédric Le Goater 
177024ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1771c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1772c035851aSCédric Le Goater 
1773c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
17744fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1775d2fd9612SCédric Le Goater         i++;
1776d2fd9612SCédric Le Goater     }
177751c04728SCédric Le Goater }
177851c04728SCédric Le Goater 
177951c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
178051c04728SCédric Le Goater {
178151c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
178251c04728SCédric Le Goater     Error *error = NULL;
178351c04728SCédric Le Goater 
178451c04728SCédric Le Goater     /* Cores */
178551c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
178651c04728SCédric Le Goater     if (error) {
178751c04728SCédric Le Goater         error_propagate(errp, error);
178851c04728SCédric Le Goater         return;
178951c04728SCédric Le Goater     }
1790e997040eSCédric Le Goater }
1791e997040eSCédric Le Goater 
1792e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1793e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1794e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1795e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1796397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1797397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1798764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
1799e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1800e997040eSCédric Le Goater };
1801e997040eSCédric Le Goater 
1802e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1803e997040eSCédric Le Goater {
1804e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1805e997040eSCédric Le Goater 
18069d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1807e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
18084f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1809e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1810e997040eSCédric Le Goater }
1811e997040eSCédric Le Goater 
1812119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1813119eaa9dSCédric Le Goater {
1814119eaa9dSCédric Le Goater     int i, j;
1815119eaa9dSCédric Le Goater 
1816119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1817119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1818119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1819119eaa9dSCédric Le Goater 
1820119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1821119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1822119eaa9dSCédric Le Goater                 return pc->threads[j];
1823119eaa9dSCédric Le Goater             }
1824119eaa9dSCédric Le Goater         }
1825119eaa9dSCédric Le Goater     }
1826119eaa9dSCédric Le Goater     return NULL;
1827119eaa9dSCédric Le Goater }
1828119eaa9dSCédric Le Goater 
18292ff73ddaSCédric Le Goater typedef struct ForeachPhb3Args {
18302ff73ddaSCédric Le Goater     int irq;
18312ff73ddaSCédric Le Goater     ICSState *ics;
18322ff73ddaSCédric Le Goater } ForeachPhb3Args;
18332ff73ddaSCédric Le Goater 
18342ff73ddaSCédric Le Goater static int pnv_ics_get_child(Object *child, void *opaque)
18352ff73ddaSCédric Le Goater {
18362ff73ddaSCédric Le Goater     ForeachPhb3Args *args = opaque;
18372ff73ddaSCédric Le Goater     PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
18382ff73ddaSCédric Le Goater 
18392ff73ddaSCédric Le Goater     if (phb3) {
18402ff73ddaSCédric Le Goater         if (ics_valid_irq(&phb3->lsis, args->irq)) {
18412ff73ddaSCédric Le Goater             args->ics = &phb3->lsis;
18422ff73ddaSCédric Le Goater         }
18432ff73ddaSCédric Le Goater         if (ics_valid_irq(ICS(&phb3->msis), args->irq)) {
18442ff73ddaSCédric Le Goater             args->ics = ICS(&phb3->msis);
18452ff73ddaSCédric Le Goater         }
18462ff73ddaSCédric Le Goater     }
18472ff73ddaSCédric Le Goater     return args->ics ? 1 : 0;
18482ff73ddaSCédric Le Goater }
18492ff73ddaSCédric Le Goater 
185054f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
185154f59d78SCédric Le Goater {
1852b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18532ff73ddaSCédric Le Goater     ForeachPhb3Args args = { irq, NULL };
18542ff73ddaSCédric Le Goater     int i;
185554f59d78SCédric Le Goater 
185654f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18579ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
185877864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
185977864267SCédric Le Goater 
186077864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
186177864267SCédric Le Goater             return &chip8->psi.ics;
186254f59d78SCédric Le Goater         }
18632ff73ddaSCédric Le Goater 
18642ff73ddaSCédric Le Goater         object_child_foreach(OBJECT(chip), pnv_ics_get_child, &args);
18652ff73ddaSCédric Le Goater         if (args.ics) {
18662ff73ddaSCédric Le Goater             return args.ics;
18679ae1329eSCédric Le Goater         }
186854f59d78SCédric Le Goater     }
186954f59d78SCédric Le Goater     return NULL;
187054f59d78SCédric Le Goater }
187154f59d78SCédric Le Goater 
1872c29dd003SCédric Le Goater void pnv_chip_parent_fixup(PnvChip *chip, Object *obj, int index)
1873c29dd003SCédric Le Goater {
1874c29dd003SCédric Le Goater     Object *parent = OBJECT(chip);
1875c29dd003SCédric Le Goater     g_autofree char *default_id =
1876c29dd003SCédric Le Goater         g_strdup_printf("%s[%d]", object_get_typename(obj), index);
1877c29dd003SCédric Le Goater 
1878c29dd003SCédric Le Goater     if (obj->parent == parent) {
1879c29dd003SCédric Le Goater         return;
1880c29dd003SCédric Le Goater     }
1881c29dd003SCédric Le Goater 
1882c29dd003SCédric Le Goater     object_ref(obj);
1883c29dd003SCédric Le Goater     object_unparent(obj);
1884c29dd003SCédric Le Goater     object_property_add_child(
1885c29dd003SCédric Le Goater         parent, DEVICE(obj)->id ? DEVICE(obj)->id : default_id, obj);
1886c29dd003SCédric Le Goater     object_unref(obj);
1887c29dd003SCédric Le Goater }
1888c29dd003SCédric Le Goater 
18891f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
18901f6a88ffSCédric Le Goater {
18911f6a88ffSCédric Le Goater     int i;
18921f6a88ffSCédric Le Goater 
18931f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18941f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
18951f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
18961f6a88ffSCédric Le Goater             return chip;
18971f6a88ffSCédric Le Goater         }
18981f6a88ffSCédric Le Goater     }
18991f6a88ffSCédric Le Goater     return NULL;
19001f6a88ffSCédric Le Goater }
19011f6a88ffSCédric Le Goater 
19022ff73ddaSCédric Le Goater static int pnv_ics_resend_child(Object *child, void *opaque)
19032ff73ddaSCédric Le Goater {
19042ff73ddaSCédric Le Goater     PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
19052ff73ddaSCédric Le Goater 
19062ff73ddaSCédric Le Goater     if (phb3) {
19072ff73ddaSCédric Le Goater         ics_resend(&phb3->lsis);
19082ff73ddaSCédric Le Goater         ics_resend(ICS(&phb3->msis));
19092ff73ddaSCédric Le Goater     }
19102ff73ddaSCédric Le Goater     return 0;
19112ff73ddaSCédric Le Goater }
19122ff73ddaSCédric Le Goater 
191354f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
191454f59d78SCédric Le Goater {
1915b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
19162ff73ddaSCédric Le Goater     int i;
191754f59d78SCédric Le Goater 
191854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
19199ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
192077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
19219ae1329eSCédric Le Goater 
192277864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
19232ff73ddaSCédric Le Goater         object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
192454f59d78SCédric Le Goater     }
192554f59d78SCédric Le Goater }
192654f59d78SCédric Le Goater 
192736fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
192836fc6f08SCédric Le Goater {
192936fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
193036fc6f08SCédric Le Goater 
1931956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
193236fc6f08SCédric Le Goater }
193336fc6f08SCédric Le Goater 
193447fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
193547fea43aSCédric Le Goater                                Monitor *mon)
193647fea43aSCédric Le Goater {
1937b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
193854f59d78SCédric Le Goater     int i;
193947fea43aSCédric Le Goater     CPUState *cs;
194047fea43aSCédric Le Goater 
194147fea43aSCédric Le Goater     CPU_FOREACH(cs) {
194247fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
194347fea43aSCédric Le Goater 
194485913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
194585913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
194685913070SGreg Kurz                                                            mon);
1947d8e4aad5SCédric Le Goater     }
194854f59d78SCédric Le Goater 
194954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1950d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
195154f59d78SCédric Le Goater     }
195247fea43aSCédric Le Goater }
195347fea43aSCédric Le Goater 
1954c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1955c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1956c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1957c722579eSCédric Le Goater                          uint32_t logic_serv,
1958c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1959c722579eSCédric Le Goater {
1960c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1961c722579eSCédric Le Goater     int total_count = 0;
1962c722579eSCédric Le Goater     int i;
1963c722579eSCédric Le Goater 
1964c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1965c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1966c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1967c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1968c722579eSCédric Le Goater         int count;
1969c722579eSCédric Le Goater 
1970c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1971c722579eSCédric Le Goater                                priority, logic_serv, match);
1972c722579eSCédric Le Goater 
1973c722579eSCédric Le Goater         if (count < 0) {
1974c722579eSCédric Le Goater             return count;
1975c722579eSCédric Le Goater         }
1976c722579eSCédric Le Goater 
1977c722579eSCédric Le Goater         total_count += count;
1978c722579eSCédric Le Goater     }
1979c722579eSCédric Le Goater 
1980c722579eSCédric Le Goater     return total_count;
1981c722579eSCédric Le Goater }
1982c722579eSCédric Le Goater 
1983da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
1984da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
1985da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
1986da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
1987da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
1988da71b7e3SCédric Le Goater {
1989da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1990da71b7e3SCédric Le Goater     int total_count = 0;
1991da71b7e3SCédric Le Goater     int i;
1992da71b7e3SCédric Le Goater 
1993da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1994da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
1995da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
1996da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1997da71b7e3SCédric Le Goater         int count;
1998da71b7e3SCédric Le Goater 
1999da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2000da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2001da71b7e3SCédric Le Goater 
2002da71b7e3SCédric Le Goater         if (count < 0) {
2003da71b7e3SCédric Le Goater             return count;
2004da71b7e3SCédric Le Goater         }
2005da71b7e3SCédric Le Goater 
2006da71b7e3SCédric Le Goater         total_count += count;
2007da71b7e3SCédric Le Goater     }
2008da71b7e3SCédric Le Goater 
2009da71b7e3SCédric Le Goater     return total_count;
2010da71b7e3SCédric Le Goater }
2011da71b7e3SCédric Le Goater 
2012f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
20139e933f4aSBenjamin Herrenschmidt {
20149e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
201536fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2016d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2017d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2018f30c843cSCédric Le Goater 
2019f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2020f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
2021f30c843cSCédric Le Goater 
2022f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2023f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2024f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2025d76f2da7SGreg Kurz 
2026d76f2da7SGreg Kurz     pmc->compat = compat;
2027d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2028db041b06SCédric Le Goater 
2029db041b06SCédric Le Goater     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB3);
2030f30c843cSCédric Le Goater }
2031f30c843cSCédric Le Goater 
2032f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2033f30c843cSCédric Le Goater {
2034f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2035c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2036d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2037d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2038f30c843cSCédric Le Goater 
2039f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2040f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
2041c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2042f30c843cSCédric Le Goater 
2043f30c843cSCédric Le Goater     mc->alias = "powernv";
2044d76f2da7SGreg Kurz 
2045d76f2da7SGreg Kurz     pmc->compat = compat;
2046d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
20477a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
20485bc67b05SDaniel Henrique Barboza 
20495bc67b05SDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB4);
2050f30c843cSCédric Le Goater }
2051f30c843cSCédric Le Goater 
20522b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
20532b548a42SCédric Le Goater {
20542b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2055d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2056da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2057d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
20582b548a42SCédric Le Goater 
20592b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
20606bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2061d76f2da7SGreg Kurz 
2062d76f2da7SGreg Kurz     pmc->compat = compat;
2063d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
20647a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2065da71b7e3SCédric Le Goater 
2066da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
20672b548a42SCédric Le Goater }
20682b548a42SCédric Le Goater 
206908c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
207008c3f3a7SCédric Le Goater {
207108c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
207208c3f3a7SCédric Le Goater 
207308c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
207408c3f3a7SCédric Le Goater }
207508c3f3a7SCédric Le Goater 
207608c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
207708c3f3a7SCédric Le Goater {
207808c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
207908c3f3a7SCédric Le Goater 
208008c3f3a7SCédric Le Goater     if (value) {
208108c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
208208c3f3a7SCédric Le Goater     }
208308c3f3a7SCédric Le Goater }
208408c3f3a7SCédric Le Goater 
208501b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
208601b552b0SNicholas Piggin {
208701b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
208801b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
208901b552b0SNicholas Piggin 
209001b552b0SNicholas Piggin     cpu_synchronize_state(cs);
209101b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
20920911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
209301b552b0SNicholas Piggin         /*
2094fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2095fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2096fe837714SNicholas Piggin          * (PPC_BIT(43)).
209701b552b0SNicholas Piggin          */
20980911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2099fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
21000911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
210101b552b0SNicholas Piggin         }
2102fe837714SNicholas Piggin     } else {
2103fe837714SNicholas Piggin         /*
2104fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2105fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2106fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2107fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2108fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2109fe837714SNicholas Piggin          */
21100911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2111fe837714SNicholas Piggin     }
2112fe837714SNicholas Piggin }
211301b552b0SNicholas Piggin 
211401b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
211501b552b0SNicholas Piggin {
211601b552b0SNicholas Piggin     CPUState *cs;
211701b552b0SNicholas Piggin 
211801b552b0SNicholas Piggin     CPU_FOREACH(cs) {
211901b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
212001b552b0SNicholas Piggin     }
212101b552b0SNicholas Piggin }
212201b552b0SNicholas Piggin 
2123f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2124f30c843cSCédric Le Goater {
2125f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
212647fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
212701b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
21289e933f4aSBenjamin Herrenschmidt 
21299e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2130b168a138SCédric Le Goater     mc->init = pnv_init;
2131b168a138SCédric Le Goater     mc->reset = pnv_reset;
21329e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
213359b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
213459b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
21359e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
21369e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2137f1d18b0aSJoel Stanley     /*
2138f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2139f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2140f1d18b0aSJoel Stanley      */
2141dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2142173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
214347fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
214401b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
214508c3f3a7SCédric Le Goater 
214608c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2147d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
214808c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
21497eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
21509e933f4aSBenjamin Herrenschmidt }
21519e933f4aSBenjamin Herrenschmidt 
215277864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2153beba5c0fSIgor Mammedov     {                                             \
2154beba5c0fSIgor Mammedov         .name          = type,                    \
2155beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
215677864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
215777864267SCédric Le Goater     }
215877864267SCédric Le Goater 
215977864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
216077864267SCédric Le Goater     {                                             \
216177864267SCédric Le Goater         .name          = type,                    \
216277864267SCédric Le Goater         .class_init    = class_initfn,            \
216377864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2164beba5c0fSIgor Mammedov     }
2165beba5c0fSIgor Mammedov 
21662b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
21672b548a42SCédric Le Goater     {                                              \
21682b548a42SCédric Le Goater         .name          = type,                     \
21692b548a42SCédric Le Goater         .class_init    = class_initfn,             \
21702b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
21712b548a42SCédric Le Goater     }
21722b548a42SCédric Le Goater 
2173beba5c0fSIgor Mammedov static const TypeInfo types[] = {
21741aba8716SCédric Le Goater     {
21752b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
21762b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
21772b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2178da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2179da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2180da71b7e3SCédric Le Goater             { },
2181da71b7e3SCédric Le Goater         },
21822b548a42SCédric Le Goater     },
21832b548a42SCédric Le Goater     {
21841aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
21851aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
21861aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2187c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2188c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2189c722579eSCédric Le Goater             { },
2190c722579eSCédric Le Goater         },
21911aba8716SCédric Le Goater     },
21921aba8716SCédric Le Goater     {
21931aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
21941aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
21951aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
21961aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
21971aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
21981aba8716SCédric Le Goater             { },
21991aba8716SCédric Le Goater         },
22001aba8716SCédric Le Goater     },
2201beba5c0fSIgor Mammedov     {
2202b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
22039e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2204f30c843cSCédric Le Goater         .abstract       = true,
22059e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2206b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2207d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
220836fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
220947fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
221001b552b0SNicholas Piggin             { TYPE_NMI },
221136fc6f08SCédric Le Goater             { },
221236fc6f08SCédric Le Goater         },
2213beba5c0fSIgor Mammedov     },
2214beba5c0fSIgor Mammedov     {
2215beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2216beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2217beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2218beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2219beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2220beba5c0fSIgor Mammedov         .abstract      = true,
2221beba5c0fSIgor Mammedov     },
222277864267SCédric Le Goater 
222377864267SCédric Le Goater     /*
22242b548a42SCédric Le Goater      * P10 chip and variants
22252b548a42SCédric Le Goater      */
22262b548a42SCédric Le Goater     {
22272b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
22282b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
22292b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
22302b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
22312b548a42SCédric Le Goater     },
22322b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
22332b548a42SCédric Le Goater 
22342b548a42SCédric Le Goater     /*
223577864267SCédric Le Goater      * P9 chip and variants
223677864267SCédric Le Goater      */
223777864267SCédric Le Goater     {
223877864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
223977864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
224077864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
224177864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
224277864267SCédric Le Goater     },
224377864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
224477864267SCédric Le Goater 
224577864267SCédric Le Goater     /*
224677864267SCédric Le Goater      * P8 chip and variants
224777864267SCédric Le Goater      */
224877864267SCédric Le Goater     {
224977864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
225077864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
225177864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
225277864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
225377864267SCédric Le Goater     },
225477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
225577864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
225677864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2257beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
22589e933f4aSBenjamin Herrenschmidt };
22599e933f4aSBenjamin Herrenschmidt 
2260beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2261