xref: /qemu/hw/ppc/pnv.c (revision 3c6ef471)
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
99e933f4aSBenjamin Herrenschmidt  * version 2 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"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2671e8a915SMarkus Armbruster #include "sysemu/reset.h"
2754d31236SMarkus Armbruster #include "sysemu/runstate.h"
28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
298d409261SCédric Le Goater #include "sysemu/device_tree.h"
3001b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
31fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
329e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
36d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
379e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
3801b552b0SNicholas Piggin #include "hw/nmi.h"
399e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
40e997040eSCédric Le Goater #include "qapi/visitor.h"
4147fea43aSCédric Le Goater #include "monitor/monitor.h"
4247fea43aSCédric Le Goater #include "hw/intc/intc.h"
43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h"
469e933f4aSBenjamin Herrenschmidt 
4736fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
48a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
49967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5035dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
51967b7523SCédric Le Goater 
523495b6b6SCédric Le Goater #include "hw/isa/isa.h"
5312e9493dSMarkus Armbruster #include "hw/boards.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
63b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
649e933f4aSBenjamin Herrenschmidt 
659e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
66b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
67fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
68584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * 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 
199d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
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) {
59025f3170bSCédric Le Goater             warn_report("machine has no BMC device. Use '-device "
59125f3170bSCédric Le Goater                         "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59225f3170bSCédric Le Goater                         "to define one");
59325f3170bSCédric Le Goater         } else {
59425f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
59525f3170bSCédric Le Goater             pnv->bmc = bmc;
59625f3170bSCédric Le Goater         }
59725f3170bSCédric Le Goater     }
59825f3170bSCédric Le Goater 
599b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6009e933f4aSBenjamin Herrenschmidt 
6019e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6029e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6039e933f4aSBenjamin Herrenschmidt 
6048d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6059e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
606b2fb7a43SPan Nengyuan 
607b2fb7a43SPan Nengyuan     g_free(fdt);
6089e933f4aSBenjamin Herrenschmidt }
6099e933f4aSBenjamin Herrenschmidt 
61004026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6113495b6b6SCédric Le Goater {
61277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
61377864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
61404026890SCédric Le Goater }
6153495b6b6SCédric Le Goater 
61604026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
61704026890SCédric Le Goater {
61877864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
61977864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
62004026890SCédric Le Goater }
6213495b6b6SCédric Le Goater 
62204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
62304026890SCédric Le Goater {
62415376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
62515376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
62604026890SCédric Le Goater }
6273495b6b6SCédric Le Goater 
6282b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6292b548a42SCédric Le Goater {
6302661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6312661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6322b548a42SCédric Le Goater }
6332b548a42SCédric Le Goater 
63404026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
63504026890SCédric Le Goater {
63604026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6373495b6b6SCédric Le Goater }
6383495b6b6SCédric Le Goater 
639d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
640d8e4aad5SCédric Le Goater {
641d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6429ae1329eSCédric Le Goater     int i;
643d8e4aad5SCédric Le Goater 
644d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6459ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
6469ae1329eSCédric Le Goater         pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
6479ae1329eSCédric Le Goater         ics_pic_print_info(&chip8->phbs[i].lsis, mon);
6489ae1329eSCédric Le Goater     }
649d8e4aad5SCédric Le Goater }
650d8e4aad5SCédric Le Goater 
651d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
652d8e4aad5SCédric Le Goater {
653d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
6544f9924c4SBenjamin Herrenschmidt     int i, j;
655d8e4aad5SCédric Le Goater 
656d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
657c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6584f9924c4SBenjamin Herrenschmidt 
6594f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
6604f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
6614f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks; j++) {
6624f9924c4SBenjamin Herrenschmidt             pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
6634f9924c4SBenjamin Herrenschmidt         }
6644f9924c4SBenjamin Herrenschmidt     }
665d8e4aad5SCédric Le Goater }
666d8e4aad5SCédric Le Goater 
667c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
668c4b2c40cSGreg Kurz                                                 uint32_t core_id)
669c4b2c40cSGreg Kurz {
670c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
671c4b2c40cSGreg Kurz }
672c4b2c40cSGreg Kurz 
673c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
674c4b2c40cSGreg Kurz                                                 uint32_t core_id)
675c4b2c40cSGreg Kurz {
676c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
677c4b2c40cSGreg Kurz }
678c4b2c40cSGreg Kurz 
679c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
680c4b2c40cSGreg Kurz                                                  uint32_t core_id)
681c4b2c40cSGreg Kurz {
682c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
683c4b2c40cSGreg Kurz }
684c4b2c40cSGreg Kurz 
685f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
686f30c843cSCédric Le Goater {
687f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
688f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
689f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
690f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
691f30c843cSCédric Le Goater 
692f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
693f30c843cSCédric Le Goater }
694f30c843cSCédric Le Goater 
695e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
696e2392d43SCédric Le Goater {
697c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
698e2392d43SCédric Le Goater 
699c23e0561SMarkus Armbruster     object_property_set_link(OBJECT(dev), OBJECT(bmc), "bmc", &error_fatal);
700c23e0561SMarkus Armbruster     object_property_set_int(OBJECT(dev), irq, "irq", &error_fatal);
701c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
702e2392d43SCédric Le Goater }
703e2392d43SCédric Le Goater 
7042b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7052b548a42SCédric Le Goater {
7068b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7078b50ce85SCédric Le Goater 
7088b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
7092b548a42SCédric Le Goater }
7102b548a42SCédric Le Goater 
711b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7129e933f4aSBenjamin Herrenschmidt {
713b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
714f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7159e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7169e933f4aSBenjamin Herrenschmidt     long fw_size;
717e997040eSCédric Le Goater     int i;
718e997040eSCédric Le Goater     char *chip_typename;
71935dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
72035dde576SCédric Le Goater     DeviceState *dev;
7219e933f4aSBenjamin Herrenschmidt 
7229e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
723d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
7243dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
7259e933f4aSBenjamin Herrenschmidt     }
726173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7279e933f4aSBenjamin Herrenschmidt 
72835dde576SCédric Le Goater     /*
72935dde576SCédric Le Goater      * Create our simple PNOR device
73035dde576SCédric Le Goater      */
7313e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
73235dde576SCédric Le Goater     if (pnor) {
73335dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
73435dde576SCédric Le Goater                             &error_abort);
73535dde576SCédric Le Goater     }
736*3c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
73735dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
73835dde576SCédric Le Goater 
7399e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7409e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
7419e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
7429e933f4aSBenjamin Herrenschmidt     }
7439e933f4aSBenjamin Herrenschmidt 
7449e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
74515fcedb2SCédric Le Goater     if (!fw_filename) {
74615fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
74715fcedb2SCédric Le Goater         exit(1);
74815fcedb2SCédric Le Goater     }
7499e933f4aSBenjamin Herrenschmidt 
75008c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
7519e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
75215fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7539e933f4aSBenjamin Herrenschmidt         exit(1);
7549e933f4aSBenjamin Herrenschmidt     }
7559e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7569e933f4aSBenjamin Herrenschmidt 
7579e933f4aSBenjamin Herrenschmidt     /* load kernel */
7589e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7599e933f4aSBenjamin Herrenschmidt         long kernel_size;
7609e933f4aSBenjamin Herrenschmidt 
7619e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
762b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7639e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
764802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7659e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7669e933f4aSBenjamin Herrenschmidt             exit(1);
7679e933f4aSBenjamin Herrenschmidt         }
7689e933f4aSBenjamin Herrenschmidt     }
7699e933f4aSBenjamin Herrenschmidt 
7709e933f4aSBenjamin Herrenschmidt     /* load initrd */
7719e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7729e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7739e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
774584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7759e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
776802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7779e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7789e933f4aSBenjamin Herrenschmidt             exit(1);
7799e933f4aSBenjamin Herrenschmidt         }
7809e933f4aSBenjamin Herrenschmidt     }
781e997040eSCédric Le Goater 
7824f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
7834f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
7844f9924c4SBenjamin Herrenschmidt 
785f30c843cSCédric Le Goater     /*
786f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
787f30c843cSCédric Le Goater      * default.
788f30c843cSCédric Le Goater      */
789f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
790f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
791f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
792f30c843cSCédric Le Goater         exit(1);
793f30c843cSCédric Le Goater     }
794f30c843cSCédric Le Goater 
795e997040eSCédric Le Goater     /* Create the processor chips */
7964a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7977fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7984a12c699SIgor Mammedov                                     i, machine->cpu_type);
799e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
800f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
801f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
802e997040eSCédric Le Goater         exit(1);
803e997040eSCédric Le Goater     }
804e997040eSCédric Le Goater 
805e44acde2SGreg Kurz     pnv->num_chips =
806e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
807e44acde2SGreg Kurz     /*
808e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
809e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
810e44acde2SGreg Kurz      */
811e44acde2SGreg Kurz     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 4) {
812e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
813e44acde2SGreg Kurz         error_printf("Try '-smp sockets=N'. Valid values are : 1, 2 or 4.\n");
814e44acde2SGreg Kurz         exit(1);
815e44acde2SGreg Kurz     }
816e44acde2SGreg Kurz 
817e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
818e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
819e997040eSCédric Le Goater         char chip_name[32];
820df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
821e997040eSCédric Le Goater 
822e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
823e997040eSCédric Le Goater 
82459b7c1c2SBalamuruhan S         /*
82559b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
826e997040eSCédric Le Goater          * way to specify different ranges for each chip
827e997040eSCédric Le Goater          */
828e997040eSCédric Le Goater         if (i == 0) {
829e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
830e997040eSCédric Le Goater                                     &error_fatal);
831e997040eSCédric Le Goater         }
832e997040eSCédric Le Goater 
833e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
834d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
835e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
836e997040eSCédric Le Goater                                 &error_fatal);
837fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
838fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
839764f9b25SGreg Kurz         object_property_set_int(chip, machine->smp.threads,
840764f9b25SGreg Kurz                                 "nr-threads", &error_fatal);
841245cdb7fSCédric Le Goater         /*
842245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
843245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
844245cdb7fSCédric Le Goater          */
845245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
846245cdb7fSCédric Le Goater             object_property_set_link(chip, OBJECT(pnv), "xics", &error_abort);
847245cdb7fSCédric Le Goater         }
848d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
849d1214b81SGreg Kurz             object_property_set_link(chip, OBJECT(pnv), "xive-fabric",
850d1214b81SGreg Kurz                                      &error_abort);
851d1214b81SGreg Kurz         }
852*3c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
853e997040eSCédric Le Goater     }
854e997040eSCédric Le Goater     g_free(chip_typename);
8553495b6b6SCédric Le Goater 
8563495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
85704026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
8583495b6b6SCédric Le Goater 
8593495b6b6SCédric Le Goater     /* Create serial port */
860def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
8613495b6b6SCédric Le Goater 
8623495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8636c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
864bce0b691SCédric Le Goater 
86525f3170bSCédric Le Goater     /*
86625f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
86725f3170bSCédric Le Goater      * communication with the BMC
86825f3170bSCédric Le Goater      */
86925f3170bSCédric Le Goater     if (defaults_enabled()) {
87025f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
871e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
87225f3170bSCédric Le Goater     }
873e2392d43SCédric Le Goater 
87459b7c1c2SBalamuruhan S     /*
87559b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
87659b7c1c2SBalamuruhan S      * host to powerdown
87759b7c1c2SBalamuruhan S      */
878bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
879bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
880e997040eSCédric Le Goater }
881e997040eSCédric Le Goater 
882631adaffSCédric Le Goater /*
883631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
884631adaffSCédric Le Goater  *   22:24  Chip ID
885631adaffSCédric Le Goater  *   25:28  Core number
886631adaffSCédric Le Goater  *   29:31  Thread ID
887631adaffSCédric Le Goater  */
888631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
889631adaffSCédric Le Goater {
890631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
891631adaffSCédric Le Goater }
892631adaffSCédric Le Goater 
8938fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
894d35aefa9SCédric Le Goater                                         Error **errp)
895d35aefa9SCédric Le Goater {
896245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
8978fa1f4efSCédric Le Goater     Error *local_err = NULL;
8988fa1f4efSCédric Le Goater     Object *obj;
8998907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9008fa1f4efSCédric Le Goater 
901245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9028fa1f4efSCédric Le Goater     if (local_err) {
9038fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9048fa1f4efSCédric Le Goater         return;
9058fa1f4efSCédric Le Goater     }
9068fa1f4efSCédric Le Goater 
907956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
908d35aefa9SCédric Le Goater }
909d35aefa9SCédric Le Goater 
9100990ce6aSGreg Kurz 
911d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
912d49e8a9bSCédric Le Goater {
913d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
914d49e8a9bSCédric Le Goater 
915d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
916d49e8a9bSCédric Le Goater }
917d49e8a9bSCédric Le Goater 
9180990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9190990ce6aSGreg Kurz {
9200990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9210990ce6aSGreg Kurz 
9220990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9230990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9240990ce6aSGreg Kurz }
9250990ce6aSGreg Kurz 
92685913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
92785913070SGreg Kurz                                             Monitor *mon)
92885913070SGreg Kurz {
92985913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
93085913070SGreg Kurz }
93185913070SGreg Kurz 
932631adaffSCédric Le Goater /*
933631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
934631adaffSCédric Le Goater  *   49:52  Node ID
935631adaffSCédric Le Goater  *   53:55  Chip ID
936631adaffSCédric Le Goater  *   56     Reserved - Read as zero
937631adaffSCédric Le Goater  *   57:61  Core number
938631adaffSCédric Le Goater  *   62:63  Thread ID
939631adaffSCédric Le Goater  *
940631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
941631adaffSCédric Le Goater  */
942631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
943631adaffSCédric Le Goater {
944631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
945631adaffSCédric Le Goater }
946631adaffSCédric Le Goater 
9472b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
9482b548a42SCédric Le Goater {
9492b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
9502b548a42SCédric Le Goater }
9512b548a42SCédric Le Goater 
9528fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
953d35aefa9SCédric Le Goater                                         Error **errp)
954d35aefa9SCédric Le Goater {
9552dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
9562dfa91a2SCédric Le Goater     Error *local_err = NULL;
9572dfa91a2SCédric Le Goater     Object *obj;
9582dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9592dfa91a2SCédric Le Goater 
9602dfa91a2SCédric Le Goater     /*
9612dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
9622dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
9632dfa91a2SCédric Le Goater      * only used at runtime.
9642dfa91a2SCédric Le Goater      */
96547950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
96647950946SCédric Le Goater                            &local_err);
9672dfa91a2SCédric Le Goater     if (local_err) {
9682dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9698fa1f4efSCédric Le Goater         return;
970d35aefa9SCédric Le Goater     }
971d35aefa9SCédric Le Goater 
9722dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
9732dfa91a2SCédric Le Goater }
9742dfa91a2SCédric Le Goater 
975d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
976d49e8a9bSCédric Le Goater {
977d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
978d49e8a9bSCédric Le Goater 
979d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
980d49e8a9bSCédric Le Goater }
981d49e8a9bSCédric Le Goater 
9820990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9830990ce6aSGreg Kurz {
9840990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9850990ce6aSGreg Kurz 
9860990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
9870990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9880990ce6aSGreg Kurz }
9890990ce6aSGreg Kurz 
99085913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
99185913070SGreg Kurz                                             Monitor *mon)
99285913070SGreg Kurz {
99385913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
99485913070SGreg Kurz }
99585913070SGreg Kurz 
9962b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
9972b548a42SCédric Le Goater                                         Error **errp)
9982b548a42SCédric Le Goater {
9992b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10002b548a42SCédric Le Goater 
10012b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
10022b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10032b548a42SCédric Le Goater }
10042b548a42SCédric Le Goater 
10052b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10062b548a42SCédric Le Goater {
10072b548a42SCédric Le Goater     ;
10082b548a42SCédric Le Goater }
10092b548a42SCédric Le Goater 
10102b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10112b548a42SCédric Le Goater {
10122b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10132b548a42SCédric Le Goater 
10142b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10152b548a42SCédric Le Goater }
10162b548a42SCédric Le Goater 
101785913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
101885913070SGreg Kurz                                              Monitor *mon)
101985913070SGreg Kurz {
102085913070SGreg Kurz }
102185913070SGreg Kurz 
102259b7c1c2SBalamuruhan S /*
102359b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1024397a79e7SCédric Le Goater  *
1025397a79e7SCédric Le Goater  * <EX0 reserved>
1026397a79e7SCédric Le Goater  *  EX1  - Venice only
1027397a79e7SCédric Le Goater  *  EX2  - Venice only
1028397a79e7SCédric Le Goater  *  EX3  - Venice only
1029397a79e7SCédric Le Goater  *  EX4
1030397a79e7SCédric Le Goater  *  EX5
1031397a79e7SCédric Le Goater  *  EX6
1032397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1033397a79e7SCédric Le Goater  *  EX9  - Venice only
1034397a79e7SCédric Le Goater  *  EX10 - Venice only
1035397a79e7SCédric Le Goater  *  EX11 - Venice only
1036397a79e7SCédric Le Goater  *  EX12
1037397a79e7SCédric Le Goater  *  EX13
1038397a79e7SCédric Le Goater  *  EX14
1039397a79e7SCédric Le Goater  * <EX15 reserved>
1040397a79e7SCédric Le Goater  */
1041397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1042397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1043397a79e7SCédric Le Goater 
1044397a79e7SCédric Le Goater /*
104509279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1046397a79e7SCédric Le Goater  */
104709279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1048397a79e7SCédric Le Goater 
10492b548a42SCédric Le Goater 
10502b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
10512b548a42SCédric Le Goater 
105277864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
105377864267SCédric Le Goater {
10549ae1329eSCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
105577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
10569ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
10579ae1329eSCédric Le Goater     int i;
105877864267SCédric Le Goater 
1059245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1060245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1061245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1062d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1063245cdb7fSCédric Le Goater 
10649fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
106577864267SCédric Le Goater 
10669fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
106777864267SCédric Le Goater 
10689fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
10693887d241SBalamuruhan S 
10709fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
10719ae1329eSCédric Le Goater 
10729ae1329eSCédric Le Goater     for (i = 0; i < pcc->num_phbs; i++) {
10739fc7fc4dSMarkus Armbruster         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
10749ae1329eSCédric Le Goater     }
10759ae1329eSCédric Le Goater 
10769ae1329eSCédric Le Goater     /*
10779ae1329eSCédric Le Goater      * Number of PHBs is the chip default
10789ae1329eSCédric Le Goater      */
10799ae1329eSCédric Le Goater     chip->num_phbs = pcc->num_phbs;
108077864267SCédric Le Goater }
108177864267SCédric Le Goater 
108277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
108377864267SCédric Le Goater  {
108477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
108577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
108677864267SCédric Le Goater     int i, j;
108777864267SCédric Le Goater     char *name;
108877864267SCédric Le Goater 
108977864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
109077864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
109177864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
109277864267SCédric Le Goater     g_free(name);
109377864267SCédric Le Goater 
109477864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
109577864267SCédric Le Goater 
109677864267SCédric Le Goater     /* Map the ICP registers for each thread */
109777864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
10984fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
109977864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
110077864267SCédric Le Goater 
110177864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
110277864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1103245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
110477864267SCédric Le Goater 
110577864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
110677864267SCédric Le Goater                                         &icp->mmio);
110777864267SCédric Le Goater         }
110877864267SCédric Le Goater     }
110977864267SCédric Le Goater }
111077864267SCédric Le Goater 
111177864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
111277864267SCédric Le Goater {
111377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
111477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
111577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1116ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
111777864267SCédric Le Goater     Error *local_err = NULL;
11189ae1329eSCédric Le Goater     int i;
111977864267SCédric Le Goater 
1120245cdb7fSCédric Le Goater     assert(chip8->xics);
1121245cdb7fSCédric Le Goater 
1122709044fdSCédric Le Goater     /* XSCOM bridge is first */
1123709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1124709044fdSCédric Le Goater     if (local_err) {
1125709044fdSCédric Le Goater         error_propagate(errp, local_err);
1126709044fdSCédric Le Goater         return;
1127709044fdSCédric Le Goater     }
1128709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1129709044fdSCédric Le Goater 
113077864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
113177864267SCédric Le Goater     if (local_err) {
113277864267SCédric Le Goater         error_propagate(errp, local_err);
113377864267SCédric Le Goater         return;
113477864267SCédric Le Goater     }
113577864267SCédric Le Goater 
113677864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
113777864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
113877864267SCédric Le Goater                             "bar", &error_fatal);
1139245cdb7fSCédric Le Goater     object_property_set_link(OBJECT(&chip8->psi), OBJECT(chip8->xics),
114034bdca8fSCédric Le Goater                              ICS_PROP_XICS, &error_abort);
114177864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
114277864267SCédric Le Goater     if (local_err) {
114377864267SCédric Le Goater         error_propagate(errp, local_err);
114477864267SCédric Le Goater         return;
114577864267SCédric Le Goater     }
1146ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1147ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
114877864267SCédric Le Goater 
114977864267SCédric Le Goater     /* Create LPC controller */
1150b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi",
1151b63f3893SGreg Kurz                              &error_abort);
115277864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
115377864267SCédric Le Goater                              &error_fatal);
115477864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
115577864267SCédric Le Goater 
115664d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
115764d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
115864d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
115964d011d5SCédric Le Goater 
116059b7c1c2SBalamuruhan S     /*
116159b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
116259b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
116359b7c1c2SBalamuruhan S      */
116477864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
116577864267SCédric Le Goater     if (local_err) {
116677864267SCédric Le Goater         error_propagate(errp, local_err);
116777864267SCédric Le Goater         return;
116877864267SCédric Le Goater     }
116977864267SCédric Le Goater 
117077864267SCédric Le Goater     /* Create the simplified OCC model */
1171ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi",
1172ee3d2713SGreg Kurz                              &error_abort);
117377864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
117477864267SCédric Le Goater     if (local_err) {
117577864267SCédric Le Goater         error_propagate(errp, local_err);
117677864267SCédric Le Goater         return;
117777864267SCédric Le Goater     }
117877864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1179f3db8266SBalamuruhan S 
1180f3db8266SBalamuruhan S     /* OCC SRAM model */
11813a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1182f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
11833887d241SBalamuruhan S 
11843887d241SBalamuruhan S     /* HOMER */
1185f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip",
1186f2582acfSGreg Kurz                              &error_abort);
11873887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
11883887d241SBalamuruhan S                              &local_err);
11893887d241SBalamuruhan S     if (local_err) {
11903887d241SBalamuruhan S         error_propagate(errp, local_err);
11913887d241SBalamuruhan S         return;
11923887d241SBalamuruhan S     }
11938f092316SCédric Le Goater     /* Homer Xscom region */
11948f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
11958f092316SCédric Le Goater 
11968f092316SCédric Le Goater     /* Homer mmio region */
11973887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
11983887d241SBalamuruhan S                                 &chip8->homer.regs);
11999ae1329eSCédric Le Goater 
12009ae1329eSCédric Le Goater     /* PHB3 controllers */
12019ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
12029ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
12039ae1329eSCédric Le Goater         PnvPBCQState *pbcq = &phb->pbcq;
12049ae1329eSCédric Le Goater 
12059ae1329eSCédric Le Goater         object_property_set_int(OBJECT(phb), i, "index", &error_fatal);
12069ae1329eSCédric Le Goater         object_property_set_int(OBJECT(phb), chip->chip_id, "chip-id",
12079ae1329eSCédric Le Goater                                 &error_fatal);
1208*3c6ef471SMarkus Armbruster         sysbus_realize(SYS_BUS_DEVICE(phb), &local_err);
12099ae1329eSCédric Le Goater         if (local_err) {
12109ae1329eSCédric Le Goater             error_propagate(errp, local_err);
12119ae1329eSCédric Le Goater             return;
12129ae1329eSCédric Le Goater         }
12139ae1329eSCédric Le Goater 
12149ae1329eSCédric Le Goater         /* Populate the XSCOM address space. */
12159ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12169ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
12179ae1329eSCédric Le Goater                                 &pbcq->xscom_nest_regs);
12189ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12199ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
12209ae1329eSCédric Le Goater                                 &pbcq->xscom_pci_regs);
12219ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12229ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
12239ae1329eSCédric Le Goater                                 &pbcq->xscom_spci_regs);
12249ae1329eSCédric Le Goater     }
122577864267SCédric Le Goater }
122677864267SCédric Le Goater 
122770c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
122870c059e9SGreg Kurz {
122970c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
123070c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
123170c059e9SGreg Kurz }
123270c059e9SGreg Kurz 
1233e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1234e997040eSCédric Le Goater {
1235e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1236e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1237e997040eSCédric Le Goater 
1238e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1239397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
12409ae1329eSCédric Le Goater     k->num_phbs = 3;
1241631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1242d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1243d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12440990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
124585913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
124604026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1247eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1248d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1249c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
125070c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1251e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
125277864267SCédric Le Goater 
125377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
125477864267SCédric Le Goater                                     &k->parent_realize);
1255e997040eSCédric Le Goater }
1256e997040eSCédric Le Goater 
1257e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1258e997040eSCédric Le Goater {
1259e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1260e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1261e997040eSCédric Le Goater 
1262e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1263397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12649ae1329eSCédric Le Goater     k->num_phbs = 3;
1265631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1266d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1267d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12680990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
126985913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
127004026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1271eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1272d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1273c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
127470c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1275e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
127677864267SCédric Le Goater 
127777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
127877864267SCédric Le Goater                                     &k->parent_realize);
1279e997040eSCédric Le Goater }
1280e997040eSCédric Le Goater 
1281e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1282e997040eSCédric Le Goater {
1283e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1284e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1285e997040eSCédric Le Goater 
1286e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1287397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12889ae1329eSCédric Le Goater     k->num_phbs = 3;
1289631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1290d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1291d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12920990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
129385913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
129404026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1295eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1296d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1297c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
129870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1299e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
130077864267SCédric Le Goater 
130177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
130277864267SCédric Le Goater                                     &k->parent_realize);
130377864267SCédric Le Goater }
130477864267SCédric Le Goater 
130577864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
130677864267SCédric Le Goater {
13074f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13082dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13094f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13104f9924c4SBenjamin Herrenschmidt     int i;
13112dfa91a2SCédric Le Goater 
13129354eaafSMarkus Armbruster     sysbus_init_child_obj(obj, "xive", &chip9->xive, sizeof(chip9->xive),
13139354eaafSMarkus Armbruster                           TYPE_PNV_XIVE);
1314d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1315d2623129SMarkus Armbruster                               "xive-fabric");
1316c38536bcSCédric Le Goater 
13179fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
131815376c66SCédric Le Goater 
13199fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
13206598a70dSCédric Le Goater 
13219fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
13223887d241SBalamuruhan S 
13239fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
13244f9924c4SBenjamin Herrenschmidt 
13254f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13264f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
13279fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
13284f9924c4SBenjamin Herrenschmidt     }
13294f9924c4SBenjamin Herrenschmidt 
13304f9924c4SBenjamin Herrenschmidt     /*
13314f9924c4SBenjamin Herrenschmidt      * Number of PHBs is the chip default
13324f9924c4SBenjamin Herrenschmidt      */
13334f9924c4SBenjamin Herrenschmidt     chip->num_phbs = pcc->num_phbs;
133477864267SCédric Le Goater }
133577864267SCédric Le Goater 
13365dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
13375dad902cSCédric Le Goater {
13385dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
13395dad902cSCédric Le Goater     int i;
13405dad902cSCédric Le Goater 
13415dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
13425dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
13435dad902cSCédric Le Goater 
13445dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
13455dad902cSCédric Le Goater         char eq_name[32];
13465dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
13474fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
13485dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
13495dad902cSCédric Le Goater 
13505dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
13519fc7fc4dSMarkus Armbruster         object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
13529fc7fc4dSMarkus Armbruster                                            sizeof(*eq), TYPE_PNV_QUAD,
13539fc7fc4dSMarkus Armbruster                                            &error_fatal, NULL);
13545dad902cSCédric Le Goater 
13555dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
13565dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
13575dad902cSCédric Le Goater 
13585dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
13595dad902cSCédric Le Goater                                 &eq->xscom_regs);
13605dad902cSCédric Le Goater     }
13615dad902cSCédric Le Goater }
13625dad902cSCédric Le Goater 
13634f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
13644f9924c4SBenjamin Herrenschmidt {
13654f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
13664f9924c4SBenjamin Herrenschmidt     Error *local_err = NULL;
13674f9924c4SBenjamin Herrenschmidt     int i, j;
13684f9924c4SBenjamin Herrenschmidt     int phb_id = 0;
13694f9924c4SBenjamin Herrenschmidt 
13704f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13714f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
13724f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
13734f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
13744f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
13754f9924c4SBenjamin Herrenschmidt 
13764f9924c4SBenjamin Herrenschmidt         object_property_set_int(OBJECT(pec), i, "index", &error_fatal);
13774f9924c4SBenjamin Herrenschmidt         /*
13784f9924c4SBenjamin Herrenschmidt          * PEC0 -> 1 stack
13794f9924c4SBenjamin Herrenschmidt          * PEC1 -> 2 stacks
13804f9924c4SBenjamin Herrenschmidt          * PEC2 -> 3 stacks
13814f9924c4SBenjamin Herrenschmidt          */
13824f9924c4SBenjamin Herrenschmidt         object_property_set_int(OBJECT(pec), i + 1, "num-stacks",
13834f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
13844f9924c4SBenjamin Herrenschmidt         object_property_set_int(OBJECT(pec), chip->chip_id, "chip-id",
13854f9924c4SBenjamin Herrenschmidt                                  &error_fatal);
13864f9924c4SBenjamin Herrenschmidt         object_property_set_link(OBJECT(pec), OBJECT(get_system_memory()),
13874f9924c4SBenjamin Herrenschmidt                                  "system-memory", &error_abort);
13884f9924c4SBenjamin Herrenschmidt         object_property_set_bool(OBJECT(pec), true, "realized", &local_err);
13894f9924c4SBenjamin Herrenschmidt         if (local_err) {
13904f9924c4SBenjamin Herrenschmidt             error_propagate(errp, local_err);
13914f9924c4SBenjamin Herrenschmidt             return;
13924f9924c4SBenjamin Herrenschmidt         }
13934f9924c4SBenjamin Herrenschmidt 
13944f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
13954f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
13964f9924c4SBenjamin Herrenschmidt 
13974f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
13984f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
13994f9924c4SBenjamin Herrenschmidt 
14004f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs;
14014f9924c4SBenjamin Herrenschmidt              j++, phb_id++) {
14024f9924c4SBenjamin Herrenschmidt             PnvPhb4PecStack *stack = &pec->stacks[j];
14034f9924c4SBenjamin Herrenschmidt             Object *obj = OBJECT(&stack->phb);
14044f9924c4SBenjamin Herrenschmidt 
14054f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, phb_id, "index", &error_fatal);
14064f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, chip->chip_id, "chip-id",
14074f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14084f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, PNV_PHB4_VERSION, "version",
14094f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14104f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, PNV_PHB4_DEVICE_ID, "device-id",
14114f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14124f9924c4SBenjamin Herrenschmidt             object_property_set_link(obj, OBJECT(stack), "stack", &error_abort);
1413*3c6ef471SMarkus Armbruster             sysbus_realize(SYS_BUS_DEVICE(obj), &local_err);
14144f9924c4SBenjamin Herrenschmidt             if (local_err) {
14154f9924c4SBenjamin Herrenschmidt                 error_propagate(errp, local_err);
14164f9924c4SBenjamin Herrenschmidt                 return;
14174f9924c4SBenjamin Herrenschmidt             }
14184f9924c4SBenjamin Herrenschmidt 
14194f9924c4SBenjamin Herrenschmidt             /* Populate the XSCOM address space. */
14204f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14214f9924c4SBenjamin Herrenschmidt                                    pec_nest_base + 0x40 * (stack->stack_no + 1),
14224f9924c4SBenjamin Herrenschmidt                                    &stack->nest_regs_mr);
14234f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14244f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + 0x40 * (stack->stack_no + 1),
14254f9924c4SBenjamin Herrenschmidt                                     &stack->pci_regs_mr);
14264f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14274f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
14284f9924c4SBenjamin Herrenschmidt                                     0x40 * stack->stack_no,
14294f9924c4SBenjamin Herrenschmidt                                     &stack->phb_regs_mr);
14304f9924c4SBenjamin Herrenschmidt         }
14314f9924c4SBenjamin Herrenschmidt     }
14324f9924c4SBenjamin Herrenschmidt }
14334f9924c4SBenjamin Herrenschmidt 
143477864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
143577864267SCédric Le Goater {
143677864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14372dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14382dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1439c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
144077864267SCédric Le Goater     Error *local_err = NULL;
144177864267SCédric Le Goater 
1442709044fdSCédric Le Goater     /* XSCOM bridge is first */
1443709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1444709044fdSCédric Le Goater     if (local_err) {
1445709044fdSCédric Le Goater         error_propagate(errp, local_err);
1446709044fdSCédric Le Goater         return;
1447709044fdSCédric Le Goater     }
1448709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1449709044fdSCédric Le Goater 
145077864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
145177864267SCédric Le Goater     if (local_err) {
145277864267SCédric Le Goater         error_propagate(errp, local_err);
145377864267SCédric Le Goater         return;
145477864267SCédric Le Goater     }
14552dfa91a2SCédric Le Goater 
14565dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14575dad902cSCédric Le Goater     if (local_err) {
14585dad902cSCédric Le Goater         error_propagate(errp, local_err);
14595dad902cSCédric Le Goater         return;
14605dad902cSCédric Le Goater     }
14615dad902cSCédric Le Goater 
14622dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
14632dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
14642dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
14652dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
14662dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
14672dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
14682dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
14692dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
14702dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
14717ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
14727ae54cc3SGreg Kurz                              &error_abort);
14732dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
14742dfa91a2SCédric Le Goater                              &local_err);
14752dfa91a2SCédric Le Goater     if (local_err) {
14762dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
14772dfa91a2SCédric Le Goater         return;
14782dfa91a2SCédric Le Goater     }
14792dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
14802dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1481c38536bcSCédric Le Goater 
1482c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1483c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1484c38536bcSCédric Le Goater                             "bar", &error_fatal);
1485c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1486c38536bcSCédric Le Goater     if (local_err) {
1487c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1488c38536bcSCédric Le Goater         return;
1489c38536bcSCédric Le Goater     }
1490c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1491c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
149215376c66SCédric Le Goater 
149315376c66SCédric Le Goater     /* LPC */
1494b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1495b63f3893SGreg Kurz                              &error_abort);
149615376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
149715376c66SCédric Le Goater     if (local_err) {
149815376c66SCédric Le Goater         error_propagate(errp, local_err);
149915376c66SCédric Le Goater         return;
150015376c66SCédric Le Goater     }
150115376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
150215376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
150315376c66SCédric Le Goater 
150415376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
150515376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15066598a70dSCédric Le Goater 
15076598a70dSCédric Le Goater     /* Create the simplified OCC model */
1508ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1509ee3d2713SGreg Kurz                              &error_abort);
15106598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
15116598a70dSCédric Le Goater     if (local_err) {
15126598a70dSCédric Le Goater         error_propagate(errp, local_err);
15136598a70dSCédric Le Goater         return;
15146598a70dSCédric Le Goater     }
15156598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1516f3db8266SBalamuruhan S 
1517f3db8266SBalamuruhan S     /* OCC SRAM model */
15183a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1519f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15203887d241SBalamuruhan S 
15213887d241SBalamuruhan S     /* HOMER */
1522f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1523f2582acfSGreg Kurz                              &error_abort);
15243887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
15253887d241SBalamuruhan S                              &local_err);
15263887d241SBalamuruhan S     if (local_err) {
15273887d241SBalamuruhan S         error_propagate(errp, local_err);
15283887d241SBalamuruhan S         return;
15293887d241SBalamuruhan S     }
15308f092316SCédric Le Goater     /* Homer Xscom region */
15318f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15328f092316SCédric Le Goater 
15338f092316SCédric Le Goater     /* Homer mmio region */
15343887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15353887d241SBalamuruhan S                                 &chip9->homer.regs);
15364f9924c4SBenjamin Herrenschmidt 
15374f9924c4SBenjamin Herrenschmidt     /* PHBs */
15384f9924c4SBenjamin Herrenschmidt     pnv_chip_power9_phb_realize(chip, &local_err);
15394f9924c4SBenjamin Herrenschmidt     if (local_err) {
15404f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15414f9924c4SBenjamin Herrenschmidt         return;
15424f9924c4SBenjamin Herrenschmidt     }
1543e997040eSCédric Le Goater }
1544e997040eSCédric Le Goater 
154570c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
154670c059e9SGreg Kurz {
154770c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
154870c059e9SGreg Kurz     return addr >> 3;
154970c059e9SGreg Kurz }
155070c059e9SGreg Kurz 
1551e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1552e997040eSCédric Le Goater {
1553e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1554e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1555e997040eSCédric Le Goater 
155683028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1557397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1558631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1559d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1560d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15610990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
156285913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
156304026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1564eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1565d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1566c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
156770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1568e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
15694f9924c4SBenjamin Herrenschmidt     k->num_phbs = 6;
157077864267SCédric Le Goater 
157177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
157277864267SCédric Le Goater                                     &k->parent_realize);
1573e997040eSCédric Le Goater }
1574e997040eSCédric Le Goater 
15752b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
15762b548a42SCédric Le Goater {
15778b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
15788b50ce85SCédric Le Goater 
15799fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
15809fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
15812b548a42SCédric Le Goater }
15822b548a42SCédric Le Goater 
15832b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
15842b548a42SCédric Le Goater {
15852b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15862b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
15878b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
15882b548a42SCédric Le Goater     Error *local_err = NULL;
15892b548a42SCédric Le Goater 
15902b548a42SCédric Le Goater     /* XSCOM bridge is first */
15912b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
15922b548a42SCédric Le Goater     if (local_err) {
15932b548a42SCédric Le Goater         error_propagate(errp, local_err);
15942b548a42SCédric Le Goater         return;
15952b548a42SCédric Le Goater     }
15962b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
15972b548a42SCédric Le Goater 
15982b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
15992b548a42SCédric Le Goater     if (local_err) {
16002b548a42SCédric Le Goater         error_propagate(errp, local_err);
16012b548a42SCédric Le Goater         return;
16022b548a42SCédric Le Goater     }
16038b50ce85SCédric Le Goater 
16048b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
16058b50ce85SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip),
16068b50ce85SCédric Le Goater                             "bar", &error_fatal);
16078b50ce85SCédric Le Goater     object_property_set_bool(OBJECT(&chip10->psi), true, "realized",
16088b50ce85SCédric Le Goater                              &local_err);
16098b50ce85SCédric Le Goater     if (local_err) {
16108b50ce85SCédric Le Goater         error_propagate(errp, local_err);
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 */
16172661f6abSCédric Le Goater     object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi",
16182661f6abSCédric Le Goater                              &error_abort);
16192661f6abSCédric Le Goater     object_property_set_bool(OBJECT(&chip10->lpc), true, "realized",
16202661f6abSCédric Le Goater                              &local_err);
16212661f6abSCédric Le Goater     if (local_err) {
16222661f6abSCédric Le Goater         error_propagate(errp, local_err);
16232661f6abSCédric Le Goater         return;
16242661f6abSCédric Le Goater     }
16252661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
16262661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
16272661f6abSCédric Le Goater 
16282661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
16292661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
16302b548a42SCédric Le Goater }
16312b548a42SCédric Le Goater 
163270c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
163370c059e9SGreg Kurz {
163470c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
163570c059e9SGreg Kurz     return addr >> 3;
163670c059e9SGreg Kurz }
163770c059e9SGreg Kurz 
16382b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
16392b548a42SCédric Le Goater {
16402b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
16412b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16422b548a42SCédric Le Goater 
16432b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
16442b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
16452b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
16462b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
16472b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
16482b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
164985913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
16502b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
16512b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
16522b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1653c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
165470c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
16552b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
16562b548a42SCédric Le Goater 
16572b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
16582b548a42SCédric Le Goater                                     &k->parent_realize);
16592b548a42SCédric Le Goater }
16602b548a42SCédric Le Goater 
1661397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1662397a79e7SCédric Le Goater {
1663397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1664397a79e7SCédric Le Goater     int cores_max;
1665397a79e7SCédric Le Goater 
1666397a79e7SCédric Le Goater     /*
1667397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1668397a79e7SCédric Le Goater      * the chip class
1669397a79e7SCédric Le Goater      */
1670397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1671397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1672397a79e7SCédric Le Goater     }
1673397a79e7SCédric Le Goater 
1674397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1675397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1676397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1677397a79e7SCédric Le Goater                    chip->cores_mask);
1678397a79e7SCédric Le Goater         return;
1679397a79e7SCédric Le Goater     }
1680397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1681397a79e7SCédric Le Goater 
1682397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
168327d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1684397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1685397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1686397a79e7SCédric Le Goater                    cores_max);
1687397a79e7SCédric Le Goater         return;
1688397a79e7SCédric Le Goater     }
1689397a79e7SCédric Le Goater }
1690397a79e7SCédric Le Goater 
169151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1692e997040eSCédric Le Goater {
1693397a79e7SCédric Le Goater     Error *error = NULL;
1694d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
169540abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1696d2fd9612SCédric Le Goater     int i, core_hwid;
169708c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1698397a79e7SCédric Le Goater 
1699d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1700d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1701d2fd9612SCédric Le Goater         return;
1702d2fd9612SCédric Le Goater     }
1703d2fd9612SCédric Le Goater 
1704d2fd9612SCédric Le Goater     /* Cores */
1705397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1706397a79e7SCédric Le Goater     if (error) {
1707397a79e7SCédric Le Goater         error_propagate(errp, error);
1708397a79e7SCédric Le Goater         return;
1709397a79e7SCédric Le Goater     }
1710d2fd9612SCédric Le Goater 
17114fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1712d2fd9612SCédric Le Goater 
1713d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1714d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1715d2fd9612SCédric Le Goater         char core_name[32];
17164fa28f23SGreg Kurz         PnvCore *pnv_core;
1717c035851aSCédric Le Goater         uint64_t xscom_core_base;
1718d2fd9612SCédric Le Goater 
1719d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1720d2fd9612SCédric Le Goater             continue;
1721d2fd9612SCédric Le Goater         }
1722d2fd9612SCédric Le Goater 
17234fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
17244fa28f23SGreg Kurz 
1725d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1726d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
17274fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1728764f9b25SGreg Kurz         object_property_set_int(OBJECT(pnv_core), chip->nr_threads,
1729764f9b25SGreg Kurz                                 "nr-threads", &error_fatal);
1730d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1731d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1732d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1733d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1734d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
173508c3f3a7SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), pnv->fw_load_addr,
173608c3f3a7SCédric Le Goater                                 "hrmor", &error_fatal);
1737158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1738158e17a6SGreg Kurz                                  &error_abort);
1739d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1740d2fd9612SCédric Le Goater                                  &error_fatal);
174124ece072SCédric Le Goater 
174224ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1743c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1744c035851aSCédric Le Goater 
1745c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
17464fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1747d2fd9612SCédric Le Goater         i++;
1748d2fd9612SCédric Le Goater     }
174951c04728SCédric Le Goater }
175051c04728SCédric Le Goater 
175151c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
175251c04728SCédric Le Goater {
175351c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
175451c04728SCédric Le Goater     Error *error = NULL;
175551c04728SCédric Le Goater 
175651c04728SCédric Le Goater     /* Cores */
175751c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
175851c04728SCédric Le Goater     if (error) {
175951c04728SCédric Le Goater         error_propagate(errp, error);
176051c04728SCédric Le Goater         return;
176151c04728SCédric Le Goater     }
1762e997040eSCédric Le Goater }
1763e997040eSCédric Le Goater 
1764e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1765e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1766e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1767e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1768397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1769397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1770764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
17714f9924c4SBenjamin Herrenschmidt     DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
1772e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1773e997040eSCédric Le Goater };
1774e997040eSCédric Le Goater 
1775e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1776e997040eSCédric Le Goater {
1777e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1778e997040eSCédric Le Goater 
17799d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1780e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
17814f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1782e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1783e997040eSCédric Le Goater }
1784e997040eSCédric Le Goater 
1785119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1786119eaa9dSCédric Le Goater {
1787119eaa9dSCédric Le Goater     int i, j;
1788119eaa9dSCédric Le Goater 
1789119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1790119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1791119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1792119eaa9dSCédric Le Goater 
1793119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1794119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1795119eaa9dSCédric Le Goater                 return pc->threads[j];
1796119eaa9dSCédric Le Goater             }
1797119eaa9dSCédric Le Goater         }
1798119eaa9dSCédric Le Goater     }
1799119eaa9dSCédric Le Goater     return NULL;
1800119eaa9dSCédric Le Goater }
1801119eaa9dSCédric Le Goater 
180254f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
180354f59d78SCédric Le Goater {
1804b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18059ae1329eSCédric Le Goater     int i, j;
180654f59d78SCédric Le Goater 
180754f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18089ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
180977864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
181077864267SCédric Le Goater 
181177864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
181277864267SCédric Le Goater             return &chip8->psi.ics;
181354f59d78SCédric Le Goater         }
18149ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18159ae1329eSCédric Le Goater             if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
18169ae1329eSCédric Le Goater                 return &chip8->phbs[j].lsis;
18179ae1329eSCédric Le Goater             }
18189ae1329eSCédric Le Goater             if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
18199ae1329eSCédric Le Goater                 return ICS(&chip8->phbs[j].msis);
18209ae1329eSCédric Le Goater             }
18219ae1329eSCédric Le Goater         }
182254f59d78SCédric Le Goater     }
182354f59d78SCédric Le Goater     return NULL;
182454f59d78SCédric Le Goater }
182554f59d78SCédric Le Goater 
182654f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
182754f59d78SCédric Le Goater {
1828b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18299ae1329eSCédric Le Goater     int i, j;
183054f59d78SCédric Le Goater 
183154f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18329ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
183377864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
18349ae1329eSCédric Le Goater 
183577864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
18369ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18379ae1329eSCédric Le Goater             ics_resend(&chip8->phbs[j].lsis);
18389ae1329eSCédric Le Goater             ics_resend(ICS(&chip8->phbs[j].msis));
18399ae1329eSCédric Le Goater         }
184054f59d78SCédric Le Goater     }
184154f59d78SCédric Le Goater }
184254f59d78SCédric Le Goater 
184336fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
184436fc6f08SCédric Le Goater {
184536fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
184636fc6f08SCédric Le Goater 
1847956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
184836fc6f08SCédric Le Goater }
184936fc6f08SCédric Le Goater 
185047fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
185147fea43aSCédric Le Goater                                Monitor *mon)
185247fea43aSCédric Le Goater {
1853b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
185454f59d78SCédric Le Goater     int i;
185547fea43aSCédric Le Goater     CPUState *cs;
185647fea43aSCédric Le Goater 
185747fea43aSCédric Le Goater     CPU_FOREACH(cs) {
185847fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
185947fea43aSCédric Le Goater 
186085913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
186185913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
186285913070SGreg Kurz                                                            mon);
1863d8e4aad5SCédric Le Goater     }
186454f59d78SCédric Le Goater 
186554f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1866d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
186754f59d78SCédric Le Goater     }
186847fea43aSCédric Le Goater }
186947fea43aSCédric Le Goater 
1870c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1871c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1872c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1873c722579eSCédric Le Goater                          uint32_t logic_serv,
1874c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1875c722579eSCédric Le Goater {
1876c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1877c722579eSCédric Le Goater     int total_count = 0;
1878c722579eSCédric Le Goater     int i;
1879c722579eSCédric Le Goater 
1880c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1881c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1882c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1883c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1884c722579eSCédric Le Goater         int count;
1885c722579eSCédric Le Goater 
1886c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1887c722579eSCédric Le Goater                                priority, logic_serv, match);
1888c722579eSCédric Le Goater 
1889c722579eSCédric Le Goater         if (count < 0) {
1890c722579eSCédric Le Goater             return count;
1891c722579eSCédric Le Goater         }
1892c722579eSCédric Le Goater 
1893c722579eSCédric Le Goater         total_count += count;
1894c722579eSCédric Le Goater     }
1895c722579eSCédric Le Goater 
1896c722579eSCédric Le Goater     return total_count;
1897c722579eSCédric Le Goater }
1898c722579eSCédric Le Goater 
1899f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
19009e933f4aSBenjamin Herrenschmidt {
19019e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
190236fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1903d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1904d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1905f30c843cSCédric Le Goater 
1906f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1907f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1908f30c843cSCédric Le Goater 
1909f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1910f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1911f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1912d76f2da7SGreg Kurz 
1913d76f2da7SGreg Kurz     pmc->compat = compat;
1914d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1915f30c843cSCédric Le Goater }
1916f30c843cSCédric Le Goater 
1917f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1918f30c843cSCédric Le Goater {
1919f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1920c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1921d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1922d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1923f30c843cSCédric Le Goater 
1924f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1925f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1926c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1927f30c843cSCédric Le Goater 
1928f30c843cSCédric Le Goater     mc->alias = "powernv";
1929d76f2da7SGreg Kurz 
1930d76f2da7SGreg Kurz     pmc->compat = compat;
1931d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19327a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1933f30c843cSCédric Le Goater }
1934f30c843cSCédric Le Goater 
19352b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
19362b548a42SCédric Le Goater {
19372b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1938d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1939d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
19402b548a42SCédric Le Goater 
19412b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
19422b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
1943d76f2da7SGreg Kurz 
1944d76f2da7SGreg Kurz     pmc->compat = compat;
1945d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19467a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
19472b548a42SCédric Le Goater }
19482b548a42SCédric Le Goater 
194908c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
195008c3f3a7SCédric Le Goater {
195108c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
195208c3f3a7SCédric Le Goater 
195308c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
195408c3f3a7SCédric Le Goater }
195508c3f3a7SCédric Le Goater 
195608c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
195708c3f3a7SCédric Le Goater {
195808c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
195908c3f3a7SCédric Le Goater 
196008c3f3a7SCédric Le Goater     if (value) {
196108c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
196208c3f3a7SCédric Le Goater     }
196308c3f3a7SCédric Le Goater }
196408c3f3a7SCédric Le Goater 
196501b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
196601b552b0SNicholas Piggin {
196701b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
196801b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
196901b552b0SNicholas Piggin 
197001b552b0SNicholas Piggin     cpu_synchronize_state(cs);
197101b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
19720911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
197301b552b0SNicholas Piggin         /*
1974fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
1975fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
1976fe837714SNicholas Piggin          * (PPC_BIT(43)).
197701b552b0SNicholas Piggin          */
19780911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
1979fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
19800911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
198101b552b0SNicholas Piggin         }
1982fe837714SNicholas Piggin     } else {
1983fe837714SNicholas Piggin         /*
1984fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
1985fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
1986fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
1987fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
1988fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
1989fe837714SNicholas Piggin          */
19900911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
1991fe837714SNicholas Piggin     }
1992fe837714SNicholas Piggin }
199301b552b0SNicholas Piggin 
199401b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
199501b552b0SNicholas Piggin {
199601b552b0SNicholas Piggin     CPUState *cs;
199701b552b0SNicholas Piggin 
199801b552b0SNicholas Piggin     CPU_FOREACH(cs) {
199901b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
200001b552b0SNicholas Piggin     }
200101b552b0SNicholas Piggin }
200201b552b0SNicholas Piggin 
2003f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2004f30c843cSCédric Le Goater {
2005f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
200647fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
200701b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
20089e933f4aSBenjamin Herrenschmidt 
20099e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2010b168a138SCédric Le Goater     mc->init = pnv_init;
2011b168a138SCédric Le Goater     mc->reset = pnv_reset;
20129e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
201359b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
201459b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
20159e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
20169e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2017f1d18b0aSJoel Stanley     /*
2018f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2019f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2020f1d18b0aSJoel Stanley      */
2021f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
2022173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
202347fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
202401b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
202508c3f3a7SCédric Le Goater 
202608c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2027d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
202808c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
20297eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
20309e933f4aSBenjamin Herrenschmidt }
20319e933f4aSBenjamin Herrenschmidt 
203277864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2033beba5c0fSIgor Mammedov     {                                             \
2034beba5c0fSIgor Mammedov         .name          = type,                    \
2035beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
203677864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
203777864267SCédric Le Goater     }
203877864267SCédric Le Goater 
203977864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
204077864267SCédric Le Goater     {                                             \
204177864267SCédric Le Goater         .name          = type,                    \
204277864267SCédric Le Goater         .class_init    = class_initfn,            \
204377864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2044beba5c0fSIgor Mammedov     }
2045beba5c0fSIgor Mammedov 
20462b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
20472b548a42SCédric Le Goater     {                                              \
20482b548a42SCédric Le Goater         .name          = type,                     \
20492b548a42SCédric Le Goater         .class_init    = class_initfn,             \
20502b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
20512b548a42SCédric Le Goater     }
20522b548a42SCédric Le Goater 
2053beba5c0fSIgor Mammedov static const TypeInfo types[] = {
20541aba8716SCédric Le Goater     {
20552b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
20562b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20572b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
20582b548a42SCédric Le Goater     },
20592b548a42SCédric Le Goater     {
20601aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
20611aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20621aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2063c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2064c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2065c722579eSCédric Le Goater             { },
2066c722579eSCédric Le Goater         },
20671aba8716SCédric Le Goater     },
20681aba8716SCédric Le Goater     {
20691aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
20701aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20711aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
20721aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
20731aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
20741aba8716SCédric Le Goater             { },
20751aba8716SCédric Le Goater         },
20761aba8716SCédric Le Goater     },
2077beba5c0fSIgor Mammedov     {
2078b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
20799e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2080f30c843cSCédric Le Goater         .abstract       = true,
20819e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2082b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2083d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
208436fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
208547fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
208601b552b0SNicholas Piggin             { TYPE_NMI },
208736fc6f08SCédric Le Goater             { },
208836fc6f08SCédric Le Goater         },
2089beba5c0fSIgor Mammedov     },
2090beba5c0fSIgor Mammedov     {
2091beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2092beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2093beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2094beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2095beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2096beba5c0fSIgor Mammedov         .abstract      = true,
2097beba5c0fSIgor Mammedov     },
209877864267SCédric Le Goater 
209977864267SCédric Le Goater     /*
21002b548a42SCédric Le Goater      * P10 chip and variants
21012b548a42SCédric Le Goater      */
21022b548a42SCédric Le Goater     {
21032b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
21042b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
21052b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
21062b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
21072b548a42SCédric Le Goater     },
21082b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
21092b548a42SCédric Le Goater 
21102b548a42SCédric Le Goater     /*
211177864267SCédric Le Goater      * P9 chip and variants
211277864267SCédric Le Goater      */
211377864267SCédric Le Goater     {
211477864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
211577864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
211677864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
211777864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
211877864267SCédric Le Goater     },
211977864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
212077864267SCédric Le Goater 
212177864267SCédric Le Goater     /*
212277864267SCédric Le Goater      * P8 chip and variants
212377864267SCédric Le Goater      */
212477864267SCédric Le Goater     {
212577864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
212677864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
212777864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
212877864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
212977864267SCédric Le Goater     },
213077864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
213177864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
213277864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2133beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
21349e933f4aSBenjamin Herrenschmidt };
21359e933f4aSBenjamin Herrenschmidt 
2136beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2137