xref: /qemu/hw/ppc/pnv.c (revision f640afec)
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     };
383cb228f5aSCédric Le Goater     char *name;
384cb228f5aSCédric Le Goater     int node;
385cb228f5aSCédric Le Goater 
386cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
387cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
388cb228f5aSCédric Le Goater     _FDT(node);
389cb228f5aSCédric Le Goater     g_free(name);
390cb228f5aSCédric Le Goater 
391cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
392cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
393cb228f5aSCédric Le Goater                       sizeof(compatible))));
394cb228f5aSCédric Le Goater 
395cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
396cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
397cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
398cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
399cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
400cb228f5aSCédric Le Goater 
401cb228f5aSCédric Le Goater     /* This is needed by Linux */
402cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
403cb228f5aSCédric Le Goater }
404cb228f5aSCédric Le Goater 
405b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40604f6c8b2SCédric Le Goater {
40704f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
40804f6c8b2SCédric Le Goater     uint32_t io_base;
40904f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
41004f6c8b2SCédric Le Goater         cpu_to_be32(1),
41104f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41204f6c8b2SCédric Le Goater         cpu_to_be32(3)
41304f6c8b2SCédric Le Goater     };
41404f6c8b2SCédric Le Goater     uint32_t irq;
41504f6c8b2SCédric Le Goater     char *name;
41604f6c8b2SCédric Le Goater     int node;
41704f6c8b2SCédric Le Goater 
41804f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
41904f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
42004f6c8b2SCédric Le Goater 
42104f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42204f6c8b2SCédric Le Goater 
42304f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42404f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42504f6c8b2SCédric Le Goater     _FDT(node);
42604f6c8b2SCédric Le Goater     g_free(name);
42704f6c8b2SCédric Le Goater 
4287032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4297032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4307032d92aSCédric Le Goater                       sizeof(compatible))));
43104f6c8b2SCédric Le Goater 
43204f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43304f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43604f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
43704f6c8b2SCédric Le Goater }
43804f6c8b2SCédric Le Goater 
439e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
440e7a3fee3SCédric Le Goater     void *fdt;
441e7a3fee3SCédric Le Goater     int offset;
442e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
443e7a3fee3SCédric Le Goater 
444b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
445e7a3fee3SCédric Le Goater {
446c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
447c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
448c5ffdcaeSCédric Le Goater 
449c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
450b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
451cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
452b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45304f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
454b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
455c5ffdcaeSCédric Le Goater     } else {
456c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
457c5ffdcaeSCédric Le Goater                      d->ioport_id);
458c5ffdcaeSCédric Le Goater     }
459c5ffdcaeSCédric Le Goater 
460e7a3fee3SCédric Le Goater     return 0;
461e7a3fee3SCédric Le Goater }
462e7a3fee3SCédric Le Goater 
46359b7c1c2SBalamuruhan S /*
46459b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
465bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
466bb7ab95cSCédric Le Goater  */
467bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
468bb7ab95cSCédric Le Goater {
46964d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
470e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
471e7a3fee3SCédric Le Goater         .fdt = fdt,
472bb7ab95cSCédric Le Goater         .offset = isa_offset,
473e7a3fee3SCédric Le Goater     };
474f47a08d1SCédric Le Goater     uint32_t phandle;
475e7a3fee3SCédric Le Goater 
476bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
477bb7ab95cSCédric Le Goater 
478f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
479f47a08d1SCédric Le Goater     assert(phandle > 0);
480f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
481f47a08d1SCédric Le Goater 
48259b7c1c2SBalamuruhan S     /*
48359b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48459b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48559b7c1c2SBalamuruhan S      */
486bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
487bb7ab95cSCédric Le Goater                        &args);
488e7a3fee3SCédric Le Goater }
489e7a3fee3SCédric Le Goater 
4907a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
491e5694793SCédric Le Goater {
492e5694793SCédric Le Goater     int off;
493e5694793SCédric Le Goater 
494e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
495e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
496e5694793SCédric Le Goater 
497e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
498e5694793SCédric Le Goater }
499e5694793SCédric Le Goater 
500b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5019e933f4aSBenjamin Herrenschmidt {
502d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
503b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5049e933f4aSBenjamin Herrenschmidt     void *fdt;
5059e933f4aSBenjamin Herrenschmidt     char *buf;
5069e933f4aSBenjamin Herrenschmidt     int off;
507e997040eSCédric Le Goater     int i;
5089e933f4aSBenjamin Herrenschmidt 
5099e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5109e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5119e933f4aSBenjamin Herrenschmidt 
512ccb099b3SCédric Le Goater     /* /qemu node */
513ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
514ccb099b3SCédric Le Goater 
5159e933f4aSBenjamin Herrenschmidt     /* Root node */
5169e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5179e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5189e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5199e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
520d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5219e933f4aSBenjamin Herrenschmidt 
5229e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5239e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5249e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5259e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5269e933f4aSBenjamin Herrenschmidt     }
5279e933f4aSBenjamin Herrenschmidt     g_free(buf);
5289e933f4aSBenjamin Herrenschmidt 
5299e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5309e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5319e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5329e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5339e933f4aSBenjamin Herrenschmidt     }
5349e933f4aSBenjamin Herrenschmidt 
5359e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5369e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5379e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5389e933f4aSBenjamin Herrenschmidt 
5399e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5409e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5419e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5429e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5439e933f4aSBenjamin Herrenschmidt     }
5449e933f4aSBenjamin Herrenschmidt 
545e997040eSCédric Le Goater     /* Populate device tree for each chip */
546e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
547eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
548e997040eSCédric Le Goater     }
549e7a3fee3SCédric Le Goater 
550e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
551bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
552aeaef83dSCédric Le Goater 
553aeaef83dSCédric Le Goater     if (pnv->bmc) {
554b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
555aeaef83dSCédric Le Goater     }
556aeaef83dSCédric Le Goater 
5577a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5587a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5597a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
560e5694793SCédric Le Goater     }
561e5694793SCédric Le Goater 
5629e933f4aSBenjamin Herrenschmidt     return fdt;
5639e933f4aSBenjamin Herrenschmidt }
5649e933f4aSBenjamin Herrenschmidt 
565bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
566bce0b691SCédric Le Goater {
5678f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
568bce0b691SCédric Le Goater 
569bce0b691SCédric Le Goater     if (pnv->bmc) {
570bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
571bce0b691SCédric Le Goater     }
572bce0b691SCédric Le Goater }
573bce0b691SCédric Le Goater 
574a0628599SLike Xu static void pnv_reset(MachineState *machine)
5759e933f4aSBenjamin Herrenschmidt {
57625f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
57725f3170bSCédric Le Goater     IPMIBmc *bmc;
5789e933f4aSBenjamin Herrenschmidt     void *fdt;
5799e933f4aSBenjamin Herrenschmidt 
5809e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5819e933f4aSBenjamin Herrenschmidt 
58225f3170bSCédric Le Goater     /*
58325f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
58425f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
58525f3170bSCédric Le Goater      * line.
58625f3170bSCédric Le Goater      */
58725f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
58825f3170bSCédric Le Goater     if (!pnv->bmc) {
58925f3170bSCédric Le Goater         if (!bmc) {
59038d2448aSGreg Kurz             if (!qtest_enabled()) {
59125f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
59225f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59325f3170bSCédric Le Goater                             "to define one");
59438d2448aSGreg Kurz             }
59525f3170bSCédric Le Goater         } else {
59625f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
59725f3170bSCédric Le Goater             pnv->bmc = bmc;
59825f3170bSCédric Le Goater         }
59925f3170bSCédric Le Goater     }
60025f3170bSCédric Le Goater 
601b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6029e933f4aSBenjamin Herrenschmidt 
6039e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6049e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6059e933f4aSBenjamin Herrenschmidt 
6068d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6079e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
608b2fb7a43SPan Nengyuan 
609b2fb7a43SPan Nengyuan     g_free(fdt);
6109e933f4aSBenjamin Herrenschmidt }
6119e933f4aSBenjamin Herrenschmidt 
61204026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6133495b6b6SCédric Le Goater {
61477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
61577864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
61604026890SCédric Le Goater }
6173495b6b6SCédric Le Goater 
61804026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
61904026890SCédric Le Goater {
62077864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
62177864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
62204026890SCédric Le Goater }
6233495b6b6SCédric Le Goater 
62404026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
62504026890SCédric Le Goater {
62615376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
62715376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
62804026890SCédric Le Goater }
6293495b6b6SCédric Le Goater 
6302b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6312b548a42SCédric Le Goater {
6322661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6332661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6342b548a42SCédric Le Goater }
6352b548a42SCédric Le Goater 
63604026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
63704026890SCédric Le Goater {
63804026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6393495b6b6SCédric Le Goater }
6403495b6b6SCédric Le Goater 
641d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
642d8e4aad5SCédric Le Goater {
643d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6449ae1329eSCédric Le Goater     int i;
645d8e4aad5SCédric Le Goater 
646d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6479ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
6489ae1329eSCédric Le Goater         pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
6499ae1329eSCédric Le Goater         ics_pic_print_info(&chip8->phbs[i].lsis, mon);
6509ae1329eSCédric Le Goater     }
651d8e4aad5SCédric Le Goater }
652d8e4aad5SCédric Le Goater 
653d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
654d8e4aad5SCédric Le Goater {
655d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
6564f9924c4SBenjamin Herrenschmidt     int i, j;
657d8e4aad5SCédric Le Goater 
658d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
659c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6604f9924c4SBenjamin Herrenschmidt 
6614f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
6624f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
6634f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks; j++) {
6644f9924c4SBenjamin Herrenschmidt             pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
6654f9924c4SBenjamin Herrenschmidt         }
6664f9924c4SBenjamin Herrenschmidt     }
667d8e4aad5SCédric Le Goater }
668d8e4aad5SCédric Le Goater 
669c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
670c4b2c40cSGreg Kurz                                                 uint32_t core_id)
671c4b2c40cSGreg Kurz {
672c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
673c4b2c40cSGreg Kurz }
674c4b2c40cSGreg Kurz 
675c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
676c4b2c40cSGreg Kurz                                                 uint32_t core_id)
677c4b2c40cSGreg Kurz {
678c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
679c4b2c40cSGreg Kurz }
680c4b2c40cSGreg Kurz 
681c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
682c4b2c40cSGreg Kurz                                                  uint32_t core_id)
683c4b2c40cSGreg Kurz {
684c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
685c4b2c40cSGreg Kurz }
686c4b2c40cSGreg Kurz 
687f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
688f30c843cSCédric Le Goater {
689f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
690f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
691f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
692f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
693f30c843cSCédric Le Goater 
694f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
695f30c843cSCédric Le Goater }
696f30c843cSCédric Le Goater 
697e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
698e2392d43SCédric Le Goater {
699c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
700e2392d43SCédric Le Goater 
7015325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7025325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
703c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
704e2392d43SCédric Le Goater }
705e2392d43SCédric Le Goater 
7062b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7072b548a42SCédric Le Goater {
7088b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7098b50ce85SCédric Le Goater 
7108b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
7112b548a42SCédric Le Goater }
7122b548a42SCédric Le Goater 
713458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
714458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
715458c6f01SCédric Le Goater {
716458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
717458c6f01SCédric Le Goater     uint64_t ram_per_chip;
718458c6f01SCédric Le Goater 
719458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
720458c6f01SCédric Le Goater 
721458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
722458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
723458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
724458c6f01SCédric Le Goater     }
725458c6f01SCédric Le Goater 
726*f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
727*f640afecSCédric Le Goater 
728458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
729458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
730458c6f01SCédric Le Goater }
731458c6f01SCédric Le Goater 
732b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7339e933f4aSBenjamin Herrenschmidt {
734cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
735b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
736f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7379e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7389e933f4aSBenjamin Herrenschmidt     long fw_size;
739458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
740e997040eSCédric Le Goater     int i;
741e997040eSCédric Le Goater     char *chip_typename;
74235dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
74335dde576SCédric Le Goater     DeviceState *dev;
7449e933f4aSBenjamin Herrenschmidt 
7459e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
746dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
747dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
748dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
749dd7ef911SCédric Le Goater         g_free(sz);
750dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
7519e933f4aSBenjamin Herrenschmidt     }
752173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7539e933f4aSBenjamin Herrenschmidt 
75435dde576SCédric Le Goater     /*
75535dde576SCédric Le Goater      * Create our simple PNOR device
75635dde576SCédric Le Goater      */
7573e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
75835dde576SCédric Le Goater     if (pnor) {
759934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
76035dde576SCédric Le Goater     }
7613c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
76235dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
76335dde576SCédric Le Goater 
7649e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7659e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
76615fcedb2SCédric Le Goater     if (!fw_filename) {
76715fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
76815fcedb2SCédric Le Goater         exit(1);
76915fcedb2SCédric Le Goater     }
7709e933f4aSBenjamin Herrenschmidt 
77108c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
7729e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
77315fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7749e933f4aSBenjamin Herrenschmidt         exit(1);
7759e933f4aSBenjamin Herrenschmidt     }
7769e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7779e933f4aSBenjamin Herrenschmidt 
7789e933f4aSBenjamin Herrenschmidt     /* load kernel */
7799e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7809e933f4aSBenjamin Herrenschmidt         long kernel_size;
7819e933f4aSBenjamin Herrenschmidt 
7829e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
783b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7849e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
785802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7869e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7879e933f4aSBenjamin Herrenschmidt             exit(1);
7889e933f4aSBenjamin Herrenschmidt         }
7899e933f4aSBenjamin Herrenschmidt     }
7909e933f4aSBenjamin Herrenschmidt 
7919e933f4aSBenjamin Herrenschmidt     /* load initrd */
7929e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7939e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7949e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
795584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7969e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
797802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7989e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7999e933f4aSBenjamin Herrenschmidt             exit(1);
8009e933f4aSBenjamin Herrenschmidt         }
8019e933f4aSBenjamin Herrenschmidt     }
802e997040eSCédric Le Goater 
8034f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8044f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8054f9924c4SBenjamin Herrenschmidt 
806f30c843cSCédric Le Goater     /*
807f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
808f30c843cSCédric Le Goater      * default.
809f30c843cSCédric Le Goater      */
810f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
811f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
812f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
813f30c843cSCédric Le Goater         exit(1);
814f30c843cSCédric Le Goater     }
815f30c843cSCédric Le Goater 
816e997040eSCédric Le Goater     /* Create the processor chips */
8174a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8187fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8194a12c699SIgor Mammedov                                     i, machine->cpu_type);
820e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
821f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
822f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
823e997040eSCédric Le Goater         exit(1);
824e997040eSCédric Le Goater     }
825e997040eSCédric Le Goater 
826e44acde2SGreg Kurz     pnv->num_chips =
827e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
828e44acde2SGreg Kurz     /*
829e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
830e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
831e44acde2SGreg Kurz      */
832ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
833e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
834ab17a3feSCédric Le Goater         error_printf(
835ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
836e44acde2SGreg Kurz         exit(1);
837e44acde2SGreg Kurz     }
838e44acde2SGreg Kurz 
839e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
840e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
841e997040eSCédric Le Goater         char chip_name[32];
842df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
8430e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
844e997040eSCédric Le Goater 
845e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
846e997040eSCédric Le Goater 
847458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
848458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
849e997040eSCédric Le Goater                                 &error_fatal);
850458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
851458c6f01SCédric Le Goater                                 &error_fatal);
852458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
853e997040eSCédric Le Goater 
8540e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
855d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
8560e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
8575325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
8585325cc34SMarkus Armbruster                                 &error_fatal);
8595325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
8605325cc34SMarkus Armbruster                                 &error_fatal);
861245cdb7fSCédric Le Goater         /*
862245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
863245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
864245cdb7fSCédric Le Goater          */
865245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
8665325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
867245cdb7fSCédric Le Goater         }
868d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
8695325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
870d1214b81SGreg Kurz                                      &error_abort);
871d1214b81SGreg Kurz         }
8723c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
873e997040eSCédric Le Goater     }
874e997040eSCédric Le Goater     g_free(chip_typename);
8753495b6b6SCédric Le Goater 
8763495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
87704026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
8783495b6b6SCédric Le Goater 
8793495b6b6SCédric Le Goater     /* Create serial port */
880def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
8813495b6b6SCédric Le Goater 
8823495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8836c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
884bce0b691SCédric Le Goater 
88525f3170bSCédric Le Goater     /*
88625f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
88725f3170bSCédric Le Goater      * communication with the BMC
88825f3170bSCédric Le Goater      */
88925f3170bSCédric Le Goater     if (defaults_enabled()) {
89025f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
891e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
89225f3170bSCédric Le Goater     }
893e2392d43SCédric Le Goater 
89459b7c1c2SBalamuruhan S     /*
895032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
896032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
897032c226bSCédric Le Goater      * map it always for now.
898032c226bSCédric Le Goater      */
899032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
900032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
901032c226bSCédric Le Goater 
902032c226bSCédric Le Goater     /*
90359b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
90459b7c1c2SBalamuruhan S      * host to powerdown
90559b7c1c2SBalamuruhan S      */
906bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
907bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
908e997040eSCédric Le Goater }
909e997040eSCédric Le Goater 
910631adaffSCédric Le Goater /*
911631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
912631adaffSCédric Le Goater  *   22:24  Chip ID
913631adaffSCédric Le Goater  *   25:28  Core number
914631adaffSCédric Le Goater  *   29:31  Thread ID
915631adaffSCédric Le Goater  */
916631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
917631adaffSCédric Le Goater {
918631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
919631adaffSCédric Le Goater }
920631adaffSCédric Le Goater 
9218fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
922d35aefa9SCédric Le Goater                                         Error **errp)
923d35aefa9SCédric Le Goater {
924245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9258fa1f4efSCédric Le Goater     Error *local_err = NULL;
9268fa1f4efSCédric Le Goater     Object *obj;
9278907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9288fa1f4efSCédric Le Goater 
929245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9308fa1f4efSCédric Le Goater     if (local_err) {
9318fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9328fa1f4efSCédric Le Goater         return;
9338fa1f4efSCédric Le Goater     }
9348fa1f4efSCédric Le Goater 
935956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
936d35aefa9SCédric Le Goater }
937d35aefa9SCédric Le Goater 
9380990ce6aSGreg Kurz 
939d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
940d49e8a9bSCédric Le Goater {
941d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
942d49e8a9bSCédric Le Goater 
943d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
944d49e8a9bSCédric Le Goater }
945d49e8a9bSCédric Le Goater 
9460990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9470990ce6aSGreg Kurz {
9480990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9490990ce6aSGreg Kurz 
9500990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9510990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9520990ce6aSGreg Kurz }
9530990ce6aSGreg Kurz 
95485913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
95585913070SGreg Kurz                                             Monitor *mon)
95685913070SGreg Kurz {
95785913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
95885913070SGreg Kurz }
95985913070SGreg Kurz 
960631adaffSCédric Le Goater /*
961631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
962631adaffSCédric Le Goater  *   49:52  Node ID
963631adaffSCédric Le Goater  *   53:55  Chip ID
964631adaffSCédric Le Goater  *   56     Reserved - Read as zero
965631adaffSCédric Le Goater  *   57:61  Core number
966631adaffSCédric Le Goater  *   62:63  Thread ID
967631adaffSCédric Le Goater  *
968631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
969631adaffSCédric Le Goater  */
970631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
971631adaffSCédric Le Goater {
972631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
973631adaffSCédric Le Goater }
974631adaffSCédric Le Goater 
9752b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
9762b548a42SCédric Le Goater {
9772b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
9782b548a42SCédric Le Goater }
9792b548a42SCédric Le Goater 
9808fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
981d35aefa9SCédric Le Goater                                         Error **errp)
982d35aefa9SCédric Le Goater {
9832dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
9842dfa91a2SCédric Le Goater     Error *local_err = NULL;
9852dfa91a2SCédric Le Goater     Object *obj;
9862dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9872dfa91a2SCédric Le Goater 
9882dfa91a2SCédric Le Goater     /*
9892dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
9902dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
9912dfa91a2SCédric Le Goater      * only used at runtime.
9922dfa91a2SCédric Le Goater      */
99347950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
99447950946SCédric Le Goater                            &local_err);
9952dfa91a2SCédric Le Goater     if (local_err) {
9962dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9978fa1f4efSCédric Le Goater         return;
998d35aefa9SCédric Le Goater     }
999d35aefa9SCédric Le Goater 
10002dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10012dfa91a2SCédric Le Goater }
10022dfa91a2SCédric Le Goater 
1003d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1004d49e8a9bSCédric Le Goater {
1005d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1006d49e8a9bSCédric Le Goater 
1007d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1008d49e8a9bSCédric Le Goater }
1009d49e8a9bSCédric Le Goater 
10100990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10110990ce6aSGreg Kurz {
10120990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10130990ce6aSGreg Kurz 
10140990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10150990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10160990ce6aSGreg Kurz }
10170990ce6aSGreg Kurz 
101885913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
101985913070SGreg Kurz                                             Monitor *mon)
102085913070SGreg Kurz {
102185913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
102285913070SGreg Kurz }
102385913070SGreg Kurz 
10242b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10252b548a42SCédric Le Goater                                         Error **errp)
10262b548a42SCédric Le Goater {
10272b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10282b548a42SCédric Le Goater 
10292b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
10302b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10312b548a42SCédric Le Goater }
10322b548a42SCédric Le Goater 
10332b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10342b548a42SCédric Le Goater {
10352b548a42SCédric Le Goater     ;
10362b548a42SCédric Le Goater }
10372b548a42SCédric Le Goater 
10382b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10392b548a42SCédric Le Goater {
10402b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10412b548a42SCédric Le Goater 
10422b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10432b548a42SCédric Le Goater }
10442b548a42SCédric Le Goater 
104585913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
104685913070SGreg Kurz                                              Monitor *mon)
104785913070SGreg Kurz {
104885913070SGreg Kurz }
104985913070SGreg Kurz 
105059b7c1c2SBalamuruhan S /*
105159b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1052397a79e7SCédric Le Goater  *
1053397a79e7SCédric Le Goater  * <EX0 reserved>
1054397a79e7SCédric Le Goater  *  EX1  - Venice only
1055397a79e7SCédric Le Goater  *  EX2  - Venice only
1056397a79e7SCédric Le Goater  *  EX3  - Venice only
1057397a79e7SCédric Le Goater  *  EX4
1058397a79e7SCédric Le Goater  *  EX5
1059397a79e7SCédric Le Goater  *  EX6
1060397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1061397a79e7SCédric Le Goater  *  EX9  - Venice only
1062397a79e7SCédric Le Goater  *  EX10 - Venice only
1063397a79e7SCédric Le Goater  *  EX11 - Venice only
1064397a79e7SCédric Le Goater  *  EX12
1065397a79e7SCédric Le Goater  *  EX13
1066397a79e7SCédric Le Goater  *  EX14
1067397a79e7SCédric Le Goater  * <EX15 reserved>
1068397a79e7SCédric Le Goater  */
1069397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1070397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1071397a79e7SCédric Le Goater 
1072397a79e7SCédric Le Goater /*
107309279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1074397a79e7SCédric Le Goater  */
107509279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1076397a79e7SCédric Le Goater 
10772b548a42SCédric Le Goater 
10782b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
10792b548a42SCédric Le Goater 
108077864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
108177864267SCédric Le Goater {
10829ae1329eSCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
108377864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
10849ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
10859ae1329eSCédric Le Goater     int i;
108677864267SCédric Le Goater 
1087245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1088245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1089245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1090d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1091245cdb7fSCédric Le Goater 
10929fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
109377864267SCédric Le Goater 
10949fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
109577864267SCédric Le Goater 
10969fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
10973887d241SBalamuruhan S 
10989fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
10999ae1329eSCédric Le Goater 
11009ae1329eSCédric Le Goater     for (i = 0; i < pcc->num_phbs; i++) {
11019fc7fc4dSMarkus Armbruster         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
11029ae1329eSCédric Le Goater     }
11039ae1329eSCédric Le Goater 
11049ae1329eSCédric Le Goater     /*
11059ae1329eSCédric Le Goater      * Number of PHBs is the chip default
11069ae1329eSCédric Le Goater      */
11079ae1329eSCédric Le Goater     chip->num_phbs = pcc->num_phbs;
110877864267SCédric Le Goater }
110977864267SCédric Le Goater 
111077864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
111177864267SCédric Le Goater  {
111277864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
111377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
111477864267SCédric Le Goater     int i, j;
111577864267SCédric Le Goater     char *name;
111677864267SCédric Le Goater 
111777864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
111877864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
111977864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
112077864267SCédric Le Goater     g_free(name);
112177864267SCédric Le Goater 
112277864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
112377864267SCédric Le Goater 
112477864267SCédric Le Goater     /* Map the ICP registers for each thread */
112577864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
11264fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
112777864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
112877864267SCédric Le Goater 
112977864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
113077864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1131245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
113277864267SCédric Le Goater 
113377864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
113477864267SCédric Le Goater                                         &icp->mmio);
113577864267SCédric Le Goater         }
113677864267SCédric Le Goater     }
113777864267SCédric Le Goater }
113877864267SCédric Le Goater 
113977864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
114077864267SCédric Le Goater {
114177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
114277864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
114377864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1144ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
114577864267SCédric Le Goater     Error *local_err = NULL;
11469ae1329eSCédric Le Goater     int i;
114777864267SCédric Le Goater 
1148245cdb7fSCédric Le Goater     assert(chip8->xics);
1149245cdb7fSCédric Le Goater 
1150709044fdSCédric Le Goater     /* XSCOM bridge is first */
1151709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1152709044fdSCédric Le Goater     if (local_err) {
1153709044fdSCédric Le Goater         error_propagate(errp, local_err);
1154709044fdSCédric Le Goater         return;
1155709044fdSCédric Le Goater     }
1156709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1157709044fdSCédric Le Goater 
115877864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
115977864267SCédric Le Goater     if (local_err) {
116077864267SCédric Le Goater         error_propagate(errp, local_err);
116177864267SCédric Le Goater         return;
116277864267SCédric Le Goater     }
116377864267SCédric Le Goater 
116477864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
11655325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
11665325cc34SMarkus Armbruster                             &error_fatal);
11675325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
11685325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1169668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
117077864267SCédric Le Goater         return;
117177864267SCédric Le Goater     }
1172ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1173ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
117477864267SCédric Le Goater 
117577864267SCédric Le Goater     /* Create LPC controller */
11765325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi),
1177b63f3893SGreg Kurz                              &error_abort);
1178ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
117977864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
118077864267SCédric Le Goater 
1181032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
118264d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
118364d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
118464d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
118564d011d5SCédric Le Goater 
118659b7c1c2SBalamuruhan S     /*
118759b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
118859b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
118959b7c1c2SBalamuruhan S      */
119077864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
119177864267SCédric Le Goater     if (local_err) {
119277864267SCédric Le Goater         error_propagate(errp, local_err);
119377864267SCédric Le Goater         return;
119477864267SCédric Le Goater     }
119577864267SCédric Le Goater 
119677864267SCédric Le Goater     /* Create the simplified OCC model */
11975325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi),
1198ee3d2713SGreg Kurz                              &error_abort);
1199668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
120077864267SCédric Le Goater         return;
120177864267SCédric Le Goater     }
120277864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1203f3db8266SBalamuruhan S 
1204f3db8266SBalamuruhan S     /* OCC SRAM model */
12053a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1206f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
12073887d241SBalamuruhan S 
12083887d241SBalamuruhan S     /* HOMER */
12095325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1210f2582acfSGreg Kurz                              &error_abort);
1211668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
12123887d241SBalamuruhan S         return;
12133887d241SBalamuruhan S     }
12148f092316SCédric Le Goater     /* Homer Xscom region */
12158f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
12168f092316SCédric Le Goater 
12178f092316SCédric Le Goater     /* Homer mmio region */
12183887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
12193887d241SBalamuruhan S                                 &chip8->homer.regs);
12209ae1329eSCédric Le Goater 
12219ae1329eSCédric Le Goater     /* PHB3 controllers */
12229ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
12239ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
12249ae1329eSCédric Le Goater         PnvPBCQState *pbcq = &phb->pbcq;
12259ae1329eSCédric Le Goater 
12265325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
12275325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
12289ae1329eSCédric Le Goater                                 &error_fatal);
1229668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
12309ae1329eSCédric Le Goater             return;
12319ae1329eSCédric Le Goater         }
12329ae1329eSCédric Le Goater 
12339ae1329eSCédric Le Goater         /* Populate the XSCOM address space. */
12349ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12359ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
12369ae1329eSCédric Le Goater                                 &pbcq->xscom_nest_regs);
12379ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12389ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
12399ae1329eSCédric Le Goater                                 &pbcq->xscom_pci_regs);
12409ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12419ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
12429ae1329eSCédric Le Goater                                 &pbcq->xscom_spci_regs);
12439ae1329eSCédric Le Goater     }
124477864267SCédric Le Goater }
124577864267SCédric Le Goater 
124670c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
124770c059e9SGreg Kurz {
124870c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
124970c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
125070c059e9SGreg Kurz }
125170c059e9SGreg Kurz 
1252e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1253e997040eSCédric Le Goater {
1254e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1255e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1256e997040eSCédric Le Goater 
1257e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1258397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
12599ae1329eSCédric Le Goater     k->num_phbs = 3;
1260631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1261d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1262d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12630990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
126485913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
126504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1266eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1267d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1268c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
126970c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1270e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
127177864267SCédric Le Goater 
127277864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
127377864267SCédric Le Goater                                     &k->parent_realize);
1274e997040eSCédric Le Goater }
1275e997040eSCédric Le Goater 
1276e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1277e997040eSCédric Le Goater {
1278e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1279e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1280e997040eSCédric Le Goater 
1281e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1282397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12839ae1329eSCédric Le Goater     k->num_phbs = 3;
1284631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1285d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1286d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12870990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
128885913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
128904026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1290eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1291d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1292c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
129370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1294e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
129577864267SCédric Le Goater 
129677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
129777864267SCédric Le Goater                                     &k->parent_realize);
1298e997040eSCédric Le Goater }
1299e997040eSCédric Le Goater 
1300e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1301e997040eSCédric Le Goater {
1302e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1303e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1304e997040eSCédric Le Goater 
1305e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1306397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13079ae1329eSCédric Le Goater     k->num_phbs = 3;
1308631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1309d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1310d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13110990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
131285913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
131304026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1314eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1315d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1316c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
131770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1318e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
131977864267SCédric Le Goater 
132077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
132177864267SCédric Le Goater                                     &k->parent_realize);
132277864267SCédric Le Goater }
132377864267SCédric Le Goater 
132477864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
132577864267SCédric Le Goater {
13264f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13272dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13284f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13294f9924c4SBenjamin Herrenschmidt     int i;
13302dfa91a2SCédric Le Goater 
1331db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1332d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1333d2623129SMarkus Armbruster                               "xive-fabric");
1334c38536bcSCédric Le Goater 
13359fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
133615376c66SCédric Le Goater 
13379fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
13386598a70dSCédric Le Goater 
13399fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
13403887d241SBalamuruhan S 
13419fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
13424f9924c4SBenjamin Herrenschmidt 
13434f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13444f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
13459fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
13464f9924c4SBenjamin Herrenschmidt     }
13474f9924c4SBenjamin Herrenschmidt 
13484f9924c4SBenjamin Herrenschmidt     /*
13494f9924c4SBenjamin Herrenschmidt      * Number of PHBs is the chip default
13504f9924c4SBenjamin Herrenschmidt      */
13514f9924c4SBenjamin Herrenschmidt     chip->num_phbs = pcc->num_phbs;
135277864267SCédric Le Goater }
135377864267SCédric Le Goater 
13545dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
13555dad902cSCédric Le Goater {
13565dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
13575dad902cSCédric Le Goater     int i;
13585dad902cSCédric Le Goater 
13595dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
13605dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
13615dad902cSCédric Le Goater 
13625dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
13635dad902cSCédric Le Goater         char eq_name[32];
13645dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
13654fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
13665dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
13675dad902cSCédric Le Goater 
13685dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
13699fc7fc4dSMarkus Armbruster         object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
13709fc7fc4dSMarkus Armbruster                                            sizeof(*eq), TYPE_PNV_QUAD,
13719fc7fc4dSMarkus Armbruster                                            &error_fatal, NULL);
13725dad902cSCédric Le Goater 
137392612f15SCédric Le Goater         object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1374ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(eq), NULL, &error_fatal);
13755dad902cSCédric Le Goater 
137692612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
13775dad902cSCédric Le Goater                                 &eq->xscom_regs);
13785dad902cSCédric Le Goater     }
13795dad902cSCédric Le Goater }
13805dad902cSCédric Le Goater 
13814f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
13824f9924c4SBenjamin Herrenschmidt {
13834f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
13844f9924c4SBenjamin Herrenschmidt     int i, j;
13854f9924c4SBenjamin Herrenschmidt     int phb_id = 0;
13864f9924c4SBenjamin Herrenschmidt 
13874f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13884f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
13894f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
13904f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
13914f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
13924f9924c4SBenjamin Herrenschmidt 
13935325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
13944f9924c4SBenjamin Herrenschmidt         /*
13954f9924c4SBenjamin Herrenschmidt          * PEC0 -> 1 stack
13964f9924c4SBenjamin Herrenschmidt          * PEC1 -> 2 stacks
13974f9924c4SBenjamin Herrenschmidt          * PEC2 -> 3 stacks
13984f9924c4SBenjamin Herrenschmidt          */
13995325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "num-stacks", i + 1,
14004f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14015325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
14024f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14035325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pec), "system-memory",
14045325cc34SMarkus Armbruster                                  OBJECT(get_system_memory()), &error_abort);
1405668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14064f9924c4SBenjamin Herrenschmidt             return;
14074f9924c4SBenjamin Herrenschmidt         }
14084f9924c4SBenjamin Herrenschmidt 
14094f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14104f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14114f9924c4SBenjamin Herrenschmidt 
14124f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
14134f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
14144f9924c4SBenjamin Herrenschmidt 
14154f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs;
14164f9924c4SBenjamin Herrenschmidt              j++, phb_id++) {
14174f9924c4SBenjamin Herrenschmidt             PnvPhb4PecStack *stack = &pec->stacks[j];
14184f9924c4SBenjamin Herrenschmidt             Object *obj = OBJECT(&stack->phb);
14194f9924c4SBenjamin Herrenschmidt 
14205325cc34SMarkus Armbruster             object_property_set_int(obj, "index", phb_id, &error_fatal);
14215325cc34SMarkus Armbruster             object_property_set_int(obj, "chip-id", chip->chip_id,
14224f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14235325cc34SMarkus Armbruster             object_property_set_int(obj, "version", PNV_PHB4_VERSION,
14244f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14255325cc34SMarkus Armbruster             object_property_set_int(obj, "device-id", PNV_PHB4_DEVICE_ID,
14264f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14275325cc34SMarkus Armbruster             object_property_set_link(obj, "stack", OBJECT(stack),
14285325cc34SMarkus Armbruster                                      &error_abort);
1429668f62ecSMarkus Armbruster             if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) {
14304f9924c4SBenjamin Herrenschmidt                 return;
14314f9924c4SBenjamin Herrenschmidt             }
14324f9924c4SBenjamin Herrenschmidt 
14334f9924c4SBenjamin Herrenschmidt             /* Populate the XSCOM address space. */
14344f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14354f9924c4SBenjamin Herrenschmidt                                    pec_nest_base + 0x40 * (stack->stack_no + 1),
14364f9924c4SBenjamin Herrenschmidt                                    &stack->nest_regs_mr);
14374f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14384f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + 0x40 * (stack->stack_no + 1),
14394f9924c4SBenjamin Herrenschmidt                                     &stack->pci_regs_mr);
14404f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14414f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
14424f9924c4SBenjamin Herrenschmidt                                     0x40 * stack->stack_no,
14434f9924c4SBenjamin Herrenschmidt                                     &stack->phb_regs_mr);
14444f9924c4SBenjamin Herrenschmidt         }
14454f9924c4SBenjamin Herrenschmidt     }
14464f9924c4SBenjamin Herrenschmidt }
14474f9924c4SBenjamin Herrenschmidt 
144877864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
144977864267SCédric Le Goater {
145077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14512dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14522dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1453c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
145477864267SCédric Le Goater     Error *local_err = NULL;
145577864267SCédric Le Goater 
1456709044fdSCédric Le Goater     /* XSCOM bridge is first */
1457709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1458709044fdSCédric Le Goater     if (local_err) {
1459709044fdSCédric Le Goater         error_propagate(errp, local_err);
1460709044fdSCédric Le Goater         return;
1461709044fdSCédric Le Goater     }
1462709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1463709044fdSCédric Le Goater 
146477864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
146577864267SCédric Le Goater     if (local_err) {
146677864267SCédric Le Goater         error_propagate(errp, local_err);
146777864267SCédric Le Goater         return;
146877864267SCédric Le Goater     }
14692dfa91a2SCédric Le Goater 
14705dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14715dad902cSCédric Le Goater     if (local_err) {
14725dad902cSCédric Le Goater         error_propagate(errp, local_err);
14735dad902cSCédric Le Goater         return;
14745dad902cSCédric Le Goater     }
14755dad902cSCédric Le Goater 
14762dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
14775325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
14785325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
14795325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
14805325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
14815325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
14825325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
14835325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
14845325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
14855325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
14867ae54cc3SGreg Kurz                              &error_abort);
1487668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
14882dfa91a2SCédric Le Goater         return;
14892dfa91a2SCédric Le Goater     }
14902dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
14912dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1492c38536bcSCédric Le Goater 
1493c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
14945325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
14955325cc34SMarkus Armbruster                             &error_fatal);
1496668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1497c38536bcSCédric Le Goater         return;
1498c38536bcSCédric Le Goater     }
1499c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1500c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
150115376c66SCédric Le Goater 
150215376c66SCédric Le Goater     /* LPC */
15035325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi),
1504b63f3893SGreg Kurz                              &error_abort);
1505668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
150615376c66SCédric Le Goater         return;
150715376c66SCédric Le Goater     }
150815376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
150915376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
151015376c66SCédric Le Goater 
1511032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
151215376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
151315376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15146598a70dSCédric Le Goater 
15156598a70dSCédric Le Goater     /* Create the simplified OCC model */
15165325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi),
1517ee3d2713SGreg Kurz                              &error_abort);
1518668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
15196598a70dSCédric Le Goater         return;
15206598a70dSCédric Le Goater     }
15216598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1522f3db8266SBalamuruhan S 
1523f3db8266SBalamuruhan S     /* OCC SRAM model */
15243a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1525f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15263887d241SBalamuruhan S 
15273887d241SBalamuruhan S     /* HOMER */
15285325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1529f2582acfSGreg Kurz                              &error_abort);
1530668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15313887d241SBalamuruhan S         return;
15323887d241SBalamuruhan S     }
15338f092316SCédric Le Goater     /* Homer Xscom region */
15348f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15358f092316SCédric Le Goater 
15368f092316SCédric Le Goater     /* Homer mmio region */
15373887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15383887d241SBalamuruhan S                                 &chip9->homer.regs);
15394f9924c4SBenjamin Herrenschmidt 
15404f9924c4SBenjamin Herrenschmidt     /* PHBs */
15414f9924c4SBenjamin Herrenschmidt     pnv_chip_power9_phb_realize(chip, &local_err);
15424f9924c4SBenjamin Herrenschmidt     if (local_err) {
15434f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15444f9924c4SBenjamin Herrenschmidt         return;
15454f9924c4SBenjamin Herrenschmidt     }
1546e997040eSCédric Le Goater }
1547e997040eSCédric Le Goater 
154870c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
154970c059e9SGreg Kurz {
155070c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
155170c059e9SGreg Kurz     return addr >> 3;
155270c059e9SGreg Kurz }
155370c059e9SGreg Kurz 
1554e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1555e997040eSCédric Le Goater {
1556e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1557e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1558e997040eSCédric Le Goater 
155983028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1560397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1561631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1562d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1563d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15640990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
156585913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
156604026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1567eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1568d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1569c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
157070c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1571e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
15724f9924c4SBenjamin Herrenschmidt     k->num_phbs = 6;
157377864267SCédric Le Goater 
157477864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
157577864267SCédric Le Goater                                     &k->parent_realize);
1576e997040eSCédric Le Goater }
1577e997040eSCédric Le Goater 
15782b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
15792b548a42SCédric Le Goater {
15808b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
15818b50ce85SCédric Le Goater 
15829fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
15839fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
15842b548a42SCédric Le Goater }
15852b548a42SCédric Le Goater 
15862b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
15872b548a42SCédric Le Goater {
15882b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15892b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
15908b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
15912b548a42SCédric Le Goater     Error *local_err = NULL;
15922b548a42SCédric Le Goater 
15932b548a42SCédric Le Goater     /* XSCOM bridge is first */
15942b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
15952b548a42SCédric Le Goater     if (local_err) {
15962b548a42SCédric Le Goater         error_propagate(errp, local_err);
15972b548a42SCédric Le Goater         return;
15982b548a42SCédric Le Goater     }
15992b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
16002b548a42SCédric Le Goater 
16012b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
16022b548a42SCédric Le Goater     if (local_err) {
16032b548a42SCédric Le Goater         error_propagate(errp, local_err);
16042b548a42SCédric Le Goater         return;
16052b548a42SCédric Le Goater     }
16068b50ce85SCédric Le Goater 
16078b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
16085325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
16095325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
1610668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
16118b50ce85SCédric Le Goater         return;
16128b50ce85SCédric Le Goater     }
16138b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
16148b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
16152661f6abSCédric Le Goater 
16162661f6abSCédric Le Goater     /* LPC */
16175325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip10->lpc), "psi",
16185325cc34SMarkus Armbruster                              OBJECT(&chip10->psi), &error_abort);
1619668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
16202661f6abSCédric Le Goater         return;
16212661f6abSCédric Le Goater     }
16222661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
16232661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
16242661f6abSCédric Le Goater 
1625032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
16262661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
16272661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
16282b548a42SCédric Le Goater }
16292b548a42SCédric Le Goater 
163070c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
163170c059e9SGreg Kurz {
163270c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
163370c059e9SGreg Kurz     return addr >> 3;
163470c059e9SGreg Kurz }
163570c059e9SGreg Kurz 
16362b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
16372b548a42SCédric Le Goater {
16382b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
16392b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16402b548a42SCédric Le Goater 
16412b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
16422b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
16432b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
16442b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
16452b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
16462b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
164785913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
16482b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
16492b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
16502b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1651c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
165270c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
16532b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
16542b548a42SCédric Le Goater 
16552b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
16562b548a42SCédric Le Goater                                     &k->parent_realize);
16572b548a42SCédric Le Goater }
16582b548a42SCédric Le Goater 
1659397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1660397a79e7SCédric Le Goater {
1661397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1662397a79e7SCédric Le Goater     int cores_max;
1663397a79e7SCédric Le Goater 
1664397a79e7SCédric Le Goater     /*
1665397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1666397a79e7SCédric Le Goater      * the chip class
1667397a79e7SCédric Le Goater      */
1668397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1669397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1670397a79e7SCédric Le Goater     }
1671397a79e7SCédric Le Goater 
1672397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1673397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1674397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1675397a79e7SCédric Le Goater                    chip->cores_mask);
1676397a79e7SCédric Le Goater         return;
1677397a79e7SCédric Le Goater     }
1678397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1679397a79e7SCédric Le Goater 
1680397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
168127d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1682397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1683397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1684397a79e7SCédric Le Goater                    cores_max);
1685397a79e7SCédric Le Goater         return;
1686397a79e7SCédric Le Goater     }
1687397a79e7SCédric Le Goater }
1688397a79e7SCédric Le Goater 
168951c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1690e997040eSCédric Le Goater {
1691397a79e7SCédric Le Goater     Error *error = NULL;
1692d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
169340abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1694d2fd9612SCédric Le Goater     int i, core_hwid;
169508c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1696397a79e7SCédric Le Goater 
1697d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1698d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1699d2fd9612SCédric Le Goater         return;
1700d2fd9612SCédric Le Goater     }
1701d2fd9612SCédric Le Goater 
1702d2fd9612SCédric Le Goater     /* Cores */
1703397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1704397a79e7SCédric Le Goater     if (error) {
1705397a79e7SCédric Le Goater         error_propagate(errp, error);
1706397a79e7SCédric Le Goater         return;
1707397a79e7SCédric Le Goater     }
1708d2fd9612SCédric Le Goater 
17094fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1710d2fd9612SCédric Le Goater 
1711d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1712d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1713d2fd9612SCédric Le Goater         char core_name[32];
17144fa28f23SGreg Kurz         PnvCore *pnv_core;
1715c035851aSCédric Le Goater         uint64_t xscom_core_base;
1716d2fd9612SCédric Le Goater 
1717d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1718d2fd9612SCédric Le Goater             continue;
1719d2fd9612SCédric Le Goater         }
1720d2fd9612SCédric Le Goater 
17214fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
17224fa28f23SGreg Kurz 
1723d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1724d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
17254fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
17265325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
17275325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
17285325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
17295325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
17305325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
17315325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
17325325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
17335325cc34SMarkus Armbruster                                 &error_fatal);
17345325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1735158e17a6SGreg Kurz                                  &error_abort);
1736ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
173724ece072SCédric Le Goater 
173824ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1739c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1740c035851aSCédric Le Goater 
1741c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
17424fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1743d2fd9612SCédric Le Goater         i++;
1744d2fd9612SCédric Le Goater     }
174551c04728SCédric Le Goater }
174651c04728SCédric Le Goater 
174751c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
174851c04728SCédric Le Goater {
174951c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
175051c04728SCédric Le Goater     Error *error = NULL;
175151c04728SCédric Le Goater 
175251c04728SCédric Le Goater     /* Cores */
175351c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
175451c04728SCédric Le Goater     if (error) {
175551c04728SCédric Le Goater         error_propagate(errp, error);
175651c04728SCédric Le Goater         return;
175751c04728SCédric Le Goater     }
1758e997040eSCédric Le Goater }
1759e997040eSCédric Le Goater 
1760e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1761e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1762e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1763e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1764397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1765397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1766764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
17674f9924c4SBenjamin Herrenschmidt     DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
1768e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1769e997040eSCédric Le Goater };
1770e997040eSCédric Le Goater 
1771e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1772e997040eSCédric Le Goater {
1773e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1774e997040eSCédric Le Goater 
17759d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1776e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
17774f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1778e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1779e997040eSCédric Le Goater }
1780e997040eSCédric Le Goater 
1781119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1782119eaa9dSCédric Le Goater {
1783119eaa9dSCédric Le Goater     int i, j;
1784119eaa9dSCédric Le Goater 
1785119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1786119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1787119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1788119eaa9dSCédric Le Goater 
1789119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1790119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1791119eaa9dSCédric Le Goater                 return pc->threads[j];
1792119eaa9dSCédric Le Goater             }
1793119eaa9dSCédric Le Goater         }
1794119eaa9dSCédric Le Goater     }
1795119eaa9dSCédric Le Goater     return NULL;
1796119eaa9dSCédric Le Goater }
1797119eaa9dSCédric Le Goater 
179854f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
179954f59d78SCédric Le Goater {
1800b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18019ae1329eSCédric Le Goater     int i, j;
180254f59d78SCédric Le Goater 
180354f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18049ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
180577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
180677864267SCédric Le Goater 
180777864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
180877864267SCédric Le Goater             return &chip8->psi.ics;
180954f59d78SCédric Le Goater         }
18109ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18119ae1329eSCédric Le Goater             if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
18129ae1329eSCédric Le Goater                 return &chip8->phbs[j].lsis;
18139ae1329eSCédric Le Goater             }
18149ae1329eSCédric Le Goater             if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
18159ae1329eSCédric Le Goater                 return ICS(&chip8->phbs[j].msis);
18169ae1329eSCédric Le Goater             }
18179ae1329eSCédric Le Goater         }
181854f59d78SCédric Le Goater     }
181954f59d78SCédric Le Goater     return NULL;
182054f59d78SCédric Le Goater }
182154f59d78SCédric Le Goater 
182254f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
182354f59d78SCédric Le Goater {
1824b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18259ae1329eSCédric Le Goater     int i, j;
182654f59d78SCédric Le Goater 
182754f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18289ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
182977864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
18309ae1329eSCédric Le Goater 
183177864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
18329ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18339ae1329eSCédric Le Goater             ics_resend(&chip8->phbs[j].lsis);
18349ae1329eSCédric Le Goater             ics_resend(ICS(&chip8->phbs[j].msis));
18359ae1329eSCédric Le Goater         }
183654f59d78SCédric Le Goater     }
183754f59d78SCédric Le Goater }
183854f59d78SCédric Le Goater 
183936fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
184036fc6f08SCédric Le Goater {
184136fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
184236fc6f08SCédric Le Goater 
1843956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
184436fc6f08SCédric Le Goater }
184536fc6f08SCédric Le Goater 
184647fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
184747fea43aSCédric Le Goater                                Monitor *mon)
184847fea43aSCédric Le Goater {
1849b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
185054f59d78SCédric Le Goater     int i;
185147fea43aSCédric Le Goater     CPUState *cs;
185247fea43aSCédric Le Goater 
185347fea43aSCédric Le Goater     CPU_FOREACH(cs) {
185447fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
185547fea43aSCédric Le Goater 
185685913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
185785913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
185885913070SGreg Kurz                                                            mon);
1859d8e4aad5SCédric Le Goater     }
186054f59d78SCédric Le Goater 
186154f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1862d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
186354f59d78SCédric Le Goater     }
186447fea43aSCédric Le Goater }
186547fea43aSCédric Le Goater 
1866c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1867c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1868c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1869c722579eSCédric Le Goater                          uint32_t logic_serv,
1870c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1871c722579eSCédric Le Goater {
1872c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1873c722579eSCédric Le Goater     int total_count = 0;
1874c722579eSCédric Le Goater     int i;
1875c722579eSCédric Le Goater 
1876c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1877c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1878c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1879c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1880c722579eSCédric Le Goater         int count;
1881c722579eSCédric Le Goater 
1882c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1883c722579eSCédric Le Goater                                priority, logic_serv, match);
1884c722579eSCédric Le Goater 
1885c722579eSCédric Le Goater         if (count < 0) {
1886c722579eSCédric Le Goater             return count;
1887c722579eSCédric Le Goater         }
1888c722579eSCédric Le Goater 
1889c722579eSCédric Le Goater         total_count += count;
1890c722579eSCédric Le Goater     }
1891c722579eSCédric Le Goater 
1892c722579eSCédric Le Goater     return total_count;
1893c722579eSCédric Le Goater }
1894c722579eSCédric Le Goater 
1895f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
18969e933f4aSBenjamin Herrenschmidt {
18979e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
189836fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1899d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1900d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1901f30c843cSCédric Le Goater 
1902f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1903f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1904f30c843cSCédric Le Goater 
1905f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1906f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1907f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1908d76f2da7SGreg Kurz 
1909d76f2da7SGreg Kurz     pmc->compat = compat;
1910d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1911f30c843cSCédric Le Goater }
1912f30c843cSCédric Le Goater 
1913f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1914f30c843cSCédric Le Goater {
1915f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1916c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1917d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1918d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1919f30c843cSCédric Le Goater 
1920f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1921f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1922c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1923f30c843cSCédric Le Goater 
1924f30c843cSCédric Le Goater     mc->alias = "powernv";
1925d76f2da7SGreg Kurz 
1926d76f2da7SGreg Kurz     pmc->compat = compat;
1927d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19287a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1929f30c843cSCédric Le Goater }
1930f30c843cSCédric Le Goater 
19312b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
19322b548a42SCédric Le Goater {
19332b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1934d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1935d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
19362b548a42SCédric Le Goater 
19372b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
19386bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
1939d76f2da7SGreg Kurz 
1940d76f2da7SGreg Kurz     pmc->compat = compat;
1941d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19427a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
19432b548a42SCédric Le Goater }
19442b548a42SCédric Le Goater 
194508c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
194608c3f3a7SCédric Le Goater {
194708c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
194808c3f3a7SCédric Le Goater 
194908c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
195008c3f3a7SCédric Le Goater }
195108c3f3a7SCédric Le Goater 
195208c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
195308c3f3a7SCédric Le Goater {
195408c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
195508c3f3a7SCédric Le Goater 
195608c3f3a7SCédric Le Goater     if (value) {
195708c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
195808c3f3a7SCédric Le Goater     }
195908c3f3a7SCédric Le Goater }
196008c3f3a7SCédric Le Goater 
196101b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
196201b552b0SNicholas Piggin {
196301b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
196401b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
196501b552b0SNicholas Piggin 
196601b552b0SNicholas Piggin     cpu_synchronize_state(cs);
196701b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
19680911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
196901b552b0SNicholas Piggin         /*
1970fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
1971fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
1972fe837714SNicholas Piggin          * (PPC_BIT(43)).
197301b552b0SNicholas Piggin          */
19740911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
1975fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
19760911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
197701b552b0SNicholas Piggin         }
1978fe837714SNicholas Piggin     } else {
1979fe837714SNicholas Piggin         /*
1980fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
1981fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
1982fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
1983fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
1984fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
1985fe837714SNicholas Piggin          */
19860911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
1987fe837714SNicholas Piggin     }
1988fe837714SNicholas Piggin }
198901b552b0SNicholas Piggin 
199001b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
199101b552b0SNicholas Piggin {
199201b552b0SNicholas Piggin     CPUState *cs;
199301b552b0SNicholas Piggin 
199401b552b0SNicholas Piggin     CPU_FOREACH(cs) {
199501b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
199601b552b0SNicholas Piggin     }
199701b552b0SNicholas Piggin }
199801b552b0SNicholas Piggin 
1999f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2000f30c843cSCédric Le Goater {
2001f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
200247fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
200301b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
20049e933f4aSBenjamin Herrenschmidt 
20059e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2006b168a138SCédric Le Goater     mc->init = pnv_init;
2007b168a138SCédric Le Goater     mc->reset = pnv_reset;
20089e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
200959b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
201059b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
20119e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
20129e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2013f1d18b0aSJoel Stanley     /*
2014f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2015f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2016f1d18b0aSJoel Stanley      */
2017dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2018173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
201947fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
202001b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
202108c3f3a7SCédric Le Goater 
202208c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2023d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
202408c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
20257eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
20269e933f4aSBenjamin Herrenschmidt }
20279e933f4aSBenjamin Herrenschmidt 
202877864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2029beba5c0fSIgor Mammedov     {                                             \
2030beba5c0fSIgor Mammedov         .name          = type,                    \
2031beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
203277864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
203377864267SCédric Le Goater     }
203477864267SCédric Le Goater 
203577864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
203677864267SCédric Le Goater     {                                             \
203777864267SCédric Le Goater         .name          = type,                    \
203877864267SCédric Le Goater         .class_init    = class_initfn,            \
203977864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2040beba5c0fSIgor Mammedov     }
2041beba5c0fSIgor Mammedov 
20422b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
20432b548a42SCédric Le Goater     {                                              \
20442b548a42SCédric Le Goater         .name          = type,                     \
20452b548a42SCédric Le Goater         .class_init    = class_initfn,             \
20462b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
20472b548a42SCédric Le Goater     }
20482b548a42SCédric Le Goater 
2049beba5c0fSIgor Mammedov static const TypeInfo types[] = {
20501aba8716SCédric Le Goater     {
20512b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
20522b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20532b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
20542b548a42SCédric Le Goater     },
20552b548a42SCédric Le Goater     {
20561aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
20571aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20581aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2059c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2060c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2061c722579eSCédric Le Goater             { },
2062c722579eSCédric Le Goater         },
20631aba8716SCédric Le Goater     },
20641aba8716SCédric Le Goater     {
20651aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
20661aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20671aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
20681aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
20691aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
20701aba8716SCédric Le Goater             { },
20711aba8716SCédric Le Goater         },
20721aba8716SCédric Le Goater     },
2073beba5c0fSIgor Mammedov     {
2074b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
20759e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2076f30c843cSCédric Le Goater         .abstract       = true,
20779e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2078b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2079d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
208036fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
208147fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
208201b552b0SNicholas Piggin             { TYPE_NMI },
208336fc6f08SCédric Le Goater             { },
208436fc6f08SCédric Le Goater         },
2085beba5c0fSIgor Mammedov     },
2086beba5c0fSIgor Mammedov     {
2087beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2088beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2089beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2090beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2091beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2092beba5c0fSIgor Mammedov         .abstract      = true,
2093beba5c0fSIgor Mammedov     },
209477864267SCédric Le Goater 
209577864267SCédric Le Goater     /*
20962b548a42SCédric Le Goater      * P10 chip and variants
20972b548a42SCédric Le Goater      */
20982b548a42SCédric Le Goater     {
20992b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
21002b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
21012b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
21022b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
21032b548a42SCédric Le Goater     },
21042b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
21052b548a42SCédric Le Goater 
21062b548a42SCédric Le Goater     /*
210777864267SCédric Le Goater      * P9 chip and variants
210877864267SCédric Le Goater      */
210977864267SCédric Le Goater     {
211077864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
211177864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
211277864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
211377864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
211477864267SCédric Le Goater     },
211577864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
211677864267SCédric Le Goater 
211777864267SCédric Le Goater     /*
211877864267SCédric Le Goater      * P8 chip and variants
211977864267SCédric Le Goater      */
212077864267SCédric Le Goater     {
212177864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
212277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
212377864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
212477864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
212577864267SCédric Le Goater     },
212677864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
212777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
212877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2129beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
21309e933f4aSBenjamin Herrenschmidt };
21319e933f4aSBenjamin Herrenschmidt 
2132beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2133