xref: /qemu/hw/ppc/pnv.c (revision 2c6fe2e2)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
9f70c5966SChetan Pant  * version 2.1 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
212c65db5eSPaolo Bonzini #include "qemu/datadir.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
23dd7ef911SCédric Le Goater #include "qemu/cutils.h"
249e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
2538d2448aSGreg Kurz #include "sysemu/qtest.h"
269e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
279e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2871e8a915SMarkus Armbruster #include "sysemu/reset.h"
2954d31236SMarkus Armbruster #include "sysemu/runstate.h"
30d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
318d409261SCédric Le Goater #include "sysemu/device_tree.h"
3201b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
33fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
3901b552b0SNicholas Piggin #include "hw/nmi.h"
40e997040eSCédric Le Goater #include "qapi/visitor.h"
4147fea43aSCédric Le Goater #include "monitor/monitor.h"
4247fea43aSCédric Le Goater #include "hw/intc/intc.h"
43aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4458969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
454f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h"
461f5d6b2aSDaniel Henrique Barboza #include "hw/pci-host/pnv_phb.h"
472c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb3.h"
482c6fe2e2SMarkus Armbruster #include "hw/pci-host/pnv_phb4.h"
499e933f4aSBenjamin Herrenschmidt 
5036fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
51a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
522c6fe2e2SMarkus Armbruster #include "hw/ppc/pnv_chip.h"
53967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5435dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
55967b7523SCédric Le Goater 
563495b6b6SCédric Le Goater #include "hw/isa/isa.h"
573495b6b6SCédric Le Goater #include "hw/char/serial.h"
58bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
593495b6b6SCédric Le Goater 
609e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
619e933f4aSBenjamin Herrenschmidt 
62b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
639e933f4aSBenjamin Herrenschmidt 
649e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
659e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
6683fa6e2aSCédric Le Goater #define FW_MAX_SIZE             (16 * MiB)
679e933f4aSBenjamin Herrenschmidt 
689e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
6905ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE         (128 * MiB)
7005ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR        0x28000000
7105ce9b73SCédric Le Goater #define INITRD_MAX_SIZE         (128 * MiB)
729e933f4aSBenjamin Herrenschmidt 
7340abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7440abf43fSIgor Mammedov {
7540abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7640abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7740abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7840abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7940abf43fSIgor Mammedov     g_free(s);
8040abf43fSIgor Mammedov     return core_type;
8140abf43fSIgor Mammedov }
8240abf43fSIgor Mammedov 
839e933f4aSBenjamin Herrenschmidt /*
849e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
859e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
869e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
879e933f4aSBenjamin Herrenschmidt  */
889e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
899e933f4aSBenjamin Herrenschmidt 
909e933f4aSBenjamin Herrenschmidt /*
919e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
929e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
939e933f4aSBenjamin Herrenschmidt  * per chip.
949e933f4aSBenjamin Herrenschmidt  */
95b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
969e933f4aSBenjamin Herrenschmidt {
979e933f4aSBenjamin Herrenschmidt     char *mem_name;
989e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
999e933f4aSBenjamin Herrenschmidt     int off;
1009e933f4aSBenjamin Herrenschmidt 
1019e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
1029e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
1039e933f4aSBenjamin Herrenschmidt 
1049e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1059e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1069e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1079e933f4aSBenjamin Herrenschmidt 
1089e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1099e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1109e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1119e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1129e933f4aSBenjamin Herrenschmidt }
1139e933f4aSBenjamin Herrenschmidt 
114d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
115d2fd9612SCédric Le Goater {
116d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
117d2fd9612SCédric Le Goater 
118d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
119a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
120d2fd9612SCédric Le Goater         if (cpus_offset) {
121d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
122d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
123d2fd9612SCédric Le Goater         }
124d2fd9612SCédric Le Goater     }
125d2fd9612SCédric Le Goater     _FDT(cpus_offset);
126d2fd9612SCédric Le Goater     return cpus_offset;
127d2fd9612SCédric Le Goater }
128d2fd9612SCédric Le Goater 
129d2fd9612SCédric Le Goater /*
130d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
131d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
132d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
133d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
134d2fd9612SCédric Le Goater  * servers.
135d2fd9612SCédric Le Goater  */
136b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
137d2fd9612SCédric Le Goater {
13808304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13908304a86SDavid Gibson     CPUState *cs = CPU(cpu);
140d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1418bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
142d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
143d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
144a580fdcdSPhilippe Mathieu-Daudé     g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
145d2fd9612SCédric Le Goater     int i;
146d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
147d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
148d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
149d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
150d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
151d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
152d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
153d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
154d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
155d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
156d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
157d2fd9612SCédric Le Goater     int offset;
158d2fd9612SCédric Le Goater     char *nodename;
159d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
160d2fd9612SCédric Le Goater 
161d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
162d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
163d2fd9612SCédric Le Goater     _FDT(offset);
164d2fd9612SCédric Le Goater     g_free(nodename);
165d2fd9612SCédric Le Goater 
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
167d2fd9612SCédric Le Goater 
168d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
171d2fd9612SCédric Le Goater 
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
174d2fd9612SCédric Le Goater                             env->dcache_line_size)));
175d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
176d2fd9612SCédric Le Goater                             env->dcache_line_size)));
177d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
178d2fd9612SCédric Le Goater                             env->icache_line_size)));
179d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
180d2fd9612SCédric Le Goater                             env->icache_line_size)));
181d2fd9612SCédric Le Goater 
182d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
183d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
184d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
185d2fd9612SCédric Le Goater     } else {
1863dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
187d2fd9612SCédric Le Goater     }
188d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
189d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
190d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
191d2fd9612SCédric Le Goater     } else {
1923dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
193d2fd9612SCédric Le Goater     }
194d2fd9612SCédric Le Goater 
195d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
196d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19759b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19859b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
199d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
200d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
201d2fd9612SCédric Le Goater 
20203282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
203d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
204d2fd9612SCédric Le Goater     }
205d2fd9612SCédric Le Goater 
20658969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
207d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
208d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
209d2fd9612SCédric Le Goater     }
210d2fd9612SCédric Le Goater 
21159b7c1c2SBalamuruhan S     /*
21259b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
213d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
214d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21559b7c1c2SBalamuruhan S      *   2               == VSX available
21659b7c1c2SBalamuruhan S      */
217d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
218d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
219d2fd9612SCédric Le Goater 
220d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
221d2fd9612SCédric Le Goater     }
222d2fd9612SCédric Le Goater 
22359b7c1c2SBalamuruhan S     /*
22459b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
225d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22659b7c1c2SBalamuruhan S      *   1               == DFP available
22759b7c1c2SBalamuruhan S      */
228d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
229d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
230d2fd9612SCédric Le Goater     }
231d2fd9612SCédric Le Goater 
232644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
233d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
234d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
235d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
236d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
237d2fd9612SCédric Le Goater     }
238d2fd9612SCédric Le Goater 
239d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
240d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
241d2fd9612SCédric Le Goater 
242d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
243d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
244d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
245d2fd9612SCédric Le Goater     }
246d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
247a580fdcdSPhilippe Mathieu-Daudé                        servers_prop, sizeof(*servers_prop) * smt_threads)));
248d2fd9612SCédric Le Goater }
249d2fd9612SCédric Le Goater 
250b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
251bf5615e7SCédric Le Goater                        uint32_t nr_threads)
252bf5615e7SCédric Le Goater {
253bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
254bf5615e7SCédric Le Goater     char *name;
255bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
256bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
257bf5615e7SCédric Le Goater     uint64_t *reg;
258bf5615e7SCédric Le Goater     int offset;
259bf5615e7SCédric Le Goater 
260bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
261bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
262bf5615e7SCédric Le Goater 
263bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
264bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
265bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
266bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
267bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
268bf5615e7SCédric Le Goater     }
269bf5615e7SCédric Le Goater 
270bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
271bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
272bf5615e7SCédric Le Goater     _FDT(offset);
273bf5615e7SCédric Le Goater     g_free(name);
274bf5615e7SCédric Le Goater 
275bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
278bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
279bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
280bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
281bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
282bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
283bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
284bf5615e7SCédric Le Goater     g_free(reg);
285bf5615e7SCédric Le Goater }
286bf5615e7SCédric Le Goater 
287c1471772SDaniel Henrique Barboza static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb,
288c1471772SDaniel Henrique Barboza                                          Error **errp)
289c1471772SDaniel Henrique Barboza {
290607e9316SDaniel Henrique Barboza     PnvPHB *phb_base = phb->phb_base;
291607e9316SDaniel Henrique Barboza     PnvPhb4PecState *pecs = NULL;
292c1471772SDaniel Henrique Barboza     int chip_id = phb->chip_id;
293c1471772SDaniel Henrique Barboza     int index = phb->phb_id;
294c1471772SDaniel Henrique Barboza     int i, j;
295c1471772SDaniel Henrique Barboza 
296607e9316SDaniel Henrique Barboza     if (phb_base->version == 4) {
297607e9316SDaniel Henrique Barboza         Pnv9Chip *chip9 = PNV9_CHIP(chip);
298607e9316SDaniel Henrique Barboza 
299607e9316SDaniel Henrique Barboza         pecs = chip9->pecs;
300607e9316SDaniel Henrique Barboza     } else if (phb_base->version == 5) {
301607e9316SDaniel Henrique Barboza         Pnv10Chip *chip10 = PNV10_CHIP(chip);
302607e9316SDaniel Henrique Barboza 
303607e9316SDaniel Henrique Barboza         pecs = chip10->pecs;
304607e9316SDaniel Henrique Barboza     } else {
305607e9316SDaniel Henrique Barboza         g_assert_not_reached();
306607e9316SDaniel Henrique Barboza     }
307607e9316SDaniel Henrique Barboza 
308c1471772SDaniel Henrique Barboza     for (i = 0; i < chip->num_pecs; i++) {
309c1471772SDaniel Henrique Barboza         /*
310c1471772SDaniel Henrique Barboza          * For each PEC, check the amount of phbs it supports
311c1471772SDaniel Henrique Barboza          * and see if the given phb4 index matches an index.
312c1471772SDaniel Henrique Barboza          */
313607e9316SDaniel Henrique Barboza         PnvPhb4PecState *pec = &pecs[i];
314c1471772SDaniel Henrique Barboza 
315c1471772SDaniel Henrique Barboza         for (j = 0; j < pec->num_phbs; j++) {
316c1471772SDaniel Henrique Barboza             if (index == pnv_phb4_pec_get_phb_id(pec, j)) {
317c1471772SDaniel Henrique Barboza                 return pec;
318c1471772SDaniel Henrique Barboza             }
319c1471772SDaniel Henrique Barboza         }
320c1471772SDaniel Henrique Barboza     }
321c1471772SDaniel Henrique Barboza     error_setg(errp,
322c1471772SDaniel Henrique Barboza                "pnv-phb4 chip-id %d index %d didn't match any existing PEC",
323c1471772SDaniel Henrique Barboza                chip_id, index);
324c1471772SDaniel Henrique Barboza 
325c1471772SDaniel Henrique Barboza     return NULL;
326c1471772SDaniel Henrique Barboza }
327c1471772SDaniel Henrique Barboza 
328ba47c3a4SDaniel Henrique Barboza /*
329ba47c3a4SDaniel Henrique Barboza  * Adds a PnvPHB to the chip. Returns the parent obj of the
330ba47c3a4SDaniel Henrique Barboza  * PHB which varies with each version (phb version 3 is parented
331ba47c3a4SDaniel Henrique Barboza  * by the chip, version 4 and 5 are parented by the PEC
332ba47c3a4SDaniel Henrique Barboza  * device).
333ba47c3a4SDaniel Henrique Barboza  *
334ba47c3a4SDaniel Henrique Barboza  * TODO: for version 3 we're still parenting the PHB with the
335ba47c3a4SDaniel Henrique Barboza  * chip. We should parent with a (so far not implemented)
336ba47c3a4SDaniel Henrique Barboza  * PHB3 PEC device.
337ba47c3a4SDaniel Henrique Barboza  */
338ba47c3a4SDaniel Henrique Barboza Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp)
339ba47c3a4SDaniel Henrique Barboza {
340ba47c3a4SDaniel Henrique Barboza     if (phb->version == 3) {
3410d512c71SDaniel Henrique Barboza         Pnv8Chip *chip8 = PNV8_CHIP(chip);
3420d512c71SDaniel Henrique Barboza 
3430d512c71SDaniel Henrique Barboza         phb->chip = chip;
3440d512c71SDaniel Henrique Barboza 
3450d512c71SDaniel Henrique Barboza         chip8->phbs[chip8->num_phbs] = phb;
3460d512c71SDaniel Henrique Barboza         chip8->num_phbs++;
3470d512c71SDaniel Henrique Barboza 
348ba47c3a4SDaniel Henrique Barboza         return OBJECT(chip);
349ba47c3a4SDaniel Henrique Barboza     }
350c1471772SDaniel Henrique Barboza 
351c1471772SDaniel Henrique Barboza     phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp);
352c1471772SDaniel Henrique Barboza 
353c1471772SDaniel Henrique Barboza     return OBJECT(phb->pec);
354ba47c3a4SDaniel Henrique Barboza }
355ba47c3a4SDaniel Henrique Barboza 
356eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
357e997040eSCédric Le Goater {
358c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
359d2fd9612SCédric Le Goater     int i;
360d2fd9612SCédric Le Goater 
3613f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3623f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
363c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
364c396c58aSGreg Kurz                  compat, sizeof(compat));
365967b7523SCédric Le Goater 
366d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3674fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
368d2fd9612SCédric Le Goater 
369b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
370bf5615e7SCédric Le Goater 
371bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
372b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
373d2fd9612SCédric Le Goater     }
374d2fd9612SCédric Le Goater 
375e997040eSCédric Le Goater     if (chip->ram_size) {
376b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
377e997040eSCédric Le Goater     }
378e997040eSCédric Le Goater }
379e997040eSCédric Le Goater 
380eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
381eb859a27SCédric Le Goater {
382c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
383eb859a27SCédric Le Goater     int i;
384eb859a27SCédric Le Goater 
3853f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3863f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
387c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
388c396c58aSGreg Kurz                  compat, sizeof(compat));
389eb859a27SCédric Le Goater 
390eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3914fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
392eb859a27SCédric Le Goater 
393eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
394eb859a27SCédric Le Goater     }
395eb859a27SCédric Le Goater 
396eb859a27SCédric Le Goater     if (chip->ram_size) {
397eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
398eb859a27SCédric Le Goater     }
39915376c66SCédric Le Goater 
4002661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
401eb859a27SCédric Le Goater }
402eb859a27SCédric Le Goater 
4032b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
4042b548a42SCédric Le Goater {
405c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
4062b548a42SCédric Le Goater     int i;
4072b548a42SCédric Le Goater 
4083f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
4093f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
410c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
411c396c58aSGreg Kurz                  compat, sizeof(compat));
4122b548a42SCédric Le Goater 
4132b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
4142b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
4152b548a42SCédric Le Goater 
4162b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
4172b548a42SCédric Le Goater     }
4182b548a42SCédric Le Goater 
4192b548a42SCédric Le Goater     if (chip->ram_size) {
4202b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
4212b548a42SCédric Le Goater     }
4222661f6abSCédric Le Goater 
4232661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
4242b548a42SCédric Le Goater }
4252b548a42SCédric Le Goater 
426b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
427c5ffdcaeSCédric Le Goater {
428c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
429c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
430c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
431c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
432c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
433c5ffdcaeSCédric Le Goater     };
434c5ffdcaeSCédric Le Goater     char *name;
435c5ffdcaeSCédric Le Goater     int node;
436c5ffdcaeSCédric Le Goater 
437c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
438c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
439c5ffdcaeSCédric Le Goater     _FDT(node);
440c5ffdcaeSCédric Le Goater     g_free(name);
441c5ffdcaeSCédric Le Goater 
442c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
443c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
444c5ffdcaeSCédric Le Goater }
445c5ffdcaeSCédric Le Goater 
446b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
447cb228f5aSCédric Le Goater {
448cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
449cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
450cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
451cb228f5aSCédric Le Goater         cpu_to_be32(1),
452cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
453cb228f5aSCédric Le Goater         cpu_to_be32(8)
454cb228f5aSCédric Le Goater     };
455632fc0b3SBernhard Beschow     uint32_t irq;
456cb228f5aSCédric Le Goater     char *name;
457cb228f5aSCédric Le Goater     int node;
458cb228f5aSCédric Le Goater 
459632fc0b3SBernhard Beschow     irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
460632fc0b3SBernhard Beschow 
461cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
462cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
463cb228f5aSCédric Le Goater     _FDT(node);
464cb228f5aSCédric Le Goater     g_free(name);
465cb228f5aSCédric Le Goater 
466cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
467cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
468cb228f5aSCédric Le Goater                       sizeof(compatible))));
469cb228f5aSCédric Le Goater 
470cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
471cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
472632fc0b3SBernhard Beschow     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
473cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
474cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
475cb228f5aSCédric Le Goater 
476cb228f5aSCédric Le Goater     /* This is needed by Linux */
477cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
478cb228f5aSCédric Le Goater }
479cb228f5aSCédric Le Goater 
480b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
48104f6c8b2SCédric Le Goater {
48204f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
48304f6c8b2SCédric Le Goater     uint32_t io_base;
48404f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
48504f6c8b2SCédric Le Goater         cpu_to_be32(1),
48604f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
48704f6c8b2SCédric Le Goater         cpu_to_be32(3)
48804f6c8b2SCédric Le Goater     };
48904f6c8b2SCédric Le Goater     uint32_t irq;
49004f6c8b2SCédric Le Goater     char *name;
49104f6c8b2SCédric Le Goater     int node;
49204f6c8b2SCédric Le Goater 
49304f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
49404f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
49504f6c8b2SCédric Le Goater 
49604f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
49704f6c8b2SCédric Le Goater 
49804f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
49904f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
50004f6c8b2SCédric Le Goater     _FDT(node);
50104f6c8b2SCédric Le Goater     g_free(name);
50204f6c8b2SCédric Le Goater 
5037032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
5047032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
5057032d92aSCédric Le Goater                       sizeof(compatible))));
50604f6c8b2SCédric Le Goater 
50704f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
50804f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
50904f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
51004f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
51104f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
51204f6c8b2SCédric Le Goater }
51304f6c8b2SCédric Le Goater 
514e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
515e7a3fee3SCédric Le Goater     void *fdt;
516e7a3fee3SCédric Le Goater     int offset;
517e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
518e7a3fee3SCédric Le Goater 
519b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
520e7a3fee3SCédric Le Goater {
521c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
522c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
523c5ffdcaeSCédric Le Goater 
524c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
525b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
526cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
527b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
52804f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
529b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
530c5ffdcaeSCédric Le Goater     } else {
531c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
532c5ffdcaeSCédric Le Goater                      d->ioport_id);
533c5ffdcaeSCédric Le Goater     }
534c5ffdcaeSCédric Le Goater 
535e7a3fee3SCédric Le Goater     return 0;
536e7a3fee3SCédric Le Goater }
537e7a3fee3SCédric Le Goater 
53859b7c1c2SBalamuruhan S /*
53959b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
540bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
541bb7ab95cSCédric Le Goater  */
542bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
543bb7ab95cSCédric Le Goater {
54464d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
545e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
546e7a3fee3SCédric Le Goater         .fdt = fdt,
547bb7ab95cSCédric Le Goater         .offset = isa_offset,
548e7a3fee3SCédric Le Goater     };
549f47a08d1SCédric Le Goater     uint32_t phandle;
550e7a3fee3SCédric Le Goater 
551bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
552bb7ab95cSCédric Le Goater 
553f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
554f47a08d1SCédric Le Goater     assert(phandle > 0);
555f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
556f47a08d1SCédric Le Goater 
55759b7c1c2SBalamuruhan S     /*
55859b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
55959b7c1c2SBalamuruhan S      * can not use object_child_foreach()
56059b7c1c2SBalamuruhan S      */
561bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
562bb7ab95cSCédric Le Goater                        &args);
563e7a3fee3SCédric Le Goater }
564e7a3fee3SCédric Le Goater 
5657a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
566e5694793SCédric Le Goater {
567e5694793SCédric Le Goater     int off;
568e5694793SCédric Le Goater 
569e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
570e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
571e5694793SCédric Le Goater 
572e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
573e5694793SCédric Le Goater }
574e5694793SCédric Le Goater 
575b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5769e933f4aSBenjamin Herrenschmidt {
577d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
578b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5799e933f4aSBenjamin Herrenschmidt     void *fdt;
5809e933f4aSBenjamin Herrenschmidt     char *buf;
5819e933f4aSBenjamin Herrenschmidt     int off;
582e997040eSCédric Le Goater     int i;
5839e933f4aSBenjamin Herrenschmidt 
5849e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5859e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5869e933f4aSBenjamin Herrenschmidt 
587ccb099b3SCédric Le Goater     /* /qemu node */
588ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
589ccb099b3SCédric Le Goater 
5909e933f4aSBenjamin Herrenschmidt     /* Root node */
5919e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5929e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5939e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5949e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
595d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5969e933f4aSBenjamin Herrenschmidt 
5979e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5989e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5999e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
600bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
6019e933f4aSBenjamin Herrenschmidt     }
6029e933f4aSBenjamin Herrenschmidt     g_free(buf);
6039e933f4aSBenjamin Herrenschmidt 
6049e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
6059e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
6069e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
6079e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
6089e933f4aSBenjamin Herrenschmidt     }
6099e933f4aSBenjamin Herrenschmidt 
6109e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
6119e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
6129e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
6139e933f4aSBenjamin Herrenschmidt 
6149e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
6159e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
6169e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
6179e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
6189e933f4aSBenjamin Herrenschmidt     }
6199e933f4aSBenjamin Herrenschmidt 
620e997040eSCédric Le Goater     /* Populate device tree for each chip */
621e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
622eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
623e997040eSCédric Le Goater     }
624e7a3fee3SCédric Le Goater 
625e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
626bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
627aeaef83dSCédric Le Goater 
628aeaef83dSCédric Le Goater     if (pnv->bmc) {
629b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
630aeaef83dSCédric Le Goater     }
631aeaef83dSCédric Le Goater 
6327a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
6337a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
6347a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
635e5694793SCédric Le Goater     }
636e5694793SCédric Le Goater 
6379e933f4aSBenjamin Herrenschmidt     return fdt;
6389e933f4aSBenjamin Herrenschmidt }
6399e933f4aSBenjamin Herrenschmidt 
640bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
641bce0b691SCédric Le Goater {
6428f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
643bce0b691SCédric Le Goater 
644bce0b691SCédric Le Goater     if (pnv->bmc) {
645bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
646bce0b691SCédric Le Goater     }
647bce0b691SCédric Le Goater }
648bce0b691SCédric Le Goater 
6497966d70fSJason A. Donenfeld static void pnv_reset(MachineState *machine, ShutdownCause reason)
6509e933f4aSBenjamin Herrenschmidt {
65125f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
65225f3170bSCédric Le Goater     IPMIBmc *bmc;
6539e933f4aSBenjamin Herrenschmidt     void *fdt;
6549e933f4aSBenjamin Herrenschmidt 
6557966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
6569e933f4aSBenjamin Herrenschmidt 
65725f3170bSCédric Le Goater     /*
65825f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
65925f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
66025f3170bSCédric Le Goater      * line.
66125f3170bSCédric Le Goater      */
66225f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
66325f3170bSCédric Le Goater     if (!pnv->bmc) {
66425f3170bSCédric Le Goater         if (!bmc) {
66538d2448aSGreg Kurz             if (!qtest_enabled()) {
66625f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
66725f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
66825f3170bSCédric Le Goater                             "to define one");
66938d2448aSGreg Kurz             }
67025f3170bSCédric Le Goater         } else {
67125f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
67225f3170bSCédric Le Goater             pnv->bmc = bmc;
67325f3170bSCédric Le Goater         }
67425f3170bSCédric Le Goater     }
67525f3170bSCédric Le Goater 
676b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6779e933f4aSBenjamin Herrenschmidt 
6789e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6799e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6809e933f4aSBenjamin Herrenschmidt 
6818d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6829e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
683b2fb7a43SPan Nengyuan 
684adb77996SDaniel Henrique Barboza     /*
685adb77996SDaniel Henrique Barboza      * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
686adb77996SDaniel Henrique Barboza      * the existing machine->fdt to avoid leaking it during
687adb77996SDaniel Henrique Barboza      * a reset.
688adb77996SDaniel Henrique Barboza      */
689adb77996SDaniel Henrique Barboza     g_free(machine->fdt);
690adb77996SDaniel Henrique Barboza     machine->fdt = fdt;
6919e933f4aSBenjamin Herrenschmidt }
6929e933f4aSBenjamin Herrenschmidt 
69304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6943495b6b6SCédric Le Goater {
69577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
696c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
697c05aa140SCédric Le Goater 
698c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
69977864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
70004026890SCédric Le Goater }
7013495b6b6SCédric Le Goater 
70204026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
70304026890SCédric Le Goater {
70477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
705c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
706c05aa140SCédric Le Goater 
707c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
70877864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
70904026890SCédric Le Goater }
7103495b6b6SCédric Le Goater 
71104026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
71204026890SCédric Le Goater {
71315376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
714c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
715c05aa140SCédric Le Goater 
716c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq);
71715376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
71804026890SCédric Le Goater }
7193495b6b6SCédric Le Goater 
7202b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
7212b548a42SCédric Le Goater {
7222661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
723c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
724c05aa140SCédric Le Goater 
725c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq);
7262661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
7272b548a42SCédric Le Goater }
7282b548a42SCédric Le Goater 
72904026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
73004026890SCédric Le Goater {
73104026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
7323495b6b6SCédric Le Goater }
7333495b6b6SCédric Le Goater 
734d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
735d8e4aad5SCédric Le Goater {
736d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
7378a69bca7SDaniel Henrique Barboza     int i;
738d8e4aad5SCédric Le Goater 
739d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
7408a69bca7SDaniel Henrique Barboza 
7418a69bca7SDaniel Henrique Barboza     for (i = 0; i < chip8->num_phbs; i++) {
7420d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
7431f5d6b2aSDaniel Henrique Barboza         PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
7448a69bca7SDaniel Henrique Barboza 
7458a69bca7SDaniel Henrique Barboza         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
7468a69bca7SDaniel Henrique Barboza         ics_pic_print_info(&phb3->lsis, mon);
7478a69bca7SDaniel Henrique Barboza     }
748d8e4aad5SCédric Le Goater }
749d8e4aad5SCédric Le Goater 
7500e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
7510e6232bcSCédric Le Goater {
7520e6232bcSCédric Le Goater     Monitor *mon = opaque;
753210aacb3SDaniel Henrique Barboza     PnvPHB *phb =  (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
7540e6232bcSCédric Le Goater 
755210aacb3SDaniel Henrique Barboza     if (!phb) {
756210aacb3SDaniel Henrique Barboza         return 0;
7570e6232bcSCédric Le Goater     }
758210aacb3SDaniel Henrique Barboza 
759210aacb3SDaniel Henrique Barboza     pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon);
760210aacb3SDaniel Henrique Barboza 
7610e6232bcSCédric Le Goater     return 0;
7620e6232bcSCédric Le Goater }
7630e6232bcSCédric Le Goater 
764d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
765d8e4aad5SCédric Le Goater {
766d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
767d8e4aad5SCédric Le Goater 
768d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
769c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
7704f9924c4SBenjamin Herrenschmidt 
7710e6232bcSCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
7720e6232bcSCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
773d8e4aad5SCédric Le Goater }
774d8e4aad5SCédric Le Goater 
775c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
776c4b2c40cSGreg Kurz                                                 uint32_t core_id)
777c4b2c40cSGreg Kurz {
778c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
779c4b2c40cSGreg Kurz }
780c4b2c40cSGreg Kurz 
781c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
782c4b2c40cSGreg Kurz                                                 uint32_t core_id)
783c4b2c40cSGreg Kurz {
784c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
785c4b2c40cSGreg Kurz }
786c4b2c40cSGreg Kurz 
787c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
788c4b2c40cSGreg Kurz                                                  uint32_t core_id)
789c4b2c40cSGreg Kurz {
790c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
791c4b2c40cSGreg Kurz }
792c4b2c40cSGreg Kurz 
793f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
794f30c843cSCédric Le Goater {
795f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
796f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
797f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
798f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
799f30c843cSCédric Le Goater 
80021d3a78eSNicholas Piggin     return ppc_default->pvr_match(ppc_default, ppc->pvr, false);
801f30c843cSCédric Le Goater }
802f30c843cSCédric Le Goater 
803e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
804e2392d43SCédric Le Goater {
805c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
806e2392d43SCédric Le Goater 
8075325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
8085325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
809c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
810e2392d43SCédric Le Goater }
811e2392d43SCédric Le Goater 
8122b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
8132b548a42SCédric Le Goater {
8148b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
8158b50ce85SCédric Le Goater 
816da71b7e3SCédric Le Goater     pnv_xive2_pic_print_info(&chip10->xive, mon);
8178b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
818623575e1SCédric Le Goater 
819623575e1SCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
820623575e1SCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
8212b548a42SCédric Le Goater }
8222b548a42SCédric Le Goater 
823458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
824458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
825458c6f01SCédric Le Goater {
826458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
827458c6f01SCédric Le Goater     uint64_t ram_per_chip;
828458c6f01SCédric Le Goater 
829458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
830458c6f01SCédric Le Goater 
831458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
832458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
833458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
834458c6f01SCédric Le Goater     }
835458c6f01SCédric Le Goater 
836f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
837f640afecSCédric Le Goater 
838458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
839458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
840458c6f01SCédric Le Goater }
841458c6f01SCédric Le Goater 
842b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
8439e933f4aSBenjamin Herrenschmidt {
844cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
845b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
846f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
8479e933f4aSBenjamin Herrenschmidt     char *fw_filename;
8489e933f4aSBenjamin Herrenschmidt     long fw_size;
849458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
850e997040eSCédric Le Goater     int i;
851e997040eSCédric Le Goater     char *chip_typename;
85235dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
85335dde576SCédric Le Goater     DeviceState *dev;
8549e933f4aSBenjamin Herrenschmidt 
855ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
856ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
857ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
858ebe6c3faSDaniel Henrique Barboza     }
859ebe6c3faSDaniel Henrique Barboza 
8609e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
861dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
862dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
863dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
864dd7ef911SCédric Le Goater         g_free(sz);
865dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
8669e933f4aSBenjamin Herrenschmidt     }
867173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
8689e933f4aSBenjamin Herrenschmidt 
86935dde576SCédric Le Goater     /*
87035dde576SCédric Le Goater      * Create our simple PNOR device
87135dde576SCédric Le Goater      */
8723e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
87335dde576SCédric Le Goater     if (pnor) {
874934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
87535dde576SCédric Le Goater     }
8763c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
87735dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
87835dde576SCédric Le Goater 
8799e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
8809e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
88115fcedb2SCédric Le Goater     if (!fw_filename) {
88215fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
88315fcedb2SCédric Le Goater         exit(1);
88415fcedb2SCédric Le Goater     }
8859e933f4aSBenjamin Herrenschmidt 
88608c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
8879e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
88815fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
8899e933f4aSBenjamin Herrenschmidt         exit(1);
8909e933f4aSBenjamin Herrenschmidt     }
8919e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8929e933f4aSBenjamin Herrenschmidt 
8939e933f4aSBenjamin Herrenschmidt     /* load kernel */
8949e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8959e933f4aSBenjamin Herrenschmidt         long kernel_size;
8969e933f4aSBenjamin Herrenschmidt 
8979e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
898b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8999e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
900802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
9019e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
9029e933f4aSBenjamin Herrenschmidt             exit(1);
9039e933f4aSBenjamin Herrenschmidt         }
9049e933f4aSBenjamin Herrenschmidt     }
9059e933f4aSBenjamin Herrenschmidt 
9069e933f4aSBenjamin Herrenschmidt     /* load initrd */
9079e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
9089e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
9099e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
910584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
9119e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
912802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
9139e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
9149e933f4aSBenjamin Herrenschmidt             exit(1);
9159e933f4aSBenjamin Herrenschmidt         }
9169e933f4aSBenjamin Herrenschmidt     }
917e997040eSCédric Le Goater 
9184f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
9194f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
9204f9924c4SBenjamin Herrenschmidt 
921f30c843cSCédric Le Goater     /*
922f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
923f30c843cSCédric Le Goater      * default.
924f30c843cSCédric Le Goater      */
925f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
926f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
927f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
928f30c843cSCédric Le Goater         exit(1);
929f30c843cSCédric Le Goater     }
930f30c843cSCédric Le Goater 
931e997040eSCédric Le Goater     /* Create the processor chips */
9324a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
9337fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
9344a12c699SIgor Mammedov                                     i, machine->cpu_type);
935e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
936f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
937f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
938e997040eSCédric Le Goater         exit(1);
939e997040eSCédric Le Goater     }
940e997040eSCédric Le Goater 
941e44acde2SGreg Kurz     pnv->num_chips =
942e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
943e44acde2SGreg Kurz     /*
944e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
945e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
946e44acde2SGreg Kurz      */
947ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
948e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
949ab17a3feSCédric Le Goater         error_printf(
950ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
951e44acde2SGreg Kurz         exit(1);
952e44acde2SGreg Kurz     }
953e44acde2SGreg Kurz 
954e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
955e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
956e997040eSCédric Le Goater         char chip_name[32];
957df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
9580e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
959e997040eSCédric Le Goater 
960e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
961e997040eSCédric Le Goater 
962458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
963458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
964e997040eSCédric Le Goater                                 &error_fatal);
965458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
966458c6f01SCédric Le Goater                                 &error_fatal);
967458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
968e997040eSCédric Le Goater 
9690e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
970d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
9710e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
9725325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
9735325cc34SMarkus Armbruster                                 &error_fatal);
9745325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
9755325cc34SMarkus Armbruster                                 &error_fatal);
976245cdb7fSCédric Le Goater         /*
977245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
978245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
979245cdb7fSCédric Le Goater          */
980245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
9815325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
982245cdb7fSCédric Le Goater         }
983d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
9845325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
985d1214b81SGreg Kurz                                      &error_abort);
986d1214b81SGreg Kurz         }
9873c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
988e997040eSCédric Le Goater     }
989e997040eSCédric Le Goater     g_free(chip_typename);
9903495b6b6SCédric Le Goater 
9913495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
99204026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9933495b6b6SCédric Le Goater 
9943495b6b6SCédric Le Goater     /* Create serial port */
995def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9963495b6b6SCédric Le Goater 
9973495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9986c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
999bce0b691SCédric Le Goater 
100025f3170bSCédric Le Goater     /*
100125f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
100225f3170bSCédric Le Goater      * communication with the BMC
100325f3170bSCédric Le Goater      */
100425f3170bSCédric Le Goater     if (defaults_enabled()) {
100525f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
1006e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
100725f3170bSCédric Le Goater     }
1008e2392d43SCédric Le Goater 
100959b7c1c2SBalamuruhan S     /*
1010032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
1011032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
1012032c226bSCédric Le Goater      * map it always for now.
1013032c226bSCédric Le Goater      */
1014032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
1015032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
1016032c226bSCédric Le Goater 
1017032c226bSCédric Le Goater     /*
101859b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
101959b7c1c2SBalamuruhan S      * host to powerdown
102059b7c1c2SBalamuruhan S      */
1021bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
1022bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
1023e997040eSCédric Le Goater }
1024e997040eSCédric Le Goater 
1025631adaffSCédric Le Goater /*
1026631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
1027631adaffSCédric Le Goater  *   22:24  Chip ID
1028631adaffSCédric Le Goater  *   25:28  Core number
1029631adaffSCédric Le Goater  *   29:31  Thread ID
1030631adaffSCédric Le Goater  */
1031631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
1032631adaffSCédric Le Goater {
1033631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
1034631adaffSCédric Le Goater }
1035631adaffSCédric Le Goater 
10368fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1037d35aefa9SCédric Le Goater                                         Error **errp)
1038d35aefa9SCédric Le Goater {
1039245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
10408fa1f4efSCédric Le Goater     Error *local_err = NULL;
10418fa1f4efSCédric Le Goater     Object *obj;
10428907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10438fa1f4efSCédric Le Goater 
1044245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
10458fa1f4efSCédric Le Goater     if (local_err) {
10468fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
10478fa1f4efSCédric Le Goater         return;
10488fa1f4efSCédric Le Goater     }
10498fa1f4efSCédric Le Goater 
1050956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
1051d35aefa9SCédric Le Goater }
1052d35aefa9SCédric Le Goater 
10530990ce6aSGreg Kurz 
1054d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1055d49e8a9bSCédric Le Goater {
1056d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1057d49e8a9bSCédric Le Goater 
1058d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
1059d49e8a9bSCédric Le Goater }
1060d49e8a9bSCédric Le Goater 
10610990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10620990ce6aSGreg Kurz {
10630990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10640990ce6aSGreg Kurz 
10650990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
10660990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10670990ce6aSGreg Kurz }
10680990ce6aSGreg Kurz 
106985913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
107085913070SGreg Kurz                                             Monitor *mon)
107185913070SGreg Kurz {
107285913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
107385913070SGreg Kurz }
107485913070SGreg Kurz 
1075631adaffSCédric Le Goater /*
1076631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
1077631adaffSCédric Le Goater  *   49:52  Node ID
1078631adaffSCédric Le Goater  *   53:55  Chip ID
1079631adaffSCédric Le Goater  *   56     Reserved - Read as zero
1080631adaffSCédric Le Goater  *   57:61  Core number
1081631adaffSCédric Le Goater  *   62:63  Thread ID
1082631adaffSCédric Le Goater  *
1083631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
1084631adaffSCédric Le Goater  */
1085631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
1086631adaffSCédric Le Goater {
1087631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
1088631adaffSCédric Le Goater }
1089631adaffSCédric Le Goater 
10902b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10912b548a42SCédric Le Goater {
10922b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10932b548a42SCédric Le Goater }
10942b548a42SCédric Le Goater 
10958fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1096d35aefa9SCédric Le Goater                                         Error **errp)
1097d35aefa9SCédric Le Goater {
10982dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10992dfa91a2SCédric Le Goater     Error *local_err = NULL;
11002dfa91a2SCédric Le Goater     Object *obj;
11012dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11022dfa91a2SCédric Le Goater 
11032dfa91a2SCédric Le Goater     /*
11042dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
11052dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
11062dfa91a2SCédric Le Goater      * only used at runtime.
11072dfa91a2SCédric Le Goater      */
110847950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
110947950946SCédric Le Goater                            &local_err);
11102dfa91a2SCédric Le Goater     if (local_err) {
11112dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
11128fa1f4efSCédric Le Goater         return;
1113d35aefa9SCédric Le Goater     }
1114d35aefa9SCédric Le Goater 
11152dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
11162dfa91a2SCédric Le Goater }
11172dfa91a2SCédric Le Goater 
1118d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1119d49e8a9bSCédric Le Goater {
1120d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1121d49e8a9bSCédric Le Goater 
1122d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1123d49e8a9bSCédric Le Goater }
1124d49e8a9bSCédric Le Goater 
11250990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11260990ce6aSGreg Kurz {
11270990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11280990ce6aSGreg Kurz 
11290990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
11300990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
11310990ce6aSGreg Kurz }
11320990ce6aSGreg Kurz 
113385913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
113485913070SGreg Kurz                                             Monitor *mon)
113585913070SGreg Kurz {
113685913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
113785913070SGreg Kurz }
113885913070SGreg Kurz 
11392b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
11402b548a42SCédric Le Goater                                         Error **errp)
11412b548a42SCédric Le Goater {
1142da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1143da71b7e3SCédric Le Goater     Error *local_err = NULL;
1144da71b7e3SCédric Le Goater     Object *obj;
11452b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11462b548a42SCédric Le Goater 
1147da71b7e3SCédric Le Goater     /*
1148da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1149da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1150da71b7e3SCédric Le Goater      * only used at runtime.
1151da71b7e3SCédric Le Goater      */
1152da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1153da71b7e3SCédric Le Goater                            &local_err);
1154da71b7e3SCédric Le Goater     if (local_err) {
1155da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1156da71b7e3SCédric Le Goater         return;
1157da71b7e3SCédric Le Goater     }
1158da71b7e3SCédric Le Goater 
1159da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
11602b548a42SCédric Le Goater }
11612b548a42SCédric Le Goater 
11622b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
11632b548a42SCédric Le Goater {
1164da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1165da71b7e3SCédric Le Goater 
1166da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
11672b548a42SCédric Le Goater }
11682b548a42SCédric Le Goater 
11692b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11702b548a42SCédric Le Goater {
11712b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11722b548a42SCédric Le Goater 
1173da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
11742b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
11752b548a42SCédric Le Goater }
11762b548a42SCédric Le Goater 
117785913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
117885913070SGreg Kurz                                              Monitor *mon)
117985913070SGreg Kurz {
1180da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
118185913070SGreg Kurz }
118285913070SGreg Kurz 
118359b7c1c2SBalamuruhan S /*
118459b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1185397a79e7SCédric Le Goater  *
1186397a79e7SCédric Le Goater  * <EX0 reserved>
1187397a79e7SCédric Le Goater  *  EX1  - Venice only
1188397a79e7SCédric Le Goater  *  EX2  - Venice only
1189397a79e7SCédric Le Goater  *  EX3  - Venice only
1190397a79e7SCédric Le Goater  *  EX4
1191397a79e7SCédric Le Goater  *  EX5
1192397a79e7SCédric Le Goater  *  EX6
1193397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1194397a79e7SCédric Le Goater  *  EX9  - Venice only
1195397a79e7SCédric Le Goater  *  EX10 - Venice only
1196397a79e7SCédric Le Goater  *  EX11 - Venice only
1197397a79e7SCédric Le Goater  *  EX12
1198397a79e7SCédric Le Goater  *  EX13
1199397a79e7SCédric Le Goater  *  EX14
1200397a79e7SCédric Le Goater  * <EX15 reserved>
1201397a79e7SCédric Le Goater  */
1202397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1203397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1204397a79e7SCédric Le Goater 
1205397a79e7SCédric Le Goater /*
120609279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1207397a79e7SCédric Le Goater  */
120809279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1209397a79e7SCédric Le Goater 
12102b548a42SCédric Le Goater 
12112b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
12122b548a42SCédric Le Goater 
121377864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
121477864267SCédric Le Goater {
121577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
12169ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
12179ae1329eSCédric Le Goater     int i;
121877864267SCédric Le Goater 
1219245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1220245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1221245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1222d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1223245cdb7fSCédric Le Goater 
12249fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
122577864267SCédric Le Goater 
12269fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
122777864267SCédric Le Goater 
12289fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
12293887d241SBalamuruhan S 
12309fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
12319ae1329eSCédric Le Goater 
1232892c3ad0SDaniel Henrique Barboza     if (defaults_enabled()) {
1233eb93c828SCédric Le Goater         chip8->num_phbs = pcc->num_phbs;
12341f6a88ffSCédric Le Goater 
1235eb93c828SCédric Le Goater         for (i = 0; i < chip8->num_phbs; i++) {
12360d512c71SDaniel Henrique Barboza             Object *phb = object_new(TYPE_PNV_PHB);
12370d512c71SDaniel Henrique Barboza 
12380d512c71SDaniel Henrique Barboza             /*
12390d512c71SDaniel Henrique Barboza              * We need the chip to parent the PHB to allow the DT
12400d512c71SDaniel Henrique Barboza              * to build correctly (via pnv_xscom_dt()).
12410d512c71SDaniel Henrique Barboza              *
12420d512c71SDaniel Henrique Barboza              * TODO: the PHB should be parented by a PEC device that, at
12430d512c71SDaniel Henrique Barboza              * this moment, is not modelled powernv8/phb3.
12440d512c71SDaniel Henrique Barboza              */
12450d512c71SDaniel Henrique Barboza             object_property_add_child(obj, "phb[*]", phb);
12460d512c71SDaniel Henrique Barboza             chip8->phbs[i] = PNV_PHB(phb);
12479ae1329eSCédric Le Goater         }
1248892c3ad0SDaniel Henrique Barboza     }
12499ae1329eSCédric Le Goater 
125077864267SCédric Le Goater }
125177864267SCédric Le Goater 
125277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
125377864267SCédric Le Goater  {
125477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
125577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
125677864267SCédric Le Goater     int i, j;
125777864267SCédric Le Goater     char *name;
125877864267SCédric Le Goater 
125977864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
126077864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
126177864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
126277864267SCédric Le Goater     g_free(name);
126377864267SCédric Le Goater 
126477864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
126577864267SCédric Le Goater 
126677864267SCédric Le Goater     /* Map the ICP registers for each thread */
126777864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
12684fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
126977864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
127077864267SCédric Le Goater 
127177864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
127277864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1273245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
127477864267SCédric Le Goater 
127577864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
127677864267SCédric Le Goater                                         &icp->mmio);
127777864267SCédric Le Goater         }
127877864267SCédric Le Goater     }
127977864267SCédric Le Goater }
128077864267SCédric Le Goater 
128177864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
128277864267SCédric Le Goater {
128377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
128477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
128577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1286ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
128777864267SCédric Le Goater     Error *local_err = NULL;
12889ae1329eSCédric Le Goater     int i;
128977864267SCédric Le Goater 
1290245cdb7fSCédric Le Goater     assert(chip8->xics);
1291245cdb7fSCédric Le Goater 
1292709044fdSCédric Le Goater     /* XSCOM bridge is first */
1293709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1294709044fdSCédric Le Goater     if (local_err) {
1295709044fdSCédric Le Goater         error_propagate(errp, local_err);
1296709044fdSCédric Le Goater         return;
1297709044fdSCédric Le Goater     }
1298709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1299709044fdSCédric Le Goater 
130077864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
130177864267SCédric Le Goater     if (local_err) {
130277864267SCédric Le Goater         error_propagate(errp, local_err);
130377864267SCédric Le Goater         return;
130477864267SCédric Le Goater     }
130577864267SCédric Le Goater 
130677864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
13075325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
13085325cc34SMarkus Armbruster                             &error_fatal);
13095325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
13105325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1311668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
131277864267SCédric Le Goater         return;
131377864267SCédric Le Goater     }
1314ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1315ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
131677864267SCédric Le Goater 
131777864267SCédric Le Goater     /* Create LPC controller */
1318ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
131977864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
132077864267SCédric Le Goater 
1321032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
132264d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
132364d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
132464d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
132564d011d5SCédric Le Goater 
132659b7c1c2SBalamuruhan S     /*
132759b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
132859b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
132959b7c1c2SBalamuruhan S      */
133077864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
133177864267SCédric Le Goater     if (local_err) {
133277864267SCédric Le Goater         error_propagate(errp, local_err);
133377864267SCédric Le Goater         return;
133477864267SCédric Le Goater     }
133577864267SCédric Le Goater 
133677864267SCédric Le Goater     /* Create the simplified OCC model */
1337668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
133877864267SCédric Le Goater         return;
133977864267SCédric Le Goater     }
134077864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1341b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1342b0ae5c69SCédric Le Goater                           qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC));
1343f3db8266SBalamuruhan S 
1344f3db8266SBalamuruhan S     /* OCC SRAM model */
13453a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1346f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
13473887d241SBalamuruhan S 
13483887d241SBalamuruhan S     /* HOMER */
13495325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1350f2582acfSGreg Kurz                              &error_abort);
1351668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
13523887d241SBalamuruhan S         return;
13533887d241SBalamuruhan S     }
13548f092316SCédric Le Goater     /* Homer Xscom region */
13558f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
13568f092316SCédric Le Goater 
13578f092316SCédric Le Goater     /* Homer mmio region */
13583887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
13593887d241SBalamuruhan S                                 &chip8->homer.regs);
13609ae1329eSCédric Le Goater 
13611f5d6b2aSDaniel Henrique Barboza     /* PHB controllers */
1362eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
13630d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
13649ae1329eSCédric Le Goater 
13655325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
13665325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
13679ae1329eSCédric Le Goater                                 &error_fatal);
13682c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
13692c4d3a50SCédric Le Goater                                  &error_fatal);
1370668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
13719ae1329eSCédric Le Goater             return;
13729ae1329eSCédric Le Goater         }
13739ae1329eSCédric Le Goater     }
137477864267SCédric Le Goater }
137577864267SCédric Le Goater 
137670c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
137770c059e9SGreg Kurz {
137870c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
137970c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
138070c059e9SGreg Kurz }
138170c059e9SGreg Kurz 
1382e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1383e997040eSCédric Le Goater {
1384e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1385e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1386e997040eSCédric Le Goater 
1387e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1388397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
13899ae1329eSCédric Le Goater     k->num_phbs = 3;
1390631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1391d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1392d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13930990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
139485913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
139504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1396eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1397d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1398c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
139970c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1400e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
140177864267SCédric Le Goater 
140277864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
140377864267SCédric Le Goater                                     &k->parent_realize);
1404e997040eSCédric Le Goater }
1405e997040eSCédric Le Goater 
1406e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1407e997040eSCédric Le Goater {
1408e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1409e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1410e997040eSCédric Le Goater 
1411e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1412397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
14139ae1329eSCédric Le Goater     k->num_phbs = 3;
1414631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1415d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1416d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
14170990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
141885913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
141904026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1420eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1421d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1422c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
142370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1424e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
142577864267SCédric Le Goater 
142677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
142777864267SCédric Le Goater                                     &k->parent_realize);
1428e997040eSCédric Le Goater }
1429e997040eSCédric Le Goater 
1430e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1431e997040eSCédric Le Goater {
1432e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1433e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1434e997040eSCédric Le Goater 
1435e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1436397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1437316717feSCédric Le Goater     k->num_phbs = 4;
1438631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1439d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1440d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
14410990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
144285913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
144304026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1444eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1445d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1446c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
144770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1448e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
144977864267SCédric Le Goater 
145077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
145177864267SCédric Le Goater                                     &k->parent_realize);
145277864267SCédric Le Goater }
145377864267SCédric Le Goater 
145477864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
145577864267SCédric Le Goater {
14564f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
14572dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
14584f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
14594f9924c4SBenjamin Herrenschmidt     int i;
14602dfa91a2SCédric Le Goater 
1461db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1462d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1463d2623129SMarkus Armbruster                               "xive-fabric");
1464c38536bcSCédric Le Goater 
14659fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
146615376c66SCédric Le Goater 
14679fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
14686598a70dSCédric Le Goater 
14699fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
14703887d241SBalamuruhan S 
14710bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
14720bf4d77eSNicholas Piggin 
14739fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
14744f9924c4SBenjamin Herrenschmidt 
1475422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1476422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1477422fd92eSCédric Le Goater 
1478422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14794f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
14809fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
14814f9924c4SBenjamin Herrenschmidt     }
148277864267SCédric Le Goater }
148377864267SCédric Le Goater 
1484ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1485ae4c68e3SCédric Le Goater                                       PnvCore *pnv_core)
14865dad902cSCédric Le Goater {
14875dad902cSCédric Le Goater     char eq_name[32];
14885dad902cSCédric Le Goater     int core_id = CPU_CORE(pnv_core)->core_id;
14895dad902cSCédric Le Goater 
14905dad902cSCédric Le Goater     snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14919fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
14929fc7fc4dSMarkus Armbruster                                        sizeof(*eq), TYPE_PNV_QUAD,
14939fc7fc4dSMarkus Armbruster                                        &error_fatal, NULL);
14945dad902cSCédric Le Goater 
149592612f15SCédric Le Goater     object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1496ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(eq), NULL, &error_fatal);
1497ae4c68e3SCédric Le Goater }
1498ae4c68e3SCédric Le Goater 
1499ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1500ae4c68e3SCédric Le Goater {
1501ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
1502ae4c68e3SCédric Le Goater     int i;
1503ae4c68e3SCédric Le Goater 
1504ae4c68e3SCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1505ae4c68e3SCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1506ae4c68e3SCédric Le Goater 
1507ae4c68e3SCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
1508ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
1509ae4c68e3SCédric Le Goater 
1510ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
15115dad902cSCédric Le Goater 
151292612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
15135dad902cSCédric Le Goater                                 &eq->xscom_regs);
15145dad902cSCédric Le Goater     }
15155dad902cSCédric Le Goater }
15165dad902cSCédric Le Goater 
151713480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
15184f9924c4SBenjamin Herrenschmidt {
15194f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
152013480fc5SCédric Le Goater     int i;
15214f9924c4SBenjamin Herrenschmidt 
1522422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
15234f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
15244f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
15254f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
15264f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
15274f9924c4SBenjamin Herrenschmidt 
15285325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
15295325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
15304f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
15316f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
15326f43d255SCédric Le Goater                                  &error_fatal);
1533668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
15344f9924c4SBenjamin Herrenschmidt             return;
15354f9924c4SBenjamin Herrenschmidt         }
15364f9924c4SBenjamin Herrenschmidt 
15374f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
15384f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
15394f9924c4SBenjamin Herrenschmidt 
15404f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
15414f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
15424f9924c4SBenjamin Herrenschmidt     }
15434f9924c4SBenjamin Herrenschmidt }
15444f9924c4SBenjamin Herrenschmidt 
154577864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
154677864267SCédric Le Goater {
154777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15482dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
15492dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1550c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
155177864267SCédric Le Goater     Error *local_err = NULL;
155277864267SCédric Le Goater 
1553709044fdSCédric Le Goater     /* XSCOM bridge is first */
1554709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1555709044fdSCédric Le Goater     if (local_err) {
1556709044fdSCédric Le Goater         error_propagate(errp, local_err);
1557709044fdSCédric Le Goater         return;
1558709044fdSCédric Le Goater     }
1559709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1560709044fdSCédric Le Goater 
156177864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
156277864267SCédric Le Goater     if (local_err) {
156377864267SCédric Le Goater         error_propagate(errp, local_err);
156477864267SCédric Le Goater         return;
156577864267SCédric Le Goater     }
15662dfa91a2SCédric Le Goater 
15675dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
15685dad902cSCédric Le Goater     if (local_err) {
15695dad902cSCédric Le Goater         error_propagate(errp, local_err);
15705dad902cSCédric Le Goater         return;
15715dad902cSCédric Le Goater     }
15725dad902cSCédric Le Goater 
15732dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
15745325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
15755325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
15765325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
15775325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
15785325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
15795325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
15805325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
15815325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
15825325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
15837ae54cc3SGreg Kurz                              &error_abort);
1584668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
15852dfa91a2SCédric Le Goater         return;
15862dfa91a2SCédric Le Goater     }
15872dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
15882dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1589c38536bcSCédric Le Goater 
1590c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15915325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
15925325cc34SMarkus Armbruster                             &error_fatal);
159324c8fa96SCédric Le Goater     /* This is the only device with 4k ESB pages */
159424c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
159524c8fa96SCédric Le Goater                             &error_fatal);
1596668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1597c38536bcSCédric Le Goater         return;
1598c38536bcSCédric Le Goater     }
1599c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1600c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
160115376c66SCédric Le Goater 
160215376c66SCédric Le Goater     /* LPC */
1603668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
160415376c66SCédric Le Goater         return;
160515376c66SCédric Le Goater     }
160615376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
160715376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
160815376c66SCédric Le Goater 
1609032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
161015376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
161115376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
16126598a70dSCédric Le Goater 
16136598a70dSCédric Le Goater     /* Create the simplified OCC model */
1614668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
16156598a70dSCédric Le Goater         return;
16166598a70dSCédric Le Goater     }
16176598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1618b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1619b0ae5c69SCédric Le Goater                               DEVICE(&chip9->psi), PSIHB9_IRQ_OCC));
1620f3db8266SBalamuruhan S 
1621f3db8266SBalamuruhan S     /* OCC SRAM model */
16223a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1623f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
16243887d241SBalamuruhan S 
16250bf4d77eSNicholas Piggin     /* SBE */
16260bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
16270bf4d77eSNicholas Piggin         return;
16280bf4d77eSNicholas Piggin     }
16290bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
16300bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_ctrl_regs);
16310bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
16320bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_mbox_regs);
16330bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
16340bf4d77eSNicholas Piggin                               DEVICE(&chip9->psi), PSIHB9_IRQ_PSU));
16350bf4d77eSNicholas Piggin 
16363887d241SBalamuruhan S     /* HOMER */
16375325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1638f2582acfSGreg Kurz                              &error_abort);
1639668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
16403887d241SBalamuruhan S         return;
16413887d241SBalamuruhan S     }
16428f092316SCédric Le Goater     /* Homer Xscom region */
16438f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
16448f092316SCédric Le Goater 
16458f092316SCédric Le Goater     /* Homer mmio region */
16463887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
16473887d241SBalamuruhan S                                 &chip9->homer.regs);
16484f9924c4SBenjamin Herrenschmidt 
164913480fc5SCédric Le Goater     /* PEC PHBs */
165013480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
16514f9924c4SBenjamin Herrenschmidt     if (local_err) {
16524f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
16534f9924c4SBenjamin Herrenschmidt         return;
16544f9924c4SBenjamin Herrenschmidt     }
1655e997040eSCédric Le Goater }
1656e997040eSCédric Le Goater 
165770c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
165870c059e9SGreg Kurz {
165970c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
166070c059e9SGreg Kurz     return addr >> 3;
166170c059e9SGreg Kurz }
166270c059e9SGreg Kurz 
1663e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1664e997040eSCédric Le Goater {
1665e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1666e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1667e997040eSCédric Le Goater 
166883028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1669397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1670631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1671d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1672d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
16730990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
167485913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
167504026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1676eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1677d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1678c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
167970c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1680e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1681422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
168277864267SCédric Le Goater 
168377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
168477864267SCédric Le Goater                                     &k->parent_realize);
1685e997040eSCédric Le Goater }
1686e997040eSCédric Le Goater 
16872b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
16882b548a42SCédric Le Goater {
1689623575e1SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
16908b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1691623575e1SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1692623575e1SCédric Le Goater     int i;
16938b50ce85SCédric Le Goater 
1694da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1695da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1696da71b7e3SCédric Le Goater                               "xive-fabric");
16979fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
16989fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
16998bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
17000bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe",  &chip10->sbe, TYPE_PNV10_SBE);
170192499676SCédric Le Goater     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1702623575e1SCédric Le Goater 
1703623575e1SCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1704623575e1SCédric Le Goater 
1705623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1706623575e1SCédric Le Goater         object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1707623575e1SCédric Le Goater                                 TYPE_PNV_PHB5_PEC);
1708623575e1SCédric Le Goater     }
17092b548a42SCédric Le Goater }
17102b548a42SCédric Le Goater 
1711ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1712ae4c68e3SCédric Le Goater {
1713ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip10);
1714ae4c68e3SCédric Le Goater     int i;
1715ae4c68e3SCédric Le Goater 
1716ae4c68e3SCédric Le Goater     chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1717ae4c68e3SCédric Le Goater     chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1718ae4c68e3SCédric Le Goater 
1719ae4c68e3SCédric Le Goater     for (i = 0; i < chip10->nr_quads; i++) {
1720ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip10->quads[i];
1721ae4c68e3SCédric Le Goater 
1722ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
1723ae4c68e3SCédric Le Goater 
1724ae4c68e3SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1725ae4c68e3SCédric Le Goater                                 &eq->xscom_regs);
1726ae4c68e3SCédric Le Goater     }
1727ae4c68e3SCédric Le Goater }
1728ae4c68e3SCédric Le Goater 
1729623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1730623575e1SCédric Le Goater {
1731623575e1SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1732623575e1SCédric Le Goater     int i;
1733623575e1SCédric Le Goater 
1734623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1735623575e1SCédric Le Goater         PnvPhb4PecState *pec = &chip10->pecs[i];
1736623575e1SCédric Le Goater         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1737623575e1SCédric Le Goater         uint32_t pec_nest_base;
1738623575e1SCédric Le Goater         uint32_t pec_pci_base;
1739623575e1SCédric Le Goater 
1740623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1741623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1742623575e1SCédric Le Goater                                 &error_fatal);
1743623575e1SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1744623575e1SCédric Le Goater                                  &error_fatal);
1745623575e1SCédric Le Goater         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1746623575e1SCédric Le Goater             return;
1747623575e1SCédric Le Goater         }
1748623575e1SCédric Le Goater 
1749623575e1SCédric Le Goater         pec_nest_base = pecc->xscom_nest_base(pec);
1750623575e1SCédric Le Goater         pec_pci_base = pecc->xscom_pci_base(pec);
1751623575e1SCédric Le Goater 
1752623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1753623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1754623575e1SCédric Le Goater     }
1755623575e1SCédric Le Goater }
1756623575e1SCédric Le Goater 
17572b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
17582b548a42SCédric Le Goater {
17592b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
17602b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
17618b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
17622b548a42SCédric Le Goater     Error *local_err = NULL;
17632b548a42SCédric Le Goater 
17642b548a42SCédric Le Goater     /* XSCOM bridge is first */
17652b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
17662b548a42SCédric Le Goater     if (local_err) {
17672b548a42SCédric Le Goater         error_propagate(errp, local_err);
17682b548a42SCédric Le Goater         return;
17692b548a42SCédric Le Goater     }
17702b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
17712b548a42SCédric Le Goater 
17722b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
17732b548a42SCédric Le Goater     if (local_err) {
17742b548a42SCédric Le Goater         error_propagate(errp, local_err);
17752b548a42SCédric Le Goater         return;
17762b548a42SCédric Le Goater     }
17778b50ce85SCédric Le Goater 
1778ae4c68e3SCédric Le Goater     pnv_chip_power10_quad_realize(chip10, &local_err);
1779ae4c68e3SCédric Le Goater     if (local_err) {
1780ae4c68e3SCédric Le Goater         error_propagate(errp, local_err);
1781ae4c68e3SCédric Le Goater         return;
1782ae4c68e3SCédric Le Goater     }
1783ae4c68e3SCédric Le Goater 
1784da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1785da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1786da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1787da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1788da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1789da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1790da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1791da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1792da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1793da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1794da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1795da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1796da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1797da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1798da71b7e3SCédric Le Goater                              &error_abort);
1799da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1800da71b7e3SCédric Le Goater         return;
1801da71b7e3SCédric Le Goater     }
1802da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1803da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1804da71b7e3SCédric Le Goater 
18058b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
18065325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
18075325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
180824c8fa96SCédric Le Goater     /* PSI can now be configured to use 64k ESB pages on POWER10 */
180924c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
181024c8fa96SCédric Le Goater                             &error_fatal);
1811668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
18128b50ce85SCédric Le Goater         return;
18138b50ce85SCédric Le Goater     }
18148b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
18158b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
18162661f6abSCédric Le Goater 
18172661f6abSCédric Le Goater     /* LPC */
1818668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
18192661f6abSCédric Le Goater         return;
18202661f6abSCédric Le Goater     }
18212661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
18222661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
18232661f6abSCédric Le Goater 
1824032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
18252661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
18262661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
18278bf682a3SCédric Le Goater 
18288bf682a3SCédric Le Goater     /* Create the simplified OCC model */
18298bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
18308bf682a3SCédric Le Goater         return;
18318bf682a3SCédric Le Goater     }
18328bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
18338bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
1834b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1835b0ae5c69SCédric Le Goater                               DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1836623575e1SCédric Le Goater 
183792499676SCédric Le Goater     /* OCC SRAM model */
183892499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(),
183992499676SCédric Le Goater                                 PNV10_OCC_SENSOR_BASE(chip),
184092499676SCédric Le Goater                                 &chip10->occ.sram_regs);
184192499676SCédric Le Goater 
18420bf4d77eSNicholas Piggin     /* SBE */
18430bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
18440bf4d77eSNicholas Piggin         return;
18450bf4d77eSNicholas Piggin     }
18460bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
18470bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_ctrl_regs);
18480bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
18490bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_mbox_regs);
18500bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
18510bf4d77eSNicholas Piggin                               DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
18520bf4d77eSNicholas Piggin 
185392499676SCédric Le Goater     /* HOMER */
185492499676SCédric Le Goater     object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
185592499676SCédric Le Goater                              &error_abort);
185692499676SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
185792499676SCédric Le Goater         return;
185892499676SCédric Le Goater     }
185992499676SCédric Le Goater     /* Homer Xscom region */
186092499676SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
186192499676SCédric Le Goater                             &chip10->homer.pba_regs);
186292499676SCédric Le Goater 
186392499676SCédric Le Goater     /* Homer mmio region */
186492499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
186592499676SCédric Le Goater                                 &chip10->homer.regs);
186692499676SCédric Le Goater 
1867623575e1SCédric Le Goater     /* PHBs */
1868623575e1SCédric Le Goater     pnv_chip_power10_phb_realize(chip, &local_err);
1869623575e1SCédric Le Goater     if (local_err) {
1870623575e1SCédric Le Goater         error_propagate(errp, local_err);
1871623575e1SCédric Le Goater         return;
1872623575e1SCédric Le Goater     }
18732b548a42SCédric Le Goater }
18742b548a42SCédric Le Goater 
187570c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
187670c059e9SGreg Kurz {
187770c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
187870c059e9SGreg Kurz     return addr >> 3;
187970c059e9SGreg Kurz }
188070c059e9SGreg Kurz 
18812b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
18822b548a42SCédric Le Goater {
18832b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
18842b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
18852b548a42SCédric Le Goater 
18862b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
18872b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
18882b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
18892b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
18902b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
18912b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
189285913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
18932b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
18942b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
18952b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1896c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
189770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
18982b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
1899623575e1SCédric Le Goater     k->num_pecs = PNV10_CHIP_MAX_PEC;
19002b548a42SCédric Le Goater 
19012b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
19022b548a42SCédric Le Goater                                     &k->parent_realize);
19032b548a42SCédric Le Goater }
19042b548a42SCédric Le Goater 
1905397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1906397a79e7SCédric Le Goater {
1907397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1908397a79e7SCédric Le Goater     int cores_max;
1909397a79e7SCédric Le Goater 
1910397a79e7SCédric Le Goater     /*
1911397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1912397a79e7SCédric Le Goater      * the chip class
1913397a79e7SCédric Le Goater      */
1914397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1915397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1916397a79e7SCédric Le Goater     }
1917397a79e7SCédric Le Goater 
1918397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1919397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1920397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1921397a79e7SCédric Le Goater                    chip->cores_mask);
1922397a79e7SCédric Le Goater         return;
1923397a79e7SCédric Le Goater     }
1924397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1925397a79e7SCédric Le Goater 
1926397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
192727d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1928397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1929397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1930397a79e7SCédric Le Goater                    cores_max);
1931397a79e7SCédric Le Goater         return;
1932397a79e7SCédric Le Goater     }
1933397a79e7SCédric Le Goater }
1934397a79e7SCédric Le Goater 
193551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1936e997040eSCédric Le Goater {
1937397a79e7SCédric Le Goater     Error *error = NULL;
1938d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
193940abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1940d2fd9612SCédric Le Goater     int i, core_hwid;
194108c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1942397a79e7SCédric Le Goater 
1943d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1944d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1945d2fd9612SCédric Le Goater         return;
1946d2fd9612SCédric Le Goater     }
1947d2fd9612SCédric Le Goater 
1948d2fd9612SCédric Le Goater     /* Cores */
1949397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1950397a79e7SCédric Le Goater     if (error) {
1951397a79e7SCédric Le Goater         error_propagate(errp, error);
1952397a79e7SCédric Le Goater         return;
1953397a79e7SCédric Le Goater     }
1954d2fd9612SCédric Le Goater 
19554fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1956d2fd9612SCédric Le Goater 
1957d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1958d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1959d2fd9612SCédric Le Goater         char core_name[32];
19604fa28f23SGreg Kurz         PnvCore *pnv_core;
1961c035851aSCédric Le Goater         uint64_t xscom_core_base;
1962d2fd9612SCédric Le Goater 
1963d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1964d2fd9612SCédric Le Goater             continue;
1965d2fd9612SCédric Le Goater         }
1966d2fd9612SCédric Le Goater 
19674fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
19684fa28f23SGreg Kurz 
1969d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1970d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
19714fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
19725325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
19735325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
19745325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
19755325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
19765325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
19775325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
19785325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
19795325cc34SMarkus Armbruster                                 &error_fatal);
19805325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1981158e17a6SGreg Kurz                                  &error_abort);
1982ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
198324ece072SCédric Le Goater 
198424ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1985c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1986c035851aSCédric Le Goater 
1987c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
19884fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1989d2fd9612SCédric Le Goater         i++;
1990d2fd9612SCédric Le Goater     }
199151c04728SCédric Le Goater }
199251c04728SCédric Le Goater 
199351c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
199451c04728SCédric Le Goater {
199551c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
199651c04728SCédric Le Goater     Error *error = NULL;
199751c04728SCédric Le Goater 
199851c04728SCédric Le Goater     /* Cores */
199951c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
200051c04728SCédric Le Goater     if (error) {
200151c04728SCédric Le Goater         error_propagate(errp, error);
200251c04728SCédric Le Goater         return;
200351c04728SCédric Le Goater     }
2004e997040eSCédric Le Goater }
2005e997040eSCédric Le Goater 
2006e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
2007e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
2008e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
2009e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
2010397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
2011397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
2012764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
2013e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
2014e997040eSCédric Le Goater };
2015e997040eSCédric Le Goater 
2016e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
2017e997040eSCédric Le Goater {
2018e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
2019e997040eSCédric Le Goater 
20209d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
2021e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
20224f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
2023e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
2024e997040eSCédric Le Goater }
2025e997040eSCédric Le Goater 
2026119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
2027119eaa9dSCédric Le Goater {
2028119eaa9dSCédric Le Goater     int i, j;
2029119eaa9dSCédric Le Goater 
2030119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2031119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
2032119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
2033119eaa9dSCédric Le Goater 
2034119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
2035119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
2036119eaa9dSCédric Le Goater                 return pc->threads[j];
2037119eaa9dSCédric Le Goater             }
2038119eaa9dSCédric Le Goater         }
2039119eaa9dSCédric Le Goater     }
2040119eaa9dSCédric Le Goater     return NULL;
2041119eaa9dSCédric Le Goater }
2042119eaa9dSCédric Le Goater 
204354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
204454f59d78SCédric Le Goater {
2045b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2046da6be501SDaniel Henrique Barboza     int i, j;
204754f59d78SCédric Le Goater 
204854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
204977864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
205077864267SCédric Le Goater 
205177864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
205277864267SCédric Le Goater             return &chip8->psi.ics;
205354f59d78SCédric Le Goater         }
20542ff73ddaSCédric Le Goater 
2055da6be501SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20560d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20571f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2058da6be501SDaniel Henrique Barboza 
2059da6be501SDaniel Henrique Barboza             if (ics_valid_irq(&phb3->lsis, irq)) {
2060da6be501SDaniel Henrique Barboza                 return &phb3->lsis;
2061da6be501SDaniel Henrique Barboza             }
2062da6be501SDaniel Henrique Barboza 
2063da6be501SDaniel Henrique Barboza             if (ics_valid_irq(ICS(&phb3->msis), irq)) {
2064da6be501SDaniel Henrique Barboza                 return ICS(&phb3->msis);
2065da6be501SDaniel Henrique Barboza             }
20669ae1329eSCédric Le Goater         }
206754f59d78SCédric Le Goater     }
206854f59d78SCédric Le Goater     return NULL;
206954f59d78SCédric Le Goater }
207054f59d78SCédric Le Goater 
20711f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
20721f6a88ffSCédric Le Goater {
20731f6a88ffSCédric Le Goater     int i;
20741f6a88ffSCédric Le Goater 
20751f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
20761f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
20771f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
20781f6a88ffSCédric Le Goater             return chip;
20791f6a88ffSCédric Le Goater         }
20801f6a88ffSCédric Le Goater     }
20811f6a88ffSCédric Le Goater     return NULL;
20821f6a88ffSCédric Le Goater }
20831f6a88ffSCédric Le Goater 
208454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
208554f59d78SCédric Le Goater {
2086b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2087ca459489SDaniel Henrique Barboza     int i, j;
208854f59d78SCédric Le Goater 
208954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
209077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
20919ae1329eSCédric Le Goater 
209277864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
2093ca459489SDaniel Henrique Barboza 
2094ca459489SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20950d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20961f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2097ca459489SDaniel Henrique Barboza 
2098ca459489SDaniel Henrique Barboza             ics_resend(&phb3->lsis);
2099ca459489SDaniel Henrique Barboza             ics_resend(ICS(&phb3->msis));
2100ca459489SDaniel Henrique Barboza         }
210154f59d78SCédric Le Goater     }
210254f59d78SCédric Le Goater }
210354f59d78SCédric Le Goater 
210436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
210536fc6f08SCédric Le Goater {
210636fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
210736fc6f08SCédric Le Goater 
2108956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
210936fc6f08SCédric Le Goater }
211036fc6f08SCédric Le Goater 
211147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
211247fea43aSCédric Le Goater                                Monitor *mon)
211347fea43aSCédric Le Goater {
2114b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
211554f59d78SCédric Le Goater     int i;
211647fea43aSCédric Le Goater     CPUState *cs;
211747fea43aSCédric Le Goater 
211847fea43aSCédric Le Goater     CPU_FOREACH(cs) {
211947fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
212047fea43aSCédric Le Goater 
212185913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
212285913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
212385913070SGreg Kurz                                                            mon);
2124d8e4aad5SCédric Le Goater     }
212554f59d78SCédric Le Goater 
212654f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2127d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
212854f59d78SCédric Le Goater     }
212947fea43aSCédric Le Goater }
213047fea43aSCédric Le Goater 
2131c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2132c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
2133c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
2134c722579eSCédric Le Goater                          uint32_t logic_serv,
2135c722579eSCédric Le Goater                          XiveTCTXMatch *match)
2136c722579eSCédric Le Goater {
2137c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2138c722579eSCédric Le Goater     int total_count = 0;
2139c722579eSCédric Le Goater     int i;
2140c722579eSCédric Le Goater 
2141c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2142c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2143c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2144c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2145c722579eSCédric Le Goater         int count;
2146c722579eSCédric Le Goater 
2147c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2148c722579eSCédric Le Goater                                priority, logic_serv, match);
2149c722579eSCédric Le Goater 
2150c722579eSCédric Le Goater         if (count < 0) {
2151c722579eSCédric Le Goater             return count;
2152c722579eSCédric Le Goater         }
2153c722579eSCédric Le Goater 
2154c722579eSCédric Le Goater         total_count += count;
2155c722579eSCédric Le Goater     }
2156c722579eSCédric Le Goater 
2157c722579eSCédric Le Goater     return total_count;
2158c722579eSCédric Le Goater }
2159c722579eSCédric Le Goater 
2160da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2161da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
2162da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
2163da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
2164da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
2165da71b7e3SCédric Le Goater {
2166da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2167da71b7e3SCédric Le Goater     int total_count = 0;
2168da71b7e3SCédric Le Goater     int i;
2169da71b7e3SCédric Le Goater 
2170da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2171da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2172da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2173da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2174da71b7e3SCédric Le Goater         int count;
2175da71b7e3SCédric Le Goater 
2176da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2177da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2178da71b7e3SCédric Le Goater 
2179da71b7e3SCédric Le Goater         if (count < 0) {
2180da71b7e3SCédric Le Goater             return count;
2181da71b7e3SCédric Le Goater         }
2182da71b7e3SCédric Le Goater 
2183da71b7e3SCédric Le Goater         total_count += count;
2184da71b7e3SCédric Le Goater     }
2185da71b7e3SCédric Le Goater 
2186da71b7e3SCédric Le Goater     return total_count;
2187da71b7e3SCédric Le Goater }
2188da71b7e3SCédric Le Goater 
2189f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
21909e933f4aSBenjamin Herrenschmidt {
21919e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
219236fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2193d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2194d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2195f30c843cSCédric Le Goater 
21961f5d6b2aSDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
21971f5d6b2aSDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "3" },
219880515061SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
21991f5d6b2aSDaniel Henrique Barboza     };
22001f5d6b2aSDaniel Henrique Barboza 
2201f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2202f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
22031f5d6b2aSDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2204f30c843cSCédric Le Goater 
2205f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2206f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2207f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2208d76f2da7SGreg Kurz 
2209d76f2da7SGreg Kurz     pmc->compat = compat;
2210d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2211892c3ad0SDaniel Henrique Barboza 
2212892c3ad0SDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2213f30c843cSCédric Le Goater }
2214f30c843cSCédric Le Goater 
2215f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2216f30c843cSCédric Le Goater {
2217f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2218c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2219d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2220d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2221f30c843cSCédric Le Goater 
2222210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2223210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "4" },
2224c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "4" },
2225210aacb3SDaniel Henrique Barboza     };
2226210aacb3SDaniel Henrique Barboza 
2227f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2228f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
2229210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2230210aacb3SDaniel Henrique Barboza 
2231c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2232f30c843cSCédric Le Goater 
2233f30c843cSCédric Le Goater     mc->alias = "powernv";
2234d76f2da7SGreg Kurz 
2235d76f2da7SGreg Kurz     pmc->compat = compat;
2236d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22377a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2238d786be3fSDaniel Henrique Barboza 
2239d786be3fSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2240f30c843cSCédric Le Goater }
2241f30c843cSCédric Le Goater 
22422b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
22432b548a42SCédric Le Goater {
22442b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2245d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2246da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2247d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
22482b548a42SCédric Le Goater 
2249210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2250210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "5" },
2251c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
2252210aacb3SDaniel Henrique Barboza     };
2253210aacb3SDaniel Henrique Barboza 
22542b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
22556bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2256210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2257d76f2da7SGreg Kurz 
2258d76f2da7SGreg Kurz     pmc->compat = compat;
2259d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22607a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2261da71b7e3SCédric Le Goater 
2262da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
2263f1327fdeSDaniel Henrique Barboza 
2264f1327fdeSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
22652b548a42SCédric Le Goater }
22662b548a42SCédric Le Goater 
226708c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
226808c3f3a7SCédric Le Goater {
226908c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
227008c3f3a7SCédric Le Goater 
227108c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
227208c3f3a7SCédric Le Goater }
227308c3f3a7SCédric Le Goater 
227408c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
227508c3f3a7SCédric Le Goater {
227608c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
227708c3f3a7SCédric Le Goater 
227808c3f3a7SCédric Le Goater     if (value) {
227908c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
228008c3f3a7SCédric Le Goater     }
228108c3f3a7SCédric Le Goater }
228208c3f3a7SCédric Le Goater 
228301b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
228401b552b0SNicholas Piggin {
228501b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
228601b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
228701b552b0SNicholas Piggin 
228801b552b0SNicholas Piggin     cpu_synchronize_state(cs);
228901b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
22900911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
229101b552b0SNicholas Piggin         /*
2292fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2293fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2294fe837714SNicholas Piggin          * (PPC_BIT(43)).
229501b552b0SNicholas Piggin          */
22960911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2297fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
22980911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
229901b552b0SNicholas Piggin         }
2300fe837714SNicholas Piggin     } else {
2301fe837714SNicholas Piggin         /*
2302fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2303fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2304fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2305fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2306fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2307fe837714SNicholas Piggin          */
23080911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2309fe837714SNicholas Piggin     }
2310fe837714SNicholas Piggin }
231101b552b0SNicholas Piggin 
231201b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
231301b552b0SNicholas Piggin {
231401b552b0SNicholas Piggin     CPUState *cs;
231501b552b0SNicholas Piggin 
231601b552b0SNicholas Piggin     CPU_FOREACH(cs) {
231701b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
231801b552b0SNicholas Piggin     }
231901b552b0SNicholas Piggin }
232001b552b0SNicholas Piggin 
2321f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2322f30c843cSCédric Le Goater {
2323f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
232447fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
232501b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
23269e933f4aSBenjamin Herrenschmidt 
23279e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2328b168a138SCédric Le Goater     mc->init = pnv_init;
2329b168a138SCédric Le Goater     mc->reset = pnv_reset;
23309e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
233159b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
233259b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
23339e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
23349e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2335f1d18b0aSJoel Stanley     /*
2336f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2337f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2338f1d18b0aSJoel Stanley      */
2339dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2340173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
234147fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
234201b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
234308c3f3a7SCédric Le Goater 
234408c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2345d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
234608c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
23477eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
23489e933f4aSBenjamin Herrenschmidt }
23499e933f4aSBenjamin Herrenschmidt 
235077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2351beba5c0fSIgor Mammedov     {                                             \
2352beba5c0fSIgor Mammedov         .name          = type,                    \
2353beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
235477864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
235577864267SCédric Le Goater     }
235677864267SCédric Le Goater 
235777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
235877864267SCédric Le Goater     {                                             \
235977864267SCédric Le Goater         .name          = type,                    \
236077864267SCédric Le Goater         .class_init    = class_initfn,            \
236177864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2362beba5c0fSIgor Mammedov     }
2363beba5c0fSIgor Mammedov 
23642b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
23652b548a42SCédric Le Goater     {                                              \
23662b548a42SCédric Le Goater         .name          = type,                     \
23672b548a42SCédric Le Goater         .class_init    = class_initfn,             \
23682b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
23692b548a42SCédric Le Goater     }
23702b548a42SCédric Le Goater 
2371beba5c0fSIgor Mammedov static const TypeInfo types[] = {
23721aba8716SCédric Le Goater     {
23732b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
23742b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23752b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2376da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2377da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2378da71b7e3SCédric Le Goater             { },
2379da71b7e3SCédric Le Goater         },
23802b548a42SCédric Le Goater     },
23812b548a42SCédric Le Goater     {
23821aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
23831aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23841aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2385c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2386c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2387c722579eSCédric Le Goater             { },
2388c722579eSCédric Le Goater         },
23891aba8716SCédric Le Goater     },
23901aba8716SCédric Le Goater     {
23911aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
23921aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23931aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
23941aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
23951aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
23961aba8716SCédric Le Goater             { },
23971aba8716SCédric Le Goater         },
23981aba8716SCédric Le Goater     },
2399beba5c0fSIgor Mammedov     {
2400b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
24019e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2402f30c843cSCédric Le Goater         .abstract       = true,
24039e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2404b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2405d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
240636fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
240747fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
240801b552b0SNicholas Piggin             { TYPE_NMI },
240936fc6f08SCédric Le Goater             { },
241036fc6f08SCédric Le Goater         },
2411beba5c0fSIgor Mammedov     },
2412beba5c0fSIgor Mammedov     {
2413beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2414beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2415beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2416beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2417beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2418beba5c0fSIgor Mammedov         .abstract      = true,
2419beba5c0fSIgor Mammedov     },
242077864267SCédric Le Goater 
242177864267SCédric Le Goater     /*
24222b548a42SCédric Le Goater      * P10 chip and variants
24232b548a42SCédric Le Goater      */
24242b548a42SCédric Le Goater     {
24252b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
24262b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
24272b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
24282b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
24292b548a42SCédric Le Goater     },
24302b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
24312b548a42SCédric Le Goater 
24322b548a42SCédric Le Goater     /*
243377864267SCédric Le Goater      * P9 chip and variants
243477864267SCédric Le Goater      */
243577864267SCédric Le Goater     {
243677864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
243777864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
243877864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
243977864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
244077864267SCédric Le Goater     },
244177864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
244277864267SCédric Le Goater 
244377864267SCédric Le Goater     /*
244477864267SCédric Le Goater      * P8 chip and variants
244577864267SCédric Le Goater      */
244677864267SCédric Le Goater     {
244777864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
244877864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
244977864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
245077864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
245177864267SCédric Le Goater     },
245277864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
245377864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
245477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2455beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
24569e933f4aSBenjamin Herrenschmidt };
24579e933f4aSBenjamin Herrenschmidt 
2458beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2459