xref: /qemu/hw/ppc/pnv.c (revision 210aacb3)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
9f70c5966SChetan Pant  * version 2.1 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
212c65db5eSPaolo Bonzini #include "qemu/datadir.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
23dd7ef911SCédric Le Goater #include "qemu/cutils.h"
249e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
2538d2448aSGreg Kurz #include "sysemu/qtest.h"
269e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
279e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2871e8a915SMarkus Armbruster #include "sysemu/reset.h"
2954d31236SMarkus Armbruster #include "sysemu/runstate.h"
30d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
318d409261SCédric Le Goater #include "sysemu/device_tree.h"
3201b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
33fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
3901b552b0SNicholas Piggin #include "hw/nmi.h"
40e997040eSCédric Le Goater #include "qapi/visitor.h"
4147fea43aSCédric Le Goater #include "monitor/monitor.h"
4247fea43aSCédric Le Goater #include "hw/intc/intc.h"
43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h"
461f5d6b2aSDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h"
479e933f4aSBenjamin Herrenschmidt 
4836fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
49a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
50967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5135dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
52967b7523SCédric Le Goater 
533495b6b6SCédric Le Goater #include "hw/isa/isa.h"
543495b6b6SCédric Le Goater #include "hw/char/serial.h"
55bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
563495b6b6SCédric Le Goater 
579e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
589e933f4aSBenjamin Herrenschmidt 
59b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
609e933f4aSBenjamin Herrenschmidt 
619e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
629e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
6383fa6e2aSCédric Le Goater #define FW_MAX_SIZE             (16 * MiB)
649e933f4aSBenjamin Herrenschmidt 
659e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
6605ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE         (128 * MiB)
6705ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR        0x28000000
6805ce9b73SCédric Le Goater #define INITRD_MAX_SIZE         (128 * MiB)
699e933f4aSBenjamin Herrenschmidt 
7040abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7140abf43fSIgor Mammedov {
7240abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7340abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7440abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7540abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7640abf43fSIgor Mammedov     g_free(s);
7740abf43fSIgor Mammedov     return core_type;
7840abf43fSIgor Mammedov }
7940abf43fSIgor Mammedov 
809e933f4aSBenjamin Herrenschmidt /*
819e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
829e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
839e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
849e933f4aSBenjamin Herrenschmidt  */
859e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
869e933f4aSBenjamin Herrenschmidt 
879e933f4aSBenjamin Herrenschmidt /*
889e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
899e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
909e933f4aSBenjamin Herrenschmidt  * per chip.
919e933f4aSBenjamin Herrenschmidt  */
92b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
939e933f4aSBenjamin Herrenschmidt {
949e933f4aSBenjamin Herrenschmidt     char *mem_name;
959e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
969e933f4aSBenjamin Herrenschmidt     int off;
979e933f4aSBenjamin Herrenschmidt 
989e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
999e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
1009e933f4aSBenjamin Herrenschmidt 
1019e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1029e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1039e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1049e933f4aSBenjamin Herrenschmidt 
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1069e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1079e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1089e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1099e933f4aSBenjamin Herrenschmidt }
1109e933f4aSBenjamin Herrenschmidt 
111d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
112d2fd9612SCédric Le Goater {
113d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
114d2fd9612SCédric Le Goater 
115d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
116a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
117d2fd9612SCédric Le Goater         if (cpus_offset) {
118d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
119d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
120d2fd9612SCédric Le Goater         }
121d2fd9612SCédric Le Goater     }
122d2fd9612SCédric Le Goater     _FDT(cpus_offset);
123d2fd9612SCédric Le Goater     return cpus_offset;
124d2fd9612SCédric Le Goater }
125d2fd9612SCédric Le Goater 
126d2fd9612SCédric Le Goater /*
127d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
128d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
129d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
130d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
131d2fd9612SCédric Le Goater  * servers.
132d2fd9612SCédric Le Goater  */
133b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
134d2fd9612SCédric Le Goater {
13508304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13608304a86SDavid Gibson     CPUState *cs = CPU(cpu);
137d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1388bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
139d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
140d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
141d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
142d2fd9612SCédric Le Goater     int i;
143d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
144d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
145d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
146d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
147d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
148d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
149d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
150d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
151d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
152d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
153d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
154d2fd9612SCédric Le Goater     int offset;
155d2fd9612SCédric Le Goater     char *nodename;
156d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
157d2fd9612SCédric Le Goater 
158d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
159d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
160d2fd9612SCédric Le Goater     _FDT(offset);
161d2fd9612SCédric Le Goater     g_free(nodename);
162d2fd9612SCédric Le Goater 
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
164d2fd9612SCédric Le Goater 
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
168d2fd9612SCédric Le Goater 
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
171d2fd9612SCédric Le Goater                             env->dcache_line_size)));
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
173d2fd9612SCédric Le Goater                             env->dcache_line_size)));
174d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
175d2fd9612SCédric Le Goater                             env->icache_line_size)));
176d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
177d2fd9612SCédric Le Goater                             env->icache_line_size)));
178d2fd9612SCédric Le Goater 
179d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
180d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
181d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
182d2fd9612SCédric Le Goater     } else {
1833dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
184d2fd9612SCédric Le Goater     }
185d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
186d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
187d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
188d2fd9612SCédric Le Goater     } else {
1893dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
190d2fd9612SCédric Le Goater     }
191d2fd9612SCédric Le Goater 
192d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19459b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19559b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
196d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
197d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
198d2fd9612SCédric Le Goater 
19903282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
200d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
201d2fd9612SCédric Le Goater     }
202d2fd9612SCédric Le Goater 
20358969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
204d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
205d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
206d2fd9612SCédric Le Goater     }
207d2fd9612SCédric Le Goater 
20859b7c1c2SBalamuruhan S     /*
20959b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
210d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
211d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21259b7c1c2SBalamuruhan S      *   2               == VSX available
21359b7c1c2SBalamuruhan S      */
214d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
215d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
216d2fd9612SCédric Le Goater 
217d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
218d2fd9612SCédric Le Goater     }
219d2fd9612SCédric Le Goater 
22059b7c1c2SBalamuruhan S     /*
22159b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
222d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22359b7c1c2SBalamuruhan S      *   1               == DFP available
22459b7c1c2SBalamuruhan S      */
225d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
226d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
227d2fd9612SCédric Le Goater     }
228d2fd9612SCédric Le Goater 
229644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
230d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
231d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
232d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
233d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
234d2fd9612SCédric Le Goater     }
235d2fd9612SCédric Le Goater 
236d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
237d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
238d2fd9612SCédric Le Goater 
239d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
240d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
241d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
242d2fd9612SCédric Le Goater     }
243d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
244d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
245d2fd9612SCédric Le Goater }
246d2fd9612SCédric Le Goater 
247b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
248bf5615e7SCédric Le Goater                        uint32_t nr_threads)
249bf5615e7SCédric Le Goater {
250bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
251bf5615e7SCédric Le Goater     char *name;
252bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
253bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
254bf5615e7SCédric Le Goater     uint64_t *reg;
255bf5615e7SCédric Le Goater     int offset;
256bf5615e7SCédric Le Goater 
257bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
258bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
259bf5615e7SCédric Le Goater 
260bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
261bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
262bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
263bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
264bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
265bf5615e7SCédric Le Goater     }
266bf5615e7SCédric Le Goater 
267bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
268bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
269bf5615e7SCédric Le Goater     _FDT(offset);
270bf5615e7SCédric Le Goater     g_free(name);
271bf5615e7SCédric Le Goater 
272bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
275bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
278bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
279bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
280bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
281bf5615e7SCédric Le Goater     g_free(reg);
282bf5615e7SCédric Le Goater }
283bf5615e7SCédric Le Goater 
284eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
285e997040eSCédric Le Goater {
286c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
287d2fd9612SCédric Le Goater     int i;
288d2fd9612SCédric Le Goater 
2893f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2903f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
291c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
292c396c58aSGreg Kurz                  compat, sizeof(compat));
293967b7523SCédric Le Goater 
294d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2954fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
296d2fd9612SCédric Le Goater 
297b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
298bf5615e7SCédric Le Goater 
299bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
300b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
301d2fd9612SCédric Le Goater     }
302d2fd9612SCédric Le Goater 
303e997040eSCédric Le Goater     if (chip->ram_size) {
304b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
305e997040eSCédric Le Goater     }
306e997040eSCédric Le Goater }
307e997040eSCédric Le Goater 
308eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
309eb859a27SCédric Le Goater {
310c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
311eb859a27SCédric Le Goater     int i;
312eb859a27SCédric Le Goater 
3133f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3143f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
315c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
316c396c58aSGreg Kurz                  compat, sizeof(compat));
317eb859a27SCédric Le Goater 
318eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3194fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
320eb859a27SCédric Le Goater 
321eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
322eb859a27SCédric Le Goater     }
323eb859a27SCédric Le Goater 
324eb859a27SCédric Le Goater     if (chip->ram_size) {
325eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
326eb859a27SCédric Le Goater     }
32715376c66SCédric Le Goater 
3282661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
329eb859a27SCédric Le Goater }
330eb859a27SCédric Le Goater 
3312b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3322b548a42SCédric Le Goater {
333c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3342b548a42SCédric Le Goater     int i;
3352b548a42SCédric Le Goater 
3363f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3373f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
338c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
339c396c58aSGreg Kurz                  compat, sizeof(compat));
3402b548a42SCédric Le Goater 
3412b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3422b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3432b548a42SCédric Le Goater 
3442b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3452b548a42SCédric Le Goater     }
3462b548a42SCédric Le Goater 
3472b548a42SCédric Le Goater     if (chip->ram_size) {
3482b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3492b548a42SCédric Le Goater     }
3502661f6abSCédric Le Goater 
3512661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3522b548a42SCédric Le Goater }
3532b548a42SCédric Le Goater 
354b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
355c5ffdcaeSCédric Le Goater {
356c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
357c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
358c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
359c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
360c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
361c5ffdcaeSCédric Le Goater     };
362c5ffdcaeSCédric Le Goater     char *name;
363c5ffdcaeSCédric Le Goater     int node;
364c5ffdcaeSCédric Le Goater 
365c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
366c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
367c5ffdcaeSCédric Le Goater     _FDT(node);
368c5ffdcaeSCédric Le Goater     g_free(name);
369c5ffdcaeSCédric Le Goater 
370c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
371c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
372c5ffdcaeSCédric Le Goater }
373c5ffdcaeSCédric Le Goater 
374b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
375cb228f5aSCédric Le Goater {
376cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
377cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
378cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
379cb228f5aSCédric Le Goater         cpu_to_be32(1),
380cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
381cb228f5aSCédric Le Goater         cpu_to_be32(8)
382cb228f5aSCédric Le Goater     };
383632fc0b3SBernhard Beschow     uint32_t irq;
384cb228f5aSCédric Le Goater     char *name;
385cb228f5aSCédric Le Goater     int node;
386cb228f5aSCédric Le Goater 
387632fc0b3SBernhard Beschow     irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
388632fc0b3SBernhard Beschow 
389cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
390cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
391cb228f5aSCédric Le Goater     _FDT(node);
392cb228f5aSCédric Le Goater     g_free(name);
393cb228f5aSCédric Le Goater 
394cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
395cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
396cb228f5aSCédric Le Goater                       sizeof(compatible))));
397cb228f5aSCédric Le Goater 
398cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
399cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
400632fc0b3SBernhard Beschow     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
401cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
402cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
403cb228f5aSCédric Le Goater 
404cb228f5aSCédric Le Goater     /* This is needed by Linux */
405cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
406cb228f5aSCédric Le Goater }
407cb228f5aSCédric Le Goater 
408b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40904f6c8b2SCédric Le Goater {
41004f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
41104f6c8b2SCédric Le Goater     uint32_t io_base;
41204f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
41304f6c8b2SCédric Le Goater         cpu_to_be32(1),
41404f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41504f6c8b2SCédric Le Goater         cpu_to_be32(3)
41604f6c8b2SCédric Le Goater     };
41704f6c8b2SCédric Le Goater     uint32_t irq;
41804f6c8b2SCédric Le Goater     char *name;
41904f6c8b2SCédric Le Goater     int node;
42004f6c8b2SCédric Le Goater 
42104f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
42204f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
42304f6c8b2SCédric Le Goater 
42404f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42504f6c8b2SCédric Le Goater 
42604f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42704f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42804f6c8b2SCédric Le Goater     _FDT(node);
42904f6c8b2SCédric Le Goater     g_free(name);
43004f6c8b2SCédric Le Goater 
4317032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4327032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4337032d92aSCédric Le Goater                       sizeof(compatible))));
43404f6c8b2SCédric Le Goater 
43504f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43704f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43804f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43904f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
44004f6c8b2SCédric Le Goater }
44104f6c8b2SCédric Le Goater 
442e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
443e7a3fee3SCédric Le Goater     void *fdt;
444e7a3fee3SCédric Le Goater     int offset;
445e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
446e7a3fee3SCédric Le Goater 
447b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
448e7a3fee3SCédric Le Goater {
449c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
450c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
451c5ffdcaeSCédric Le Goater 
452c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
453b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
454cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
455b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45604f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
457b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
458c5ffdcaeSCédric Le Goater     } else {
459c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
460c5ffdcaeSCédric Le Goater                      d->ioport_id);
461c5ffdcaeSCédric Le Goater     }
462c5ffdcaeSCédric Le Goater 
463e7a3fee3SCédric Le Goater     return 0;
464e7a3fee3SCédric Le Goater }
465e7a3fee3SCédric Le Goater 
46659b7c1c2SBalamuruhan S /*
46759b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
468bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
469bb7ab95cSCédric Le Goater  */
470bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
471bb7ab95cSCédric Le Goater {
47264d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
473e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
474e7a3fee3SCédric Le Goater         .fdt = fdt,
475bb7ab95cSCédric Le Goater         .offset = isa_offset,
476e7a3fee3SCédric Le Goater     };
477f47a08d1SCédric Le Goater     uint32_t phandle;
478e7a3fee3SCédric Le Goater 
479bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
480bb7ab95cSCédric Le Goater 
481f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
482f47a08d1SCédric Le Goater     assert(phandle > 0);
483f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
484f47a08d1SCédric Le Goater 
48559b7c1c2SBalamuruhan S     /*
48659b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48759b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48859b7c1c2SBalamuruhan S      */
489bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
490bb7ab95cSCédric Le Goater                        &args);
491e7a3fee3SCédric Le Goater }
492e7a3fee3SCédric Le Goater 
4937a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
494e5694793SCédric Le Goater {
495e5694793SCédric Le Goater     int off;
496e5694793SCédric Le Goater 
497e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
498e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
499e5694793SCédric Le Goater 
500e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
501e5694793SCédric Le Goater }
502e5694793SCédric Le Goater 
503b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5049e933f4aSBenjamin Herrenschmidt {
505d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
506b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5079e933f4aSBenjamin Herrenschmidt     void *fdt;
5089e933f4aSBenjamin Herrenschmidt     char *buf;
5099e933f4aSBenjamin Herrenschmidt     int off;
510e997040eSCédric Le Goater     int i;
5119e933f4aSBenjamin Herrenschmidt 
5129e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5139e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5149e933f4aSBenjamin Herrenschmidt 
515ccb099b3SCédric Le Goater     /* /qemu node */
516ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
517ccb099b3SCédric Le Goater 
5189e933f4aSBenjamin Herrenschmidt     /* Root node */
5199e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5209e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5219e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5229e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
523d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5249e933f4aSBenjamin Herrenschmidt 
5259e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5269e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5279e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
528bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
5299e933f4aSBenjamin Herrenschmidt     }
5309e933f4aSBenjamin Herrenschmidt     g_free(buf);
5319e933f4aSBenjamin Herrenschmidt 
5329e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5339e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5349e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5359e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5369e933f4aSBenjamin Herrenschmidt     }
5379e933f4aSBenjamin Herrenschmidt 
5389e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5399e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5409e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5419e933f4aSBenjamin Herrenschmidt 
5429e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5439e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5449e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5459e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5469e933f4aSBenjamin Herrenschmidt     }
5479e933f4aSBenjamin Herrenschmidt 
548e997040eSCédric Le Goater     /* Populate device tree for each chip */
549e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
550eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
551e997040eSCédric Le Goater     }
552e7a3fee3SCédric Le Goater 
553e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
554bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
555aeaef83dSCédric Le Goater 
556aeaef83dSCédric Le Goater     if (pnv->bmc) {
557b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
558aeaef83dSCédric Le Goater     }
559aeaef83dSCédric Le Goater 
5607a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5617a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5627a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
563e5694793SCédric Le Goater     }
564e5694793SCédric Le Goater 
5659e933f4aSBenjamin Herrenschmidt     return fdt;
5669e933f4aSBenjamin Herrenschmidt }
5679e933f4aSBenjamin Herrenschmidt 
568bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
569bce0b691SCédric Le Goater {
5708f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
571bce0b691SCédric Le Goater 
572bce0b691SCédric Le Goater     if (pnv->bmc) {
573bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
574bce0b691SCédric Le Goater     }
575bce0b691SCédric Le Goater }
576bce0b691SCédric Le Goater 
577a0628599SLike Xu static void pnv_reset(MachineState *machine)
5789e933f4aSBenjamin Herrenschmidt {
57925f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
58025f3170bSCédric Le Goater     IPMIBmc *bmc;
5819e933f4aSBenjamin Herrenschmidt     void *fdt;
5829e933f4aSBenjamin Herrenschmidt 
5839e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5849e933f4aSBenjamin Herrenschmidt 
58525f3170bSCédric Le Goater     /*
58625f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
58725f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
58825f3170bSCédric Le Goater      * line.
58925f3170bSCédric Le Goater      */
59025f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
59125f3170bSCédric Le Goater     if (!pnv->bmc) {
59225f3170bSCédric Le Goater         if (!bmc) {
59338d2448aSGreg Kurz             if (!qtest_enabled()) {
59425f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
59525f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59625f3170bSCédric Le Goater                             "to define one");
59738d2448aSGreg Kurz             }
59825f3170bSCédric Le Goater         } else {
59925f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
60025f3170bSCédric Le Goater             pnv->bmc = bmc;
60125f3170bSCédric Le Goater         }
60225f3170bSCédric Le Goater     }
60325f3170bSCédric Le Goater 
604b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6059e933f4aSBenjamin Herrenschmidt 
6069e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6079e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6089e933f4aSBenjamin Herrenschmidt 
6098d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6109e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
611b2fb7a43SPan Nengyuan 
612b2fb7a43SPan Nengyuan     g_free(fdt);
6139e933f4aSBenjamin Herrenschmidt }
6149e933f4aSBenjamin Herrenschmidt 
61504026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6163495b6b6SCédric Le Goater {
61777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
618c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
619c05aa140SCédric Le Goater 
620c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
62177864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
62204026890SCédric Le Goater }
6233495b6b6SCédric Le Goater 
62404026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
62504026890SCédric Le Goater {
62677864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
627c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
628c05aa140SCédric Le Goater 
629c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
63077864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
63104026890SCédric Le Goater }
6323495b6b6SCédric Le Goater 
63304026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
63404026890SCédric Le Goater {
63515376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
636c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
637c05aa140SCédric Le Goater 
638c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq);
63915376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
64004026890SCédric Le Goater }
6413495b6b6SCédric Le Goater 
6422b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6432b548a42SCédric Le Goater {
6442661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
645c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
646c05aa140SCédric Le Goater 
647c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq);
6482661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6492b548a42SCédric Le Goater }
6502b548a42SCédric Le Goater 
65104026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
65204026890SCédric Le Goater {
65304026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6543495b6b6SCédric Le Goater }
6553495b6b6SCédric Le Goater 
656d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
657d8e4aad5SCédric Le Goater {
658d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6598a69bca7SDaniel Henrique Barboza     int i;
660d8e4aad5SCédric Le Goater 
661d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6628a69bca7SDaniel Henrique Barboza 
6638a69bca7SDaniel Henrique Barboza     for (i = 0; i < chip8->num_phbs; i++) {
6641f5d6b2aSDaniel Henrique Barboza         PnvPHB *phb = &chip8->phbs[i];
6651f5d6b2aSDaniel Henrique Barboza         PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
6668a69bca7SDaniel Henrique Barboza 
6678a69bca7SDaniel Henrique Barboza         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
6688a69bca7SDaniel Henrique Barboza         ics_pic_print_info(&phb3->lsis, mon);
6698a69bca7SDaniel Henrique Barboza     }
670d8e4aad5SCédric Le Goater }
671d8e4aad5SCédric Le Goater 
6720e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
6730e6232bcSCédric Le Goater {
6740e6232bcSCédric Le Goater     Monitor *mon = opaque;
675210aacb3SDaniel Henrique Barboza     PnvPHB *phb =  (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
6760e6232bcSCédric Le Goater 
677210aacb3SDaniel Henrique Barboza     if (!phb) {
678210aacb3SDaniel Henrique Barboza         return 0;
6790e6232bcSCédric Le Goater     }
680210aacb3SDaniel Henrique Barboza 
681210aacb3SDaniel Henrique Barboza     pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon);
682210aacb3SDaniel Henrique Barboza 
6830e6232bcSCédric Le Goater     return 0;
6840e6232bcSCédric Le Goater }
6850e6232bcSCédric Le Goater 
686d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
687d8e4aad5SCédric Le Goater {
688d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
689d8e4aad5SCédric Le Goater 
690d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
691c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6924f9924c4SBenjamin Herrenschmidt 
6930e6232bcSCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
6940e6232bcSCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
695d8e4aad5SCédric Le Goater }
696d8e4aad5SCédric Le Goater 
697c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
698c4b2c40cSGreg Kurz                                                 uint32_t core_id)
699c4b2c40cSGreg Kurz {
700c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
701c4b2c40cSGreg Kurz }
702c4b2c40cSGreg Kurz 
703c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
704c4b2c40cSGreg Kurz                                                 uint32_t core_id)
705c4b2c40cSGreg Kurz {
706c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
707c4b2c40cSGreg Kurz }
708c4b2c40cSGreg Kurz 
709c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
710c4b2c40cSGreg Kurz                                                  uint32_t core_id)
711c4b2c40cSGreg Kurz {
712c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
713c4b2c40cSGreg Kurz }
714c4b2c40cSGreg Kurz 
715f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
716f30c843cSCédric Le Goater {
717f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
718f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
719f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
720f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
721f30c843cSCédric Le Goater 
72221d3a78eSNicholas Piggin     return ppc_default->pvr_match(ppc_default, ppc->pvr, false);
723f30c843cSCédric Le Goater }
724f30c843cSCédric Le Goater 
725e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
726e2392d43SCédric Le Goater {
727c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
728e2392d43SCédric Le Goater 
7295325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7305325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
731c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
732e2392d43SCédric Le Goater }
733e2392d43SCédric Le Goater 
7342b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7352b548a42SCédric Le Goater {
7368b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7378b50ce85SCédric Le Goater 
738da71b7e3SCédric Le Goater     pnv_xive2_pic_print_info(&chip10->xive, mon);
7398b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
740623575e1SCédric Le Goater 
741623575e1SCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
742623575e1SCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
7432b548a42SCédric Le Goater }
7442b548a42SCédric Le Goater 
745458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
746458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
747458c6f01SCédric Le Goater {
748458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
749458c6f01SCédric Le Goater     uint64_t ram_per_chip;
750458c6f01SCédric Le Goater 
751458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
752458c6f01SCédric Le Goater 
753458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
754458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
755458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
756458c6f01SCédric Le Goater     }
757458c6f01SCédric Le Goater 
758f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
759f640afecSCédric Le Goater 
760458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
761458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
762458c6f01SCédric Le Goater }
763458c6f01SCédric Le Goater 
764b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7659e933f4aSBenjamin Herrenschmidt {
766cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
767b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
768f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7699e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7709e933f4aSBenjamin Herrenschmidt     long fw_size;
771458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
772e997040eSCédric Le Goater     int i;
773e997040eSCédric Le Goater     char *chip_typename;
77435dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
77535dde576SCédric Le Goater     DeviceState *dev;
7769e933f4aSBenjamin Herrenschmidt 
777ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
778ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
779ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
780ebe6c3faSDaniel Henrique Barboza     }
781ebe6c3faSDaniel Henrique Barboza 
7829e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
783dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
784dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
785dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
786dd7ef911SCédric Le Goater         g_free(sz);
787dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
7889e933f4aSBenjamin Herrenschmidt     }
789173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7909e933f4aSBenjamin Herrenschmidt 
79135dde576SCédric Le Goater     /*
79235dde576SCédric Le Goater      * Create our simple PNOR device
79335dde576SCédric Le Goater      */
7943e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
79535dde576SCédric Le Goater     if (pnor) {
796934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
79735dde576SCédric Le Goater     }
7983c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
79935dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
80035dde576SCédric Le Goater 
8019e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
8029e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
80315fcedb2SCédric Le Goater     if (!fw_filename) {
80415fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
80515fcedb2SCédric Le Goater         exit(1);
80615fcedb2SCédric Le Goater     }
8079e933f4aSBenjamin Herrenschmidt 
80808c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
8099e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
81015fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
8119e933f4aSBenjamin Herrenschmidt         exit(1);
8129e933f4aSBenjamin Herrenschmidt     }
8139e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8149e933f4aSBenjamin Herrenschmidt 
8159e933f4aSBenjamin Herrenschmidt     /* load kernel */
8169e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8179e933f4aSBenjamin Herrenschmidt         long kernel_size;
8189e933f4aSBenjamin Herrenschmidt 
8199e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
820b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8219e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
822802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8239e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8249e933f4aSBenjamin Herrenschmidt             exit(1);
8259e933f4aSBenjamin Herrenschmidt         }
8269e933f4aSBenjamin Herrenschmidt     }
8279e933f4aSBenjamin Herrenschmidt 
8289e933f4aSBenjamin Herrenschmidt     /* load initrd */
8299e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
8309e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
8319e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
832584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
8339e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
834802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
8359e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
8369e933f4aSBenjamin Herrenschmidt             exit(1);
8379e933f4aSBenjamin Herrenschmidt         }
8389e933f4aSBenjamin Herrenschmidt     }
839e997040eSCédric Le Goater 
8404f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8414f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8424f9924c4SBenjamin Herrenschmidt 
843f30c843cSCédric Le Goater     /*
844f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
845f30c843cSCédric Le Goater      * default.
846f30c843cSCédric Le Goater      */
847f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
848f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
849f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
850f30c843cSCédric Le Goater         exit(1);
851f30c843cSCédric Le Goater     }
852f30c843cSCédric Le Goater 
853e997040eSCédric Le Goater     /* Create the processor chips */
8544a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8557fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8564a12c699SIgor Mammedov                                     i, machine->cpu_type);
857e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
858f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
859f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
860e997040eSCédric Le Goater         exit(1);
861e997040eSCédric Le Goater     }
862e997040eSCédric Le Goater 
863e44acde2SGreg Kurz     pnv->num_chips =
864e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
865e44acde2SGreg Kurz     /*
866e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
867e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
868e44acde2SGreg Kurz      */
869ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
870e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
871ab17a3feSCédric Le Goater         error_printf(
872ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
873e44acde2SGreg Kurz         exit(1);
874e44acde2SGreg Kurz     }
875e44acde2SGreg Kurz 
876e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
877e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
878e997040eSCédric Le Goater         char chip_name[32];
879df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
8800e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
881e997040eSCédric Le Goater 
882e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
883e997040eSCédric Le Goater 
884458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
885458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
886e997040eSCédric Le Goater                                 &error_fatal);
887458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
888458c6f01SCédric Le Goater                                 &error_fatal);
889458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
890e997040eSCédric Le Goater 
8910e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
892d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
8930e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
8945325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
8955325cc34SMarkus Armbruster                                 &error_fatal);
8965325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
8975325cc34SMarkus Armbruster                                 &error_fatal);
898245cdb7fSCédric Le Goater         /*
899245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
900245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
901245cdb7fSCédric Le Goater          */
902245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
9035325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
904245cdb7fSCédric Le Goater         }
905d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
9065325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
907d1214b81SGreg Kurz                                      &error_abort);
908d1214b81SGreg Kurz         }
9093c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
910e997040eSCédric Le Goater     }
911e997040eSCédric Le Goater     g_free(chip_typename);
9123495b6b6SCédric Le Goater 
9133495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
91404026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9153495b6b6SCédric Le Goater 
9163495b6b6SCédric Le Goater     /* Create serial port */
917def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9183495b6b6SCédric Le Goater 
9193495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9206c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
921bce0b691SCédric Le Goater 
92225f3170bSCédric Le Goater     /*
92325f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
92425f3170bSCédric Le Goater      * communication with the BMC
92525f3170bSCédric Le Goater      */
92625f3170bSCédric Le Goater     if (defaults_enabled()) {
92725f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
928e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
92925f3170bSCédric Le Goater     }
930e2392d43SCédric Le Goater 
93159b7c1c2SBalamuruhan S     /*
932032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
933032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
934032c226bSCédric Le Goater      * map it always for now.
935032c226bSCédric Le Goater      */
936032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
937032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
938032c226bSCédric Le Goater 
939032c226bSCédric Le Goater     /*
94059b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
94159b7c1c2SBalamuruhan S      * host to powerdown
94259b7c1c2SBalamuruhan S      */
943bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
944bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
945e997040eSCédric Le Goater }
946e997040eSCédric Le Goater 
947631adaffSCédric Le Goater /*
948631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
949631adaffSCédric Le Goater  *   22:24  Chip ID
950631adaffSCédric Le Goater  *   25:28  Core number
951631adaffSCédric Le Goater  *   29:31  Thread ID
952631adaffSCédric Le Goater  */
953631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
954631adaffSCédric Le Goater {
955631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
956631adaffSCédric Le Goater }
957631adaffSCédric Le Goater 
9588fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
959d35aefa9SCédric Le Goater                                         Error **errp)
960d35aefa9SCédric Le Goater {
961245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9628fa1f4efSCédric Le Goater     Error *local_err = NULL;
9638fa1f4efSCédric Le Goater     Object *obj;
9648907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9658fa1f4efSCédric Le Goater 
966245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9678fa1f4efSCédric Le Goater     if (local_err) {
9688fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9698fa1f4efSCédric Le Goater         return;
9708fa1f4efSCédric Le Goater     }
9718fa1f4efSCédric Le Goater 
972956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
973d35aefa9SCédric Le Goater }
974d35aefa9SCédric Le Goater 
9750990ce6aSGreg Kurz 
976d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
977d49e8a9bSCédric Le Goater {
978d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
979d49e8a9bSCédric Le Goater 
980d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
981d49e8a9bSCédric Le Goater }
982d49e8a9bSCédric Le Goater 
9830990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9840990ce6aSGreg Kurz {
9850990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9860990ce6aSGreg Kurz 
9870990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9880990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9890990ce6aSGreg Kurz }
9900990ce6aSGreg Kurz 
99185913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
99285913070SGreg Kurz                                             Monitor *mon)
99385913070SGreg Kurz {
99485913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
99585913070SGreg Kurz }
99685913070SGreg Kurz 
997631adaffSCédric Le Goater /*
998631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
999631adaffSCédric Le Goater  *   49:52  Node ID
1000631adaffSCédric Le Goater  *   53:55  Chip ID
1001631adaffSCédric Le Goater  *   56     Reserved - Read as zero
1002631adaffSCédric Le Goater  *   57:61  Core number
1003631adaffSCédric Le Goater  *   62:63  Thread ID
1004631adaffSCédric Le Goater  *
1005631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
1006631adaffSCédric Le Goater  */
1007631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
1008631adaffSCédric Le Goater {
1009631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
1010631adaffSCédric Le Goater }
1011631adaffSCédric Le Goater 
10122b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10132b548a42SCédric Le Goater {
10142b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10152b548a42SCédric Le Goater }
10162b548a42SCédric Le Goater 
10178fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1018d35aefa9SCédric Le Goater                                         Error **errp)
1019d35aefa9SCédric Le Goater {
10202dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10212dfa91a2SCédric Le Goater     Error *local_err = NULL;
10222dfa91a2SCédric Le Goater     Object *obj;
10232dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10242dfa91a2SCédric Le Goater 
10252dfa91a2SCédric Le Goater     /*
10262dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
10272dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
10282dfa91a2SCédric Le Goater      * only used at runtime.
10292dfa91a2SCédric Le Goater      */
103047950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
103147950946SCédric Le Goater                            &local_err);
10322dfa91a2SCédric Le Goater     if (local_err) {
10332dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
10348fa1f4efSCédric Le Goater         return;
1035d35aefa9SCédric Le Goater     }
1036d35aefa9SCédric Le Goater 
10372dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10382dfa91a2SCédric Le Goater }
10392dfa91a2SCédric Le Goater 
1040d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1041d49e8a9bSCédric Le Goater {
1042d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1043d49e8a9bSCédric Le Goater 
1044d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1045d49e8a9bSCédric Le Goater }
1046d49e8a9bSCédric Le Goater 
10470990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10480990ce6aSGreg Kurz {
10490990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10500990ce6aSGreg Kurz 
10510990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10520990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10530990ce6aSGreg Kurz }
10540990ce6aSGreg Kurz 
105585913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
105685913070SGreg Kurz                                             Monitor *mon)
105785913070SGreg Kurz {
105885913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
105985913070SGreg Kurz }
106085913070SGreg Kurz 
10612b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10622b548a42SCédric Le Goater                                         Error **errp)
10632b548a42SCédric Le Goater {
1064da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1065da71b7e3SCédric Le Goater     Error *local_err = NULL;
1066da71b7e3SCédric Le Goater     Object *obj;
10672b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10682b548a42SCédric Le Goater 
1069da71b7e3SCédric Le Goater     /*
1070da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1071da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1072da71b7e3SCédric Le Goater      * only used at runtime.
1073da71b7e3SCédric Le Goater      */
1074da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1075da71b7e3SCédric Le Goater                            &local_err);
1076da71b7e3SCédric Le Goater     if (local_err) {
1077da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1078da71b7e3SCédric Le Goater         return;
1079da71b7e3SCédric Le Goater     }
1080da71b7e3SCédric Le Goater 
1081da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
10822b548a42SCédric Le Goater }
10832b548a42SCédric Le Goater 
10842b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10852b548a42SCédric Le Goater {
1086da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1087da71b7e3SCédric Le Goater 
1088da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
10892b548a42SCédric Le Goater }
10902b548a42SCédric Le Goater 
10912b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10922b548a42SCédric Le Goater {
10932b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10942b548a42SCédric Le Goater 
1095da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10962b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10972b548a42SCédric Le Goater }
10982b548a42SCédric Le Goater 
109985913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
110085913070SGreg Kurz                                              Monitor *mon)
110185913070SGreg Kurz {
1102da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
110385913070SGreg Kurz }
110485913070SGreg Kurz 
110559b7c1c2SBalamuruhan S /*
110659b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1107397a79e7SCédric Le Goater  *
1108397a79e7SCédric Le Goater  * <EX0 reserved>
1109397a79e7SCédric Le Goater  *  EX1  - Venice only
1110397a79e7SCédric Le Goater  *  EX2  - Venice only
1111397a79e7SCédric Le Goater  *  EX3  - Venice only
1112397a79e7SCédric Le Goater  *  EX4
1113397a79e7SCédric Le Goater  *  EX5
1114397a79e7SCédric Le Goater  *  EX6
1115397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1116397a79e7SCédric Le Goater  *  EX9  - Venice only
1117397a79e7SCédric Le Goater  *  EX10 - Venice only
1118397a79e7SCédric Le Goater  *  EX11 - Venice only
1119397a79e7SCédric Le Goater  *  EX12
1120397a79e7SCédric Le Goater  *  EX13
1121397a79e7SCédric Le Goater  *  EX14
1122397a79e7SCédric Le Goater  * <EX15 reserved>
1123397a79e7SCédric Le Goater  */
1124397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1125397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1126397a79e7SCédric Le Goater 
1127397a79e7SCédric Le Goater /*
112809279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1129397a79e7SCédric Le Goater  */
113009279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1131397a79e7SCédric Le Goater 
11322b548a42SCédric Le Goater 
11332b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
11342b548a42SCédric Le Goater 
113577864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
113677864267SCédric Le Goater {
113777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
11389ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
11399ae1329eSCédric Le Goater     int i;
114077864267SCédric Le Goater 
1141245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1142245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1143245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1144d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1145245cdb7fSCédric Le Goater 
11469fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
114777864267SCédric Le Goater 
11489fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
114977864267SCédric Le Goater 
11509fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
11513887d241SBalamuruhan S 
11529fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
11539ae1329eSCédric Le Goater 
1154eb93c828SCédric Le Goater     chip8->num_phbs = pcc->num_phbs;
11551f6a88ffSCédric Le Goater 
1156eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
11571f5d6b2aSDaniel Henrique Barboza         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB);
11589ae1329eSCédric Le Goater     }
11599ae1329eSCédric Le Goater 
116077864267SCédric Le Goater }
116177864267SCédric Le Goater 
116277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
116377864267SCédric Le Goater  {
116477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
116577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
116677864267SCédric Le Goater     int i, j;
116777864267SCédric Le Goater     char *name;
116877864267SCédric Le Goater 
116977864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
117077864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
117177864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
117277864267SCédric Le Goater     g_free(name);
117377864267SCédric Le Goater 
117477864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
117577864267SCédric Le Goater 
117677864267SCédric Le Goater     /* Map the ICP registers for each thread */
117777864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
11784fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
117977864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
118077864267SCédric Le Goater 
118177864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
118277864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1183245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
118477864267SCédric Le Goater 
118577864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
118677864267SCédric Le Goater                                         &icp->mmio);
118777864267SCédric Le Goater         }
118877864267SCédric Le Goater     }
118977864267SCédric Le Goater }
119077864267SCédric Le Goater 
1191792e8bb6SDaniel Henrique Barboza /*
1192792e8bb6SDaniel Henrique Barboza  * Attach a root port device.
1193792e8bb6SDaniel Henrique Barboza  *
1194792e8bb6SDaniel Henrique Barboza  * 'index' will be used both as a PCIE slot value and to calculate
1195792e8bb6SDaniel Henrique Barboza  * QOM id. 'chip_id' is going to be used as PCIE chassis for the
1196792e8bb6SDaniel Henrique Barboza  * root port.
1197792e8bb6SDaniel Henrique Barboza  */
1198792e8bb6SDaniel Henrique Barboza void pnv_phb_attach_root_port(PCIHostState *pci, const char *name,
1199792e8bb6SDaniel Henrique Barboza                               int index, int chip_id)
1200a71cd51eSCédric Le Goater {
1201a71cd51eSCédric Le Goater     PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
12028625164aSDaniel Henrique Barboza     g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index);
12038625164aSDaniel Henrique Barboza     const char *dev_id = DEVICE(root)->id;
12048625164aSDaniel Henrique Barboza 
12058625164aSDaniel Henrique Barboza     object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
12068625164aSDaniel Henrique Barboza                               OBJECT(root));
1207a71cd51eSCédric Le Goater 
1208792e8bb6SDaniel Henrique Barboza     /* Set unique chassis/slot values for the root port */
1209792e8bb6SDaniel Henrique Barboza     qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id);
1210792e8bb6SDaniel Henrique Barboza     qdev_prop_set_uint16(DEVICE(root), "slot", index);
1211792e8bb6SDaniel Henrique Barboza 
1212a71cd51eSCédric Le Goater     pci_realize_and_unref(root, pci->bus, &error_fatal);
1213a71cd51eSCédric Le Goater }
1214a71cd51eSCédric Le Goater 
121577864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
121677864267SCédric Le Goater {
121777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
121877864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
121977864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1220ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
122177864267SCédric Le Goater     Error *local_err = NULL;
12229ae1329eSCédric Le Goater     int i;
122377864267SCédric Le Goater 
1224245cdb7fSCédric Le Goater     assert(chip8->xics);
1225245cdb7fSCédric Le Goater 
1226709044fdSCédric Le Goater     /* XSCOM bridge is first */
1227709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1228709044fdSCédric Le Goater     if (local_err) {
1229709044fdSCédric Le Goater         error_propagate(errp, local_err);
1230709044fdSCédric Le Goater         return;
1231709044fdSCédric Le Goater     }
1232709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1233709044fdSCédric Le Goater 
123477864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
123577864267SCédric Le Goater     if (local_err) {
123677864267SCédric Le Goater         error_propagate(errp, local_err);
123777864267SCédric Le Goater         return;
123877864267SCédric Le Goater     }
123977864267SCédric Le Goater 
124077864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
12415325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
12425325cc34SMarkus Armbruster                             &error_fatal);
12435325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
12445325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1245668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
124677864267SCédric Le Goater         return;
124777864267SCédric Le Goater     }
1248ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1249ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
125077864267SCédric Le Goater 
125177864267SCédric Le Goater     /* Create LPC controller */
1252ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
125377864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
125477864267SCédric Le Goater 
1255032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
125664d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
125764d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
125864d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
125964d011d5SCédric Le Goater 
126059b7c1c2SBalamuruhan S     /*
126159b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
126259b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
126359b7c1c2SBalamuruhan S      */
126477864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
126577864267SCédric Le Goater     if (local_err) {
126677864267SCédric Le Goater         error_propagate(errp, local_err);
126777864267SCédric Le Goater         return;
126877864267SCédric Le Goater     }
126977864267SCédric Le Goater 
127077864267SCédric Le Goater     /* Create the simplified OCC model */
1271668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
127277864267SCédric Le Goater         return;
127377864267SCédric Le Goater     }
127477864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1275b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1276b0ae5c69SCédric Le Goater                           qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC));
1277f3db8266SBalamuruhan S 
1278f3db8266SBalamuruhan S     /* OCC SRAM model */
12793a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1280f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
12813887d241SBalamuruhan S 
12823887d241SBalamuruhan S     /* HOMER */
12835325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1284f2582acfSGreg Kurz                              &error_abort);
1285668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
12863887d241SBalamuruhan S         return;
12873887d241SBalamuruhan S     }
12888f092316SCédric Le Goater     /* Homer Xscom region */
12898f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
12908f092316SCédric Le Goater 
12918f092316SCédric Le Goater     /* Homer mmio region */
12923887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
12933887d241SBalamuruhan S                                 &chip8->homer.regs);
12949ae1329eSCédric Le Goater 
12951f5d6b2aSDaniel Henrique Barboza     /* PHB controllers */
1296eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
12971f5d6b2aSDaniel Henrique Barboza         PnvPHB *phb = &chip8->phbs[i];
12989ae1329eSCédric Le Goater 
12995325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
13005325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
13019ae1329eSCédric Le Goater                                 &error_fatal);
13022c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
13032c4d3a50SCédric Le Goater                                  &error_fatal);
1304668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
13059ae1329eSCédric Le Goater             return;
13069ae1329eSCédric Le Goater         }
13079ae1329eSCédric Le Goater     }
130877864267SCédric Le Goater }
130977864267SCédric Le Goater 
131070c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
131170c059e9SGreg Kurz {
131270c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
131370c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
131470c059e9SGreg Kurz }
131570c059e9SGreg Kurz 
1316e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1317e997040eSCédric Le Goater {
1318e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1319e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1320e997040eSCédric Le Goater 
1321e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1322397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
13239ae1329eSCédric Le Goater     k->num_phbs = 3;
1324631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1325d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1326d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13270990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
132885913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
132904026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1330eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1331d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1332c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
133370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1334e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
133577864267SCédric Le Goater 
133677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
133777864267SCédric Le Goater                                     &k->parent_realize);
1338e997040eSCédric Le Goater }
1339e997040eSCédric Le Goater 
1340e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1341e997040eSCédric Le Goater {
1342e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1343e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1344e997040eSCédric Le Goater 
1345e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1346397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13479ae1329eSCédric Le Goater     k->num_phbs = 3;
1348631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1349d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1350d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13510990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
135285913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
135304026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1354eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1355d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1356c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
135770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1358e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
135977864267SCédric Le Goater 
136077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
136177864267SCédric Le Goater                                     &k->parent_realize);
1362e997040eSCédric Le Goater }
1363e997040eSCédric Le Goater 
1364e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1365e997040eSCédric Le Goater {
1366e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1367e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1368e997040eSCédric Le Goater 
1369e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1370397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1371316717feSCédric Le Goater     k->num_phbs = 4;
1372631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1373d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1374d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13750990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
137685913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
137704026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1378eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1379d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1380c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
138170c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1382e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
138377864267SCédric Le Goater 
138477864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
138577864267SCédric Le Goater                                     &k->parent_realize);
138677864267SCédric Le Goater }
138777864267SCédric Le Goater 
138877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
138977864267SCédric Le Goater {
13904f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13912dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13924f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13934f9924c4SBenjamin Herrenschmidt     int i;
13942dfa91a2SCédric Le Goater 
1395db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1396d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1397d2623129SMarkus Armbruster                               "xive-fabric");
1398c38536bcSCédric Le Goater 
13999fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
140015376c66SCédric Le Goater 
14019fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
14026598a70dSCédric Le Goater 
14039fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
14043887d241SBalamuruhan S 
14050bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
14060bf4d77eSNicholas Piggin 
14079fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
14084f9924c4SBenjamin Herrenschmidt 
1409422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1410422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1411422fd92eSCédric Le Goater 
1412422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14134f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
14149fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
14154f9924c4SBenjamin Herrenschmidt     }
141677864267SCédric Le Goater }
141777864267SCédric Le Goater 
1418ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1419ae4c68e3SCédric Le Goater                                       PnvCore *pnv_core)
14205dad902cSCédric Le Goater {
14215dad902cSCédric Le Goater     char eq_name[32];
14225dad902cSCédric Le Goater     int core_id = CPU_CORE(pnv_core)->core_id;
14235dad902cSCédric Le Goater 
14245dad902cSCédric Le Goater     snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14259fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
14269fc7fc4dSMarkus Armbruster                                        sizeof(*eq), TYPE_PNV_QUAD,
14279fc7fc4dSMarkus Armbruster                                        &error_fatal, NULL);
14285dad902cSCédric Le Goater 
142992612f15SCédric Le Goater     object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1430ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(eq), NULL, &error_fatal);
1431ae4c68e3SCédric Le Goater }
1432ae4c68e3SCédric Le Goater 
1433ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1434ae4c68e3SCédric Le Goater {
1435ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
1436ae4c68e3SCédric Le Goater     int i;
1437ae4c68e3SCédric Le Goater 
1438ae4c68e3SCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1439ae4c68e3SCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1440ae4c68e3SCédric Le Goater 
1441ae4c68e3SCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
1442ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
1443ae4c68e3SCédric Le Goater 
1444ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
14455dad902cSCédric Le Goater 
144692612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
14475dad902cSCédric Le Goater                                 &eq->xscom_regs);
14485dad902cSCédric Le Goater     }
14495dad902cSCédric Le Goater }
14505dad902cSCédric Le Goater 
145113480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
14524f9924c4SBenjamin Herrenschmidt {
14534f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
145413480fc5SCédric Le Goater     int i;
14554f9924c4SBenjamin Herrenschmidt 
1456422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14574f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
14584f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
14594f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
14604f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
14614f9924c4SBenjamin Herrenschmidt 
14625325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
14635325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
14644f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14656f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
14666f43d255SCédric Le Goater                                  &error_fatal);
1467668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14684f9924c4SBenjamin Herrenschmidt             return;
14694f9924c4SBenjamin Herrenschmidt         }
14704f9924c4SBenjamin Herrenschmidt 
14714f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14724f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14734f9924c4SBenjamin Herrenschmidt 
14744f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
14754f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
14764f9924c4SBenjamin Herrenschmidt     }
14774f9924c4SBenjamin Herrenschmidt }
14784f9924c4SBenjamin Herrenschmidt 
147977864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
148077864267SCédric Le Goater {
148177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14822dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14832dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1484c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
148577864267SCédric Le Goater     Error *local_err = NULL;
148677864267SCédric Le Goater 
1487709044fdSCédric Le Goater     /* XSCOM bridge is first */
1488709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1489709044fdSCédric Le Goater     if (local_err) {
1490709044fdSCédric Le Goater         error_propagate(errp, local_err);
1491709044fdSCédric Le Goater         return;
1492709044fdSCédric Le Goater     }
1493709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1494709044fdSCédric Le Goater 
149577864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
149677864267SCédric Le Goater     if (local_err) {
149777864267SCédric Le Goater         error_propagate(errp, local_err);
149877864267SCédric Le Goater         return;
149977864267SCédric Le Goater     }
15002dfa91a2SCédric Le Goater 
15015dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
15025dad902cSCédric Le Goater     if (local_err) {
15035dad902cSCédric Le Goater         error_propagate(errp, local_err);
15045dad902cSCédric Le Goater         return;
15055dad902cSCédric Le Goater     }
15065dad902cSCédric Le Goater 
15072dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
15085325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
15095325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
15105325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
15115325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
15125325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
15135325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
15145325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
15155325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
15165325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
15177ae54cc3SGreg Kurz                              &error_abort);
1518668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
15192dfa91a2SCédric Le Goater         return;
15202dfa91a2SCédric Le Goater     }
15212dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
15222dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1523c38536bcSCédric Le Goater 
1524c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15255325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
15265325cc34SMarkus Armbruster                             &error_fatal);
152724c8fa96SCédric Le Goater     /* This is the only device with 4k ESB pages */
152824c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
152924c8fa96SCédric Le Goater                             &error_fatal);
1530668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1531c38536bcSCédric Le Goater         return;
1532c38536bcSCédric Le Goater     }
1533c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1534c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
153515376c66SCédric Le Goater 
153615376c66SCédric Le Goater     /* LPC */
1537668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
153815376c66SCédric Le Goater         return;
153915376c66SCédric Le Goater     }
154015376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
154115376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
154215376c66SCédric Le Goater 
1543032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
154415376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
154515376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15466598a70dSCédric Le Goater 
15476598a70dSCédric Le Goater     /* Create the simplified OCC model */
1548668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
15496598a70dSCédric Le Goater         return;
15506598a70dSCédric Le Goater     }
15516598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1552b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1553b0ae5c69SCédric Le Goater                               DEVICE(&chip9->psi), PSIHB9_IRQ_OCC));
1554f3db8266SBalamuruhan S 
1555f3db8266SBalamuruhan S     /* OCC SRAM model */
15563a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1557f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15583887d241SBalamuruhan S 
15590bf4d77eSNicholas Piggin     /* SBE */
15600bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
15610bf4d77eSNicholas Piggin         return;
15620bf4d77eSNicholas Piggin     }
15630bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
15640bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_ctrl_regs);
15650bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
15660bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_mbox_regs);
15670bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
15680bf4d77eSNicholas Piggin                               DEVICE(&chip9->psi), PSIHB9_IRQ_PSU));
15690bf4d77eSNicholas Piggin 
15703887d241SBalamuruhan S     /* HOMER */
15715325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1572f2582acfSGreg Kurz                              &error_abort);
1573668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15743887d241SBalamuruhan S         return;
15753887d241SBalamuruhan S     }
15768f092316SCédric Le Goater     /* Homer Xscom region */
15778f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15788f092316SCédric Le Goater 
15798f092316SCédric Le Goater     /* Homer mmio region */
15803887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15813887d241SBalamuruhan S                                 &chip9->homer.regs);
15824f9924c4SBenjamin Herrenschmidt 
158313480fc5SCédric Le Goater     /* PEC PHBs */
158413480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
15854f9924c4SBenjamin Herrenschmidt     if (local_err) {
15864f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15874f9924c4SBenjamin Herrenschmidt         return;
15884f9924c4SBenjamin Herrenschmidt     }
1589e997040eSCédric Le Goater }
1590e997040eSCédric Le Goater 
159170c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
159270c059e9SGreg Kurz {
159370c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
159470c059e9SGreg Kurz     return addr >> 3;
159570c059e9SGreg Kurz }
159670c059e9SGreg Kurz 
1597e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1598e997040eSCédric Le Goater {
1599e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1600e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1601e997040eSCédric Le Goater 
160283028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1603397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1604631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1605d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1606d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
16070990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
160885913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
160904026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1610eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1611d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1612c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
161370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1614e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1615422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
161677864267SCédric Le Goater 
161777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
161877864267SCédric Le Goater                                     &k->parent_realize);
1619e997040eSCédric Le Goater }
1620e997040eSCédric Le Goater 
16212b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
16222b548a42SCédric Le Goater {
1623623575e1SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
16248b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1625623575e1SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1626623575e1SCédric Le Goater     int i;
16278b50ce85SCédric Le Goater 
1628da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1629da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1630da71b7e3SCédric Le Goater                               "xive-fabric");
16319fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
16329fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
16338bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
16340bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe",  &chip10->sbe, TYPE_PNV10_SBE);
163592499676SCédric Le Goater     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1636623575e1SCédric Le Goater 
1637623575e1SCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1638623575e1SCédric Le Goater 
1639623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1640623575e1SCédric Le Goater         object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1641623575e1SCédric Le Goater                                 TYPE_PNV_PHB5_PEC);
1642623575e1SCédric Le Goater     }
16432b548a42SCédric Le Goater }
16442b548a42SCédric Le Goater 
1645ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1646ae4c68e3SCédric Le Goater {
1647ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip10);
1648ae4c68e3SCédric Le Goater     int i;
1649ae4c68e3SCédric Le Goater 
1650ae4c68e3SCédric Le Goater     chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1651ae4c68e3SCédric Le Goater     chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1652ae4c68e3SCédric Le Goater 
1653ae4c68e3SCédric Le Goater     for (i = 0; i < chip10->nr_quads; i++) {
1654ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip10->quads[i];
1655ae4c68e3SCédric Le Goater 
1656ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
1657ae4c68e3SCédric Le Goater 
1658ae4c68e3SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1659ae4c68e3SCédric Le Goater                                 &eq->xscom_regs);
1660ae4c68e3SCédric Le Goater     }
1661ae4c68e3SCédric Le Goater }
1662ae4c68e3SCédric Le Goater 
1663623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1664623575e1SCédric Le Goater {
1665623575e1SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1666623575e1SCédric Le Goater     int i;
1667623575e1SCédric Le Goater 
1668623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1669623575e1SCédric Le Goater         PnvPhb4PecState *pec = &chip10->pecs[i];
1670623575e1SCédric Le Goater         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1671623575e1SCédric Le Goater         uint32_t pec_nest_base;
1672623575e1SCédric Le Goater         uint32_t pec_pci_base;
1673623575e1SCédric Le Goater 
1674623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1675623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1676623575e1SCédric Le Goater                                 &error_fatal);
1677623575e1SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1678623575e1SCédric Le Goater                                  &error_fatal);
1679623575e1SCédric Le Goater         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1680623575e1SCédric Le Goater             return;
1681623575e1SCédric Le Goater         }
1682623575e1SCédric Le Goater 
1683623575e1SCédric Le Goater         pec_nest_base = pecc->xscom_nest_base(pec);
1684623575e1SCédric Le Goater         pec_pci_base = pecc->xscom_pci_base(pec);
1685623575e1SCédric Le Goater 
1686623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1687623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1688623575e1SCédric Le Goater     }
1689623575e1SCédric Le Goater }
1690623575e1SCédric Le Goater 
16912b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
16922b548a42SCédric Le Goater {
16932b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
16942b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
16958b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
16962b548a42SCédric Le Goater     Error *local_err = NULL;
16972b548a42SCédric Le Goater 
16982b548a42SCédric Le Goater     /* XSCOM bridge is first */
16992b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
17002b548a42SCédric Le Goater     if (local_err) {
17012b548a42SCédric Le Goater         error_propagate(errp, local_err);
17022b548a42SCédric Le Goater         return;
17032b548a42SCédric Le Goater     }
17042b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
17052b548a42SCédric Le Goater 
17062b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
17072b548a42SCédric Le Goater     if (local_err) {
17082b548a42SCédric Le Goater         error_propagate(errp, local_err);
17092b548a42SCédric Le Goater         return;
17102b548a42SCédric Le Goater     }
17118b50ce85SCédric Le Goater 
1712ae4c68e3SCédric Le Goater     pnv_chip_power10_quad_realize(chip10, &local_err);
1713ae4c68e3SCédric Le Goater     if (local_err) {
1714ae4c68e3SCédric Le Goater         error_propagate(errp, local_err);
1715ae4c68e3SCédric Le Goater         return;
1716ae4c68e3SCédric Le Goater     }
1717ae4c68e3SCédric Le Goater 
1718da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1719da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1720da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1721da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1722da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1723da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1724da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1725da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1726da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1727da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1728da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1729da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1730da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1731da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1732da71b7e3SCédric Le Goater                              &error_abort);
1733da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1734da71b7e3SCédric Le Goater         return;
1735da71b7e3SCédric Le Goater     }
1736da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1737da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1738da71b7e3SCédric Le Goater 
17398b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
17405325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
17415325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
174224c8fa96SCédric Le Goater     /* PSI can now be configured to use 64k ESB pages on POWER10 */
174324c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
174424c8fa96SCédric Le Goater                             &error_fatal);
1745668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
17468b50ce85SCédric Le Goater         return;
17478b50ce85SCédric Le Goater     }
17488b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
17498b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
17502661f6abSCédric Le Goater 
17512661f6abSCédric Le Goater     /* LPC */
1752668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
17532661f6abSCédric Le Goater         return;
17542661f6abSCédric Le Goater     }
17552661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
17562661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
17572661f6abSCédric Le Goater 
1758032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
17592661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
17602661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
17618bf682a3SCédric Le Goater 
17628bf682a3SCédric Le Goater     /* Create the simplified OCC model */
17638bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
17648bf682a3SCédric Le Goater         return;
17658bf682a3SCédric Le Goater     }
17668bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
17678bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
1768b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1769b0ae5c69SCédric Le Goater                               DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1770623575e1SCédric Le Goater 
177192499676SCédric Le Goater     /* OCC SRAM model */
177292499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(),
177392499676SCédric Le Goater                                 PNV10_OCC_SENSOR_BASE(chip),
177492499676SCédric Le Goater                                 &chip10->occ.sram_regs);
177592499676SCédric Le Goater 
17760bf4d77eSNicholas Piggin     /* SBE */
17770bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
17780bf4d77eSNicholas Piggin         return;
17790bf4d77eSNicholas Piggin     }
17800bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
17810bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_ctrl_regs);
17820bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
17830bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_mbox_regs);
17840bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
17850bf4d77eSNicholas Piggin                               DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
17860bf4d77eSNicholas Piggin 
178792499676SCédric Le Goater     /* HOMER */
178892499676SCédric Le Goater     object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
178992499676SCédric Le Goater                              &error_abort);
179092499676SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
179192499676SCédric Le Goater         return;
179292499676SCédric Le Goater     }
179392499676SCédric Le Goater     /* Homer Xscom region */
179492499676SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
179592499676SCédric Le Goater                             &chip10->homer.pba_regs);
179692499676SCédric Le Goater 
179792499676SCédric Le Goater     /* Homer mmio region */
179892499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
179992499676SCédric Le Goater                                 &chip10->homer.regs);
180092499676SCédric Le Goater 
1801623575e1SCédric Le Goater     /* PHBs */
1802623575e1SCédric Le Goater     pnv_chip_power10_phb_realize(chip, &local_err);
1803623575e1SCédric Le Goater     if (local_err) {
1804623575e1SCédric Le Goater         error_propagate(errp, local_err);
1805623575e1SCédric Le Goater         return;
1806623575e1SCédric Le Goater     }
18072b548a42SCédric Le Goater }
18082b548a42SCédric Le Goater 
180970c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
181070c059e9SGreg Kurz {
181170c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
181270c059e9SGreg Kurz     return addr >> 3;
181370c059e9SGreg Kurz }
181470c059e9SGreg Kurz 
18152b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
18162b548a42SCédric Le Goater {
18172b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
18182b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
18192b548a42SCédric Le Goater 
18202b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
18212b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
18222b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
18232b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
18242b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
18252b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
182685913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
18272b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
18282b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
18292b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1830c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
183170c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
18322b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
1833623575e1SCédric Le Goater     k->num_pecs = PNV10_CHIP_MAX_PEC;
18342b548a42SCédric Le Goater 
18352b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
18362b548a42SCédric Le Goater                                     &k->parent_realize);
18372b548a42SCédric Le Goater }
18382b548a42SCédric Le Goater 
1839397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1840397a79e7SCédric Le Goater {
1841397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1842397a79e7SCédric Le Goater     int cores_max;
1843397a79e7SCédric Le Goater 
1844397a79e7SCédric Le Goater     /*
1845397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1846397a79e7SCédric Le Goater      * the chip class
1847397a79e7SCédric Le Goater      */
1848397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1849397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1850397a79e7SCédric Le Goater     }
1851397a79e7SCédric Le Goater 
1852397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1853397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1854397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1855397a79e7SCédric Le Goater                    chip->cores_mask);
1856397a79e7SCédric Le Goater         return;
1857397a79e7SCédric Le Goater     }
1858397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1859397a79e7SCédric Le Goater 
1860397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
186127d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1862397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1863397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1864397a79e7SCédric Le Goater                    cores_max);
1865397a79e7SCédric Le Goater         return;
1866397a79e7SCédric Le Goater     }
1867397a79e7SCédric Le Goater }
1868397a79e7SCédric Le Goater 
186951c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1870e997040eSCédric Le Goater {
1871397a79e7SCédric Le Goater     Error *error = NULL;
1872d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
187340abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1874d2fd9612SCédric Le Goater     int i, core_hwid;
187508c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1876397a79e7SCédric Le Goater 
1877d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1878d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1879d2fd9612SCédric Le Goater         return;
1880d2fd9612SCédric Le Goater     }
1881d2fd9612SCédric Le Goater 
1882d2fd9612SCédric Le Goater     /* Cores */
1883397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1884397a79e7SCédric Le Goater     if (error) {
1885397a79e7SCédric Le Goater         error_propagate(errp, error);
1886397a79e7SCédric Le Goater         return;
1887397a79e7SCédric Le Goater     }
1888d2fd9612SCédric Le Goater 
18894fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1890d2fd9612SCédric Le Goater 
1891d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1892d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1893d2fd9612SCédric Le Goater         char core_name[32];
18944fa28f23SGreg Kurz         PnvCore *pnv_core;
1895c035851aSCédric Le Goater         uint64_t xscom_core_base;
1896d2fd9612SCédric Le Goater 
1897d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1898d2fd9612SCédric Le Goater             continue;
1899d2fd9612SCédric Le Goater         }
1900d2fd9612SCédric Le Goater 
19014fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
19024fa28f23SGreg Kurz 
1903d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1904d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
19054fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
19065325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
19075325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
19085325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
19095325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
19105325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
19115325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
19125325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
19135325cc34SMarkus Armbruster                                 &error_fatal);
19145325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1915158e17a6SGreg Kurz                                  &error_abort);
1916ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
191724ece072SCédric Le Goater 
191824ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1919c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1920c035851aSCédric Le Goater 
1921c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
19224fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1923d2fd9612SCédric Le Goater         i++;
1924d2fd9612SCédric Le Goater     }
192551c04728SCédric Le Goater }
192651c04728SCédric Le Goater 
192751c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
192851c04728SCédric Le Goater {
192951c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
193051c04728SCédric Le Goater     Error *error = NULL;
193151c04728SCédric Le Goater 
193251c04728SCédric Le Goater     /* Cores */
193351c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
193451c04728SCédric Le Goater     if (error) {
193551c04728SCédric Le Goater         error_propagate(errp, error);
193651c04728SCédric Le Goater         return;
193751c04728SCédric Le Goater     }
1938e997040eSCédric Le Goater }
1939e997040eSCédric Le Goater 
1940e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1941e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1942e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1943e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1944397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1945397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1946764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
1947e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1948e997040eSCédric Le Goater };
1949e997040eSCédric Le Goater 
1950e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1951e997040eSCédric Le Goater {
1952e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1953e997040eSCédric Le Goater 
19549d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1955e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
19564f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1957e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1958e997040eSCédric Le Goater }
1959e997040eSCédric Le Goater 
1960119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1961119eaa9dSCédric Le Goater {
1962119eaa9dSCédric Le Goater     int i, j;
1963119eaa9dSCédric Le Goater 
1964119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1965119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1966119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1967119eaa9dSCédric Le Goater 
1968119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1969119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1970119eaa9dSCédric Le Goater                 return pc->threads[j];
1971119eaa9dSCédric Le Goater             }
1972119eaa9dSCédric Le Goater         }
1973119eaa9dSCédric Le Goater     }
1974119eaa9dSCédric Le Goater     return NULL;
1975119eaa9dSCédric Le Goater }
1976119eaa9dSCédric Le Goater 
197754f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
197854f59d78SCédric Le Goater {
1979b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
1980da6be501SDaniel Henrique Barboza     int i, j;
198154f59d78SCédric Le Goater 
198254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
198377864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
198477864267SCédric Le Goater 
198577864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
198677864267SCédric Le Goater             return &chip8->psi.ics;
198754f59d78SCédric Le Goater         }
19882ff73ddaSCédric Le Goater 
1989da6be501SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
19901f5d6b2aSDaniel Henrique Barboza             PnvPHB *phb = &chip8->phbs[j];
19911f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
1992da6be501SDaniel Henrique Barboza 
1993da6be501SDaniel Henrique Barboza             if (ics_valid_irq(&phb3->lsis, irq)) {
1994da6be501SDaniel Henrique Barboza                 return &phb3->lsis;
1995da6be501SDaniel Henrique Barboza             }
1996da6be501SDaniel Henrique Barboza 
1997da6be501SDaniel Henrique Barboza             if (ics_valid_irq(ICS(&phb3->msis), irq)) {
1998da6be501SDaniel Henrique Barboza                 return ICS(&phb3->msis);
1999da6be501SDaniel Henrique Barboza             }
20009ae1329eSCédric Le Goater         }
200154f59d78SCédric Le Goater     }
200254f59d78SCédric Le Goater     return NULL;
200354f59d78SCédric Le Goater }
200454f59d78SCédric Le Goater 
20051f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
20061f6a88ffSCédric Le Goater {
20071f6a88ffSCédric Le Goater     int i;
20081f6a88ffSCédric Le Goater 
20091f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
20101f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
20111f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
20121f6a88ffSCédric Le Goater             return chip;
20131f6a88ffSCédric Le Goater         }
20141f6a88ffSCédric Le Goater     }
20151f6a88ffSCédric Le Goater     return NULL;
20161f6a88ffSCédric Le Goater }
20171f6a88ffSCédric Le Goater 
201854f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
201954f59d78SCédric Le Goater {
2020b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2021ca459489SDaniel Henrique Barboza     int i, j;
202254f59d78SCédric Le Goater 
202354f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
202477864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
20259ae1329eSCédric Le Goater 
202677864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
2027ca459489SDaniel Henrique Barboza 
2028ca459489SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20291f5d6b2aSDaniel Henrique Barboza             PnvPHB *phb = &chip8->phbs[j];
20301f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2031ca459489SDaniel Henrique Barboza 
2032ca459489SDaniel Henrique Barboza             ics_resend(&phb3->lsis);
2033ca459489SDaniel Henrique Barboza             ics_resend(ICS(&phb3->msis));
2034ca459489SDaniel Henrique Barboza         }
203554f59d78SCédric Le Goater     }
203654f59d78SCédric Le Goater }
203754f59d78SCédric Le Goater 
203836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
203936fc6f08SCédric Le Goater {
204036fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
204136fc6f08SCédric Le Goater 
2042956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
204336fc6f08SCédric Le Goater }
204436fc6f08SCédric Le Goater 
204547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
204647fea43aSCédric Le Goater                                Monitor *mon)
204747fea43aSCédric Le Goater {
2048b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
204954f59d78SCédric Le Goater     int i;
205047fea43aSCédric Le Goater     CPUState *cs;
205147fea43aSCédric Le Goater 
205247fea43aSCédric Le Goater     CPU_FOREACH(cs) {
205347fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
205447fea43aSCédric Le Goater 
205585913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
205685913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
205785913070SGreg Kurz                                                            mon);
2058d8e4aad5SCédric Le Goater     }
205954f59d78SCédric Le Goater 
206054f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2061d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
206254f59d78SCédric Le Goater     }
206347fea43aSCédric Le Goater }
206447fea43aSCédric Le Goater 
2065c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2066c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
2067c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
2068c722579eSCédric Le Goater                          uint32_t logic_serv,
2069c722579eSCédric Le Goater                          XiveTCTXMatch *match)
2070c722579eSCédric Le Goater {
2071c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2072c722579eSCédric Le Goater     int total_count = 0;
2073c722579eSCédric Le Goater     int i;
2074c722579eSCédric Le Goater 
2075c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2076c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2077c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2078c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2079c722579eSCédric Le Goater         int count;
2080c722579eSCédric Le Goater 
2081c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2082c722579eSCédric Le Goater                                priority, logic_serv, match);
2083c722579eSCédric Le Goater 
2084c722579eSCédric Le Goater         if (count < 0) {
2085c722579eSCédric Le Goater             return count;
2086c722579eSCédric Le Goater         }
2087c722579eSCédric Le Goater 
2088c722579eSCédric Le Goater         total_count += count;
2089c722579eSCédric Le Goater     }
2090c722579eSCédric Le Goater 
2091c722579eSCédric Le Goater     return total_count;
2092c722579eSCédric Le Goater }
2093c722579eSCédric Le Goater 
2094da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2095da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
2096da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
2097da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
2098da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
2099da71b7e3SCédric Le Goater {
2100da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2101da71b7e3SCédric Le Goater     int total_count = 0;
2102da71b7e3SCédric Le Goater     int i;
2103da71b7e3SCédric Le Goater 
2104da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2105da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2106da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2107da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2108da71b7e3SCédric Le Goater         int count;
2109da71b7e3SCédric Le Goater 
2110da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2111da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2112da71b7e3SCédric Le Goater 
2113da71b7e3SCédric Le Goater         if (count < 0) {
2114da71b7e3SCédric Le Goater             return count;
2115da71b7e3SCédric Le Goater         }
2116da71b7e3SCédric Le Goater 
2117da71b7e3SCédric Le Goater         total_count += count;
2118da71b7e3SCédric Le Goater     }
2119da71b7e3SCédric Le Goater 
2120da71b7e3SCédric Le Goater     return total_count;
2121da71b7e3SCédric Le Goater }
2122da71b7e3SCédric Le Goater 
2123f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
21249e933f4aSBenjamin Herrenschmidt {
21259e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
212636fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2127d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2128d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2129f30c843cSCédric Le Goater 
21301f5d6b2aSDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
21311f5d6b2aSDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "3" },
21321f5d6b2aSDaniel Henrique Barboza     };
21331f5d6b2aSDaniel Henrique Barboza 
2134f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2135f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
21361f5d6b2aSDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2137f30c843cSCédric Le Goater 
2138f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2139f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2140f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2141d76f2da7SGreg Kurz 
2142d76f2da7SGreg Kurz     pmc->compat = compat;
2143d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2144f30c843cSCédric Le Goater }
2145f30c843cSCédric Le Goater 
2146f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2147f30c843cSCédric Le Goater {
2148f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2149c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2150d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2151d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2152f30c843cSCédric Le Goater 
2153210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2154210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "4" },
2155210aacb3SDaniel Henrique Barboza     };
2156210aacb3SDaniel Henrique Barboza 
2157f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2158f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
2159210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2160210aacb3SDaniel Henrique Barboza 
2161c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2162f30c843cSCédric Le Goater 
2163f30c843cSCédric Le Goater     mc->alias = "powernv";
2164d76f2da7SGreg Kurz 
2165d76f2da7SGreg Kurz     pmc->compat = compat;
2166d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
21677a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2168f30c843cSCédric Le Goater }
2169f30c843cSCédric Le Goater 
21702b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
21712b548a42SCédric Le Goater {
21722b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2173d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2174da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2175d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
21762b548a42SCédric Le Goater 
2177210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2178210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "5" },
2179210aacb3SDaniel Henrique Barboza     };
2180210aacb3SDaniel Henrique Barboza 
21812b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
21826bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2183210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2184d76f2da7SGreg Kurz 
2185d76f2da7SGreg Kurz     pmc->compat = compat;
2186d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
21877a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2188da71b7e3SCédric Le Goater 
2189da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
21902b548a42SCédric Le Goater }
21912b548a42SCédric Le Goater 
219208c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
219308c3f3a7SCédric Le Goater {
219408c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
219508c3f3a7SCédric Le Goater 
219608c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
219708c3f3a7SCédric Le Goater }
219808c3f3a7SCédric Le Goater 
219908c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
220008c3f3a7SCédric Le Goater {
220108c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
220208c3f3a7SCédric Le Goater 
220308c3f3a7SCédric Le Goater     if (value) {
220408c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
220508c3f3a7SCédric Le Goater     }
220608c3f3a7SCédric Le Goater }
220708c3f3a7SCédric Le Goater 
220801b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
220901b552b0SNicholas Piggin {
221001b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
221101b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
221201b552b0SNicholas Piggin 
221301b552b0SNicholas Piggin     cpu_synchronize_state(cs);
221401b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
22150911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
221601b552b0SNicholas Piggin         /*
2217fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2218fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2219fe837714SNicholas Piggin          * (PPC_BIT(43)).
222001b552b0SNicholas Piggin          */
22210911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2222fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
22230911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
222401b552b0SNicholas Piggin         }
2225fe837714SNicholas Piggin     } else {
2226fe837714SNicholas Piggin         /*
2227fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2228fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2229fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2230fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2231fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2232fe837714SNicholas Piggin          */
22330911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2234fe837714SNicholas Piggin     }
2235fe837714SNicholas Piggin }
223601b552b0SNicholas Piggin 
223701b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
223801b552b0SNicholas Piggin {
223901b552b0SNicholas Piggin     CPUState *cs;
224001b552b0SNicholas Piggin 
224101b552b0SNicholas Piggin     CPU_FOREACH(cs) {
224201b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
224301b552b0SNicholas Piggin     }
224401b552b0SNicholas Piggin }
224501b552b0SNicholas Piggin 
2246f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2247f30c843cSCédric Le Goater {
2248f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
224947fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
225001b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
22519e933f4aSBenjamin Herrenschmidt 
22529e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2253b168a138SCédric Le Goater     mc->init = pnv_init;
2254b168a138SCédric Le Goater     mc->reset = pnv_reset;
22559e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
225659b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
225759b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
22589e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
22599e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2260f1d18b0aSJoel Stanley     /*
2261f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2262f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2263f1d18b0aSJoel Stanley      */
2264dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2265173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
226647fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
226701b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
226808c3f3a7SCédric Le Goater 
226908c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2270d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
227108c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
22727eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
22739e933f4aSBenjamin Herrenschmidt }
22749e933f4aSBenjamin Herrenschmidt 
227577864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2276beba5c0fSIgor Mammedov     {                                             \
2277beba5c0fSIgor Mammedov         .name          = type,                    \
2278beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
227977864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
228077864267SCédric Le Goater     }
228177864267SCédric Le Goater 
228277864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
228377864267SCédric Le Goater     {                                             \
228477864267SCédric Le Goater         .name          = type,                    \
228577864267SCédric Le Goater         .class_init    = class_initfn,            \
228677864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2287beba5c0fSIgor Mammedov     }
2288beba5c0fSIgor Mammedov 
22892b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
22902b548a42SCédric Le Goater     {                                              \
22912b548a42SCédric Le Goater         .name          = type,                     \
22922b548a42SCédric Le Goater         .class_init    = class_initfn,             \
22932b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
22942b548a42SCédric Le Goater     }
22952b548a42SCédric Le Goater 
2296beba5c0fSIgor Mammedov static const TypeInfo types[] = {
22971aba8716SCédric Le Goater     {
22982b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
22992b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23002b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2301da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2302da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2303da71b7e3SCédric Le Goater             { },
2304da71b7e3SCédric Le Goater         },
23052b548a42SCédric Le Goater     },
23062b548a42SCédric Le Goater     {
23071aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
23081aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23091aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2310c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2311c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2312c722579eSCédric Le Goater             { },
2313c722579eSCédric Le Goater         },
23141aba8716SCédric Le Goater     },
23151aba8716SCédric Le Goater     {
23161aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
23171aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23181aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
23191aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
23201aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
23211aba8716SCédric Le Goater             { },
23221aba8716SCédric Le Goater         },
23231aba8716SCédric Le Goater     },
2324beba5c0fSIgor Mammedov     {
2325b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
23269e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2327f30c843cSCédric Le Goater         .abstract       = true,
23289e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2329b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2330d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
233136fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
233247fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
233301b552b0SNicholas Piggin             { TYPE_NMI },
233436fc6f08SCédric Le Goater             { },
233536fc6f08SCédric Le Goater         },
2336beba5c0fSIgor Mammedov     },
2337beba5c0fSIgor Mammedov     {
2338beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2339beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2340beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2341beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2342beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2343beba5c0fSIgor Mammedov         .abstract      = true,
2344beba5c0fSIgor Mammedov     },
234577864267SCédric Le Goater 
234677864267SCédric Le Goater     /*
23472b548a42SCédric Le Goater      * P10 chip and variants
23482b548a42SCédric Le Goater      */
23492b548a42SCédric Le Goater     {
23502b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
23512b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
23522b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
23532b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
23542b548a42SCédric Le Goater     },
23552b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
23562b548a42SCédric Le Goater 
23572b548a42SCédric Le Goater     /*
235877864267SCédric Le Goater      * P9 chip and variants
235977864267SCédric Le Goater      */
236077864267SCédric Le Goater     {
236177864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
236277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
236377864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
236477864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
236577864267SCédric Le Goater     },
236677864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
236777864267SCédric Le Goater 
236877864267SCédric Le Goater     /*
236977864267SCédric Le Goater      * P8 chip and variants
237077864267SCédric Le Goater      */
237177864267SCédric Le Goater     {
237277864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
237377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
237477864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
237577864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
237677864267SCédric Le Goater     },
237777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
237877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
237977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2380beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
23819e933f4aSBenjamin Herrenschmidt };
23829e933f4aSBenjamin Herrenschmidt 
2383beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2384