xref: /qemu/hw/ppc/pnv.c (revision 8a69bca7)
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"
469e933f4aSBenjamin Herrenschmidt 
4736fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
48a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
49967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5035dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
51967b7523SCédric Le Goater 
523495b6b6SCédric Le Goater #include "hw/isa/isa.h"
533495b6b6SCédric Le Goater #include "hw/char/serial.h"
54bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
553495b6b6SCédric Le Goater 
569e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
579e933f4aSBenjamin Herrenschmidt 
58b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
599e933f4aSBenjamin Herrenschmidt 
609e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
619e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
6283fa6e2aSCédric Le Goater #define FW_MAX_SIZE             (16 * MiB)
639e933f4aSBenjamin Herrenschmidt 
649e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
6505ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE         (128 * MiB)
6605ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR        0x28000000
6705ce9b73SCédric Le Goater #define INITRD_MAX_SIZE         (128 * MiB)
689e933f4aSBenjamin Herrenschmidt 
6940abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7040abf43fSIgor Mammedov {
7140abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7240abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7340abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7440abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7540abf43fSIgor Mammedov     g_free(s);
7640abf43fSIgor Mammedov     return core_type;
7740abf43fSIgor Mammedov }
7840abf43fSIgor Mammedov 
799e933f4aSBenjamin Herrenschmidt /*
809e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
819e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
829e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
839e933f4aSBenjamin Herrenschmidt  */
849e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
859e933f4aSBenjamin Herrenschmidt 
869e933f4aSBenjamin Herrenschmidt /*
879e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
889e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
899e933f4aSBenjamin Herrenschmidt  * per chip.
909e933f4aSBenjamin Herrenschmidt  */
91b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
929e933f4aSBenjamin Herrenschmidt {
939e933f4aSBenjamin Herrenschmidt     char *mem_name;
949e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
959e933f4aSBenjamin Herrenschmidt     int off;
969e933f4aSBenjamin Herrenschmidt 
979e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
989e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
999e933f4aSBenjamin Herrenschmidt 
1009e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1019e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1029e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1039e933f4aSBenjamin Herrenschmidt 
1049e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1069e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1079e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1089e933f4aSBenjamin Herrenschmidt }
1099e933f4aSBenjamin Herrenschmidt 
110d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
111d2fd9612SCédric Le Goater {
112d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
113d2fd9612SCédric Le Goater 
114d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
115a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
116d2fd9612SCédric Le Goater         if (cpus_offset) {
117d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
118d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
119d2fd9612SCédric Le Goater         }
120d2fd9612SCédric Le Goater     }
121d2fd9612SCédric Le Goater     _FDT(cpus_offset);
122d2fd9612SCédric Le Goater     return cpus_offset;
123d2fd9612SCédric Le Goater }
124d2fd9612SCédric Le Goater 
125d2fd9612SCédric Le Goater /*
126d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
127d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
128d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
129d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
130d2fd9612SCédric Le Goater  * servers.
131d2fd9612SCédric Le Goater  */
132b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
133d2fd9612SCédric Le Goater {
13408304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13508304a86SDavid Gibson     CPUState *cs = CPU(cpu);
136d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1378bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
138d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
139d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
140d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
141d2fd9612SCédric Le Goater     int i;
142d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
143d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
144d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
145d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
146d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
147d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
148d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
149d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
150d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
151d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
152d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
153d2fd9612SCédric Le Goater     int offset;
154d2fd9612SCédric Le Goater     char *nodename;
155d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
156d2fd9612SCédric Le Goater 
157d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
158d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
159d2fd9612SCédric Le Goater     _FDT(offset);
160d2fd9612SCédric Le Goater     g_free(nodename);
161d2fd9612SCédric Le Goater 
162d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
163d2fd9612SCédric Le Goater 
164d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
167d2fd9612SCédric Le Goater 
168d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
170d2fd9612SCédric Le Goater                             env->dcache_line_size)));
171d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
172d2fd9612SCédric Le Goater                             env->dcache_line_size)));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
174d2fd9612SCédric Le Goater                             env->icache_line_size)));
175d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
176d2fd9612SCédric Le Goater                             env->icache_line_size)));
177d2fd9612SCédric Le Goater 
178d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
179d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
180d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
181d2fd9612SCédric Le Goater     } else {
1823dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
183d2fd9612SCédric Le Goater     }
184d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
185d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
186d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
187d2fd9612SCédric Le Goater     } else {
1883dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
189d2fd9612SCédric Le Goater     }
190d2fd9612SCédric Le Goater 
191d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
192d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19359b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19459b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
195d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
196d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
197d2fd9612SCédric Le Goater 
19803282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
199d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
200d2fd9612SCédric Le Goater     }
201d2fd9612SCédric Le Goater 
20258969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
203d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
204d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
205d2fd9612SCédric Le Goater     }
206d2fd9612SCédric Le Goater 
20759b7c1c2SBalamuruhan S     /*
20859b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
209d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
210d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21159b7c1c2SBalamuruhan S      *   2               == VSX available
21259b7c1c2SBalamuruhan S      */
213d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
214d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
215d2fd9612SCédric Le Goater 
216d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
217d2fd9612SCédric Le Goater     }
218d2fd9612SCédric Le Goater 
21959b7c1c2SBalamuruhan S     /*
22059b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
221d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22259b7c1c2SBalamuruhan S      *   1               == DFP available
22359b7c1c2SBalamuruhan S      */
224d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
225d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
226d2fd9612SCédric Le Goater     }
227d2fd9612SCédric Le Goater 
228644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
229d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
230d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
231d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
232d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
233d2fd9612SCédric Le Goater     }
234d2fd9612SCédric Le Goater 
235d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
236d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
237d2fd9612SCédric Le Goater 
238d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
239d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
240d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
241d2fd9612SCédric Le Goater     }
242d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
243d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
244d2fd9612SCédric Le Goater }
245d2fd9612SCédric Le Goater 
246b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
247bf5615e7SCédric Le Goater                        uint32_t nr_threads)
248bf5615e7SCédric Le Goater {
249bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
250bf5615e7SCédric Le Goater     char *name;
251bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
252bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
253bf5615e7SCédric Le Goater     uint64_t *reg;
254bf5615e7SCédric Le Goater     int offset;
255bf5615e7SCédric Le Goater 
256bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
257bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
258bf5615e7SCédric Le Goater 
259bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
260bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
261bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
262bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
263bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
264bf5615e7SCédric Le Goater     }
265bf5615e7SCédric Le Goater 
266bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
267bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
268bf5615e7SCédric Le Goater     _FDT(offset);
269bf5615e7SCédric Le Goater     g_free(name);
270bf5615e7SCédric Le Goater 
271bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
272bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
274bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
275bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
277bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
278bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
279bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
280bf5615e7SCédric Le Goater     g_free(reg);
281bf5615e7SCédric Le Goater }
282bf5615e7SCédric Le Goater 
283eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
284e997040eSCédric Le Goater {
285c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
286d2fd9612SCédric Le Goater     int i;
287d2fd9612SCédric Le Goater 
2883f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2893f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
290c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
291c396c58aSGreg Kurz                  compat, sizeof(compat));
292967b7523SCédric Le Goater 
293d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2944fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
295d2fd9612SCédric Le Goater 
296b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
297bf5615e7SCédric Le Goater 
298bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
299b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
300d2fd9612SCédric Le Goater     }
301d2fd9612SCédric Le Goater 
302e997040eSCédric Le Goater     if (chip->ram_size) {
303b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
304e997040eSCédric Le Goater     }
305e997040eSCédric Le Goater }
306e997040eSCédric Le Goater 
307eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
308eb859a27SCédric Le Goater {
309c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
310eb859a27SCédric Le Goater     int i;
311eb859a27SCédric Le Goater 
3123f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3133f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
314c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
315c396c58aSGreg Kurz                  compat, sizeof(compat));
316eb859a27SCédric Le Goater 
317eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3184fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
319eb859a27SCédric Le Goater 
320eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
321eb859a27SCédric Le Goater     }
322eb859a27SCédric Le Goater 
323eb859a27SCédric Le Goater     if (chip->ram_size) {
324eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
325eb859a27SCédric Le Goater     }
32615376c66SCédric Le Goater 
3272661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
328eb859a27SCédric Le Goater }
329eb859a27SCédric Le Goater 
3302b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3312b548a42SCédric Le Goater {
332c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3332b548a42SCédric Le Goater     int i;
3342b548a42SCédric Le Goater 
3353f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3363f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
337c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
338c396c58aSGreg Kurz                  compat, sizeof(compat));
3392b548a42SCédric Le Goater 
3402b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3412b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3422b548a42SCédric Le Goater 
3432b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3442b548a42SCédric Le Goater     }
3452b548a42SCédric Le Goater 
3462b548a42SCédric Le Goater     if (chip->ram_size) {
3472b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3482b548a42SCédric Le Goater     }
3492661f6abSCédric Le Goater 
3502661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3512b548a42SCédric Le Goater }
3522b548a42SCédric Le Goater 
353b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
354c5ffdcaeSCédric Le Goater {
355c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
356c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
357c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
358c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
359c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
360c5ffdcaeSCédric Le Goater     };
361c5ffdcaeSCédric Le Goater     char *name;
362c5ffdcaeSCédric Le Goater     int node;
363c5ffdcaeSCédric Le Goater 
364c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
365c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
366c5ffdcaeSCédric Le Goater     _FDT(node);
367c5ffdcaeSCédric Le Goater     g_free(name);
368c5ffdcaeSCédric Le Goater 
369c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
370c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
371c5ffdcaeSCédric Le Goater }
372c5ffdcaeSCédric Le Goater 
373b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
374cb228f5aSCédric Le Goater {
375cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
376cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
377cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
378cb228f5aSCédric Le Goater         cpu_to_be32(1),
379cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
380cb228f5aSCédric Le Goater         cpu_to_be32(8)
381cb228f5aSCédric Le Goater     };
382632fc0b3SBernhard Beschow     uint32_t irq;
383cb228f5aSCédric Le Goater     char *name;
384cb228f5aSCédric Le Goater     int node;
385cb228f5aSCédric Le Goater 
386632fc0b3SBernhard Beschow     irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
387632fc0b3SBernhard Beschow 
388cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
389cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
390cb228f5aSCédric Le Goater     _FDT(node);
391cb228f5aSCédric Le Goater     g_free(name);
392cb228f5aSCédric Le Goater 
393cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
394cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
395cb228f5aSCédric Le Goater                       sizeof(compatible))));
396cb228f5aSCédric Le Goater 
397cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
398cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
399632fc0b3SBernhard Beschow     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
400cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
401cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
402cb228f5aSCédric Le Goater 
403cb228f5aSCédric Le Goater     /* This is needed by Linux */
404cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
405cb228f5aSCédric Le Goater }
406cb228f5aSCédric Le Goater 
407b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40804f6c8b2SCédric Le Goater {
40904f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
41004f6c8b2SCédric Le Goater     uint32_t io_base;
41104f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
41204f6c8b2SCédric Le Goater         cpu_to_be32(1),
41304f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41404f6c8b2SCédric Le Goater         cpu_to_be32(3)
41504f6c8b2SCédric Le Goater     };
41604f6c8b2SCédric Le Goater     uint32_t irq;
41704f6c8b2SCédric Le Goater     char *name;
41804f6c8b2SCédric Le Goater     int node;
41904f6c8b2SCédric Le Goater 
42004f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
42104f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
42204f6c8b2SCédric Le Goater 
42304f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42404f6c8b2SCédric Le Goater 
42504f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42604f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42704f6c8b2SCédric Le Goater     _FDT(node);
42804f6c8b2SCédric Le Goater     g_free(name);
42904f6c8b2SCédric Le Goater 
4307032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4317032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4327032d92aSCédric Le Goater                       sizeof(compatible))));
43304f6c8b2SCédric Le Goater 
43404f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43704f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43804f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
43904f6c8b2SCédric Le Goater }
44004f6c8b2SCédric Le Goater 
441e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
442e7a3fee3SCédric Le Goater     void *fdt;
443e7a3fee3SCédric Le Goater     int offset;
444e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
445e7a3fee3SCédric Le Goater 
446b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
447e7a3fee3SCédric Le Goater {
448c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
449c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
450c5ffdcaeSCédric Le Goater 
451c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
452b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
453cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
454b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45504f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
456b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
457c5ffdcaeSCédric Le Goater     } else {
458c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
459c5ffdcaeSCédric Le Goater                      d->ioport_id);
460c5ffdcaeSCédric Le Goater     }
461c5ffdcaeSCédric Le Goater 
462e7a3fee3SCédric Le Goater     return 0;
463e7a3fee3SCédric Le Goater }
464e7a3fee3SCédric Le Goater 
46559b7c1c2SBalamuruhan S /*
46659b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
467bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
468bb7ab95cSCédric Le Goater  */
469bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
470bb7ab95cSCédric Le Goater {
47164d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
472e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
473e7a3fee3SCédric Le Goater         .fdt = fdt,
474bb7ab95cSCédric Le Goater         .offset = isa_offset,
475e7a3fee3SCédric Le Goater     };
476f47a08d1SCédric Le Goater     uint32_t phandle;
477e7a3fee3SCédric Le Goater 
478bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
479bb7ab95cSCédric Le Goater 
480f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
481f47a08d1SCédric Le Goater     assert(phandle > 0);
482f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
483f47a08d1SCédric Le Goater 
48459b7c1c2SBalamuruhan S     /*
48559b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48659b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48759b7c1c2SBalamuruhan S      */
488bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
489bb7ab95cSCédric Le Goater                        &args);
490e7a3fee3SCédric Le Goater }
491e7a3fee3SCédric Le Goater 
4927a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
493e5694793SCédric Le Goater {
494e5694793SCédric Le Goater     int off;
495e5694793SCédric Le Goater 
496e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
497e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
498e5694793SCédric Le Goater 
499e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
500e5694793SCédric Le Goater }
501e5694793SCédric Le Goater 
502b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5039e933f4aSBenjamin Herrenschmidt {
504d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
505b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5069e933f4aSBenjamin Herrenschmidt     void *fdt;
5079e933f4aSBenjamin Herrenschmidt     char *buf;
5089e933f4aSBenjamin Herrenschmidt     int off;
509e997040eSCédric Le Goater     int i;
5109e933f4aSBenjamin Herrenschmidt 
5119e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5129e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5139e933f4aSBenjamin Herrenschmidt 
514ccb099b3SCédric Le Goater     /* /qemu node */
515ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
516ccb099b3SCédric Le Goater 
5179e933f4aSBenjamin Herrenschmidt     /* Root node */
5189e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5199e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5209e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5219e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
522d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5239e933f4aSBenjamin Herrenschmidt 
5249e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5259e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5269e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
527bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
5289e933f4aSBenjamin Herrenschmidt     }
5299e933f4aSBenjamin Herrenschmidt     g_free(buf);
5309e933f4aSBenjamin Herrenschmidt 
5319e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5329e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5339e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5349e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5359e933f4aSBenjamin Herrenschmidt     }
5369e933f4aSBenjamin Herrenschmidt 
5379e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5389e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5399e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5409e933f4aSBenjamin Herrenschmidt 
5419e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5429e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5439e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5449e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5459e933f4aSBenjamin Herrenschmidt     }
5469e933f4aSBenjamin Herrenschmidt 
547e997040eSCédric Le Goater     /* Populate device tree for each chip */
548e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
549eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
550e997040eSCédric Le Goater     }
551e7a3fee3SCédric Le Goater 
552e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
553bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
554aeaef83dSCédric Le Goater 
555aeaef83dSCédric Le Goater     if (pnv->bmc) {
556b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
557aeaef83dSCédric Le Goater     }
558aeaef83dSCédric Le Goater 
5597a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5607a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5617a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
562e5694793SCédric Le Goater     }
563e5694793SCédric Le Goater 
5649e933f4aSBenjamin Herrenschmidt     return fdt;
5659e933f4aSBenjamin Herrenschmidt }
5669e933f4aSBenjamin Herrenschmidt 
567bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
568bce0b691SCédric Le Goater {
5698f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
570bce0b691SCédric Le Goater 
571bce0b691SCédric Le Goater     if (pnv->bmc) {
572bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
573bce0b691SCédric Le Goater     }
574bce0b691SCédric Le Goater }
575bce0b691SCédric Le Goater 
576a0628599SLike Xu static void pnv_reset(MachineState *machine)
5779e933f4aSBenjamin Herrenschmidt {
57825f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
57925f3170bSCédric Le Goater     IPMIBmc *bmc;
5809e933f4aSBenjamin Herrenschmidt     void *fdt;
5819e933f4aSBenjamin Herrenschmidt 
5829e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5839e933f4aSBenjamin Herrenschmidt 
58425f3170bSCédric Le Goater     /*
58525f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
58625f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
58725f3170bSCédric Le Goater      * line.
58825f3170bSCédric Le Goater      */
58925f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
59025f3170bSCédric Le Goater     if (!pnv->bmc) {
59125f3170bSCédric Le Goater         if (!bmc) {
59238d2448aSGreg Kurz             if (!qtest_enabled()) {
59325f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
59425f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59525f3170bSCédric Le Goater                             "to define one");
59638d2448aSGreg Kurz             }
59725f3170bSCédric Le Goater         } else {
59825f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
59925f3170bSCédric Le Goater             pnv->bmc = bmc;
60025f3170bSCédric Le Goater         }
60125f3170bSCédric Le Goater     }
60225f3170bSCédric Le Goater 
603b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6049e933f4aSBenjamin Herrenschmidt 
6059e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6069e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6079e933f4aSBenjamin Herrenschmidt 
6088d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6099e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
610b2fb7a43SPan Nengyuan 
611b2fb7a43SPan Nengyuan     g_free(fdt);
6129e933f4aSBenjamin Herrenschmidt }
6139e933f4aSBenjamin Herrenschmidt 
61404026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6153495b6b6SCédric Le Goater {
61677864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
617c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
618c05aa140SCédric Le Goater 
619c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
62077864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
62104026890SCédric Le Goater }
6223495b6b6SCédric Le Goater 
62304026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
62404026890SCédric Le Goater {
62577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
626c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
627c05aa140SCédric Le Goater 
628c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
62977864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
63004026890SCédric Le Goater }
6313495b6b6SCédric Le Goater 
63204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
63304026890SCédric Le Goater {
63415376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
635c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
636c05aa140SCédric Le Goater 
637c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq);
63815376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
63904026890SCédric Le Goater }
6403495b6b6SCédric Le Goater 
6412b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6422b548a42SCédric Le Goater {
6432661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
644c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
645c05aa140SCédric Le Goater 
646c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq);
6472661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6482b548a42SCédric Le Goater }
6492b548a42SCédric Le Goater 
65004026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
65104026890SCédric Le Goater {
65204026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6533495b6b6SCédric Le Goater }
6543495b6b6SCédric Le Goater 
655d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
656d8e4aad5SCédric Le Goater {
657d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6588a69bca7SDaniel Henrique Barboza     int i;
659d8e4aad5SCédric Le Goater 
660d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6618a69bca7SDaniel Henrique Barboza 
6628a69bca7SDaniel Henrique Barboza     for (i = 0; i < chip8->num_phbs; i++) {
6638a69bca7SDaniel Henrique Barboza         PnvPHB3 *phb3 = &chip8->phbs[i];
6648a69bca7SDaniel Henrique Barboza 
6658a69bca7SDaniel Henrique Barboza         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
6668a69bca7SDaniel Henrique Barboza         ics_pic_print_info(&phb3->lsis, mon);
6678a69bca7SDaniel Henrique Barboza     }
668d8e4aad5SCédric Le Goater }
669d8e4aad5SCédric Le Goater 
6700e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
6710e6232bcSCédric Le Goater {
6720e6232bcSCédric Le Goater     Monitor *mon = opaque;
6730e6232bcSCédric Le Goater     PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4);
6740e6232bcSCédric Le Goater 
6750e6232bcSCédric Le Goater     if (phb4) {
6760e6232bcSCédric Le Goater         pnv_phb4_pic_print_info(phb4, mon);
6770e6232bcSCédric Le Goater     }
6780e6232bcSCédric Le Goater     return 0;
6790e6232bcSCédric Le Goater }
6800e6232bcSCédric Le Goater 
681d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
682d8e4aad5SCédric Le Goater {
683d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
684d8e4aad5SCédric Le Goater 
685d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
686c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6874f9924c4SBenjamin Herrenschmidt 
6880e6232bcSCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
6890e6232bcSCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
690d8e4aad5SCédric Le Goater }
691d8e4aad5SCédric Le Goater 
692c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
693c4b2c40cSGreg Kurz                                                 uint32_t core_id)
694c4b2c40cSGreg Kurz {
695c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
696c4b2c40cSGreg Kurz }
697c4b2c40cSGreg Kurz 
698c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
699c4b2c40cSGreg Kurz                                                 uint32_t core_id)
700c4b2c40cSGreg Kurz {
701c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
702c4b2c40cSGreg Kurz }
703c4b2c40cSGreg Kurz 
704c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
705c4b2c40cSGreg Kurz                                                  uint32_t core_id)
706c4b2c40cSGreg Kurz {
707c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
708c4b2c40cSGreg Kurz }
709c4b2c40cSGreg Kurz 
710f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
711f30c843cSCédric Le Goater {
712f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
713f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
714f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
715f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
716f30c843cSCédric Le Goater 
717f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
718f30c843cSCédric Le Goater }
719f30c843cSCédric Le Goater 
720e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
721e2392d43SCédric Le Goater {
722c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
723e2392d43SCédric Le Goater 
7245325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7255325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
726c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
727e2392d43SCédric Le Goater }
728e2392d43SCédric Le Goater 
7292b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7302b548a42SCédric Le Goater {
7318b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7328b50ce85SCédric Le Goater 
733da71b7e3SCédric Le Goater     pnv_xive2_pic_print_info(&chip10->xive, mon);
7348b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
735623575e1SCédric Le Goater 
736623575e1SCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
737623575e1SCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
7382b548a42SCédric Le Goater }
7392b548a42SCédric Le Goater 
740458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
741458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
742458c6f01SCédric Le Goater {
743458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
744458c6f01SCédric Le Goater     uint64_t ram_per_chip;
745458c6f01SCédric Le Goater 
746458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
747458c6f01SCédric Le Goater 
748458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
749458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
750458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
751458c6f01SCédric Le Goater     }
752458c6f01SCédric Le Goater 
753f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
754f640afecSCédric Le Goater 
755458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
756458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
757458c6f01SCédric Le Goater }
758458c6f01SCédric Le Goater 
759b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7609e933f4aSBenjamin Herrenschmidt {
761cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
762b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
763f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7649e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7659e933f4aSBenjamin Herrenschmidt     long fw_size;
766458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
767e997040eSCédric Le Goater     int i;
768e997040eSCédric Le Goater     char *chip_typename;
76935dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
77035dde576SCédric Le Goater     DeviceState *dev;
7719e933f4aSBenjamin Herrenschmidt 
772ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
773ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
774ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
775ebe6c3faSDaniel Henrique Barboza     }
776ebe6c3faSDaniel Henrique Barboza 
7779e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
778dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
779dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
780dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
781dd7ef911SCédric Le Goater         g_free(sz);
782dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
7839e933f4aSBenjamin Herrenschmidt     }
784173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7859e933f4aSBenjamin Herrenschmidt 
78635dde576SCédric Le Goater     /*
78735dde576SCédric Le Goater      * Create our simple PNOR device
78835dde576SCédric Le Goater      */
7893e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
79035dde576SCédric Le Goater     if (pnor) {
791934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
79235dde576SCédric Le Goater     }
7933c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
79435dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
79535dde576SCédric Le Goater 
7969e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7979e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
79815fcedb2SCédric Le Goater     if (!fw_filename) {
79915fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
80015fcedb2SCédric Le Goater         exit(1);
80115fcedb2SCédric Le Goater     }
8029e933f4aSBenjamin Herrenschmidt 
80308c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
8049e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
80515fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
8069e933f4aSBenjamin Herrenschmidt         exit(1);
8079e933f4aSBenjamin Herrenschmidt     }
8089e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8099e933f4aSBenjamin Herrenschmidt 
8109e933f4aSBenjamin Herrenschmidt     /* load kernel */
8119e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8129e933f4aSBenjamin Herrenschmidt         long kernel_size;
8139e933f4aSBenjamin Herrenschmidt 
8149e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
815b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8169e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
817802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8189e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8199e933f4aSBenjamin Herrenschmidt             exit(1);
8209e933f4aSBenjamin Herrenschmidt         }
8219e933f4aSBenjamin Herrenschmidt     }
8229e933f4aSBenjamin Herrenschmidt 
8239e933f4aSBenjamin Herrenschmidt     /* load initrd */
8249e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
8259e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
8269e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
827584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
8289e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
829802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
8309e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
8319e933f4aSBenjamin Herrenschmidt             exit(1);
8329e933f4aSBenjamin Herrenschmidt         }
8339e933f4aSBenjamin Herrenschmidt     }
834e997040eSCédric Le Goater 
8354f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8364f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8374f9924c4SBenjamin Herrenschmidt 
838f30c843cSCédric Le Goater     /*
839f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
840f30c843cSCédric Le Goater      * default.
841f30c843cSCédric Le Goater      */
842f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
843f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
844f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
845f30c843cSCédric Le Goater         exit(1);
846f30c843cSCédric Le Goater     }
847f30c843cSCédric Le Goater 
848e997040eSCédric Le Goater     /* Create the processor chips */
8494a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8507fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8514a12c699SIgor Mammedov                                     i, machine->cpu_type);
852e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
853f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
854f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
855e997040eSCédric Le Goater         exit(1);
856e997040eSCédric Le Goater     }
857e997040eSCédric Le Goater 
858e44acde2SGreg Kurz     pnv->num_chips =
859e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
860e44acde2SGreg Kurz     /*
861e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
862e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
863e44acde2SGreg Kurz      */
864ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
865e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
866ab17a3feSCédric Le Goater         error_printf(
867ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
868e44acde2SGreg Kurz         exit(1);
869e44acde2SGreg Kurz     }
870e44acde2SGreg Kurz 
871e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
872e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
873e997040eSCédric Le Goater         char chip_name[32];
874df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
8750e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
876e997040eSCédric Le Goater 
877e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
878e997040eSCédric Le Goater 
879458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
880458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
881e997040eSCédric Le Goater                                 &error_fatal);
882458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
883458c6f01SCédric Le Goater                                 &error_fatal);
884458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
885e997040eSCédric Le Goater 
8860e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
887d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
8880e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
8895325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
8905325cc34SMarkus Armbruster                                 &error_fatal);
8915325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
8925325cc34SMarkus Armbruster                                 &error_fatal);
893245cdb7fSCédric Le Goater         /*
894245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
895245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
896245cdb7fSCédric Le Goater          */
897245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
8985325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
899245cdb7fSCédric Le Goater         }
900d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
9015325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
902d1214b81SGreg Kurz                                      &error_abort);
903d1214b81SGreg Kurz         }
9043c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
905e997040eSCédric Le Goater     }
906e997040eSCédric Le Goater     g_free(chip_typename);
9073495b6b6SCédric Le Goater 
9083495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
90904026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9103495b6b6SCédric Le Goater 
9113495b6b6SCédric Le Goater     /* Create serial port */
912def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9133495b6b6SCédric Le Goater 
9143495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9156c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
916bce0b691SCédric Le Goater 
91725f3170bSCédric Le Goater     /*
91825f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
91925f3170bSCédric Le Goater      * communication with the BMC
92025f3170bSCédric Le Goater      */
92125f3170bSCédric Le Goater     if (defaults_enabled()) {
92225f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
923e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
92425f3170bSCédric Le Goater     }
925e2392d43SCédric Le Goater 
92659b7c1c2SBalamuruhan S     /*
927032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
928032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
929032c226bSCédric Le Goater      * map it always for now.
930032c226bSCédric Le Goater      */
931032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
932032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
933032c226bSCédric Le Goater 
934032c226bSCédric Le Goater     /*
93559b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
93659b7c1c2SBalamuruhan S      * host to powerdown
93759b7c1c2SBalamuruhan S      */
938bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
939bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
940e997040eSCédric Le Goater }
941e997040eSCédric Le Goater 
942631adaffSCédric Le Goater /*
943631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
944631adaffSCédric Le Goater  *   22:24  Chip ID
945631adaffSCédric Le Goater  *   25:28  Core number
946631adaffSCédric Le Goater  *   29:31  Thread ID
947631adaffSCédric Le Goater  */
948631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
949631adaffSCédric Le Goater {
950631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
951631adaffSCédric Le Goater }
952631adaffSCédric Le Goater 
9538fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
954d35aefa9SCédric Le Goater                                         Error **errp)
955d35aefa9SCédric Le Goater {
956245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9578fa1f4efSCédric Le Goater     Error *local_err = NULL;
9588fa1f4efSCédric Le Goater     Object *obj;
9598907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9608fa1f4efSCédric Le Goater 
961245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9628fa1f4efSCédric Le Goater     if (local_err) {
9638fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9648fa1f4efSCédric Le Goater         return;
9658fa1f4efSCédric Le Goater     }
9668fa1f4efSCédric Le Goater 
967956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
968d35aefa9SCédric Le Goater }
969d35aefa9SCédric Le Goater 
9700990ce6aSGreg Kurz 
971d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
972d49e8a9bSCédric Le Goater {
973d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
974d49e8a9bSCédric Le Goater 
975d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
976d49e8a9bSCédric Le Goater }
977d49e8a9bSCédric Le Goater 
9780990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9790990ce6aSGreg Kurz {
9800990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9810990ce6aSGreg Kurz 
9820990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9830990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9840990ce6aSGreg Kurz }
9850990ce6aSGreg Kurz 
98685913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
98785913070SGreg Kurz                                             Monitor *mon)
98885913070SGreg Kurz {
98985913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
99085913070SGreg Kurz }
99185913070SGreg Kurz 
992631adaffSCédric Le Goater /*
993631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
994631adaffSCédric Le Goater  *   49:52  Node ID
995631adaffSCédric Le Goater  *   53:55  Chip ID
996631adaffSCédric Le Goater  *   56     Reserved - Read as zero
997631adaffSCédric Le Goater  *   57:61  Core number
998631adaffSCédric Le Goater  *   62:63  Thread ID
999631adaffSCédric Le Goater  *
1000631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
1001631adaffSCédric Le Goater  */
1002631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
1003631adaffSCédric Le Goater {
1004631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
1005631adaffSCédric Le Goater }
1006631adaffSCédric Le Goater 
10072b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10082b548a42SCédric Le Goater {
10092b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10102b548a42SCédric Le Goater }
10112b548a42SCédric Le Goater 
10128fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1013d35aefa9SCédric Le Goater                                         Error **errp)
1014d35aefa9SCédric Le Goater {
10152dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10162dfa91a2SCédric Le Goater     Error *local_err = NULL;
10172dfa91a2SCédric Le Goater     Object *obj;
10182dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10192dfa91a2SCédric Le Goater 
10202dfa91a2SCédric Le Goater     /*
10212dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
10222dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
10232dfa91a2SCédric Le Goater      * only used at runtime.
10242dfa91a2SCédric Le Goater      */
102547950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
102647950946SCédric Le Goater                            &local_err);
10272dfa91a2SCédric Le Goater     if (local_err) {
10282dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
10298fa1f4efSCédric Le Goater         return;
1030d35aefa9SCédric Le Goater     }
1031d35aefa9SCédric Le Goater 
10322dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10332dfa91a2SCédric Le Goater }
10342dfa91a2SCédric Le Goater 
1035d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1036d49e8a9bSCédric Le Goater {
1037d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1038d49e8a9bSCédric Le Goater 
1039d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1040d49e8a9bSCédric Le Goater }
1041d49e8a9bSCédric Le Goater 
10420990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10430990ce6aSGreg Kurz {
10440990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10450990ce6aSGreg Kurz 
10460990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10470990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10480990ce6aSGreg Kurz }
10490990ce6aSGreg Kurz 
105085913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
105185913070SGreg Kurz                                             Monitor *mon)
105285913070SGreg Kurz {
105385913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
105485913070SGreg Kurz }
105585913070SGreg Kurz 
10562b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10572b548a42SCédric Le Goater                                         Error **errp)
10582b548a42SCédric Le Goater {
1059da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1060da71b7e3SCédric Le Goater     Error *local_err = NULL;
1061da71b7e3SCédric Le Goater     Object *obj;
10622b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10632b548a42SCédric Le Goater 
1064da71b7e3SCédric Le Goater     /*
1065da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1066da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1067da71b7e3SCédric Le Goater      * only used at runtime.
1068da71b7e3SCédric Le Goater      */
1069da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1070da71b7e3SCédric Le Goater                            &local_err);
1071da71b7e3SCédric Le Goater     if (local_err) {
1072da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1073da71b7e3SCédric Le Goater         return;
1074da71b7e3SCédric Le Goater     }
1075da71b7e3SCédric Le Goater 
1076da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
10772b548a42SCédric Le Goater }
10782b548a42SCédric Le Goater 
10792b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10802b548a42SCédric Le Goater {
1081da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1082da71b7e3SCédric Le Goater 
1083da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
10842b548a42SCédric Le Goater }
10852b548a42SCédric Le Goater 
10862b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10872b548a42SCédric Le Goater {
10882b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10892b548a42SCédric Le Goater 
1090da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10912b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10922b548a42SCédric Le Goater }
10932b548a42SCédric Le Goater 
109485913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
109585913070SGreg Kurz                                              Monitor *mon)
109685913070SGreg Kurz {
1097da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
109885913070SGreg Kurz }
109985913070SGreg Kurz 
110059b7c1c2SBalamuruhan S /*
110159b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1102397a79e7SCédric Le Goater  *
1103397a79e7SCédric Le Goater  * <EX0 reserved>
1104397a79e7SCédric Le Goater  *  EX1  - Venice only
1105397a79e7SCédric Le Goater  *  EX2  - Venice only
1106397a79e7SCédric Le Goater  *  EX3  - Venice only
1107397a79e7SCédric Le Goater  *  EX4
1108397a79e7SCédric Le Goater  *  EX5
1109397a79e7SCédric Le Goater  *  EX6
1110397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1111397a79e7SCédric Le Goater  *  EX9  - Venice only
1112397a79e7SCédric Le Goater  *  EX10 - Venice only
1113397a79e7SCédric Le Goater  *  EX11 - Venice only
1114397a79e7SCédric Le Goater  *  EX12
1115397a79e7SCédric Le Goater  *  EX13
1116397a79e7SCédric Le Goater  *  EX14
1117397a79e7SCédric Le Goater  * <EX15 reserved>
1118397a79e7SCédric Le Goater  */
1119397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1120397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1121397a79e7SCédric Le Goater 
1122397a79e7SCédric Le Goater /*
112309279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1124397a79e7SCédric Le Goater  */
112509279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1126397a79e7SCédric Le Goater 
11272b548a42SCédric Le Goater 
11282b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
11292b548a42SCédric Le Goater 
113077864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
113177864267SCédric Le Goater {
113277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
11339ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
11349ae1329eSCédric Le Goater     int i;
113577864267SCédric Le Goater 
1136245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1137245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1138245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1139d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1140245cdb7fSCédric Le Goater 
11419fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
114277864267SCédric Le Goater 
11439fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
114477864267SCédric Le Goater 
11459fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
11463887d241SBalamuruhan S 
11479fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
11489ae1329eSCédric Le Goater 
1149eb93c828SCédric Le Goater     chip8->num_phbs = pcc->num_phbs;
11501f6a88ffSCédric Le Goater 
1151eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
11529fc7fc4dSMarkus Armbruster         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
11539ae1329eSCédric Le Goater     }
11549ae1329eSCédric Le Goater 
115577864267SCédric Le Goater }
115677864267SCédric Le Goater 
115777864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
115877864267SCédric Le Goater  {
115977864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
116077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
116177864267SCédric Le Goater     int i, j;
116277864267SCédric Le Goater     char *name;
116377864267SCédric Le Goater 
116477864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
116577864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
116677864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
116777864267SCédric Le Goater     g_free(name);
116877864267SCédric Le Goater 
116977864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
117077864267SCédric Le Goater 
117177864267SCédric Le Goater     /* Map the ICP registers for each thread */
117277864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
11734fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
117477864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
117577864267SCédric Le Goater 
117677864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
117777864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1178245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
117977864267SCédric Le Goater 
118077864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
118177864267SCédric Le Goater                                         &icp->mmio);
118277864267SCédric Le Goater         }
118377864267SCédric Le Goater     }
118477864267SCédric Le Goater }
118577864267SCédric Le Goater 
1186792e8bb6SDaniel Henrique Barboza /*
1187792e8bb6SDaniel Henrique Barboza  * Attach a root port device.
1188792e8bb6SDaniel Henrique Barboza  *
1189792e8bb6SDaniel Henrique Barboza  * 'index' will be used both as a PCIE slot value and to calculate
1190792e8bb6SDaniel Henrique Barboza  * QOM id. 'chip_id' is going to be used as PCIE chassis for the
1191792e8bb6SDaniel Henrique Barboza  * root port.
1192792e8bb6SDaniel Henrique Barboza  */
1193792e8bb6SDaniel Henrique Barboza void pnv_phb_attach_root_port(PCIHostState *pci, const char *name,
1194792e8bb6SDaniel Henrique Barboza                               int index, int chip_id)
1195a71cd51eSCédric Le Goater {
1196a71cd51eSCédric Le Goater     PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name);
11978625164aSDaniel Henrique Barboza     g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index);
11988625164aSDaniel Henrique Barboza     const char *dev_id = DEVICE(root)->id;
11998625164aSDaniel Henrique Barboza 
12008625164aSDaniel Henrique Barboza     object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id,
12018625164aSDaniel Henrique Barboza                               OBJECT(root));
1202a71cd51eSCédric Le Goater 
1203792e8bb6SDaniel Henrique Barboza     /* Set unique chassis/slot values for the root port */
1204792e8bb6SDaniel Henrique Barboza     qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id);
1205792e8bb6SDaniel Henrique Barboza     qdev_prop_set_uint16(DEVICE(root), "slot", index);
1206792e8bb6SDaniel Henrique Barboza 
1207a71cd51eSCédric Le Goater     pci_realize_and_unref(root, pci->bus, &error_fatal);
1208a71cd51eSCédric Le Goater }
1209a71cd51eSCédric Le Goater 
121077864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
121177864267SCédric Le Goater {
121277864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
121377864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
121477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1215ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
121677864267SCédric Le Goater     Error *local_err = NULL;
12179ae1329eSCédric Le Goater     int i;
121877864267SCédric Le Goater 
1219245cdb7fSCédric Le Goater     assert(chip8->xics);
1220245cdb7fSCédric Le Goater 
1221709044fdSCédric Le Goater     /* XSCOM bridge is first */
1222709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1223709044fdSCédric Le Goater     if (local_err) {
1224709044fdSCédric Le Goater         error_propagate(errp, local_err);
1225709044fdSCédric Le Goater         return;
1226709044fdSCédric Le Goater     }
1227709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1228709044fdSCédric Le Goater 
122977864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
123077864267SCédric Le Goater     if (local_err) {
123177864267SCédric Le Goater         error_propagate(errp, local_err);
123277864267SCédric Le Goater         return;
123377864267SCédric Le Goater     }
123477864267SCédric Le Goater 
123577864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
12365325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
12375325cc34SMarkus Armbruster                             &error_fatal);
12385325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
12395325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1240668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
124177864267SCédric Le Goater         return;
124277864267SCédric Le Goater     }
1243ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1244ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
124577864267SCédric Le Goater 
124677864267SCédric Le Goater     /* Create LPC controller */
1247ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
124877864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
124977864267SCédric Le Goater 
1250032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
125164d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
125264d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
125364d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
125464d011d5SCédric Le Goater 
125559b7c1c2SBalamuruhan S     /*
125659b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
125759b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
125859b7c1c2SBalamuruhan S      */
125977864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
126077864267SCédric Le Goater     if (local_err) {
126177864267SCédric Le Goater         error_propagate(errp, local_err);
126277864267SCédric Le Goater         return;
126377864267SCédric Le Goater     }
126477864267SCédric Le Goater 
126577864267SCédric Le Goater     /* Create the simplified OCC model */
1266668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
126777864267SCédric Le Goater         return;
126877864267SCédric Le Goater     }
126977864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1270b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1271b0ae5c69SCédric Le Goater                           qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC));
1272f3db8266SBalamuruhan S 
1273f3db8266SBalamuruhan S     /* OCC SRAM model */
12743a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1275f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
12763887d241SBalamuruhan S 
12773887d241SBalamuruhan S     /* HOMER */
12785325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1279f2582acfSGreg Kurz                              &error_abort);
1280668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
12813887d241SBalamuruhan S         return;
12823887d241SBalamuruhan S     }
12838f092316SCédric Le Goater     /* Homer Xscom region */
12848f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
12858f092316SCédric Le Goater 
12868f092316SCédric Le Goater     /* Homer mmio region */
12873887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
12883887d241SBalamuruhan S                                 &chip8->homer.regs);
12899ae1329eSCédric Le Goater 
12909ae1329eSCédric Le Goater     /* PHB3 controllers */
1291eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
12929ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
12939ae1329eSCédric Le Goater 
12945325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
12955325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
12969ae1329eSCédric Le Goater                                 &error_fatal);
12972c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
12982c4d3a50SCédric Le Goater                                  &error_fatal);
1299668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
13009ae1329eSCédric Le Goater             return;
13019ae1329eSCédric Le Goater         }
13029ae1329eSCédric Le Goater     }
130377864267SCédric Le Goater }
130477864267SCédric Le Goater 
130570c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
130670c059e9SGreg Kurz {
130770c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
130870c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
130970c059e9SGreg Kurz }
131070c059e9SGreg Kurz 
1311e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1312e997040eSCédric Le Goater {
1313e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1314e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1315e997040eSCédric Le Goater 
1316e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1317397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
13189ae1329eSCédric Le Goater     k->num_phbs = 3;
1319631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1320d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1321d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13220990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
132385913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
132404026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1325eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1326d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1327c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
132870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1329e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
133077864267SCédric Le Goater 
133177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
133277864267SCédric Le Goater                                     &k->parent_realize);
1333e997040eSCédric Le Goater }
1334e997040eSCédric Le Goater 
1335e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1336e997040eSCédric Le Goater {
1337e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1338e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1339e997040eSCédric Le Goater 
1340e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1341397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13429ae1329eSCédric Le Goater     k->num_phbs = 3;
1343631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1344d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1345d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13460990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
134785913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
134804026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1349eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1350d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1351c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
135270c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1353e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
135477864267SCédric Le Goater 
135577864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
135677864267SCédric Le Goater                                     &k->parent_realize);
1357e997040eSCédric Le Goater }
1358e997040eSCédric Le Goater 
1359e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1360e997040eSCédric Le Goater {
1361e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1362e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1363e997040eSCédric Le Goater 
1364e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1365397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1366316717feSCédric Le Goater     k->num_phbs = 4;
1367631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1368d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1369d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13700990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
137185913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
137204026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1373eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1374d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1375c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
137670c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1377e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
137877864267SCédric Le Goater 
137977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
138077864267SCédric Le Goater                                     &k->parent_realize);
138177864267SCédric Le Goater }
138277864267SCédric Le Goater 
138377864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
138477864267SCédric Le Goater {
13854f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13862dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13874f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13884f9924c4SBenjamin Herrenschmidt     int i;
13892dfa91a2SCédric Le Goater 
1390db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1391d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1392d2623129SMarkus Armbruster                               "xive-fabric");
1393c38536bcSCédric Le Goater 
13949fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
139515376c66SCédric Le Goater 
13969fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
13976598a70dSCédric Le Goater 
13989fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
13993887d241SBalamuruhan S 
14009fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
14014f9924c4SBenjamin Herrenschmidt 
1402422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1403422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1404422fd92eSCédric Le Goater 
1405422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14064f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
14079fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
14084f9924c4SBenjamin Herrenschmidt     }
140977864267SCédric Le Goater }
141077864267SCédric Le Goater 
1411ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1412ae4c68e3SCédric Le Goater                                       PnvCore *pnv_core)
14135dad902cSCédric Le Goater {
14145dad902cSCédric Le Goater     char eq_name[32];
14155dad902cSCédric Le Goater     int core_id = CPU_CORE(pnv_core)->core_id;
14165dad902cSCédric Le Goater 
14175dad902cSCédric Le Goater     snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14189fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
14199fc7fc4dSMarkus Armbruster                                        sizeof(*eq), TYPE_PNV_QUAD,
14209fc7fc4dSMarkus Armbruster                                        &error_fatal, NULL);
14215dad902cSCédric Le Goater 
142292612f15SCédric Le Goater     object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1423ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(eq), NULL, &error_fatal);
1424ae4c68e3SCédric Le Goater }
1425ae4c68e3SCédric Le Goater 
1426ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1427ae4c68e3SCédric Le Goater {
1428ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
1429ae4c68e3SCédric Le Goater     int i;
1430ae4c68e3SCédric Le Goater 
1431ae4c68e3SCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1432ae4c68e3SCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1433ae4c68e3SCédric Le Goater 
1434ae4c68e3SCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
1435ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
1436ae4c68e3SCédric Le Goater 
1437ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
14385dad902cSCédric Le Goater 
143992612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
14405dad902cSCédric Le Goater                                 &eq->xscom_regs);
14415dad902cSCédric Le Goater     }
14425dad902cSCédric Le Goater }
14435dad902cSCédric Le Goater 
144413480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
14454f9924c4SBenjamin Herrenschmidt {
14464f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
144713480fc5SCédric Le Goater     int i;
14484f9924c4SBenjamin Herrenschmidt 
1449422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14504f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
14514f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
14524f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
14534f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
14544f9924c4SBenjamin Herrenschmidt 
14555325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
14565325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
14574f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14586f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
14596f43d255SCédric Le Goater                                  &error_fatal);
1460668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14614f9924c4SBenjamin Herrenschmidt             return;
14624f9924c4SBenjamin Herrenschmidt         }
14634f9924c4SBenjamin Herrenschmidt 
14644f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14654f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14664f9924c4SBenjamin Herrenschmidt 
14674f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
14684f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
14694f9924c4SBenjamin Herrenschmidt     }
14704f9924c4SBenjamin Herrenschmidt }
14714f9924c4SBenjamin Herrenschmidt 
147277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
147377864267SCédric Le Goater {
147477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14752dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14762dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1477c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
147877864267SCédric Le Goater     Error *local_err = NULL;
147977864267SCédric Le Goater 
1480709044fdSCédric Le Goater     /* XSCOM bridge is first */
1481709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1482709044fdSCédric Le Goater     if (local_err) {
1483709044fdSCédric Le Goater         error_propagate(errp, local_err);
1484709044fdSCédric Le Goater         return;
1485709044fdSCédric Le Goater     }
1486709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1487709044fdSCédric Le Goater 
148877864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
148977864267SCédric Le Goater     if (local_err) {
149077864267SCédric Le Goater         error_propagate(errp, local_err);
149177864267SCédric Le Goater         return;
149277864267SCédric Le Goater     }
14932dfa91a2SCédric Le Goater 
14945dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14955dad902cSCédric Le Goater     if (local_err) {
14965dad902cSCédric Le Goater         error_propagate(errp, local_err);
14975dad902cSCédric Le Goater         return;
14985dad902cSCédric Le Goater     }
14995dad902cSCédric Le Goater 
15002dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
15015325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
15025325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
15035325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
15045325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
15055325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
15065325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
15075325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
15085325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
15095325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
15107ae54cc3SGreg Kurz                              &error_abort);
1511668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
15122dfa91a2SCédric Le Goater         return;
15132dfa91a2SCédric Le Goater     }
15142dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
15152dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1516c38536bcSCédric Le Goater 
1517c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15185325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
15195325cc34SMarkus Armbruster                             &error_fatal);
152024c8fa96SCédric Le Goater     /* This is the only device with 4k ESB pages */
152124c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
152224c8fa96SCédric Le Goater                             &error_fatal);
1523668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1524c38536bcSCédric Le Goater         return;
1525c38536bcSCédric Le Goater     }
1526c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1527c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
152815376c66SCédric Le Goater 
152915376c66SCédric Le Goater     /* LPC */
1530668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
153115376c66SCédric Le Goater         return;
153215376c66SCédric Le Goater     }
153315376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
153415376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
153515376c66SCédric Le Goater 
1536032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
153715376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
153815376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15396598a70dSCédric Le Goater 
15406598a70dSCédric Le Goater     /* Create the simplified OCC model */
1541668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
15426598a70dSCédric Le Goater         return;
15436598a70dSCédric Le Goater     }
15446598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1545b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1546b0ae5c69SCédric Le Goater                               DEVICE(&chip9->psi), PSIHB9_IRQ_OCC));
1547f3db8266SBalamuruhan S 
1548f3db8266SBalamuruhan S     /* OCC SRAM model */
15493a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1550f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15513887d241SBalamuruhan S 
15523887d241SBalamuruhan S     /* HOMER */
15535325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1554f2582acfSGreg Kurz                              &error_abort);
1555668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15563887d241SBalamuruhan S         return;
15573887d241SBalamuruhan S     }
15588f092316SCédric Le Goater     /* Homer Xscom region */
15598f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15608f092316SCédric Le Goater 
15618f092316SCédric Le Goater     /* Homer mmio region */
15623887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15633887d241SBalamuruhan S                                 &chip9->homer.regs);
15644f9924c4SBenjamin Herrenschmidt 
156513480fc5SCédric Le Goater     /* PEC PHBs */
156613480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
15674f9924c4SBenjamin Herrenschmidt     if (local_err) {
15684f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15694f9924c4SBenjamin Herrenschmidt         return;
15704f9924c4SBenjamin Herrenschmidt     }
1571e997040eSCédric Le Goater }
1572e997040eSCédric Le Goater 
157370c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
157470c059e9SGreg Kurz {
157570c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
157670c059e9SGreg Kurz     return addr >> 3;
157770c059e9SGreg Kurz }
157870c059e9SGreg Kurz 
1579e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1580e997040eSCédric Le Goater {
1581e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1582e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1583e997040eSCédric Le Goater 
158483028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1585397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1586631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1587d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1588d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15890990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
159085913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
159104026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1592eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1593d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1594c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
159570c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1596e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1597422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
159877864267SCédric Le Goater 
159977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
160077864267SCédric Le Goater                                     &k->parent_realize);
1601e997040eSCédric Le Goater }
1602e997040eSCédric Le Goater 
16032b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
16042b548a42SCédric Le Goater {
1605623575e1SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
16068b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1607623575e1SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1608623575e1SCédric Le Goater     int i;
16098b50ce85SCédric Le Goater 
1610da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1611da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1612da71b7e3SCédric Le Goater                               "xive-fabric");
16139fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
16149fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
16158bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
161692499676SCédric Le Goater     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1617623575e1SCédric Le Goater 
1618623575e1SCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1619623575e1SCédric Le Goater 
1620623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1621623575e1SCédric Le Goater         object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1622623575e1SCédric Le Goater                                 TYPE_PNV_PHB5_PEC);
1623623575e1SCédric Le Goater     }
16242b548a42SCédric Le Goater }
16252b548a42SCédric Le Goater 
1626ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1627ae4c68e3SCédric Le Goater {
1628ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip10);
1629ae4c68e3SCédric Le Goater     int i;
1630ae4c68e3SCédric Le Goater 
1631ae4c68e3SCédric Le Goater     chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1632ae4c68e3SCédric Le Goater     chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1633ae4c68e3SCédric Le Goater 
1634ae4c68e3SCédric Le Goater     for (i = 0; i < chip10->nr_quads; i++) {
1635ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip10->quads[i];
1636ae4c68e3SCédric Le Goater 
1637ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
1638ae4c68e3SCédric Le Goater 
1639ae4c68e3SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1640ae4c68e3SCédric Le Goater                                 &eq->xscom_regs);
1641ae4c68e3SCédric Le Goater     }
1642ae4c68e3SCédric Le Goater }
1643ae4c68e3SCédric Le Goater 
1644623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1645623575e1SCédric Le Goater {
1646623575e1SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1647623575e1SCédric Le Goater     int i;
1648623575e1SCédric Le Goater 
1649623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1650623575e1SCédric Le Goater         PnvPhb4PecState *pec = &chip10->pecs[i];
1651623575e1SCédric Le Goater         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1652623575e1SCédric Le Goater         uint32_t pec_nest_base;
1653623575e1SCédric Le Goater         uint32_t pec_pci_base;
1654623575e1SCédric Le Goater 
1655623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1656623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1657623575e1SCédric Le Goater                                 &error_fatal);
1658623575e1SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1659623575e1SCédric Le Goater                                  &error_fatal);
1660623575e1SCédric Le Goater         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1661623575e1SCédric Le Goater             return;
1662623575e1SCédric Le Goater         }
1663623575e1SCédric Le Goater 
1664623575e1SCédric Le Goater         pec_nest_base = pecc->xscom_nest_base(pec);
1665623575e1SCédric Le Goater         pec_pci_base = pecc->xscom_pci_base(pec);
1666623575e1SCédric Le Goater 
1667623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1668623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1669623575e1SCédric Le Goater     }
1670623575e1SCédric Le Goater }
1671623575e1SCédric Le Goater 
16722b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
16732b548a42SCédric Le Goater {
16742b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
16752b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
16768b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
16772b548a42SCédric Le Goater     Error *local_err = NULL;
16782b548a42SCédric Le Goater 
16792b548a42SCédric Le Goater     /* XSCOM bridge is first */
16802b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
16812b548a42SCédric Le Goater     if (local_err) {
16822b548a42SCédric Le Goater         error_propagate(errp, local_err);
16832b548a42SCédric Le Goater         return;
16842b548a42SCédric Le Goater     }
16852b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
16862b548a42SCédric Le Goater 
16872b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
16882b548a42SCédric Le Goater     if (local_err) {
16892b548a42SCédric Le Goater         error_propagate(errp, local_err);
16902b548a42SCédric Le Goater         return;
16912b548a42SCédric Le Goater     }
16928b50ce85SCédric Le Goater 
1693ae4c68e3SCédric Le Goater     pnv_chip_power10_quad_realize(chip10, &local_err);
1694ae4c68e3SCédric Le Goater     if (local_err) {
1695ae4c68e3SCédric Le Goater         error_propagate(errp, local_err);
1696ae4c68e3SCédric Le Goater         return;
1697ae4c68e3SCédric Le Goater     }
1698ae4c68e3SCédric Le Goater 
1699da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1700da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1701da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1702da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1703da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1704da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1705da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1706da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1707da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1708da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1709da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1710da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1711da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1712da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1713da71b7e3SCédric Le Goater                              &error_abort);
1714da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1715da71b7e3SCédric Le Goater         return;
1716da71b7e3SCédric Le Goater     }
1717da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1718da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1719da71b7e3SCédric Le Goater 
17208b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
17215325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
17225325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
172324c8fa96SCédric Le Goater     /* PSI can now be configured to use 64k ESB pages on POWER10 */
172424c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
172524c8fa96SCédric Le Goater                             &error_fatal);
1726668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
17278b50ce85SCédric Le Goater         return;
17288b50ce85SCédric Le Goater     }
17298b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
17308b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
17312661f6abSCédric Le Goater 
17322661f6abSCédric Le Goater     /* LPC */
1733668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
17342661f6abSCédric Le Goater         return;
17352661f6abSCédric Le Goater     }
17362661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
17372661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
17382661f6abSCédric Le Goater 
1739032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
17402661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
17412661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
17428bf682a3SCédric Le Goater 
17438bf682a3SCédric Le Goater     /* Create the simplified OCC model */
17448bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
17458bf682a3SCédric Le Goater         return;
17468bf682a3SCédric Le Goater     }
17478bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
17488bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
1749b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1750b0ae5c69SCédric Le Goater                               DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1751623575e1SCédric Le Goater 
175292499676SCédric Le Goater     /* OCC SRAM model */
175392499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(),
175492499676SCédric Le Goater                                 PNV10_OCC_SENSOR_BASE(chip),
175592499676SCédric Le Goater                                 &chip10->occ.sram_regs);
175692499676SCédric Le Goater 
175792499676SCédric Le Goater     /* HOMER */
175892499676SCédric Le Goater     object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
175992499676SCédric Le Goater                              &error_abort);
176092499676SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
176192499676SCédric Le Goater         return;
176292499676SCédric Le Goater     }
176392499676SCédric Le Goater     /* Homer Xscom region */
176492499676SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
176592499676SCédric Le Goater                             &chip10->homer.pba_regs);
176692499676SCédric Le Goater 
176792499676SCédric Le Goater     /* Homer mmio region */
176892499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
176992499676SCédric Le Goater                                 &chip10->homer.regs);
177092499676SCédric Le Goater 
1771623575e1SCédric Le Goater     /* PHBs */
1772623575e1SCédric Le Goater     pnv_chip_power10_phb_realize(chip, &local_err);
1773623575e1SCédric Le Goater     if (local_err) {
1774623575e1SCédric Le Goater         error_propagate(errp, local_err);
1775623575e1SCédric Le Goater         return;
1776623575e1SCédric Le Goater     }
17772b548a42SCédric Le Goater }
17782b548a42SCédric Le Goater 
177970c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
178070c059e9SGreg Kurz {
178170c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
178270c059e9SGreg Kurz     return addr >> 3;
178370c059e9SGreg Kurz }
178470c059e9SGreg Kurz 
17852b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
17862b548a42SCédric Le Goater {
17872b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
17882b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
17892b548a42SCédric Le Goater 
17902b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
17912b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
17922b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
17932b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
17942b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
17952b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
179685913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
17972b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
17982b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
17992b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1800c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
180170c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
18022b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
1803623575e1SCédric Le Goater     k->num_pecs = PNV10_CHIP_MAX_PEC;
18042b548a42SCédric Le Goater 
18052b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
18062b548a42SCédric Le Goater                                     &k->parent_realize);
18072b548a42SCédric Le Goater }
18082b548a42SCédric Le Goater 
1809397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1810397a79e7SCédric Le Goater {
1811397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1812397a79e7SCédric Le Goater     int cores_max;
1813397a79e7SCédric Le Goater 
1814397a79e7SCédric Le Goater     /*
1815397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1816397a79e7SCédric Le Goater      * the chip class
1817397a79e7SCédric Le Goater      */
1818397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1819397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1820397a79e7SCédric Le Goater     }
1821397a79e7SCédric Le Goater 
1822397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1823397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1824397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1825397a79e7SCédric Le Goater                    chip->cores_mask);
1826397a79e7SCédric Le Goater         return;
1827397a79e7SCédric Le Goater     }
1828397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1829397a79e7SCédric Le Goater 
1830397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
183127d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1832397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1833397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1834397a79e7SCédric Le Goater                    cores_max);
1835397a79e7SCédric Le Goater         return;
1836397a79e7SCédric Le Goater     }
1837397a79e7SCédric Le Goater }
1838397a79e7SCédric Le Goater 
183951c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1840e997040eSCédric Le Goater {
1841397a79e7SCédric Le Goater     Error *error = NULL;
1842d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
184340abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1844d2fd9612SCédric Le Goater     int i, core_hwid;
184508c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1846397a79e7SCédric Le Goater 
1847d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1848d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1849d2fd9612SCédric Le Goater         return;
1850d2fd9612SCédric Le Goater     }
1851d2fd9612SCédric Le Goater 
1852d2fd9612SCédric Le Goater     /* Cores */
1853397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1854397a79e7SCédric Le Goater     if (error) {
1855397a79e7SCédric Le Goater         error_propagate(errp, error);
1856397a79e7SCédric Le Goater         return;
1857397a79e7SCédric Le Goater     }
1858d2fd9612SCédric Le Goater 
18594fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1860d2fd9612SCédric Le Goater 
1861d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1862d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1863d2fd9612SCédric Le Goater         char core_name[32];
18644fa28f23SGreg Kurz         PnvCore *pnv_core;
1865c035851aSCédric Le Goater         uint64_t xscom_core_base;
1866d2fd9612SCédric Le Goater 
1867d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1868d2fd9612SCédric Le Goater             continue;
1869d2fd9612SCédric Le Goater         }
1870d2fd9612SCédric Le Goater 
18714fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
18724fa28f23SGreg Kurz 
1873d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1874d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
18754fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
18765325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
18775325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
18785325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
18795325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
18805325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
18815325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
18825325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
18835325cc34SMarkus Armbruster                                 &error_fatal);
18845325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1885158e17a6SGreg Kurz                                  &error_abort);
1886ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
188724ece072SCédric Le Goater 
188824ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1889c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1890c035851aSCédric Le Goater 
1891c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
18924fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1893d2fd9612SCédric Le Goater         i++;
1894d2fd9612SCédric Le Goater     }
189551c04728SCédric Le Goater }
189651c04728SCédric Le Goater 
189751c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
189851c04728SCédric Le Goater {
189951c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
190051c04728SCédric Le Goater     Error *error = NULL;
190151c04728SCédric Le Goater 
190251c04728SCédric Le Goater     /* Cores */
190351c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
190451c04728SCédric Le Goater     if (error) {
190551c04728SCédric Le Goater         error_propagate(errp, error);
190651c04728SCédric Le Goater         return;
190751c04728SCédric Le Goater     }
1908e997040eSCédric Le Goater }
1909e997040eSCédric Le Goater 
1910e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1911e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1912e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1913e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1914397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1915397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1916764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
1917e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1918e997040eSCédric Le Goater };
1919e997040eSCédric Le Goater 
1920e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1921e997040eSCédric Le Goater {
1922e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1923e997040eSCédric Le Goater 
19249d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1925e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
19264f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1927e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1928e997040eSCédric Le Goater }
1929e997040eSCédric Le Goater 
1930119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1931119eaa9dSCédric Le Goater {
1932119eaa9dSCédric Le Goater     int i, j;
1933119eaa9dSCédric Le Goater 
1934119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1935119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1936119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1937119eaa9dSCédric Le Goater 
1938119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1939119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1940119eaa9dSCédric Le Goater                 return pc->threads[j];
1941119eaa9dSCédric Le Goater             }
1942119eaa9dSCédric Le Goater         }
1943119eaa9dSCédric Le Goater     }
1944119eaa9dSCédric Le Goater     return NULL;
1945119eaa9dSCédric Le Goater }
1946119eaa9dSCédric Le Goater 
194754f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
194854f59d78SCédric Le Goater {
1949b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
1950da6be501SDaniel Henrique Barboza     int i, j;
195154f59d78SCédric Le Goater 
195254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
195377864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
195477864267SCédric Le Goater 
195577864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
195677864267SCédric Le Goater             return &chip8->psi.ics;
195754f59d78SCédric Le Goater         }
19582ff73ddaSCédric Le Goater 
1959da6be501SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
1960da6be501SDaniel Henrique Barboza             PnvPHB3 *phb3 = &chip8->phbs[j];
1961da6be501SDaniel Henrique Barboza 
1962da6be501SDaniel Henrique Barboza             if (ics_valid_irq(&phb3->lsis, irq)) {
1963da6be501SDaniel Henrique Barboza                 return &phb3->lsis;
1964da6be501SDaniel Henrique Barboza             }
1965da6be501SDaniel Henrique Barboza 
1966da6be501SDaniel Henrique Barboza             if (ics_valid_irq(ICS(&phb3->msis), irq)) {
1967da6be501SDaniel Henrique Barboza                 return ICS(&phb3->msis);
1968da6be501SDaniel Henrique Barboza             }
19699ae1329eSCédric Le Goater         }
197054f59d78SCédric Le Goater     }
197154f59d78SCédric Le Goater     return NULL;
197254f59d78SCédric Le Goater }
197354f59d78SCédric Le Goater 
19741f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
19751f6a88ffSCédric Le Goater {
19761f6a88ffSCédric Le Goater     int i;
19771f6a88ffSCédric Le Goater 
19781f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
19791f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
19801f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
19811f6a88ffSCédric Le Goater             return chip;
19821f6a88ffSCédric Le Goater         }
19831f6a88ffSCédric Le Goater     }
19841f6a88ffSCédric Le Goater     return NULL;
19851f6a88ffSCédric Le Goater }
19861f6a88ffSCédric Le Goater 
198754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
198854f59d78SCédric Le Goater {
1989b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
1990ca459489SDaniel Henrique Barboza     int i, j;
199154f59d78SCédric Le Goater 
199254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
199377864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
19949ae1329eSCédric Le Goater 
199577864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
1996ca459489SDaniel Henrique Barboza 
1997ca459489SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
1998ca459489SDaniel Henrique Barboza             PnvPHB3 *phb3 = &chip8->phbs[j];
1999ca459489SDaniel Henrique Barboza 
2000ca459489SDaniel Henrique Barboza             ics_resend(&phb3->lsis);
2001ca459489SDaniel Henrique Barboza             ics_resend(ICS(&phb3->msis));
2002ca459489SDaniel Henrique Barboza         }
200354f59d78SCédric Le Goater     }
200454f59d78SCédric Le Goater }
200554f59d78SCédric Le Goater 
200636fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
200736fc6f08SCédric Le Goater {
200836fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
200936fc6f08SCédric Le Goater 
2010956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
201136fc6f08SCédric Le Goater }
201236fc6f08SCédric Le Goater 
201347fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
201447fea43aSCédric Le Goater                                Monitor *mon)
201547fea43aSCédric Le Goater {
2016b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
201754f59d78SCédric Le Goater     int i;
201847fea43aSCédric Le Goater     CPUState *cs;
201947fea43aSCédric Le Goater 
202047fea43aSCédric Le Goater     CPU_FOREACH(cs) {
202147fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
202247fea43aSCédric Le Goater 
202385913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
202485913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
202585913070SGreg Kurz                                                            mon);
2026d8e4aad5SCédric Le Goater     }
202754f59d78SCédric Le Goater 
202854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2029d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
203054f59d78SCédric Le Goater     }
203147fea43aSCédric Le Goater }
203247fea43aSCédric Le Goater 
2033c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2034c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
2035c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
2036c722579eSCédric Le Goater                          uint32_t logic_serv,
2037c722579eSCédric Le Goater                          XiveTCTXMatch *match)
2038c722579eSCédric Le Goater {
2039c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2040c722579eSCédric Le Goater     int total_count = 0;
2041c722579eSCédric Le Goater     int i;
2042c722579eSCédric Le Goater 
2043c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2044c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2045c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2046c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2047c722579eSCédric Le Goater         int count;
2048c722579eSCédric Le Goater 
2049c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2050c722579eSCédric Le Goater                                priority, logic_serv, match);
2051c722579eSCédric Le Goater 
2052c722579eSCédric Le Goater         if (count < 0) {
2053c722579eSCédric Le Goater             return count;
2054c722579eSCédric Le Goater         }
2055c722579eSCédric Le Goater 
2056c722579eSCédric Le Goater         total_count += count;
2057c722579eSCédric Le Goater     }
2058c722579eSCédric Le Goater 
2059c722579eSCédric Le Goater     return total_count;
2060c722579eSCédric Le Goater }
2061c722579eSCédric Le Goater 
2062da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2063da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
2064da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
2065da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
2066da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
2067da71b7e3SCédric Le Goater {
2068da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2069da71b7e3SCédric Le Goater     int total_count = 0;
2070da71b7e3SCédric Le Goater     int i;
2071da71b7e3SCédric Le Goater 
2072da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2073da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2074da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2075da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2076da71b7e3SCédric Le Goater         int count;
2077da71b7e3SCédric Le Goater 
2078da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2079da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2080da71b7e3SCédric Le Goater 
2081da71b7e3SCédric Le Goater         if (count < 0) {
2082da71b7e3SCédric Le Goater             return count;
2083da71b7e3SCédric Le Goater         }
2084da71b7e3SCédric Le Goater 
2085da71b7e3SCédric Le Goater         total_count += count;
2086da71b7e3SCédric Le Goater     }
2087da71b7e3SCédric Le Goater 
2088da71b7e3SCédric Le Goater     return total_count;
2089da71b7e3SCédric Le Goater }
2090da71b7e3SCédric Le Goater 
2091f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
20929e933f4aSBenjamin Herrenschmidt {
20939e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
209436fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2095d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2096d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2097f30c843cSCédric Le Goater 
2098f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2099f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
2100f30c843cSCédric Le Goater 
2101f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2102f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2103f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2104d76f2da7SGreg Kurz 
2105d76f2da7SGreg Kurz     pmc->compat = compat;
2106d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2107f30c843cSCédric Le Goater }
2108f30c843cSCédric Le Goater 
2109f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2110f30c843cSCédric Le Goater {
2111f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2112c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2113d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2114d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2115f30c843cSCédric Le Goater 
2116f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2117f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
2118c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2119f30c843cSCédric Le Goater 
2120f30c843cSCédric Le Goater     mc->alias = "powernv";
2121d76f2da7SGreg Kurz 
2122d76f2da7SGreg Kurz     pmc->compat = compat;
2123d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
21247a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2125f30c843cSCédric Le Goater }
2126f30c843cSCédric Le Goater 
21272b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
21282b548a42SCédric Le Goater {
21292b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2130d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2131da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2132d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
21332b548a42SCédric Le Goater 
21342b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
21356bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2136d76f2da7SGreg Kurz 
2137d76f2da7SGreg Kurz     pmc->compat = compat;
2138d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
21397a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2140da71b7e3SCédric Le Goater 
2141da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
21422b548a42SCédric Le Goater }
21432b548a42SCédric Le Goater 
214408c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
214508c3f3a7SCédric Le Goater {
214608c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
214708c3f3a7SCédric Le Goater 
214808c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
214908c3f3a7SCédric Le Goater }
215008c3f3a7SCédric Le Goater 
215108c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
215208c3f3a7SCédric Le Goater {
215308c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
215408c3f3a7SCédric Le Goater 
215508c3f3a7SCédric Le Goater     if (value) {
215608c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
215708c3f3a7SCédric Le Goater     }
215808c3f3a7SCédric Le Goater }
215908c3f3a7SCédric Le Goater 
216001b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
216101b552b0SNicholas Piggin {
216201b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
216301b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
216401b552b0SNicholas Piggin 
216501b552b0SNicholas Piggin     cpu_synchronize_state(cs);
216601b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
21670911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
216801b552b0SNicholas Piggin         /*
2169fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2170fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2171fe837714SNicholas Piggin          * (PPC_BIT(43)).
217201b552b0SNicholas Piggin          */
21730911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2174fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
21750911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
217601b552b0SNicholas Piggin         }
2177fe837714SNicholas Piggin     } else {
2178fe837714SNicholas Piggin         /*
2179fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2180fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2181fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2182fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2183fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2184fe837714SNicholas Piggin          */
21850911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2186fe837714SNicholas Piggin     }
2187fe837714SNicholas Piggin }
218801b552b0SNicholas Piggin 
218901b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
219001b552b0SNicholas Piggin {
219101b552b0SNicholas Piggin     CPUState *cs;
219201b552b0SNicholas Piggin 
219301b552b0SNicholas Piggin     CPU_FOREACH(cs) {
219401b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
219501b552b0SNicholas Piggin     }
219601b552b0SNicholas Piggin }
219701b552b0SNicholas Piggin 
2198f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2199f30c843cSCédric Le Goater {
2200f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
220147fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
220201b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
22039e933f4aSBenjamin Herrenschmidt 
22049e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2205b168a138SCédric Le Goater     mc->init = pnv_init;
2206b168a138SCédric Le Goater     mc->reset = pnv_reset;
22079e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
220859b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
220959b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
22109e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
22119e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2212f1d18b0aSJoel Stanley     /*
2213f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2214f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2215f1d18b0aSJoel Stanley      */
2216dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2217173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
221847fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
221901b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
222008c3f3a7SCédric Le Goater 
222108c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2222d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
222308c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
22247eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
22259e933f4aSBenjamin Herrenschmidt }
22269e933f4aSBenjamin Herrenschmidt 
222777864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2228beba5c0fSIgor Mammedov     {                                             \
2229beba5c0fSIgor Mammedov         .name          = type,                    \
2230beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
223177864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
223277864267SCédric Le Goater     }
223377864267SCédric Le Goater 
223477864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
223577864267SCédric Le Goater     {                                             \
223677864267SCédric Le Goater         .name          = type,                    \
223777864267SCédric Le Goater         .class_init    = class_initfn,            \
223877864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2239beba5c0fSIgor Mammedov     }
2240beba5c0fSIgor Mammedov 
22412b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
22422b548a42SCédric Le Goater     {                                              \
22432b548a42SCédric Le Goater         .name          = type,                     \
22442b548a42SCédric Le Goater         .class_init    = class_initfn,             \
22452b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
22462b548a42SCédric Le Goater     }
22472b548a42SCédric Le Goater 
2248beba5c0fSIgor Mammedov static const TypeInfo types[] = {
22491aba8716SCédric Le Goater     {
22502b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
22512b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
22522b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2253da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2254da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2255da71b7e3SCédric Le Goater             { },
2256da71b7e3SCédric Le Goater         },
22572b548a42SCédric Le Goater     },
22582b548a42SCédric Le Goater     {
22591aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
22601aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
22611aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2262c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2263c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2264c722579eSCédric Le Goater             { },
2265c722579eSCédric Le Goater         },
22661aba8716SCédric Le Goater     },
22671aba8716SCédric Le Goater     {
22681aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
22691aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
22701aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
22711aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
22721aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
22731aba8716SCédric Le Goater             { },
22741aba8716SCédric Le Goater         },
22751aba8716SCédric Le Goater     },
2276beba5c0fSIgor Mammedov     {
2277b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
22789e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2279f30c843cSCédric Le Goater         .abstract       = true,
22809e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2281b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2282d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
228336fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
228447fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
228501b552b0SNicholas Piggin             { TYPE_NMI },
228636fc6f08SCédric Le Goater             { },
228736fc6f08SCédric Le Goater         },
2288beba5c0fSIgor Mammedov     },
2289beba5c0fSIgor Mammedov     {
2290beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2291beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2292beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2293beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2294beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2295beba5c0fSIgor Mammedov         .abstract      = true,
2296beba5c0fSIgor Mammedov     },
229777864267SCédric Le Goater 
229877864267SCédric Le Goater     /*
22992b548a42SCédric Le Goater      * P10 chip and variants
23002b548a42SCédric Le Goater      */
23012b548a42SCédric Le Goater     {
23022b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
23032b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
23042b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
23052b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
23062b548a42SCédric Le Goater     },
23072b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
23082b548a42SCédric Le Goater 
23092b548a42SCédric Le Goater     /*
231077864267SCédric Le Goater      * P9 chip and variants
231177864267SCédric Le Goater      */
231277864267SCédric Le Goater     {
231377864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
231477864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
231577864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
231677864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
231777864267SCédric Le Goater     },
231877864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
231977864267SCédric Le Goater 
232077864267SCédric Le Goater     /*
232177864267SCédric Le Goater      * P8 chip and variants
232277864267SCédric Le Goater      */
232377864267SCédric Le Goater     {
232477864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
232577864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
232677864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
232777864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
232877864267SCédric Le Goater     },
232977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
233077864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
233177864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2332beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
23339e933f4aSBenjamin Herrenschmidt };
23349e933f4aSBenjamin Herrenschmidt 
2335beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2336