xref: /qemu/hw/ppc/pnv.c (revision 277ee172)
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 
287ba47c3a4SDaniel Henrique Barboza /*
288ddf0676fSFrederic Barrat  * Adds a PnvPHB to the chip on P8.
289ddf0676fSFrederic Barrat  * Implemented here, like for defaults PHBs
290ba47c3a4SDaniel Henrique Barboza  */
291ddf0676fSFrederic Barrat PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb)
292ba47c3a4SDaniel Henrique Barboza {
2930d512c71SDaniel Henrique Barboza     Pnv8Chip *chip8 = PNV8_CHIP(chip);
2940d512c71SDaniel Henrique Barboza 
2950d512c71SDaniel Henrique Barboza     phb->chip = chip;
2960d512c71SDaniel Henrique Barboza 
2970d512c71SDaniel Henrique Barboza     chip8->phbs[chip8->num_phbs] = phb;
2980d512c71SDaniel Henrique Barboza     chip8->num_phbs++;
299ddf0676fSFrederic Barrat     return chip;
300ba47c3a4SDaniel Henrique Barboza }
301ba47c3a4SDaniel Henrique Barboza 
302eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
303e997040eSCédric Le Goater {
304c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
305d2fd9612SCédric Le Goater     int i;
306d2fd9612SCédric Le Goater 
3073f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3083f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
309c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
310c396c58aSGreg Kurz                  compat, sizeof(compat));
311967b7523SCédric Le Goater 
312d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3134fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
314d2fd9612SCédric Le Goater 
315b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
316bf5615e7SCédric Le Goater 
317bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
318b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
319d2fd9612SCédric Le Goater     }
320d2fd9612SCédric Le Goater 
321e997040eSCédric Le Goater     if (chip->ram_size) {
322b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
323e997040eSCédric Le Goater     }
324e997040eSCédric Le Goater }
325e997040eSCédric Le Goater 
326eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
327eb859a27SCédric Le Goater {
328c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
329eb859a27SCédric Le Goater     int i;
330eb859a27SCédric Le Goater 
3313f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3323f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
333c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
334c396c58aSGreg Kurz                  compat, sizeof(compat));
335eb859a27SCédric Le Goater 
336eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3374fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
338eb859a27SCédric Le Goater 
339eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
340eb859a27SCédric Le Goater     }
341eb859a27SCédric Le Goater 
342eb859a27SCédric Le Goater     if (chip->ram_size) {
343eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
344eb859a27SCédric Le Goater     }
34515376c66SCédric Le Goater 
3462661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
347eb859a27SCédric Le Goater }
348eb859a27SCédric Le Goater 
3492b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3502b548a42SCédric Le Goater {
351c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3522b548a42SCédric Le Goater     int i;
3532b548a42SCédric Le Goater 
3543f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3553f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
356c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
357c396c58aSGreg Kurz                  compat, sizeof(compat));
3582b548a42SCédric Le Goater 
3592b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3602b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3612b548a42SCédric Le Goater 
3622b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3632b548a42SCédric Le Goater     }
3642b548a42SCédric Le Goater 
3652b548a42SCédric Le Goater     if (chip->ram_size) {
3662b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3672b548a42SCédric Le Goater     }
3682661f6abSCédric Le Goater 
3692661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3702b548a42SCédric Le Goater }
3712b548a42SCédric Le Goater 
372b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
373c5ffdcaeSCédric Le Goater {
374c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
375c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
376c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
377c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
378c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
379c5ffdcaeSCédric Le Goater     };
380c5ffdcaeSCédric Le Goater     char *name;
381c5ffdcaeSCédric Le Goater     int node;
382c5ffdcaeSCédric Le Goater 
383c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
384c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
385c5ffdcaeSCédric Le Goater     _FDT(node);
386c5ffdcaeSCédric Le Goater     g_free(name);
387c5ffdcaeSCédric Le Goater 
388c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
389c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
390c5ffdcaeSCédric Le Goater }
391c5ffdcaeSCédric Le Goater 
392b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
393cb228f5aSCédric Le Goater {
394cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
395cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
396cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
397cb228f5aSCédric Le Goater         cpu_to_be32(1),
398cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
399cb228f5aSCédric Le Goater         cpu_to_be32(8)
400cb228f5aSCédric Le Goater     };
401632fc0b3SBernhard Beschow     uint32_t irq;
402cb228f5aSCédric Le Goater     char *name;
403cb228f5aSCédric Le Goater     int node;
404cb228f5aSCédric Le Goater 
405632fc0b3SBernhard Beschow     irq = object_property_get_uint(OBJECT(d), "irq", &error_fatal);
406632fc0b3SBernhard Beschow 
407cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
408cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
409cb228f5aSCédric Le Goater     _FDT(node);
410cb228f5aSCédric Le Goater     g_free(name);
411cb228f5aSCédric Le Goater 
412cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
413cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
414cb228f5aSCédric Le Goater                       sizeof(compatible))));
415cb228f5aSCédric Le Goater 
416cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
417cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
418632fc0b3SBernhard Beschow     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
419cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
420cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
421cb228f5aSCédric Le Goater 
422cb228f5aSCédric Le Goater     /* This is needed by Linux */
423cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
424cb228f5aSCédric Le Goater }
425cb228f5aSCédric Le Goater 
426b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
42704f6c8b2SCédric Le Goater {
42804f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
42904f6c8b2SCédric Le Goater     uint32_t io_base;
43004f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
43104f6c8b2SCédric Le Goater         cpu_to_be32(1),
43204f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
43304f6c8b2SCédric Le Goater         cpu_to_be32(3)
43404f6c8b2SCédric Le Goater     };
43504f6c8b2SCédric Le Goater     uint32_t irq;
43604f6c8b2SCédric Le Goater     char *name;
43704f6c8b2SCédric Le Goater     int node;
43804f6c8b2SCédric Le Goater 
43904f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
44004f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
44104f6c8b2SCédric Le Goater 
44204f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
44304f6c8b2SCédric Le Goater 
44404f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
44504f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
44604f6c8b2SCédric Le Goater     _FDT(node);
44704f6c8b2SCédric Le Goater     g_free(name);
44804f6c8b2SCédric Le Goater 
4497032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4507032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4517032d92aSCédric Le Goater                       sizeof(compatible))));
45204f6c8b2SCédric Le Goater 
45304f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
45404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
45504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
45604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
45704f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
45804f6c8b2SCédric Le Goater }
45904f6c8b2SCédric Le Goater 
460e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
461e7a3fee3SCédric Le Goater     void *fdt;
462e7a3fee3SCédric Le Goater     int offset;
463e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
464e7a3fee3SCédric Le Goater 
465b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
466e7a3fee3SCédric Le Goater {
467c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
468c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
469c5ffdcaeSCédric Le Goater 
470c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
471b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
472cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
473b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
47404f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
475b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
476c5ffdcaeSCédric Le Goater     } else {
477c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
478c5ffdcaeSCédric Le Goater                      d->ioport_id);
479c5ffdcaeSCédric Le Goater     }
480c5ffdcaeSCédric Le Goater 
481e7a3fee3SCédric Le Goater     return 0;
482e7a3fee3SCédric Le Goater }
483e7a3fee3SCédric Le Goater 
48459b7c1c2SBalamuruhan S /*
48559b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
486bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
487bb7ab95cSCédric Le Goater  */
488bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
489bb7ab95cSCédric Le Goater {
49064d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
491e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
492e7a3fee3SCédric Le Goater         .fdt = fdt,
493bb7ab95cSCédric Le Goater         .offset = isa_offset,
494e7a3fee3SCédric Le Goater     };
495f47a08d1SCédric Le Goater     uint32_t phandle;
496e7a3fee3SCédric Le Goater 
497bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
498bb7ab95cSCédric Le Goater 
499f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
500f47a08d1SCédric Le Goater     assert(phandle > 0);
501f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
502f47a08d1SCédric Le Goater 
50359b7c1c2SBalamuruhan S     /*
50459b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
50559b7c1c2SBalamuruhan S      * can not use object_child_foreach()
50659b7c1c2SBalamuruhan S      */
507bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
508bb7ab95cSCédric Le Goater                        &args);
509e7a3fee3SCédric Le Goater }
510e7a3fee3SCédric Le Goater 
5117a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
512e5694793SCédric Le Goater {
513e5694793SCédric Le Goater     int off;
514e5694793SCédric Le Goater 
515e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
516e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
517e5694793SCédric Le Goater 
518e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
519e5694793SCédric Le Goater }
520e5694793SCédric Le Goater 
521b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5229e933f4aSBenjamin Herrenschmidt {
523d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
524b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5259e933f4aSBenjamin Herrenschmidt     void *fdt;
5269e933f4aSBenjamin Herrenschmidt     char *buf;
5279e933f4aSBenjamin Herrenschmidt     int off;
528e997040eSCédric Le Goater     int i;
5299e933f4aSBenjamin Herrenschmidt 
5309e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5319e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5329e933f4aSBenjamin Herrenschmidt 
533ccb099b3SCédric Le Goater     /* /qemu node */
534ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
535ccb099b3SCédric Le Goater 
5369e933f4aSBenjamin Herrenschmidt     /* Root node */
5379e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5389e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5399e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5409e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
541d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5429e933f4aSBenjamin Herrenschmidt 
5439e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5449e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5459e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
546bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
5479e933f4aSBenjamin Herrenschmidt     }
5489e933f4aSBenjamin Herrenschmidt     g_free(buf);
5499e933f4aSBenjamin Herrenschmidt 
5509e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5519e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5529e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5539e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5549e933f4aSBenjamin Herrenschmidt     }
5559e933f4aSBenjamin Herrenschmidt 
5569e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5579e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5589e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5599e933f4aSBenjamin Herrenschmidt 
5609e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5619e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5629e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5639e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5649e933f4aSBenjamin Herrenschmidt     }
5659e933f4aSBenjamin Herrenschmidt 
566e997040eSCédric Le Goater     /* Populate device tree for each chip */
567e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
568eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
569e997040eSCédric Le Goater     }
570e7a3fee3SCédric Le Goater 
571e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
572bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
573aeaef83dSCédric Le Goater 
574aeaef83dSCédric Le Goater     if (pnv->bmc) {
575b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
576aeaef83dSCédric Le Goater     }
577aeaef83dSCédric Le Goater 
5787a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5797a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5807a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
581e5694793SCédric Le Goater     }
582e5694793SCédric Le Goater 
5839e933f4aSBenjamin Herrenschmidt     return fdt;
5849e933f4aSBenjamin Herrenschmidt }
5859e933f4aSBenjamin Herrenschmidt 
586bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
587bce0b691SCédric Le Goater {
5888f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
589bce0b691SCédric Le Goater 
590bce0b691SCédric Le Goater     if (pnv->bmc) {
591bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
592bce0b691SCédric Le Goater     }
593bce0b691SCédric Le Goater }
594bce0b691SCédric Le Goater 
5957966d70fSJason A. Donenfeld static void pnv_reset(MachineState *machine, ShutdownCause reason)
5969e933f4aSBenjamin Herrenschmidt {
59725f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
59825f3170bSCédric Le Goater     IPMIBmc *bmc;
5999e933f4aSBenjamin Herrenschmidt     void *fdt;
6009e933f4aSBenjamin Herrenschmidt 
6017966d70fSJason A. Donenfeld     qemu_devices_reset(reason);
6029e933f4aSBenjamin Herrenschmidt 
60325f3170bSCédric Le Goater     /*
60425f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
60525f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
60625f3170bSCédric Le Goater      * line.
60725f3170bSCédric Le Goater      */
60825f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
60925f3170bSCédric Le Goater     if (!pnv->bmc) {
61025f3170bSCédric Le Goater         if (!bmc) {
61138d2448aSGreg Kurz             if (!qtest_enabled()) {
61225f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
61325f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
61425f3170bSCédric Le Goater                             "to define one");
61538d2448aSGreg Kurz             }
61625f3170bSCédric Le Goater         } else {
61725f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
61825f3170bSCédric Le Goater             pnv->bmc = bmc;
61925f3170bSCédric Le Goater         }
62025f3170bSCédric Le Goater     }
62125f3170bSCédric Le Goater 
622b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6239e933f4aSBenjamin Herrenschmidt 
6249e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6259e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6269e933f4aSBenjamin Herrenschmidt 
6278d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6289e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
629b2fb7a43SPan Nengyuan 
630adb77996SDaniel Henrique Barboza     /*
631adb77996SDaniel Henrique Barboza      * Set machine->fdt for 'dumpdtb' QMP/HMP command. Free
632adb77996SDaniel Henrique Barboza      * the existing machine->fdt to avoid leaking it during
633adb77996SDaniel Henrique Barboza      * a reset.
634adb77996SDaniel Henrique Barboza      */
635adb77996SDaniel Henrique Barboza     g_free(machine->fdt);
636adb77996SDaniel Henrique Barboza     machine->fdt = fdt;
6379e933f4aSBenjamin Herrenschmidt }
6389e933f4aSBenjamin Herrenschmidt 
63904026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6403495b6b6SCédric Le Goater {
64177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
642c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_EXTERNAL);
643c05aa140SCédric Le Goater 
644c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
64577864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
64604026890SCédric Le Goater }
6473495b6b6SCédric Le Goater 
64804026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
64904026890SCédric Le Goater {
65077864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
651c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_LPC_I2C);
652c05aa140SCédric Le Goater 
653c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->lpc), 0, irq);
65477864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
65504026890SCédric Le Goater }
6563495b6b6SCédric Le Goater 
65704026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
65804026890SCédric Le Goater {
65915376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
660c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip9->psi), PSIHB9_IRQ_LPCHC);
661c05aa140SCédric Le Goater 
662c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->lpc), 0, irq);
66315376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
66404026890SCédric Le Goater }
6653495b6b6SCédric Le Goater 
6662b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6672b548a42SCédric Le Goater {
6682661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
669c05aa140SCédric Le Goater     qemu_irq irq = qdev_get_gpio_in(DEVICE(&chip10->psi), PSIHB9_IRQ_LPCHC);
670c05aa140SCédric Le Goater 
671c05aa140SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->lpc), 0, irq);
6722661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6732b548a42SCédric Le Goater }
6742b548a42SCédric Le Goater 
67504026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
67604026890SCédric Le Goater {
67704026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6783495b6b6SCédric Le Goater }
6793495b6b6SCédric Le Goater 
680d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
681d8e4aad5SCédric Le Goater {
682d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6838a69bca7SDaniel Henrique Barboza     int i;
684d8e4aad5SCédric Le Goater 
685d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6868a69bca7SDaniel Henrique Barboza 
6878a69bca7SDaniel Henrique Barboza     for (i = 0; i < chip8->num_phbs; i++) {
6880d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
6891f5d6b2aSDaniel Henrique Barboza         PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
6908a69bca7SDaniel Henrique Barboza 
6918a69bca7SDaniel Henrique Barboza         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
6928a69bca7SDaniel Henrique Barboza         ics_pic_print_info(&phb3->lsis, mon);
6938a69bca7SDaniel Henrique Barboza     }
694d8e4aad5SCédric Le Goater }
695d8e4aad5SCédric Le Goater 
6960e6232bcSCédric Le Goater static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque)
6970e6232bcSCédric Le Goater {
6980e6232bcSCédric Le Goater     Monitor *mon = opaque;
699210aacb3SDaniel Henrique Barboza     PnvPHB *phb =  (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB);
7000e6232bcSCédric Le Goater 
701210aacb3SDaniel Henrique Barboza     if (!phb) {
702210aacb3SDaniel Henrique Barboza         return 0;
7030e6232bcSCédric Le Goater     }
704210aacb3SDaniel Henrique Barboza 
705210aacb3SDaniel Henrique Barboza     pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon);
706210aacb3SDaniel Henrique Barboza 
7070e6232bcSCédric Le Goater     return 0;
7080e6232bcSCédric Le Goater }
7090e6232bcSCédric Le Goater 
710d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
711d8e4aad5SCédric Le Goater {
712d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
713d8e4aad5SCédric Le Goater 
714d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
715c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
7164f9924c4SBenjamin Herrenschmidt 
7170e6232bcSCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
7180e6232bcSCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
719d8e4aad5SCédric Le Goater }
720d8e4aad5SCédric Le Goater 
721c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
722c4b2c40cSGreg Kurz                                                 uint32_t core_id)
723c4b2c40cSGreg Kurz {
724c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
725c4b2c40cSGreg Kurz }
726c4b2c40cSGreg Kurz 
727c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
728c4b2c40cSGreg Kurz                                                 uint32_t core_id)
729c4b2c40cSGreg Kurz {
730c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
731c4b2c40cSGreg Kurz }
732c4b2c40cSGreg Kurz 
733c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
734c4b2c40cSGreg Kurz                                                  uint32_t core_id)
735c4b2c40cSGreg Kurz {
736c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
737c4b2c40cSGreg Kurz }
738c4b2c40cSGreg Kurz 
739f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
740f30c843cSCédric Le Goater {
741f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
742f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
743f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
744f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
745f30c843cSCédric Le Goater 
74621d3a78eSNicholas Piggin     return ppc_default->pvr_match(ppc_default, ppc->pvr, false);
747f30c843cSCédric Le Goater }
748f30c843cSCédric Le Goater 
749e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
750e2392d43SCédric Le Goater {
751c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
752e2392d43SCédric Le Goater 
7535325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7545325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
755c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
756e2392d43SCédric Le Goater }
757e2392d43SCédric Le Goater 
7582b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7592b548a42SCédric Le Goater {
7608b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7618b50ce85SCédric Le Goater 
762da71b7e3SCédric Le Goater     pnv_xive2_pic_print_info(&chip10->xive, mon);
7638b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
764623575e1SCédric Le Goater 
765623575e1SCédric Le Goater     object_child_foreach_recursive(OBJECT(chip),
766623575e1SCédric Le Goater                          pnv_chip_power9_pic_print_info_child, mon);
7672b548a42SCédric Le Goater }
7682b548a42SCédric Le Goater 
769458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
770458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
771458c6f01SCédric Le Goater {
772458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
773458c6f01SCédric Le Goater     uint64_t ram_per_chip;
774458c6f01SCédric Le Goater 
775458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
776458c6f01SCédric Le Goater 
777458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
778458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
779458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
780458c6f01SCédric Le Goater     }
781458c6f01SCédric Le Goater 
782f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
783f640afecSCédric Le Goater 
784458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
785458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
786458c6f01SCédric Le Goater }
787458c6f01SCédric Le Goater 
788b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7899e933f4aSBenjamin Herrenschmidt {
790cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
791b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
792f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7939e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7949e933f4aSBenjamin Herrenschmidt     long fw_size;
795458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
796e997040eSCédric Le Goater     int i;
797e997040eSCédric Le Goater     char *chip_typename;
79835dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
79935dde576SCédric Le Goater     DeviceState *dev;
8009e933f4aSBenjamin Herrenschmidt 
801ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
802ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
803ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
804ebe6c3faSDaniel Henrique Barboza     }
805ebe6c3faSDaniel Henrique Barboza 
8069e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
807dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
808dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
809dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
810dd7ef911SCédric Le Goater         g_free(sz);
811dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
8129e933f4aSBenjamin Herrenschmidt     }
813173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
8149e933f4aSBenjamin Herrenschmidt 
81535dde576SCédric Le Goater     /*
81635dde576SCédric Le Goater      * Create our simple PNOR device
81735dde576SCédric Le Goater      */
8183e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
81935dde576SCédric Le Goater     if (pnor) {
820934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
82135dde576SCédric Le Goater     }
8223c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
82335dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
82435dde576SCédric Le Goater 
8259e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
8269e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
82715fcedb2SCédric Le Goater     if (!fw_filename) {
82815fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
82915fcedb2SCédric Le Goater         exit(1);
83015fcedb2SCédric Le Goater     }
8319e933f4aSBenjamin Herrenschmidt 
83208c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
8339e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
83415fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
8359e933f4aSBenjamin Herrenschmidt         exit(1);
8369e933f4aSBenjamin Herrenschmidt     }
8379e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8389e933f4aSBenjamin Herrenschmidt 
8399e933f4aSBenjamin Herrenschmidt     /* load kernel */
8409e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8419e933f4aSBenjamin Herrenschmidt         long kernel_size;
8429e933f4aSBenjamin Herrenschmidt 
8439e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
844b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8459e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
846802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8479e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8489e933f4aSBenjamin Herrenschmidt             exit(1);
8499e933f4aSBenjamin Herrenschmidt         }
8509e933f4aSBenjamin Herrenschmidt     }
8519e933f4aSBenjamin Herrenschmidt 
8529e933f4aSBenjamin Herrenschmidt     /* load initrd */
8539e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
8549e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
8559e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
856584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
8579e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
858802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
8599e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
8609e933f4aSBenjamin Herrenschmidt             exit(1);
8619e933f4aSBenjamin Herrenschmidt         }
8629e933f4aSBenjamin Herrenschmidt     }
863e997040eSCédric Le Goater 
8644f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8654f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8664f9924c4SBenjamin Herrenschmidt 
867f30c843cSCédric Le Goater     /*
868f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
869f30c843cSCédric Le Goater      * default.
870f30c843cSCédric Le Goater      */
871f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
872f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
873f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
874f30c843cSCédric Le Goater         exit(1);
875f30c843cSCédric Le Goater     }
876f30c843cSCédric Le Goater 
877e997040eSCédric Le Goater     /* Create the processor chips */
8784a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8797fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8804a12c699SIgor Mammedov                                     i, machine->cpu_type);
881e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
882f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
883f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
884e997040eSCédric Le Goater         exit(1);
885e997040eSCédric Le Goater     }
886e997040eSCédric Le Goater 
887e44acde2SGreg Kurz     pnv->num_chips =
888e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
889e44acde2SGreg Kurz     /*
890e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
891e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
892e44acde2SGreg Kurz      */
893ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
894e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
895ab17a3feSCédric Le Goater         error_printf(
896ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
897e44acde2SGreg Kurz         exit(1);
898e44acde2SGreg Kurz     }
899e44acde2SGreg Kurz 
900e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
901e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
902e997040eSCédric Le Goater         char chip_name[32];
903df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
9040e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
905e997040eSCédric Le Goater 
906e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
907e997040eSCédric Le Goater 
908458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
909458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
910e997040eSCédric Le Goater                                 &error_fatal);
911458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
912458c6f01SCédric Le Goater                                 &error_fatal);
913458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
914e997040eSCédric Le Goater 
9150e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
916d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
9170e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
9185325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
9195325cc34SMarkus Armbruster                                 &error_fatal);
9205325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
9215325cc34SMarkus Armbruster                                 &error_fatal);
922245cdb7fSCédric Le Goater         /*
923245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
924245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
925245cdb7fSCédric Le Goater          */
926245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
9275325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
928245cdb7fSCédric Le Goater         }
929d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
9305325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
931d1214b81SGreg Kurz                                      &error_abort);
932d1214b81SGreg Kurz         }
9333c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
934e997040eSCédric Le Goater     }
935e997040eSCédric Le Goater     g_free(chip_typename);
9363495b6b6SCédric Le Goater 
9373495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
93804026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9393495b6b6SCédric Le Goater 
9403495b6b6SCédric Le Goater     /* Create serial port */
941def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9423495b6b6SCédric Le Goater 
9433495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9446c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
945bce0b691SCédric Le Goater 
94625f3170bSCédric Le Goater     /*
94725f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
94825f3170bSCédric Le Goater      * communication with the BMC
94925f3170bSCédric Le Goater      */
95025f3170bSCédric Le Goater     if (defaults_enabled()) {
95125f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
952e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
95325f3170bSCédric Le Goater     }
954e2392d43SCédric Le Goater 
95559b7c1c2SBalamuruhan S     /*
956032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
957032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
958032c226bSCédric Le Goater      * map it always for now.
959032c226bSCédric Le Goater      */
960032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
961032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
962032c226bSCédric Le Goater 
963032c226bSCédric Le Goater     /*
96459b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
96559b7c1c2SBalamuruhan S      * host to powerdown
96659b7c1c2SBalamuruhan S      */
967bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
968bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
969e997040eSCédric Le Goater }
970e997040eSCédric Le Goater 
971631adaffSCédric Le Goater /*
972631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
973631adaffSCédric Le Goater  *   22:24  Chip ID
974631adaffSCédric Le Goater  *   25:28  Core number
975631adaffSCédric Le Goater  *   29:31  Thread ID
976631adaffSCédric Le Goater  */
977631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
978631adaffSCédric Le Goater {
979631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
980631adaffSCédric Le Goater }
981631adaffSCédric Le Goater 
9828fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
983d35aefa9SCédric Le Goater                                         Error **errp)
984d35aefa9SCédric Le Goater {
985245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9868fa1f4efSCédric Le Goater     Error *local_err = NULL;
9878fa1f4efSCédric Le Goater     Object *obj;
9888907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9898fa1f4efSCédric Le Goater 
990245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9918fa1f4efSCédric Le Goater     if (local_err) {
9928fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9938fa1f4efSCédric Le Goater         return;
9948fa1f4efSCédric Le Goater     }
9958fa1f4efSCédric Le Goater 
996956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
997d35aefa9SCédric Le Goater }
998d35aefa9SCédric Le Goater 
9990990ce6aSGreg Kurz 
1000d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1001d49e8a9bSCédric Le Goater {
1002d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1003d49e8a9bSCédric Le Goater 
1004d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
1005d49e8a9bSCédric Le Goater }
1006d49e8a9bSCédric Le Goater 
10070990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10080990ce6aSGreg Kurz {
10090990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10100990ce6aSGreg Kurz 
10110990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
10120990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10130990ce6aSGreg Kurz }
10140990ce6aSGreg Kurz 
101585913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
101685913070SGreg Kurz                                             Monitor *mon)
101785913070SGreg Kurz {
101885913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
101985913070SGreg Kurz }
102085913070SGreg Kurz 
1021631adaffSCédric Le Goater /*
1022631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
1023631adaffSCédric Le Goater  *   49:52  Node ID
1024631adaffSCédric Le Goater  *   53:55  Chip ID
1025631adaffSCédric Le Goater  *   56     Reserved - Read as zero
1026631adaffSCédric Le Goater  *   57:61  Core number
1027631adaffSCédric Le Goater  *   62:63  Thread ID
1028631adaffSCédric Le Goater  *
1029631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
1030631adaffSCédric Le Goater  */
1031631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
1032631adaffSCédric Le Goater {
1033631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
1034631adaffSCédric Le Goater }
1035631adaffSCédric Le Goater 
10362b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10372b548a42SCédric Le Goater {
10382b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10392b548a42SCédric Le Goater }
10402b548a42SCédric Le Goater 
10418fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1042d35aefa9SCédric Le Goater                                         Error **errp)
1043d35aefa9SCédric Le Goater {
10442dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10452dfa91a2SCédric Le Goater     Error *local_err = NULL;
10462dfa91a2SCédric Le Goater     Object *obj;
10472dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10482dfa91a2SCédric Le Goater 
10492dfa91a2SCédric Le Goater     /*
10502dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
10512dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
10522dfa91a2SCédric Le Goater      * only used at runtime.
10532dfa91a2SCédric Le Goater      */
105447950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
105547950946SCédric Le Goater                            &local_err);
10562dfa91a2SCédric Le Goater     if (local_err) {
10572dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
10588fa1f4efSCédric Le Goater         return;
1059d35aefa9SCédric Le Goater     }
1060d35aefa9SCédric Le Goater 
10612dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10622dfa91a2SCédric Le Goater }
10632dfa91a2SCédric Le Goater 
1064d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1065d49e8a9bSCédric Le Goater {
1066d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1067d49e8a9bSCédric Le Goater 
1068d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1069d49e8a9bSCédric Le Goater }
1070d49e8a9bSCédric Le Goater 
10710990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10720990ce6aSGreg Kurz {
10730990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10740990ce6aSGreg Kurz 
10750990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10760990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10770990ce6aSGreg Kurz }
10780990ce6aSGreg Kurz 
107985913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
108085913070SGreg Kurz                                             Monitor *mon)
108185913070SGreg Kurz {
108285913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
108385913070SGreg Kurz }
108485913070SGreg Kurz 
10852b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10862b548a42SCédric Le Goater                                         Error **errp)
10872b548a42SCédric Le Goater {
1088da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1089da71b7e3SCédric Le Goater     Error *local_err = NULL;
1090da71b7e3SCédric Le Goater     Object *obj;
10912b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10922b548a42SCédric Le Goater 
1093da71b7e3SCédric Le Goater     /*
1094da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1095da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1096da71b7e3SCédric Le Goater      * only used at runtime.
1097da71b7e3SCédric Le Goater      */
1098da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1099da71b7e3SCédric Le Goater                            &local_err);
1100da71b7e3SCédric Le Goater     if (local_err) {
1101da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1102da71b7e3SCédric Le Goater         return;
1103da71b7e3SCédric Le Goater     }
1104da71b7e3SCédric Le Goater 
1105da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
11062b548a42SCédric Le Goater }
11072b548a42SCédric Le Goater 
11082b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
11092b548a42SCédric Le Goater {
1110da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1111da71b7e3SCédric Le Goater 
1112da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
11132b548a42SCédric Le Goater }
11142b548a42SCédric Le Goater 
11152b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11162b548a42SCédric Le Goater {
11172b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11182b548a42SCédric Le Goater 
1119da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
11202b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
11212b548a42SCédric Le Goater }
11222b548a42SCédric Le Goater 
112385913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
112485913070SGreg Kurz                                              Monitor *mon)
112585913070SGreg Kurz {
1126da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
112785913070SGreg Kurz }
112885913070SGreg Kurz 
112959b7c1c2SBalamuruhan S /*
113059b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1131397a79e7SCédric Le Goater  *
1132397a79e7SCédric Le Goater  * <EX0 reserved>
1133397a79e7SCédric Le Goater  *  EX1  - Venice only
1134397a79e7SCédric Le Goater  *  EX2  - Venice only
1135397a79e7SCédric Le Goater  *  EX3  - Venice only
1136397a79e7SCédric Le Goater  *  EX4
1137397a79e7SCédric Le Goater  *  EX5
1138397a79e7SCédric Le Goater  *  EX6
1139397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1140397a79e7SCédric Le Goater  *  EX9  - Venice only
1141397a79e7SCédric Le Goater  *  EX10 - Venice only
1142397a79e7SCédric Le Goater  *  EX11 - Venice only
1143397a79e7SCédric Le Goater  *  EX12
1144397a79e7SCédric Le Goater  *  EX13
1145397a79e7SCédric Le Goater  *  EX14
1146397a79e7SCédric Le Goater  * <EX15 reserved>
1147397a79e7SCédric Le Goater  */
1148397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1149397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1150397a79e7SCédric Le Goater 
1151397a79e7SCédric Le Goater /*
115209279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1153397a79e7SCédric Le Goater  */
115409279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1155397a79e7SCédric Le Goater 
11562b548a42SCédric Le Goater 
11572b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
11582b548a42SCédric Le Goater 
115977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
116077864267SCédric Le Goater {
116177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
11629ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
11639ae1329eSCédric Le Goater     int i;
116477864267SCédric Le Goater 
1165245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1166245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1167245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1168d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1169245cdb7fSCédric Le Goater 
11709fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
117177864267SCédric Le Goater 
11729fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
117377864267SCédric Le Goater 
11749fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
11753887d241SBalamuruhan S 
11769fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
11779ae1329eSCédric Le Goater 
1178892c3ad0SDaniel Henrique Barboza     if (defaults_enabled()) {
1179eb93c828SCédric Le Goater         chip8->num_phbs = pcc->num_phbs;
11801f6a88ffSCédric Le Goater 
1181eb93c828SCédric Le Goater         for (i = 0; i < chip8->num_phbs; i++) {
11820d512c71SDaniel Henrique Barboza             Object *phb = object_new(TYPE_PNV_PHB);
11830d512c71SDaniel Henrique Barboza 
11840d512c71SDaniel Henrique Barboza             /*
11850d512c71SDaniel Henrique Barboza              * We need the chip to parent the PHB to allow the DT
11860d512c71SDaniel Henrique Barboza              * to build correctly (via pnv_xscom_dt()).
11870d512c71SDaniel Henrique Barboza              *
11880d512c71SDaniel Henrique Barboza              * TODO: the PHB should be parented by a PEC device that, at
11890d512c71SDaniel Henrique Barboza              * this moment, is not modelled powernv8/phb3.
11900d512c71SDaniel Henrique Barboza              */
11910d512c71SDaniel Henrique Barboza             object_property_add_child(obj, "phb[*]", phb);
11920d512c71SDaniel Henrique Barboza             chip8->phbs[i] = PNV_PHB(phb);
11939ae1329eSCédric Le Goater         }
1194892c3ad0SDaniel Henrique Barboza     }
11959ae1329eSCédric Le Goater 
119677864267SCédric Le Goater }
119777864267SCédric Le Goater 
119877864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
119977864267SCédric Le Goater  {
120077864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
120177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
120277864267SCédric Le Goater     int i, j;
120377864267SCédric Le Goater     char *name;
120477864267SCédric Le Goater 
120577864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
120677864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
120777864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
120877864267SCédric Le Goater     g_free(name);
120977864267SCédric Le Goater 
121077864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
121177864267SCédric Le Goater 
121277864267SCédric Le Goater     /* Map the ICP registers for each thread */
121377864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
12144fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
121577864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
121677864267SCédric Le Goater 
121777864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
121877864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1219245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
122077864267SCédric Le Goater 
122177864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
122277864267SCédric Le Goater                                         &icp->mmio);
122377864267SCédric Le Goater         }
122477864267SCédric Le Goater     }
122577864267SCédric Le Goater }
122677864267SCédric Le Goater 
122777864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
122877864267SCédric Le Goater {
122977864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
123077864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
123177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1232ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
123377864267SCédric Le Goater     Error *local_err = NULL;
12349ae1329eSCédric Le Goater     int i;
123577864267SCédric Le Goater 
1236245cdb7fSCédric Le Goater     assert(chip8->xics);
1237245cdb7fSCédric Le Goater 
1238709044fdSCédric Le Goater     /* XSCOM bridge is first */
1239709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1240709044fdSCédric Le Goater     if (local_err) {
1241709044fdSCédric Le Goater         error_propagate(errp, local_err);
1242709044fdSCédric Le Goater         return;
1243709044fdSCédric Le Goater     }
1244709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1245709044fdSCédric Le Goater 
124677864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
124777864267SCédric Le Goater     if (local_err) {
124877864267SCédric Le Goater         error_propagate(errp, local_err);
124977864267SCédric Le Goater         return;
125077864267SCédric Le Goater     }
125177864267SCédric Le Goater 
125277864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
12535325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
12545325cc34SMarkus Armbruster                             &error_fatal);
12555325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
12565325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1257668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
125877864267SCédric Le Goater         return;
125977864267SCédric Le Goater     }
1260ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1261ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
126277864267SCédric Le Goater 
126377864267SCédric Le Goater     /* Create LPC controller */
1264ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
126577864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
126677864267SCédric Le Goater 
1267032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
126864d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
126964d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
127064d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
127164d011d5SCédric Le Goater 
127259b7c1c2SBalamuruhan S     /*
127359b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
127459b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
127559b7c1c2SBalamuruhan S      */
127677864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
127777864267SCédric Le Goater     if (local_err) {
127877864267SCédric Le Goater         error_propagate(errp, local_err);
127977864267SCédric Le Goater         return;
128077864267SCédric Le Goater     }
128177864267SCédric Le Goater 
128277864267SCédric Le Goater     /* Create the simplified OCC model */
1283668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
128477864267SCédric Le Goater         return;
128577864267SCédric Le Goater     }
128677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1287b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1288b0ae5c69SCédric Le Goater                           qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC));
1289f3db8266SBalamuruhan S 
1290f3db8266SBalamuruhan S     /* OCC SRAM model */
12913a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1292f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
12933887d241SBalamuruhan S 
12943887d241SBalamuruhan S     /* HOMER */
12955325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1296f2582acfSGreg Kurz                              &error_abort);
1297668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
12983887d241SBalamuruhan S         return;
12993887d241SBalamuruhan S     }
13008f092316SCédric Le Goater     /* Homer Xscom region */
13018f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
13028f092316SCédric Le Goater 
13038f092316SCédric Le Goater     /* Homer mmio region */
13043887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
13053887d241SBalamuruhan S                                 &chip8->homer.regs);
13069ae1329eSCédric Le Goater 
13071f5d6b2aSDaniel Henrique Barboza     /* PHB controllers */
1308eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
13090d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
13109ae1329eSCédric Le Goater 
13115325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
13125325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
13139ae1329eSCédric Le Goater                                 &error_fatal);
13142c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
13152c4d3a50SCédric Le Goater                                  &error_fatal);
1316668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
13179ae1329eSCédric Le Goater             return;
13189ae1329eSCédric Le Goater         }
13199ae1329eSCédric Le Goater     }
132077864267SCédric Le Goater }
132177864267SCédric Le Goater 
132270c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
132370c059e9SGreg Kurz {
132470c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
132570c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
132670c059e9SGreg Kurz }
132770c059e9SGreg Kurz 
1328e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1329e997040eSCédric Le Goater {
1330e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1331e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1332e997040eSCédric Le Goater 
1333e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1334397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
13359ae1329eSCédric Le Goater     k->num_phbs = 3;
1336631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1337d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1338d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13390990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
134085913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
134104026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1342eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1343d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1344c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
134570c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1346e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
134777864267SCédric Le Goater 
134877864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
134977864267SCédric Le Goater                                     &k->parent_realize);
1350e997040eSCédric Le Goater }
1351e997040eSCédric Le Goater 
1352e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1353e997040eSCédric Le Goater {
1354e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1355e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1356e997040eSCédric Le Goater 
1357e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1358397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13599ae1329eSCédric Le Goater     k->num_phbs = 3;
1360631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1361d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1362d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13630990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
136485913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
136504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1366eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1367d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1368c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
136970c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1370e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
137177864267SCédric Le Goater 
137277864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
137377864267SCédric Le Goater                                     &k->parent_realize);
1374e997040eSCédric Le Goater }
1375e997040eSCédric Le Goater 
1376e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1377e997040eSCédric Le Goater {
1378e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1379e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1380e997040eSCédric Le Goater 
1381e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1382397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1383316717feSCédric Le Goater     k->num_phbs = 4;
1384631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1385d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1386d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13870990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
138885913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
138904026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1390eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1391d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1392c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
139370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1394e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
139577864267SCédric Le Goater 
139677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
139777864267SCédric Le Goater                                     &k->parent_realize);
139877864267SCédric Le Goater }
139977864267SCédric Le Goater 
140077864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
140177864267SCédric Le Goater {
14024f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
14032dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
14044f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
14054f9924c4SBenjamin Herrenschmidt     int i;
14062dfa91a2SCédric Le Goater 
1407db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1408d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1409d2623129SMarkus Armbruster                               "xive-fabric");
1410c38536bcSCédric Le Goater 
14119fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
141215376c66SCédric Le Goater 
14139fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
14146598a70dSCédric Le Goater 
14159fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
14163887d241SBalamuruhan S 
14170bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
14180bf4d77eSNicholas Piggin 
14199fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
14204f9924c4SBenjamin Herrenschmidt 
1421422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1422422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1423422fd92eSCédric Le Goater 
1424422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14254f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
14269fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
14274f9924c4SBenjamin Herrenschmidt     }
142877864267SCédric Le Goater }
142977864267SCédric Le Goater 
1430ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1431ae4c68e3SCédric Le Goater                                       PnvCore *pnv_core)
14325dad902cSCédric Le Goater {
14335dad902cSCédric Le Goater     char eq_name[32];
14345dad902cSCédric Le Goater     int core_id = CPU_CORE(pnv_core)->core_id;
14355dad902cSCédric Le Goater 
14365dad902cSCédric Le Goater     snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14379fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
14389fc7fc4dSMarkus Armbruster                                        sizeof(*eq), TYPE_PNV_QUAD,
14399fc7fc4dSMarkus Armbruster                                        &error_fatal, NULL);
14405dad902cSCédric Le Goater 
144192612f15SCédric Le Goater     object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1442ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(eq), NULL, &error_fatal);
1443ae4c68e3SCédric Le Goater }
1444ae4c68e3SCédric Le Goater 
1445ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1446ae4c68e3SCédric Le Goater {
1447ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
1448ae4c68e3SCédric Le Goater     int i;
1449ae4c68e3SCédric Le Goater 
1450ae4c68e3SCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1451ae4c68e3SCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1452ae4c68e3SCédric Le Goater 
1453ae4c68e3SCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
1454ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
1455ae4c68e3SCédric Le Goater 
1456ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
14575dad902cSCédric Le Goater 
145892612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
14595dad902cSCédric Le Goater                                 &eq->xscom_regs);
14605dad902cSCédric Le Goater     }
14615dad902cSCédric Le Goater }
14625dad902cSCédric Le Goater 
146313480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
14644f9924c4SBenjamin Herrenschmidt {
14654f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
146613480fc5SCédric Le Goater     int i;
14674f9924c4SBenjamin Herrenschmidt 
1468422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14694f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
14704f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
14714f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
14724f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
14734f9924c4SBenjamin Herrenschmidt 
14745325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
14755325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
14764f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14776f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
14786f43d255SCédric Le Goater                                  &error_fatal);
1479668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14804f9924c4SBenjamin Herrenschmidt             return;
14814f9924c4SBenjamin Herrenschmidt         }
14824f9924c4SBenjamin Herrenschmidt 
14834f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14844f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14854f9924c4SBenjamin Herrenschmidt 
14864f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
14874f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
14884f9924c4SBenjamin Herrenschmidt     }
14894f9924c4SBenjamin Herrenschmidt }
14904f9924c4SBenjamin Herrenschmidt 
149177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
149277864267SCédric Le Goater {
149377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14942dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14952dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1496c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
149777864267SCédric Le Goater     Error *local_err = NULL;
149877864267SCédric Le Goater 
1499709044fdSCédric Le Goater     /* XSCOM bridge is first */
1500709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1501709044fdSCédric Le Goater     if (local_err) {
1502709044fdSCédric Le Goater         error_propagate(errp, local_err);
1503709044fdSCédric Le Goater         return;
1504709044fdSCédric Le Goater     }
1505709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1506709044fdSCédric Le Goater 
150777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
150877864267SCédric Le Goater     if (local_err) {
150977864267SCédric Le Goater         error_propagate(errp, local_err);
151077864267SCédric Le Goater         return;
151177864267SCédric Le Goater     }
15122dfa91a2SCédric Le Goater 
15135dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
15145dad902cSCédric Le Goater     if (local_err) {
15155dad902cSCédric Le Goater         error_propagate(errp, local_err);
15165dad902cSCédric Le Goater         return;
15175dad902cSCédric Le Goater     }
15185dad902cSCédric Le Goater 
15192dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
15205325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
15215325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
15225325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
15235325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
15245325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
15255325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
15265325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
15275325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
15285325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
15297ae54cc3SGreg Kurz                              &error_abort);
1530668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
15312dfa91a2SCédric Le Goater         return;
15322dfa91a2SCédric Le Goater     }
15332dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
15342dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1535c38536bcSCédric Le Goater 
1536c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15375325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
15385325cc34SMarkus Armbruster                             &error_fatal);
153924c8fa96SCédric Le Goater     /* This is the only device with 4k ESB pages */
154024c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
154124c8fa96SCédric Le Goater                             &error_fatal);
1542668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1543c38536bcSCédric Le Goater         return;
1544c38536bcSCédric Le Goater     }
1545c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1546c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
154715376c66SCédric Le Goater 
154815376c66SCédric Le Goater     /* LPC */
1549668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
155015376c66SCédric Le Goater         return;
155115376c66SCédric Le Goater     }
155215376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
155315376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
155415376c66SCédric Le Goater 
1555032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
155615376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
155715376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15586598a70dSCédric Le Goater 
15596598a70dSCédric Le Goater     /* Create the simplified OCC model */
1560668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
15616598a70dSCédric Le Goater         return;
15626598a70dSCédric Le Goater     }
15636598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1564b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1565b0ae5c69SCédric Le Goater                               DEVICE(&chip9->psi), PSIHB9_IRQ_OCC));
1566f3db8266SBalamuruhan S 
1567f3db8266SBalamuruhan S     /* OCC SRAM model */
15683a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1569f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15703887d241SBalamuruhan S 
15710bf4d77eSNicholas Piggin     /* SBE */
15720bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
15730bf4d77eSNicholas Piggin         return;
15740bf4d77eSNicholas Piggin     }
15750bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
15760bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_ctrl_regs);
15770bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
15780bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_mbox_regs);
15790bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
15800bf4d77eSNicholas Piggin                               DEVICE(&chip9->psi), PSIHB9_IRQ_PSU));
15810bf4d77eSNicholas Piggin 
15823887d241SBalamuruhan S     /* HOMER */
15835325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1584f2582acfSGreg Kurz                              &error_abort);
1585668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15863887d241SBalamuruhan S         return;
15873887d241SBalamuruhan S     }
15888f092316SCédric Le Goater     /* Homer Xscom region */
15898f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15908f092316SCédric Le Goater 
15918f092316SCédric Le Goater     /* Homer mmio region */
15923887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15933887d241SBalamuruhan S                                 &chip9->homer.regs);
15944f9924c4SBenjamin Herrenschmidt 
159513480fc5SCédric Le Goater     /* PEC PHBs */
159613480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
15974f9924c4SBenjamin Herrenschmidt     if (local_err) {
15984f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15994f9924c4SBenjamin Herrenschmidt         return;
16004f9924c4SBenjamin Herrenschmidt     }
1601e997040eSCédric Le Goater }
1602e997040eSCédric Le Goater 
160370c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
160470c059e9SGreg Kurz {
160570c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
160670c059e9SGreg Kurz     return addr >> 3;
160770c059e9SGreg Kurz }
160870c059e9SGreg Kurz 
1609e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1610e997040eSCédric Le Goater {
1611e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1612e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1613e997040eSCédric Le Goater 
161483028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1615397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1616631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1617d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1618d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
16190990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
162085913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
162104026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1622eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1623d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1624c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
162570c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1626e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1627422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
162877864267SCédric Le Goater 
162977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
163077864267SCédric Le Goater                                     &k->parent_realize);
1631e997040eSCédric Le Goater }
1632e997040eSCédric Le Goater 
16332b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
16342b548a42SCédric Le Goater {
1635623575e1SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
16368b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1637623575e1SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1638623575e1SCédric Le Goater     int i;
16398b50ce85SCédric Le Goater 
1640da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1641da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1642da71b7e3SCédric Le Goater                               "xive-fabric");
16439fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
16449fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
16458bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
16460bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe",  &chip10->sbe, TYPE_PNV10_SBE);
164792499676SCédric Le Goater     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1648623575e1SCédric Le Goater 
1649623575e1SCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1650623575e1SCédric Le Goater 
1651623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1652623575e1SCédric Le Goater         object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1653623575e1SCédric Le Goater                                 TYPE_PNV_PHB5_PEC);
1654623575e1SCédric Le Goater     }
16552b548a42SCédric Le Goater }
16562b548a42SCédric Le Goater 
1657ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1658ae4c68e3SCédric Le Goater {
1659ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip10);
1660ae4c68e3SCédric Le Goater     int i;
1661ae4c68e3SCédric Le Goater 
1662ae4c68e3SCédric Le Goater     chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1663ae4c68e3SCédric Le Goater     chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1664ae4c68e3SCédric Le Goater 
1665ae4c68e3SCédric Le Goater     for (i = 0; i < chip10->nr_quads; i++) {
1666ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip10->quads[i];
1667ae4c68e3SCédric Le Goater 
1668ae4c68e3SCédric Le Goater         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4]);
1669ae4c68e3SCédric Le Goater 
1670ae4c68e3SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1671ae4c68e3SCédric Le Goater                                 &eq->xscom_regs);
1672ae4c68e3SCédric Le Goater     }
1673ae4c68e3SCédric Le Goater }
1674ae4c68e3SCédric Le Goater 
1675623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1676623575e1SCédric Le Goater {
1677623575e1SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1678623575e1SCédric Le Goater     int i;
1679623575e1SCédric Le Goater 
1680623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1681623575e1SCédric Le Goater         PnvPhb4PecState *pec = &chip10->pecs[i];
1682623575e1SCédric Le Goater         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1683623575e1SCédric Le Goater         uint32_t pec_nest_base;
1684623575e1SCédric Le Goater         uint32_t pec_pci_base;
1685623575e1SCédric Le Goater 
1686623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1687623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1688623575e1SCédric Le Goater                                 &error_fatal);
1689623575e1SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1690623575e1SCédric Le Goater                                  &error_fatal);
1691623575e1SCédric Le Goater         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1692623575e1SCédric Le Goater             return;
1693623575e1SCédric Le Goater         }
1694623575e1SCédric Le Goater 
1695623575e1SCédric Le Goater         pec_nest_base = pecc->xscom_nest_base(pec);
1696623575e1SCédric Le Goater         pec_pci_base = pecc->xscom_pci_base(pec);
1697623575e1SCédric Le Goater 
1698623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1699623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1700623575e1SCédric Le Goater     }
1701623575e1SCédric Le Goater }
1702623575e1SCédric Le Goater 
17032b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
17042b548a42SCédric Le Goater {
17052b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
17062b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
17078b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
17082b548a42SCédric Le Goater     Error *local_err = NULL;
17092b548a42SCédric Le Goater 
17102b548a42SCédric Le Goater     /* XSCOM bridge is first */
17112b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
17122b548a42SCédric Le Goater     if (local_err) {
17132b548a42SCédric Le Goater         error_propagate(errp, local_err);
17142b548a42SCédric Le Goater         return;
17152b548a42SCédric Le Goater     }
17162b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
17172b548a42SCédric Le Goater 
17182b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
17192b548a42SCédric Le Goater     if (local_err) {
17202b548a42SCédric Le Goater         error_propagate(errp, local_err);
17212b548a42SCédric Le Goater         return;
17222b548a42SCédric Le Goater     }
17238b50ce85SCédric Le Goater 
1724ae4c68e3SCédric Le Goater     pnv_chip_power10_quad_realize(chip10, &local_err);
1725ae4c68e3SCédric Le Goater     if (local_err) {
1726ae4c68e3SCédric Le Goater         error_propagate(errp, local_err);
1727ae4c68e3SCédric Le Goater         return;
1728ae4c68e3SCédric Le Goater     }
1729ae4c68e3SCédric Le Goater 
1730da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1731da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1732da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1733da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1734da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1735da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1736da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1737da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1738da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1739da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1740da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1741da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1742da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1743da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1744da71b7e3SCédric Le Goater                              &error_abort);
1745da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1746da71b7e3SCédric Le Goater         return;
1747da71b7e3SCédric Le Goater     }
1748da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1749da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1750da71b7e3SCédric Le Goater 
17518b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
17525325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
17535325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
175424c8fa96SCédric Le Goater     /* PSI can now be configured to use 64k ESB pages on POWER10 */
175524c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
175624c8fa96SCédric Le Goater                             &error_fatal);
1757668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
17588b50ce85SCédric Le Goater         return;
17598b50ce85SCédric Le Goater     }
17608b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
17618b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
17622661f6abSCédric Le Goater 
17632661f6abSCédric Le Goater     /* LPC */
1764668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
17652661f6abSCédric Le Goater         return;
17662661f6abSCédric Le Goater     }
17672661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
17682661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
17692661f6abSCédric Le Goater 
1770032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
17712661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
17722661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
17738bf682a3SCédric Le Goater 
17748bf682a3SCédric Le Goater     /* Create the simplified OCC model */
17758bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
17768bf682a3SCédric Le Goater         return;
17778bf682a3SCédric Le Goater     }
17788bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
17798bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
1780b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1781b0ae5c69SCédric Le Goater                               DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1782623575e1SCédric Le Goater 
178392499676SCédric Le Goater     /* OCC SRAM model */
178492499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(),
178592499676SCédric Le Goater                                 PNV10_OCC_SENSOR_BASE(chip),
178692499676SCédric Le Goater                                 &chip10->occ.sram_regs);
178792499676SCédric Le Goater 
17880bf4d77eSNicholas Piggin     /* SBE */
17890bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
17900bf4d77eSNicholas Piggin         return;
17910bf4d77eSNicholas Piggin     }
17920bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
17930bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_ctrl_regs);
17940bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
17950bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_mbox_regs);
17960bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
17970bf4d77eSNicholas Piggin                               DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
17980bf4d77eSNicholas Piggin 
179992499676SCédric Le Goater     /* HOMER */
180092499676SCédric Le Goater     object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
180192499676SCédric Le Goater                              &error_abort);
180292499676SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
180392499676SCédric Le Goater         return;
180492499676SCédric Le Goater     }
180592499676SCédric Le Goater     /* Homer Xscom region */
180692499676SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
180792499676SCédric Le Goater                             &chip10->homer.pba_regs);
180892499676SCédric Le Goater 
180992499676SCédric Le Goater     /* Homer mmio region */
181092499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
181192499676SCédric Le Goater                                 &chip10->homer.regs);
181292499676SCédric Le Goater 
1813623575e1SCédric Le Goater     /* PHBs */
1814623575e1SCédric Le Goater     pnv_chip_power10_phb_realize(chip, &local_err);
1815623575e1SCédric Le Goater     if (local_err) {
1816623575e1SCédric Le Goater         error_propagate(errp, local_err);
1817623575e1SCédric Le Goater         return;
1818623575e1SCédric Le Goater     }
18192b548a42SCédric Le Goater }
18202b548a42SCédric Le Goater 
182170c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
182270c059e9SGreg Kurz {
182370c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
182470c059e9SGreg Kurz     return addr >> 3;
182570c059e9SGreg Kurz }
182670c059e9SGreg Kurz 
18272b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
18282b548a42SCédric Le Goater {
18292b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
18302b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
18312b548a42SCédric Le Goater 
18322b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
18332b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
18342b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
18352b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
18362b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
18372b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
183885913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
18392b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
18402b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
18412b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1842c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
184370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
18442b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
1845623575e1SCédric Le Goater     k->num_pecs = PNV10_CHIP_MAX_PEC;
18462b548a42SCédric Le Goater 
18472b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
18482b548a42SCédric Le Goater                                     &k->parent_realize);
18492b548a42SCédric Le Goater }
18502b548a42SCédric Le Goater 
1851397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1852397a79e7SCédric Le Goater {
1853397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1854397a79e7SCédric Le Goater     int cores_max;
1855397a79e7SCédric Le Goater 
1856397a79e7SCédric Le Goater     /*
1857397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1858397a79e7SCédric Le Goater      * the chip class
1859397a79e7SCédric Le Goater      */
1860397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1861397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1862397a79e7SCédric Le Goater     }
1863397a79e7SCédric Le Goater 
1864397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1865397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1866397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1867397a79e7SCédric Le Goater                    chip->cores_mask);
1868397a79e7SCédric Le Goater         return;
1869397a79e7SCédric Le Goater     }
1870397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1871397a79e7SCédric Le Goater 
1872397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
187327d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1874397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1875397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1876397a79e7SCédric Le Goater                    cores_max);
1877397a79e7SCédric Le Goater         return;
1878397a79e7SCédric Le Goater     }
1879397a79e7SCédric Le Goater }
1880397a79e7SCédric Le Goater 
188151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1882e997040eSCédric Le Goater {
1883397a79e7SCédric Le Goater     Error *error = NULL;
1884d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
188540abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1886d2fd9612SCédric Le Goater     int i, core_hwid;
188708c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1888397a79e7SCédric Le Goater 
1889d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1890d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1891d2fd9612SCédric Le Goater         return;
1892d2fd9612SCédric Le Goater     }
1893d2fd9612SCédric Le Goater 
1894d2fd9612SCédric Le Goater     /* Cores */
1895397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1896397a79e7SCédric Le Goater     if (error) {
1897397a79e7SCédric Le Goater         error_propagate(errp, error);
1898397a79e7SCédric Le Goater         return;
1899397a79e7SCédric Le Goater     }
1900d2fd9612SCédric Le Goater 
19014fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1902d2fd9612SCédric Le Goater 
1903d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1904d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1905d2fd9612SCédric Le Goater         char core_name[32];
19064fa28f23SGreg Kurz         PnvCore *pnv_core;
1907c035851aSCédric Le Goater         uint64_t xscom_core_base;
1908d2fd9612SCédric Le Goater 
1909d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1910d2fd9612SCédric Le Goater             continue;
1911d2fd9612SCédric Le Goater         }
1912d2fd9612SCédric Le Goater 
19134fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
19144fa28f23SGreg Kurz 
1915d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1916d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
19174fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
19185325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
19195325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
19205325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
19215325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
19225325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
19235325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
19245325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
19255325cc34SMarkus Armbruster                                 &error_fatal);
19265325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1927158e17a6SGreg Kurz                                  &error_abort);
1928ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
192924ece072SCédric Le Goater 
193024ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1931c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1932c035851aSCédric Le Goater 
1933c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
19344fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1935d2fd9612SCédric Le Goater         i++;
1936d2fd9612SCédric Le Goater     }
193751c04728SCédric Le Goater }
193851c04728SCédric Le Goater 
193951c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
194051c04728SCédric Le Goater {
194151c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
194251c04728SCédric Le Goater     Error *error = NULL;
194351c04728SCédric Le Goater 
194451c04728SCédric Le Goater     /* Cores */
194551c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
194651c04728SCédric Le Goater     if (error) {
194751c04728SCédric Le Goater         error_propagate(errp, error);
194851c04728SCédric Le Goater         return;
194951c04728SCédric Le Goater     }
1950e997040eSCédric Le Goater }
1951e997040eSCédric Le Goater 
1952e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1953e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1954e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1955e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1956397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1957397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1958764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
1959e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1960e997040eSCédric Le Goater };
1961e997040eSCédric Le Goater 
1962e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1963e997040eSCédric Le Goater {
1964e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1965e997040eSCédric Le Goater 
19669d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1967e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
19684f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1969e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1970e997040eSCédric Le Goater }
1971e997040eSCédric Le Goater 
1972119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1973119eaa9dSCédric Le Goater {
1974119eaa9dSCédric Le Goater     int i, j;
1975119eaa9dSCédric Le Goater 
1976119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1977119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1978119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1979119eaa9dSCédric Le Goater 
1980119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1981119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1982119eaa9dSCédric Le Goater                 return pc->threads[j];
1983119eaa9dSCédric Le Goater             }
1984119eaa9dSCédric Le Goater         }
1985119eaa9dSCédric Le Goater     }
1986119eaa9dSCédric Le Goater     return NULL;
1987119eaa9dSCédric Le Goater }
1988119eaa9dSCédric Le Goater 
198954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
199054f59d78SCédric Le Goater {
1991b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
1992da6be501SDaniel Henrique Barboza     int i, j;
199354f59d78SCédric Le Goater 
199454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
199577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
199677864267SCédric Le Goater 
199777864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
199877864267SCédric Le Goater             return &chip8->psi.ics;
199954f59d78SCédric Le Goater         }
20002ff73ddaSCédric Le Goater 
2001da6be501SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20020d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20031f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2004da6be501SDaniel Henrique Barboza 
2005da6be501SDaniel Henrique Barboza             if (ics_valid_irq(&phb3->lsis, irq)) {
2006da6be501SDaniel Henrique Barboza                 return &phb3->lsis;
2007da6be501SDaniel Henrique Barboza             }
2008da6be501SDaniel Henrique Barboza 
2009da6be501SDaniel Henrique Barboza             if (ics_valid_irq(ICS(&phb3->msis), irq)) {
2010da6be501SDaniel Henrique Barboza                 return ICS(&phb3->msis);
2011da6be501SDaniel Henrique Barboza             }
20129ae1329eSCédric Le Goater         }
201354f59d78SCédric Le Goater     }
201454f59d78SCédric Le Goater     return NULL;
201554f59d78SCédric Le Goater }
201654f59d78SCédric Le Goater 
20171f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
20181f6a88ffSCédric Le Goater {
20191f6a88ffSCédric Le Goater     int i;
20201f6a88ffSCédric Le Goater 
20211f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
20221f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
20231f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
20241f6a88ffSCédric Le Goater             return chip;
20251f6a88ffSCédric Le Goater         }
20261f6a88ffSCédric Le Goater     }
20271f6a88ffSCédric Le Goater     return NULL;
20281f6a88ffSCédric Le Goater }
20291f6a88ffSCédric Le Goater 
203054f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
203154f59d78SCédric Le Goater {
2032b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2033ca459489SDaniel Henrique Barboza     int i, j;
203454f59d78SCédric Le Goater 
203554f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
203677864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
20379ae1329eSCédric Le Goater 
203877864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
2039ca459489SDaniel Henrique Barboza 
2040ca459489SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20410d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20421f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2043ca459489SDaniel Henrique Barboza 
2044ca459489SDaniel Henrique Barboza             ics_resend(&phb3->lsis);
2045ca459489SDaniel Henrique Barboza             ics_resend(ICS(&phb3->msis));
2046ca459489SDaniel Henrique Barboza         }
204754f59d78SCédric Le Goater     }
204854f59d78SCédric Le Goater }
204954f59d78SCédric Le Goater 
205036fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
205136fc6f08SCédric Le Goater {
205236fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
205336fc6f08SCédric Le Goater 
2054956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
205536fc6f08SCédric Le Goater }
205636fc6f08SCédric Le Goater 
205747fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
205847fea43aSCédric Le Goater                                Monitor *mon)
205947fea43aSCédric Le Goater {
2060b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
206154f59d78SCédric Le Goater     int i;
206247fea43aSCédric Le Goater     CPUState *cs;
206347fea43aSCédric Le Goater 
206447fea43aSCédric Le Goater     CPU_FOREACH(cs) {
206547fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
206647fea43aSCédric Le Goater 
206785913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
206885913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
206985913070SGreg Kurz                                                            mon);
2070d8e4aad5SCédric Le Goater     }
207154f59d78SCédric Le Goater 
207254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2073d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
207454f59d78SCédric Le Goater     }
207547fea43aSCédric Le Goater }
207647fea43aSCédric Le Goater 
2077c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2078c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
2079c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
2080c722579eSCédric Le Goater                          uint32_t logic_serv,
2081c722579eSCédric Le Goater                          XiveTCTXMatch *match)
2082c722579eSCédric Le Goater {
2083c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2084c722579eSCédric Le Goater     int total_count = 0;
2085c722579eSCédric Le Goater     int i;
2086c722579eSCédric Le Goater 
2087c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2088c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2089c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2090c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2091c722579eSCédric Le Goater         int count;
2092c722579eSCédric Le Goater 
2093c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2094c722579eSCédric Le Goater                                priority, logic_serv, match);
2095c722579eSCédric Le Goater 
2096c722579eSCédric Le Goater         if (count < 0) {
2097c722579eSCédric Le Goater             return count;
2098c722579eSCédric Le Goater         }
2099c722579eSCédric Le Goater 
2100c722579eSCédric Le Goater         total_count += count;
2101c722579eSCédric Le Goater     }
2102c722579eSCédric Le Goater 
2103c722579eSCédric Le Goater     return total_count;
2104c722579eSCédric Le Goater }
2105c722579eSCédric Le Goater 
2106da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2107da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
2108da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
2109da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
2110da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
2111da71b7e3SCédric Le Goater {
2112da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2113da71b7e3SCédric Le Goater     int total_count = 0;
2114da71b7e3SCédric Le Goater     int i;
2115da71b7e3SCédric Le Goater 
2116da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2117da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2118da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2119da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2120da71b7e3SCédric Le Goater         int count;
2121da71b7e3SCédric Le Goater 
2122da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2123da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2124da71b7e3SCédric Le Goater 
2125da71b7e3SCédric Le Goater         if (count < 0) {
2126da71b7e3SCédric Le Goater             return count;
2127da71b7e3SCédric Le Goater         }
2128da71b7e3SCédric Le Goater 
2129da71b7e3SCédric Le Goater         total_count += count;
2130da71b7e3SCédric Le Goater     }
2131da71b7e3SCédric Le Goater 
2132da71b7e3SCédric Le Goater     return total_count;
2133da71b7e3SCédric Le Goater }
2134da71b7e3SCédric Le Goater 
2135f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
21369e933f4aSBenjamin Herrenschmidt {
21379e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
213836fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2139d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2140d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2141f30c843cSCédric Le Goater 
21421f5d6b2aSDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
21431f5d6b2aSDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "3" },
214480515061SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
21451f5d6b2aSDaniel Henrique Barboza     };
21461f5d6b2aSDaniel Henrique Barboza 
2147f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2148f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
21491f5d6b2aSDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2150f30c843cSCédric Le Goater 
2151f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2152f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2153f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2154d76f2da7SGreg Kurz 
2155d76f2da7SGreg Kurz     pmc->compat = compat;
2156d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2157892c3ad0SDaniel Henrique Barboza 
2158892c3ad0SDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2159f30c843cSCédric Le Goater }
2160f30c843cSCédric Le Goater 
2161f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2162f30c843cSCédric Le Goater {
2163f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2164c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2165d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2166d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2167f30c843cSCédric Le Goater 
2168210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2169210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "4" },
2170c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "4" },
2171210aacb3SDaniel Henrique Barboza     };
2172210aacb3SDaniel Henrique Barboza 
2173f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2174*277ee172SNicholas Piggin     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
2175210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2176210aacb3SDaniel Henrique Barboza 
2177c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2178f30c843cSCédric Le Goater 
2179f30c843cSCédric Le Goater     mc->alias = "powernv";
2180d76f2da7SGreg Kurz 
2181d76f2da7SGreg Kurz     pmc->compat = compat;
2182d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
21837a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2184d786be3fSDaniel Henrique Barboza 
2185d786be3fSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2186f30c843cSCédric Le Goater }
2187f30c843cSCédric Le Goater 
21882b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
21892b548a42SCédric Le Goater {
21902b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2191d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2192da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2193d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
21942b548a42SCédric Le Goater 
2195210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2196210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "5" },
2197c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
2198210aacb3SDaniel Henrique Barboza     };
2199210aacb3SDaniel Henrique Barboza 
22002b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
22016bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2202210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2203d76f2da7SGreg Kurz 
2204d76f2da7SGreg Kurz     pmc->compat = compat;
2205d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22067a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2207da71b7e3SCédric Le Goater 
2208da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
2209f1327fdeSDaniel Henrique Barboza 
2210f1327fdeSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
22112b548a42SCédric Le Goater }
22122b548a42SCédric Le Goater 
221308c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
221408c3f3a7SCédric Le Goater {
221508c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
221608c3f3a7SCédric Le Goater 
221708c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
221808c3f3a7SCédric Le Goater }
221908c3f3a7SCédric Le Goater 
222008c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
222108c3f3a7SCédric Le Goater {
222208c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
222308c3f3a7SCédric Le Goater 
222408c3f3a7SCédric Le Goater     if (value) {
222508c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
222608c3f3a7SCédric Le Goater     }
222708c3f3a7SCédric Le Goater }
222808c3f3a7SCédric Le Goater 
222901b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
223001b552b0SNicholas Piggin {
223101b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
223201b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
223301b552b0SNicholas Piggin 
223401b552b0SNicholas Piggin     cpu_synchronize_state(cs);
223501b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
22360911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
223701b552b0SNicholas Piggin         /*
2238fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2239fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2240fe837714SNicholas Piggin          * (PPC_BIT(43)).
224101b552b0SNicholas Piggin          */
22420911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2243fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
22440911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
224501b552b0SNicholas Piggin         }
2246fe837714SNicholas Piggin     } else {
2247fe837714SNicholas Piggin         /*
2248fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2249fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2250fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2251fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2252fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2253fe837714SNicholas Piggin          */
22540911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2255fe837714SNicholas Piggin     }
2256fe837714SNicholas Piggin }
225701b552b0SNicholas Piggin 
225801b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
225901b552b0SNicholas Piggin {
226001b552b0SNicholas Piggin     CPUState *cs;
226101b552b0SNicholas Piggin 
226201b552b0SNicholas Piggin     CPU_FOREACH(cs) {
226301b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
226401b552b0SNicholas Piggin     }
226501b552b0SNicholas Piggin }
226601b552b0SNicholas Piggin 
2267f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2268f30c843cSCédric Le Goater {
2269f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
227047fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
227101b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
22729e933f4aSBenjamin Herrenschmidt 
22739e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2274b168a138SCédric Le Goater     mc->init = pnv_init;
2275b168a138SCédric Le Goater     mc->reset = pnv_reset;
22769e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
227759b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
227859b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
22799e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
22809e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2281f1d18b0aSJoel Stanley     /*
2282f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2283f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2284f1d18b0aSJoel Stanley      */
2285dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2286173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
228747fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
228801b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
228908c3f3a7SCédric Le Goater 
229008c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2291d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
229208c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
22937eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
22949e933f4aSBenjamin Herrenschmidt }
22959e933f4aSBenjamin Herrenschmidt 
229677864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2297beba5c0fSIgor Mammedov     {                                             \
2298beba5c0fSIgor Mammedov         .name          = type,                    \
2299beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
230077864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
230177864267SCédric Le Goater     }
230277864267SCédric Le Goater 
230377864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
230477864267SCédric Le Goater     {                                             \
230577864267SCédric Le Goater         .name          = type,                    \
230677864267SCédric Le Goater         .class_init    = class_initfn,            \
230777864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2308beba5c0fSIgor Mammedov     }
2309beba5c0fSIgor Mammedov 
23102b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
23112b548a42SCédric Le Goater     {                                              \
23122b548a42SCédric Le Goater         .name          = type,                     \
23132b548a42SCédric Le Goater         .class_init    = class_initfn,             \
23142b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
23152b548a42SCédric Le Goater     }
23162b548a42SCédric Le Goater 
2317beba5c0fSIgor Mammedov static const TypeInfo types[] = {
23181aba8716SCédric Le Goater     {
23192b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
23202b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23212b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2322da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2323da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2324da71b7e3SCédric Le Goater             { },
2325da71b7e3SCédric Le Goater         },
23262b548a42SCédric Le Goater     },
23272b548a42SCédric Le Goater     {
23281aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
23291aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23301aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2331c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2332c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2333c722579eSCédric Le Goater             { },
2334c722579eSCédric Le Goater         },
23351aba8716SCédric Le Goater     },
23361aba8716SCédric Le Goater     {
23371aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
23381aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23391aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
23401aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
23411aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
23421aba8716SCédric Le Goater             { },
23431aba8716SCédric Le Goater         },
23441aba8716SCédric Le Goater     },
2345beba5c0fSIgor Mammedov     {
2346b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
23479e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2348f30c843cSCédric Le Goater         .abstract       = true,
23499e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2350b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2351d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
235236fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
235347fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
235401b552b0SNicholas Piggin             { TYPE_NMI },
235536fc6f08SCédric Le Goater             { },
235636fc6f08SCédric Le Goater         },
2357beba5c0fSIgor Mammedov     },
2358beba5c0fSIgor Mammedov     {
2359beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2360beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2361beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2362beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2363beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2364beba5c0fSIgor Mammedov         .abstract      = true,
2365beba5c0fSIgor Mammedov     },
236677864267SCédric Le Goater 
236777864267SCédric Le Goater     /*
23682b548a42SCédric Le Goater      * P10 chip and variants
23692b548a42SCédric Le Goater      */
23702b548a42SCédric Le Goater     {
23712b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
23722b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
23732b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
23742b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
23752b548a42SCédric Le Goater     },
23762b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
23772b548a42SCédric Le Goater 
23782b548a42SCédric Le Goater     /*
237977864267SCédric Le Goater      * P9 chip and variants
238077864267SCédric Le Goater      */
238177864267SCédric Le Goater     {
238277864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
238377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
238477864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
238577864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
238677864267SCédric Le Goater     },
238777864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
238877864267SCédric Le Goater 
238977864267SCédric Le Goater     /*
239077864267SCédric Le Goater      * P8 chip and variants
239177864267SCédric Le Goater      */
239277864267SCédric Le Goater     {
239377864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
239477864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
239577864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
239677864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
239777864267SCédric Le Goater     },
239877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
239977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
240077864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2401beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
24029e933f4aSBenjamin Herrenschmidt };
24039e933f4aSBenjamin Herrenschmidt 
2404beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2405