xref: /qemu/hw/ppc/pnv.c (revision 47dfdd23)
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()) {
802518f72ecSCédric Le Goater         error_report("machine %s does not support the KVM accelerator",
803518f72ecSCédric Le Goater                      mc->name);
804ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
805ebe6c3faSDaniel Henrique Barboza     }
806ebe6c3faSDaniel Henrique Barboza 
8079e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
808dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
809dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
810dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
811dd7ef911SCédric Le Goater         g_free(sz);
812dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
8139e933f4aSBenjamin Herrenschmidt     }
814173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
8159e933f4aSBenjamin Herrenschmidt 
81635dde576SCédric Le Goater     /*
81735dde576SCédric Le Goater      * Create our simple PNOR device
81835dde576SCédric Le Goater      */
8193e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
82035dde576SCédric Le Goater     if (pnor) {
821934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
82235dde576SCédric Le Goater     }
8233c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
82435dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
82535dde576SCédric Le Goater 
8269e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
8279e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
82815fcedb2SCédric Le Goater     if (!fw_filename) {
82915fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
83015fcedb2SCédric Le Goater         exit(1);
83115fcedb2SCédric Le Goater     }
8329e933f4aSBenjamin Herrenschmidt 
83308c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
8349e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
83515fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
8369e933f4aSBenjamin Herrenschmidt         exit(1);
8379e933f4aSBenjamin Herrenschmidt     }
8389e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
8399e933f4aSBenjamin Herrenschmidt 
8409e933f4aSBenjamin Herrenschmidt     /* load kernel */
8419e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
8429e933f4aSBenjamin Herrenschmidt         long kernel_size;
8439e933f4aSBenjamin Herrenschmidt 
8449e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
845b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
8469e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
847802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8489e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8499e933f4aSBenjamin Herrenschmidt             exit(1);
8509e933f4aSBenjamin Herrenschmidt         }
8519e933f4aSBenjamin Herrenschmidt     }
8529e933f4aSBenjamin Herrenschmidt 
8539e933f4aSBenjamin Herrenschmidt     /* load initrd */
8549e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
8559e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
8569e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
857584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
8589e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
859802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
8609e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
8619e933f4aSBenjamin Herrenschmidt             exit(1);
8629e933f4aSBenjamin Herrenschmidt         }
8639e933f4aSBenjamin Herrenschmidt     }
864e997040eSCédric Le Goater 
8654f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8664f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8674f9924c4SBenjamin Herrenschmidt 
868f30c843cSCédric Le Goater     /*
869f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
870f30c843cSCédric Le Goater      * default.
871f30c843cSCédric Le Goater      */
872f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
873f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
874f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
875f30c843cSCédric Le Goater         exit(1);
876f30c843cSCédric Le Goater     }
877f30c843cSCédric Le Goater 
878e997040eSCédric Le Goater     /* Create the processor chips */
8794a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8807fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8814a12c699SIgor Mammedov                                     i, machine->cpu_type);
882e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
883f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
884f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
885e997040eSCédric Le Goater         exit(1);
886e997040eSCédric Le Goater     }
887e997040eSCédric Le Goater 
888e44acde2SGreg Kurz     pnv->num_chips =
889e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
890934676c7SNicholas Piggin 
891934676c7SNicholas Piggin     if (machine->smp.threads > 8) {
892934676c7SNicholas Piggin         error_report("Cannot support more than 8 threads/core "
893934676c7SNicholas Piggin                      "on a powernv machine");
894934676c7SNicholas Piggin         exit(1);
895934676c7SNicholas Piggin     }
896934676c7SNicholas Piggin     if (!is_power_of_2(machine->smp.threads)) {
897934676c7SNicholas Piggin         error_report("Cannot support %d threads/core on a powernv"
898934676c7SNicholas Piggin                      "machine because it must be a power of 2",
899934676c7SNicholas Piggin                      machine->smp.threads);
900934676c7SNicholas Piggin         exit(1);
901934676c7SNicholas Piggin     }
902e44acde2SGreg Kurz     /*
903e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
904e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
905e44acde2SGreg Kurz      */
906ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
907e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
908ab17a3feSCédric Le Goater         error_printf(
909ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
910e44acde2SGreg Kurz         exit(1);
911e44acde2SGreg Kurz     }
912e44acde2SGreg Kurz 
913e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
914e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
915e997040eSCédric Le Goater         char chip_name[32];
916df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
9170e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
918e997040eSCédric Le Goater 
919e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
920e997040eSCédric Le Goater 
921458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
922458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
923e997040eSCédric Le Goater                                 &error_fatal);
924458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
925458c6f01SCédric Le Goater                                 &error_fatal);
926458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
927e997040eSCédric Le Goater 
9280e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
929d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
9300e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
9315325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
9325325cc34SMarkus Armbruster                                 &error_fatal);
9335325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
9345325cc34SMarkus Armbruster                                 &error_fatal);
935245cdb7fSCédric Le Goater         /*
936245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
937245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
938245cdb7fSCédric Le Goater          */
939245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
9405325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
941245cdb7fSCédric Le Goater         }
942d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
9435325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
944d1214b81SGreg Kurz                                      &error_abort);
945d1214b81SGreg Kurz         }
9463c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
947e997040eSCédric Le Goater     }
948e997040eSCédric Le Goater     g_free(chip_typename);
9493495b6b6SCédric Le Goater 
9503495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
95104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
9523495b6b6SCédric Le Goater 
9533495b6b6SCédric Le Goater     /* Create serial port */
954def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
9553495b6b6SCédric Le Goater 
9563495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
9576c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
958bce0b691SCédric Le Goater 
95925f3170bSCédric Le Goater     /*
96025f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
96125f3170bSCédric Le Goater      * communication with the BMC
96225f3170bSCédric Le Goater      */
96325f3170bSCédric Le Goater     if (defaults_enabled()) {
96425f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
965e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
96625f3170bSCédric Le Goater     }
967e2392d43SCédric Le Goater 
96859b7c1c2SBalamuruhan S     /*
969032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
970032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
971032c226bSCédric Le Goater      * map it always for now.
972032c226bSCédric Le Goater      */
973032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
974032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
975032c226bSCédric Le Goater 
976032c226bSCédric Le Goater     /*
97759b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
97859b7c1c2SBalamuruhan S      * host to powerdown
97959b7c1c2SBalamuruhan S      */
980bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
981bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
982e997040eSCédric Le Goater }
983e997040eSCédric Le Goater 
984631adaffSCédric Le Goater /*
985631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
986631adaffSCédric Le Goater  *   22:24  Chip ID
987631adaffSCédric Le Goater  *   25:28  Core number
988631adaffSCédric Le Goater  *   29:31  Thread ID
989631adaffSCédric Le Goater  */
990631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
991631adaffSCédric Le Goater {
992631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
993631adaffSCédric Le Goater }
994631adaffSCédric Le Goater 
9958fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
996d35aefa9SCédric Le Goater                                         Error **errp)
997d35aefa9SCédric Le Goater {
998245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9998fa1f4efSCédric Le Goater     Error *local_err = NULL;
10008fa1f4efSCédric Le Goater     Object *obj;
10018907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10028fa1f4efSCédric Le Goater 
1003245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
10048fa1f4efSCédric Le Goater     if (local_err) {
10058fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
10068fa1f4efSCédric Le Goater         return;
10078fa1f4efSCédric Le Goater     }
10088fa1f4efSCédric Le Goater 
1009956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
1010d35aefa9SCédric Le Goater }
1011d35aefa9SCédric Le Goater 
10120990ce6aSGreg Kurz 
1013d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1014d49e8a9bSCédric Le Goater {
1015d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1016d49e8a9bSCédric Le Goater 
1017d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
1018d49e8a9bSCédric Le Goater }
1019d49e8a9bSCédric Le Goater 
10200990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10210990ce6aSGreg Kurz {
10220990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10230990ce6aSGreg Kurz 
10240990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
10250990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10260990ce6aSGreg Kurz }
10270990ce6aSGreg Kurz 
102885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
102985913070SGreg Kurz                                             Monitor *mon)
103085913070SGreg Kurz {
103185913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
103285913070SGreg Kurz }
103385913070SGreg Kurz 
1034631adaffSCédric Le Goater /*
1035631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
1036631adaffSCédric Le Goater  *   49:52  Node ID
1037631adaffSCédric Le Goater  *   53:55  Chip ID
1038631adaffSCédric Le Goater  *   56     Reserved - Read as zero
1039631adaffSCédric Le Goater  *   57:61  Core number
1040631adaffSCédric Le Goater  *   62:63  Thread ID
1041631adaffSCédric Le Goater  *
1042631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
1043631adaffSCédric Le Goater  */
1044631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
1045631adaffSCédric Le Goater {
1046631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
1047631adaffSCédric Le Goater }
1048631adaffSCédric Le Goater 
10492b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
10502b548a42SCédric Le Goater {
10512b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
10522b548a42SCédric Le Goater }
10532b548a42SCédric Le Goater 
10548fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
1055d35aefa9SCédric Le Goater                                         Error **errp)
1056d35aefa9SCédric Le Goater {
10572dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
10582dfa91a2SCédric Le Goater     Error *local_err = NULL;
10592dfa91a2SCédric Le Goater     Object *obj;
10602dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10612dfa91a2SCédric Le Goater 
10622dfa91a2SCédric Le Goater     /*
10632dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
10642dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
10652dfa91a2SCédric Le Goater      * only used at runtime.
10662dfa91a2SCédric Le Goater      */
106747950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
106847950946SCédric Le Goater                            &local_err);
10692dfa91a2SCédric Le Goater     if (local_err) {
10702dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
10718fa1f4efSCédric Le Goater         return;
1072d35aefa9SCédric Le Goater     }
1073d35aefa9SCédric Le Goater 
10742dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10752dfa91a2SCédric Le Goater }
10762dfa91a2SCédric Le Goater 
1077d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1078d49e8a9bSCédric Le Goater {
1079d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1080d49e8a9bSCédric Le Goater 
1081d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1082d49e8a9bSCédric Le Goater }
1083d49e8a9bSCédric Le Goater 
10840990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10850990ce6aSGreg Kurz {
10860990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10870990ce6aSGreg Kurz 
10880990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10890990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10900990ce6aSGreg Kurz }
10910990ce6aSGreg Kurz 
109285913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
109385913070SGreg Kurz                                             Monitor *mon)
109485913070SGreg Kurz {
109585913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
109685913070SGreg Kurz }
109785913070SGreg Kurz 
10982b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10992b548a42SCédric Le Goater                                         Error **errp)
11002b548a42SCédric Le Goater {
1101da71b7e3SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1102da71b7e3SCédric Le Goater     Error *local_err = NULL;
1103da71b7e3SCédric Le Goater     Object *obj;
11042b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11052b548a42SCédric Le Goater 
1106da71b7e3SCédric Le Goater     /*
1107da71b7e3SCédric Le Goater      * The core creates its interrupt presenter but the XIVE2 interrupt
1108da71b7e3SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
1109da71b7e3SCédric Le Goater      * only used at runtime.
1110da71b7e3SCédric Le Goater      */
1111da71b7e3SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip10->xive),
1112da71b7e3SCédric Le Goater                            &local_err);
1113da71b7e3SCédric Le Goater     if (local_err) {
1114da71b7e3SCédric Le Goater         error_propagate(errp, local_err);
1115da71b7e3SCédric Le Goater         return;
1116da71b7e3SCédric Le Goater     }
1117da71b7e3SCédric Le Goater 
1118da71b7e3SCédric Le Goater     pnv_cpu->intc = obj;
11192b548a42SCédric Le Goater }
11202b548a42SCédric Le Goater 
11212b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
11222b548a42SCédric Le Goater {
1123da71b7e3SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1124da71b7e3SCédric Le Goater 
1125da71b7e3SCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
11262b548a42SCédric Le Goater }
11272b548a42SCédric Le Goater 
11282b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
11292b548a42SCédric Le Goater {
11302b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
11312b548a42SCédric Le Goater 
1132da71b7e3SCédric Le Goater     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
11332b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
11342b548a42SCédric Le Goater }
11352b548a42SCédric Le Goater 
113685913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
113785913070SGreg Kurz                                              Monitor *mon)
113885913070SGreg Kurz {
1139da71b7e3SCédric Le Goater     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
114085913070SGreg Kurz }
114185913070SGreg Kurz 
114259b7c1c2SBalamuruhan S /*
114359b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1144397a79e7SCédric Le Goater  *
1145397a79e7SCédric Le Goater  * <EX0 reserved>
1146397a79e7SCédric Le Goater  *  EX1  - Venice only
1147397a79e7SCédric Le Goater  *  EX2  - Venice only
1148397a79e7SCédric Le Goater  *  EX3  - Venice only
1149397a79e7SCédric Le Goater  *  EX4
1150397a79e7SCédric Le Goater  *  EX5
1151397a79e7SCédric Le Goater  *  EX6
1152397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1153397a79e7SCédric Le Goater  *  EX9  - Venice only
1154397a79e7SCédric Le Goater  *  EX10 - Venice only
1155397a79e7SCédric Le Goater  *  EX11 - Venice only
1156397a79e7SCédric Le Goater  *  EX12
1157397a79e7SCédric Le Goater  *  EX13
1158397a79e7SCédric Le Goater  *  EX14
1159397a79e7SCédric Le Goater  * <EX15 reserved>
1160397a79e7SCédric Le Goater  */
1161397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1162397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1163397a79e7SCédric Le Goater 
1164397a79e7SCédric Le Goater /*
116509279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1166397a79e7SCédric Le Goater  */
116709279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1168397a79e7SCédric Le Goater 
11692b548a42SCédric Le Goater 
11702b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
11712b548a42SCédric Le Goater 
117277864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
117377864267SCédric Le Goater {
117477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
11759ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
11769ae1329eSCédric Le Goater     int i;
117777864267SCédric Le Goater 
1178245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1179245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1180245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1181d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1182245cdb7fSCédric Le Goater 
11839fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
118477864267SCédric Le Goater 
11859fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
118677864267SCédric Le Goater 
11879fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
11883887d241SBalamuruhan S 
11899fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
11909ae1329eSCédric Le Goater 
1191892c3ad0SDaniel Henrique Barboza     if (defaults_enabled()) {
1192eb93c828SCédric Le Goater         chip8->num_phbs = pcc->num_phbs;
11931f6a88ffSCédric Le Goater 
1194eb93c828SCédric Le Goater         for (i = 0; i < chip8->num_phbs; i++) {
11950d512c71SDaniel Henrique Barboza             Object *phb = object_new(TYPE_PNV_PHB);
11960d512c71SDaniel Henrique Barboza 
11970d512c71SDaniel Henrique Barboza             /*
11980d512c71SDaniel Henrique Barboza              * We need the chip to parent the PHB to allow the DT
11990d512c71SDaniel Henrique Barboza              * to build correctly (via pnv_xscom_dt()).
12000d512c71SDaniel Henrique Barboza              *
12010d512c71SDaniel Henrique Barboza              * TODO: the PHB should be parented by a PEC device that, at
12020d512c71SDaniel Henrique Barboza              * this moment, is not modelled powernv8/phb3.
12030d512c71SDaniel Henrique Barboza              */
12040d512c71SDaniel Henrique Barboza             object_property_add_child(obj, "phb[*]", phb);
12050d512c71SDaniel Henrique Barboza             chip8->phbs[i] = PNV_PHB(phb);
12069ae1329eSCédric Le Goater         }
1207892c3ad0SDaniel Henrique Barboza     }
12089ae1329eSCédric Le Goater 
120977864267SCédric Le Goater }
121077864267SCédric Le Goater 
121177864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
121277864267SCédric Le Goater  {
121377864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
121477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
121577864267SCédric Le Goater     int i, j;
121677864267SCédric Le Goater     char *name;
121777864267SCédric Le Goater 
121877864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
121977864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
122077864267SCédric Le Goater     g_free(name);
1221bf3b9754SPhilippe Mathieu-Daudé     memory_region_add_subregion(get_system_memory(), PNV_ICP_BASE(chip),
1222bf3b9754SPhilippe Mathieu-Daudé                                 &chip8->icp_mmio);
122377864267SCédric Le Goater 
122477864267SCédric Le Goater     /* Map the ICP registers for each thread */
122577864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
12264fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
122777864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
122877864267SCédric Le Goater 
122977864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
123077864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1231245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
123277864267SCédric Le Goater 
123377864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
123477864267SCédric Le Goater                                         &icp->mmio);
123577864267SCédric Le Goater         }
123677864267SCédric Le Goater     }
123777864267SCédric Le Goater }
123877864267SCédric Le Goater 
123977864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
124077864267SCédric Le Goater {
124177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
124277864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
124377864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1244ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
124577864267SCédric Le Goater     Error *local_err = NULL;
12469ae1329eSCédric Le Goater     int i;
124777864267SCédric Le Goater 
1248245cdb7fSCédric Le Goater     assert(chip8->xics);
1249245cdb7fSCédric Le Goater 
1250709044fdSCédric Le Goater     /* XSCOM bridge is first */
1251326f7acbSPhilippe Mathieu-Daudé     pnv_xscom_init(chip, PNV_XSCOM_SIZE, PNV_XSCOM_BASE(chip));
1252709044fdSCédric Le Goater 
125377864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
125477864267SCédric Le Goater     if (local_err) {
125577864267SCédric Le Goater         error_propagate(errp, local_err);
125677864267SCédric Le Goater         return;
125777864267SCédric Le Goater     }
125877864267SCédric Le Goater 
125977864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
12605325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
12615325cc34SMarkus Armbruster                             &error_fatal);
12625325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
12635325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1264668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
126577864267SCédric Le Goater         return;
126677864267SCédric Le Goater     }
1267ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1268ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
126977864267SCédric Le Goater 
127077864267SCédric Le Goater     /* Create LPC controller */
1271ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
127277864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
127377864267SCédric Le Goater 
1274032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
127564d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
127664d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
127764d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
127864d011d5SCédric Le Goater 
127959b7c1c2SBalamuruhan S     /*
128059b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
128159b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
128259b7c1c2SBalamuruhan S      */
128377864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
128477864267SCédric Le Goater     if (local_err) {
128577864267SCédric Le Goater         error_propagate(errp, local_err);
128677864267SCédric Le Goater         return;
128777864267SCédric Le Goater     }
128877864267SCédric Le Goater 
128977864267SCédric Le Goater     /* Create the simplified OCC model */
1290668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
129177864267SCédric Le Goater         return;
129277864267SCédric Le Goater     }
129377864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1294b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip8->occ), 0,
1295b0ae5c69SCédric Le Goater                           qdev_get_gpio_in(DEVICE(&chip8->psi), PSIHB_IRQ_OCC));
1296f3db8266SBalamuruhan S 
1297f3db8266SBalamuruhan S     /* OCC SRAM model */
12983a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1299f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
13003887d241SBalamuruhan S 
13013887d241SBalamuruhan S     /* HOMER */
13025325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1303f2582acfSGreg Kurz                              &error_abort);
1304668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
13053887d241SBalamuruhan S         return;
13063887d241SBalamuruhan S     }
13078f092316SCédric Le Goater     /* Homer Xscom region */
13088f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
13098f092316SCédric Le Goater 
13108f092316SCédric Le Goater     /* Homer mmio region */
13113887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
13123887d241SBalamuruhan S                                 &chip8->homer.regs);
13139ae1329eSCédric Le Goater 
13141f5d6b2aSDaniel Henrique Barboza     /* PHB controllers */
1315eb93c828SCédric Le Goater     for (i = 0; i < chip8->num_phbs; i++) {
13160d512c71SDaniel Henrique Barboza         PnvPHB *phb = chip8->phbs[i];
13179ae1329eSCédric Le Goater 
13185325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
13195325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
13209ae1329eSCédric Le Goater                                 &error_fatal);
13212c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
13222c4d3a50SCédric Le Goater                                  &error_fatal);
1323668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
13249ae1329eSCédric Le Goater             return;
13259ae1329eSCédric Le Goater         }
13269ae1329eSCédric Le Goater     }
132777864267SCédric Le Goater }
132877864267SCédric Le Goater 
132970c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
133070c059e9SGreg Kurz {
133170c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
133270c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
133370c059e9SGreg Kurz }
133470c059e9SGreg Kurz 
1335e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1336e997040eSCédric Le Goater {
1337e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1338e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1339e997040eSCédric Le Goater 
1340e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1341397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
13429ae1329eSCédric Le Goater     k->num_phbs = 3;
1343631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1344d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1345d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13460990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
134785913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
134804026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1349eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1350d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1351c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
135270c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1353e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
135477864267SCédric Le Goater 
135577864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
135677864267SCédric Le Goater                                     &k->parent_realize);
1357e997040eSCédric Le Goater }
1358e997040eSCédric Le Goater 
1359e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1360e997040eSCédric Le Goater {
1361e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1362e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1363e997040eSCédric Le Goater 
1364e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1365397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13669ae1329eSCédric Le Goater     k->num_phbs = 3;
1367631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1368d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1369d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13700990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
137185913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
137204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1373eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1374d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1375c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
137670c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1377e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
137877864267SCédric Le Goater 
137977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
138077864267SCédric Le Goater                                     &k->parent_realize);
1381e997040eSCédric Le Goater }
1382e997040eSCédric Le Goater 
1383e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1384e997040eSCédric Le Goater {
1385e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1386e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1387e997040eSCédric Le Goater 
1388e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1389397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1390316717feSCédric Le Goater     k->num_phbs = 4;
1391631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1392d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1393d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13940990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
139585913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
139604026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1397eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1398d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1399c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
140070c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1401e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
140277864267SCédric Le Goater 
140377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
140477864267SCédric Le Goater                                     &k->parent_realize);
140577864267SCédric Le Goater }
140677864267SCédric Le Goater 
140777864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
140877864267SCédric Le Goater {
14094f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
14102dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
14114f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
14124f9924c4SBenjamin Herrenschmidt     int i;
14132dfa91a2SCédric Le Goater 
1414db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1415d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1416d2623129SMarkus Armbruster                               "xive-fabric");
1417c38536bcSCédric Le Goater 
14189fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
141915376c66SCédric Le Goater 
14209fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
14216598a70dSCédric Le Goater 
14229fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
14233887d241SBalamuruhan S 
14240bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE);
14250bf4d77eSNicholas Piggin 
14269fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
14274f9924c4SBenjamin Herrenschmidt 
1428422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1429422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1430422fd92eSCédric Le Goater 
1431422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14324f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
14339fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
14344f9924c4SBenjamin Herrenschmidt     }
14355f066121SCédric Le Goater 
14365f066121SCédric Le Goater     for (i = 0; i < pcc->i2c_num_engines; i++) {
14375f066121SCédric Le Goater         object_initialize_child(obj, "i2c[*]", &chip9->i2c[i], TYPE_PNV_I2C);
14385f066121SCédric Le Goater     }
143977864267SCédric Le Goater }
144077864267SCédric Le Goater 
1441ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize_one(PnvChip *chip, PnvQuad *eq,
1442fdc2b46aSJoel Stanley                                       PnvCore *pnv_core,
1443fdc2b46aSJoel Stanley                                       const char *type)
14445dad902cSCédric Le Goater {
14455dad902cSCédric Le Goater     char eq_name[32];
14465dad902cSCédric Le Goater     int core_id = CPU_CORE(pnv_core)->core_id;
14475dad902cSCédric Le Goater 
14485dad902cSCédric Le Goater     snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
14499fc7fc4dSMarkus Armbruster     object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
1450fdc2b46aSJoel Stanley                                        sizeof(*eq), type,
14519fc7fc4dSMarkus Armbruster                                        &error_fatal, NULL);
14525dad902cSCédric Le Goater 
145392612f15SCédric Le Goater     object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1454ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(eq), NULL, &error_fatal);
1455ae4c68e3SCédric Le Goater }
1456ae4c68e3SCédric Le Goater 
1457ae4c68e3SCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
1458ae4c68e3SCédric Le Goater {
1459ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
1460ae4c68e3SCédric Le Goater     int i;
1461ae4c68e3SCédric Le Goater 
1462ae4c68e3SCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1463ae4c68e3SCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
1464ae4c68e3SCédric Le Goater 
1465ae4c68e3SCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
1466ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
1467ae4c68e3SCédric Le Goater 
1468fdc2b46aSJoel Stanley         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
1469fdc2b46aSJoel Stanley                                   PNV_QUAD_TYPE_NAME("power9"));
14705dad902cSCédric Le Goater 
147192612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
14725dad902cSCédric Le Goater                                 &eq->xscom_regs);
14735dad902cSCédric Le Goater     }
14745dad902cSCédric Le Goater }
14755dad902cSCédric Le Goater 
147613480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
14774f9924c4SBenjamin Herrenschmidt {
14784f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
147913480fc5SCédric Le Goater     int i;
14804f9924c4SBenjamin Herrenschmidt 
1481422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
14824f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
14834f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
14844f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
14854f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
14864f9924c4SBenjamin Herrenschmidt 
14875325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
14885325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
14894f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
14906f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
14916f43d255SCédric Le Goater                                  &error_fatal);
1492668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14934f9924c4SBenjamin Herrenschmidt             return;
14944f9924c4SBenjamin Herrenschmidt         }
14954f9924c4SBenjamin Herrenschmidt 
14964f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14974f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14984f9924c4SBenjamin Herrenschmidt 
14994f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
15004f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
15014f9924c4SBenjamin Herrenschmidt     }
15024f9924c4SBenjamin Herrenschmidt }
15034f9924c4SBenjamin Herrenschmidt 
150477864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
150577864267SCédric Le Goater {
150677864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15072dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
15082dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1509c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
151077864267SCédric Le Goater     Error *local_err = NULL;
15115f066121SCédric Le Goater     int i;
151277864267SCédric Le Goater 
1513709044fdSCédric Le Goater     /* XSCOM bridge is first */
1514326f7acbSPhilippe Mathieu-Daudé     pnv_xscom_init(chip, PNV9_XSCOM_SIZE, PNV9_XSCOM_BASE(chip));
1515709044fdSCédric Le Goater 
151677864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
151777864267SCédric Le Goater     if (local_err) {
151877864267SCédric Le Goater         error_propagate(errp, local_err);
151977864267SCédric Le Goater         return;
152077864267SCédric Le Goater     }
15212dfa91a2SCédric Le Goater 
15225dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
15235dad902cSCédric Le Goater     if (local_err) {
15245dad902cSCédric Le Goater         error_propagate(errp, local_err);
15255dad902cSCédric Le Goater         return;
15265dad902cSCédric Le Goater     }
15275dad902cSCédric Le Goater 
15282dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
15295325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
15305325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
15315325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
15325325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
15335325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
15345325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
15355325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
15365325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
15375325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
15387ae54cc3SGreg Kurz                              &error_abort);
1539668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
15402dfa91a2SCédric Le Goater         return;
15412dfa91a2SCédric Le Goater     }
15422dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
15432dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1544c38536bcSCédric Le Goater 
1545c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15465325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
15475325cc34SMarkus Armbruster                             &error_fatal);
154824c8fa96SCédric Le Goater     /* This is the only device with 4k ESB pages */
154924c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), "shift", XIVE_ESB_4K,
155024c8fa96SCédric Le Goater                             &error_fatal);
1551668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1552c38536bcSCédric Le Goater         return;
1553c38536bcSCédric Le Goater     }
1554c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1555c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
155615376c66SCédric Le Goater 
155715376c66SCédric Le Goater     /* LPC */
1558668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
155915376c66SCédric Le Goater         return;
156015376c66SCédric Le Goater     }
156115376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
156215376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
156315376c66SCédric Le Goater 
1564032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
156515376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
156615376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
15676598a70dSCédric Le Goater 
15686598a70dSCédric Le Goater     /* Create the simplified OCC model */
1569668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
15706598a70dSCédric Le Goater         return;
15716598a70dSCédric Le Goater     }
15726598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1573b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip9->occ), 0, qdev_get_gpio_in(
1574b0ae5c69SCédric Le Goater                               DEVICE(&chip9->psi), PSIHB9_IRQ_OCC));
1575f3db8266SBalamuruhan S 
1576f3db8266SBalamuruhan S     /* OCC SRAM model */
15773a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1578f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15793887d241SBalamuruhan S 
15800bf4d77eSNicholas Piggin     /* SBE */
15810bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) {
15820bf4d77eSNicholas Piggin         return;
15830bf4d77eSNicholas Piggin     }
15840bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE,
15850bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_ctrl_regs);
15860bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE,
15870bf4d77eSNicholas Piggin                             &chip9->sbe.xscom_mbox_regs);
15880bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in(
15890bf4d77eSNicholas Piggin                               DEVICE(&chip9->psi), PSIHB9_IRQ_PSU));
15900bf4d77eSNicholas Piggin 
15913887d241SBalamuruhan S     /* HOMER */
15925325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1593f2582acfSGreg Kurz                              &error_abort);
1594668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15953887d241SBalamuruhan S         return;
15963887d241SBalamuruhan S     }
15978f092316SCédric Le Goater     /* Homer Xscom region */
15988f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15998f092316SCédric Le Goater 
16008f092316SCédric Le Goater     /* Homer mmio region */
16013887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
16023887d241SBalamuruhan S                                 &chip9->homer.regs);
16034f9924c4SBenjamin Herrenschmidt 
160413480fc5SCédric Le Goater     /* PEC PHBs */
160513480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
16064f9924c4SBenjamin Herrenschmidt     if (local_err) {
16074f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
16084f9924c4SBenjamin Herrenschmidt         return;
16094f9924c4SBenjamin Herrenschmidt     }
16105f066121SCédric Le Goater 
16115f066121SCédric Le Goater     /*
16125f066121SCédric Le Goater      * I2C
16135f066121SCédric Le Goater      */
16145f066121SCédric Le Goater     for (i = 0; i < pcc->i2c_num_engines; i++) {
16155f066121SCédric Le Goater         Object *obj =  OBJECT(&chip9->i2c[i]);
16165f066121SCédric Le Goater 
16175f066121SCédric Le Goater         object_property_set_int(obj, "engine", i + 1, &error_fatal);
16180d1dcb0bSGlenn Miles         object_property_set_int(obj, "num-busses",
16190d1dcb0bSGlenn Miles                                 pcc->i2c_ports_per_engine[i],
16205f066121SCédric Le Goater                                 &error_fatal);
16215f066121SCédric Le Goater         object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
16225f066121SCédric Le Goater         if (!qdev_realize(DEVICE(obj), NULL, errp)) {
16235f066121SCédric Le Goater             return;
16245f066121SCédric Le Goater         }
16255f066121SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_I2CM_BASE +
1626*47dfdd23SGlenn Miles                                 (chip9->i2c[i].engine - 1) *
1627*47dfdd23SGlenn Miles                                         PNV9_XSCOM_I2CM_SIZE,
16285f066121SCédric Le Goater                                 &chip9->i2c[i].xscom_regs);
16295f066121SCédric Le Goater         qdev_connect_gpio_out(DEVICE(&chip9->i2c[i]), 0,
16305f066121SCédric Le Goater                               qdev_get_gpio_in(DEVICE(&chip9->psi),
16315f066121SCédric Le Goater                                                PSIHB9_IRQ_SBE_I2C));
16325f066121SCédric Le Goater     }
1633e997040eSCédric Le Goater }
1634e997040eSCédric Le Goater 
163570c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
163670c059e9SGreg Kurz {
163770c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
163870c059e9SGreg Kurz     return addr >> 3;
163970c059e9SGreg Kurz }
164070c059e9SGreg Kurz 
1641e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1642e997040eSCédric Le Goater {
1643e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1644e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16450d1dcb0bSGlenn Miles     static const int i2c_ports_per_engine[PNV9_CHIP_MAX_I2C] = {2, 13, 2, 2};
1646e997040eSCédric Le Goater 
164783028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1648397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1649631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1650d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1651d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
16520990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
165385913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
165404026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1655eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1656d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1657c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
165870c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1659e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1660422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
16615f066121SCédric Le Goater     k->i2c_num_engines = PNV9_CHIP_MAX_I2C;
16620d1dcb0bSGlenn Miles     k->i2c_ports_per_engine = i2c_ports_per_engine;
166377864267SCédric Le Goater 
166477864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
166577864267SCédric Le Goater                                     &k->parent_realize);
1666e997040eSCédric Le Goater }
1667e997040eSCédric Le Goater 
16682b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
16692b548a42SCédric Le Goater {
1670623575e1SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
16718b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1672623575e1SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
1673623575e1SCédric Le Goater     int i;
16748b50ce85SCédric Le Goater 
1675da71b7e3SCédric Le Goater     object_initialize_child(obj, "xive", &chip10->xive, TYPE_PNV_XIVE2);
1676da71b7e3SCédric Le Goater     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip10->xive),
1677da71b7e3SCédric Le Goater                               "xive-fabric");
16789fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
16799fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
16808bf682a3SCédric Le Goater     object_initialize_child(obj, "occ",  &chip10->occ, TYPE_PNV10_OCC);
16810bf4d77eSNicholas Piggin     object_initialize_child(obj, "sbe",  &chip10->sbe, TYPE_PNV10_SBE);
168292499676SCédric Le Goater     object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER);
1683623575e1SCédric Le Goater 
1684623575e1SCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1685623575e1SCédric Le Goater 
1686623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1687623575e1SCédric Le Goater         object_initialize_child(obj, "pec[*]", &chip10->pecs[i],
1688623575e1SCédric Le Goater                                 TYPE_PNV_PHB5_PEC);
1689623575e1SCédric Le Goater     }
16901ceda19cSGlenn Miles 
16911ceda19cSGlenn Miles     for (i = 0; i < pcc->i2c_num_engines; i++) {
16921ceda19cSGlenn Miles         object_initialize_child(obj, "i2c[*]", &chip10->i2c[i], TYPE_PNV_I2C);
16931ceda19cSGlenn Miles     }
16942b548a42SCédric Le Goater }
16952b548a42SCédric Le Goater 
1696ae4c68e3SCédric Le Goater static void pnv_chip_power10_quad_realize(Pnv10Chip *chip10, Error **errp)
1697ae4c68e3SCédric Le Goater {
1698ae4c68e3SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip10);
1699ae4c68e3SCédric Le Goater     int i;
1700ae4c68e3SCédric Le Goater 
1701ae4c68e3SCédric Le Goater     chip10->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
1702ae4c68e3SCédric Le Goater     chip10->quads = g_new0(PnvQuad, chip10->nr_quads);
1703ae4c68e3SCédric Le Goater 
1704ae4c68e3SCédric Le Goater     for (i = 0; i < chip10->nr_quads; i++) {
1705ae4c68e3SCédric Le Goater         PnvQuad *eq = &chip10->quads[i];
1706ae4c68e3SCédric Le Goater 
1707fdc2b46aSJoel Stanley         pnv_chip_quad_realize_one(chip, eq, chip->cores[i * 4],
1708a1d64b9eSJoel Stanley                                   PNV_QUAD_TYPE_NAME("power10"));
1709ae4c68e3SCédric Le Goater 
1710ae4c68e3SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV10_XSCOM_EQ_BASE(eq->quad_id),
1711ae4c68e3SCédric Le Goater                                 &eq->xscom_regs);
1712bdb97596SJoel Stanley 
1713bdb97596SJoel Stanley         pnv_xscom_add_subregion(chip, PNV10_XSCOM_QME_BASE(eq->quad_id),
1714bdb97596SJoel Stanley                                 &eq->xscom_qme_regs);
1715ae4c68e3SCédric Le Goater     }
1716ae4c68e3SCédric Le Goater }
1717ae4c68e3SCédric Le Goater 
1718623575e1SCédric Le Goater static void pnv_chip_power10_phb_realize(PnvChip *chip, Error **errp)
1719623575e1SCédric Le Goater {
1720623575e1SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
1721623575e1SCédric Le Goater     int i;
1722623575e1SCédric Le Goater 
1723623575e1SCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
1724623575e1SCédric Le Goater         PnvPhb4PecState *pec = &chip10->pecs[i];
1725623575e1SCédric Le Goater         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
1726623575e1SCédric Le Goater         uint32_t pec_nest_base;
1727623575e1SCédric Le Goater         uint32_t pec_pci_base;
1728623575e1SCédric Le Goater 
1729623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
1730623575e1SCédric Le Goater         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
1731623575e1SCédric Le Goater                                 &error_fatal);
1732623575e1SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
1733623575e1SCédric Le Goater                                  &error_fatal);
1734623575e1SCédric Le Goater         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
1735623575e1SCédric Le Goater             return;
1736623575e1SCédric Le Goater         }
1737623575e1SCédric Le Goater 
1738623575e1SCédric Le Goater         pec_nest_base = pecc->xscom_nest_base(pec);
1739623575e1SCédric Le Goater         pec_pci_base = pecc->xscom_pci_base(pec);
1740623575e1SCédric Le Goater 
1741623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
1742623575e1SCédric Le Goater         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
1743623575e1SCédric Le Goater     }
1744623575e1SCédric Le Goater }
1745623575e1SCédric Le Goater 
17462b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
17472b548a42SCédric Le Goater {
17482b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
17492b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
17508b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
17512b548a42SCédric Le Goater     Error *local_err = NULL;
17521ceda19cSGlenn Miles     int i;
17532b548a42SCédric Le Goater 
17542b548a42SCédric Le Goater     /* XSCOM bridge is first */
1755326f7acbSPhilippe Mathieu-Daudé     pnv_xscom_init(chip, PNV10_XSCOM_SIZE, PNV10_XSCOM_BASE(chip));
17562b548a42SCédric Le Goater 
17572b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
17582b548a42SCédric Le Goater     if (local_err) {
17592b548a42SCédric Le Goater         error_propagate(errp, local_err);
17602b548a42SCédric Le Goater         return;
17612b548a42SCédric Le Goater     }
17628b50ce85SCédric Le Goater 
1763ae4c68e3SCédric Le Goater     pnv_chip_power10_quad_realize(chip10, &local_err);
1764ae4c68e3SCédric Le Goater     if (local_err) {
1765ae4c68e3SCédric Le Goater         error_propagate(errp, local_err);
1766ae4c68e3SCédric Le Goater         return;
1767ae4c68e3SCédric Le Goater     }
1768ae4c68e3SCédric Le Goater 
1769da71b7e3SCédric Le Goater     /* XIVE2 interrupt controller (POWER10) */
1770da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "ic-bar",
1771da71b7e3SCédric Le Goater                             PNV10_XIVE2_IC_BASE(chip), &error_fatal);
1772da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "esb-bar",
1773da71b7e3SCédric Le Goater                             PNV10_XIVE2_ESB_BASE(chip), &error_fatal);
1774da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "end-bar",
1775da71b7e3SCédric Le Goater                             PNV10_XIVE2_END_BASE(chip), &error_fatal);
1776da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvpg-bar",
1777da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVPG_BASE(chip), &error_fatal);
1778da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "nvc-bar",
1779da71b7e3SCédric Le Goater                             PNV10_XIVE2_NVC_BASE(chip), &error_fatal);
1780da71b7e3SCédric Le Goater     object_property_set_int(OBJECT(&chip10->xive), "tm-bar",
1781da71b7e3SCédric Le Goater                             PNV10_XIVE2_TM_BASE(chip), &error_fatal);
1782da71b7e3SCédric Le Goater     object_property_set_link(OBJECT(&chip10->xive), "chip", OBJECT(chip),
1783da71b7e3SCédric Le Goater                              &error_abort);
1784da71b7e3SCédric Le Goater     if (!sysbus_realize(SYS_BUS_DEVICE(&chip10->xive), errp)) {
1785da71b7e3SCédric Le Goater         return;
1786da71b7e3SCédric Le Goater     }
1787da71b7e3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_XIVE2_BASE,
1788da71b7e3SCédric Le Goater                             &chip10->xive.xscom_regs);
1789da71b7e3SCédric Le Goater 
17908b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
17915325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
17925325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
179324c8fa96SCédric Le Goater     /* PSI can now be configured to use 64k ESB pages on POWER10 */
179424c8fa96SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), "shift", XIVE_ESB_64K,
179524c8fa96SCédric Le Goater                             &error_fatal);
1796668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
17978b50ce85SCédric Le Goater         return;
17988b50ce85SCédric Le Goater     }
17998b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
18008b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
18012661f6abSCédric Le Goater 
18022661f6abSCédric Le Goater     /* LPC */
1803668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
18042661f6abSCédric Le Goater         return;
18052661f6abSCédric Le Goater     }
18062661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
18072661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
18082661f6abSCédric Le Goater 
1809032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
18102661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
18112661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
18128bf682a3SCédric Le Goater 
18138bf682a3SCédric Le Goater     /* Create the simplified OCC model */
18148bf682a3SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->occ), NULL, errp)) {
18158bf682a3SCédric Le Goater         return;
18168bf682a3SCédric Le Goater     }
18178bf682a3SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_OCC_BASE,
18188bf682a3SCédric Le Goater                             &chip10->occ.xscom_regs);
1819b0ae5c69SCédric Le Goater     qdev_connect_gpio_out(DEVICE(&chip10->occ), 0, qdev_get_gpio_in(
1820b0ae5c69SCédric Le Goater                               DEVICE(&chip10->psi), PSIHB9_IRQ_OCC));
1821623575e1SCédric Le Goater 
182292499676SCédric Le Goater     /* OCC SRAM model */
182392499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(),
182492499676SCédric Le Goater                                 PNV10_OCC_SENSOR_BASE(chip),
182592499676SCédric Le Goater                                 &chip10->occ.sram_regs);
182692499676SCédric Le Goater 
18270bf4d77eSNicholas Piggin     /* SBE */
18280bf4d77eSNicholas Piggin     if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) {
18290bf4d77eSNicholas Piggin         return;
18300bf4d77eSNicholas Piggin     }
18310bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE,
18320bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_ctrl_regs);
18330bf4d77eSNicholas Piggin     pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE,
18340bf4d77eSNicholas Piggin                             &chip10->sbe.xscom_mbox_regs);
18350bf4d77eSNicholas Piggin     qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in(
18360bf4d77eSNicholas Piggin                               DEVICE(&chip10->psi), PSIHB9_IRQ_PSU));
18370bf4d77eSNicholas Piggin 
183892499676SCédric Le Goater     /* HOMER */
183992499676SCédric Le Goater     object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip),
184092499676SCédric Le Goater                              &error_abort);
184192499676SCédric Le Goater     if (!qdev_realize(DEVICE(&chip10->homer), NULL, errp)) {
184292499676SCédric Le Goater         return;
184392499676SCédric Le Goater     }
184492499676SCédric Le Goater     /* Homer Xscom region */
184592499676SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PBA_BASE,
184692499676SCédric Le Goater                             &chip10->homer.pba_regs);
184792499676SCédric Le Goater 
184892499676SCédric Le Goater     /* Homer mmio region */
184992499676SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_HOMER_BASE(chip),
185092499676SCédric Le Goater                                 &chip10->homer.regs);
185192499676SCédric Le Goater 
1852623575e1SCédric Le Goater     /* PHBs */
1853623575e1SCédric Le Goater     pnv_chip_power10_phb_realize(chip, &local_err);
1854623575e1SCédric Le Goater     if (local_err) {
1855623575e1SCédric Le Goater         error_propagate(errp, local_err);
1856623575e1SCédric Le Goater         return;
1857623575e1SCédric Le Goater     }
18581ceda19cSGlenn Miles 
18591ceda19cSGlenn Miles 
18601ceda19cSGlenn Miles     /*
18611ceda19cSGlenn Miles      * I2C
18621ceda19cSGlenn Miles      */
18631ceda19cSGlenn Miles     for (i = 0; i < pcc->i2c_num_engines; i++) {
18641ceda19cSGlenn Miles         Object *obj =  OBJECT(&chip10->i2c[i]);
18651ceda19cSGlenn Miles 
18661ceda19cSGlenn Miles         object_property_set_int(obj, "engine", i + 1, &error_fatal);
18670d1dcb0bSGlenn Miles         object_property_set_int(obj, "num-busses",
18680d1dcb0bSGlenn Miles                                 pcc->i2c_ports_per_engine[i],
18691ceda19cSGlenn Miles                                 &error_fatal);
18701ceda19cSGlenn Miles         object_property_set_link(obj, "chip", OBJECT(chip), &error_abort);
18711ceda19cSGlenn Miles         if (!qdev_realize(DEVICE(obj), NULL, errp)) {
18721ceda19cSGlenn Miles             return;
18731ceda19cSGlenn Miles         }
18741ceda19cSGlenn Miles         pnv_xscom_add_subregion(chip, PNV10_XSCOM_I2CM_BASE +
1875*47dfdd23SGlenn Miles                                 (chip10->i2c[i].engine - 1) *
1876*47dfdd23SGlenn Miles                                         PNV10_XSCOM_I2CM_SIZE,
18771ceda19cSGlenn Miles                                 &chip10->i2c[i].xscom_regs);
18781ceda19cSGlenn Miles         qdev_connect_gpio_out(DEVICE(&chip10->i2c[i]), 0,
18791ceda19cSGlenn Miles                               qdev_get_gpio_in(DEVICE(&chip10->psi),
18801ceda19cSGlenn Miles                                                PSIHB9_IRQ_SBE_I2C));
18811ceda19cSGlenn Miles     }
18822b548a42SCédric Le Goater }
18832b548a42SCédric Le Goater 
188470c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
188570c059e9SGreg Kurz {
188670c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
188770c059e9SGreg Kurz     return addr >> 3;
188870c059e9SGreg Kurz }
188970c059e9SGreg Kurz 
18902b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
18912b548a42SCédric Le Goater {
18922b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
18932b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
18940d1dcb0bSGlenn Miles     static const int i2c_ports_per_engine[PNV10_CHIP_MAX_I2C] = {14, 14, 2, 16};
18952b548a42SCédric Le Goater 
18962b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
18972b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
18982b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
18992b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
19002b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
19012b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
190285913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
19032b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
19042b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
19052b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1906c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
190770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
19082b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
1909623575e1SCédric Le Goater     k->num_pecs = PNV10_CHIP_MAX_PEC;
19101ceda19cSGlenn Miles     k->i2c_num_engines = PNV10_CHIP_MAX_I2C;
19110d1dcb0bSGlenn Miles     k->i2c_ports_per_engine = i2c_ports_per_engine;
19122b548a42SCédric Le Goater 
19132b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
19142b548a42SCédric Le Goater                                     &k->parent_realize);
19152b548a42SCédric Le Goater }
19162b548a42SCédric Le Goater 
1917397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1918397a79e7SCédric Le Goater {
1919397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1920397a79e7SCédric Le Goater     int cores_max;
1921397a79e7SCédric Le Goater 
1922397a79e7SCédric Le Goater     /*
1923397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1924397a79e7SCédric Le Goater      * the chip class
1925397a79e7SCédric Le Goater      */
1926397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1927397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1928397a79e7SCédric Le Goater     }
1929397a79e7SCédric Le Goater 
1930397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1931397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1932397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1933397a79e7SCédric Le Goater                    chip->cores_mask);
1934397a79e7SCédric Le Goater         return;
1935397a79e7SCédric Le Goater     }
1936397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1937397a79e7SCédric Le Goater 
1938397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
193927d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1940397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1941397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1942397a79e7SCédric Le Goater                    cores_max);
1943397a79e7SCédric Le Goater         return;
1944397a79e7SCédric Le Goater     }
1945397a79e7SCédric Le Goater }
1946397a79e7SCédric Le Goater 
194751c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1948e997040eSCédric Le Goater {
1949397a79e7SCédric Le Goater     Error *error = NULL;
1950d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
195140abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1952d2fd9612SCédric Le Goater     int i, core_hwid;
195308c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1954397a79e7SCédric Le Goater 
1955d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1956d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1957d2fd9612SCédric Le Goater         return;
1958d2fd9612SCédric Le Goater     }
1959d2fd9612SCédric Le Goater 
1960d2fd9612SCédric Le Goater     /* Cores */
1961397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1962397a79e7SCédric Le Goater     if (error) {
1963397a79e7SCédric Le Goater         error_propagate(errp, error);
1964397a79e7SCédric Le Goater         return;
1965397a79e7SCédric Le Goater     }
1966d2fd9612SCédric Le Goater 
19674fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1968d2fd9612SCédric Le Goater 
1969d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1970d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1971d2fd9612SCédric Le Goater         char core_name[32];
19724fa28f23SGreg Kurz         PnvCore *pnv_core;
1973c035851aSCédric Le Goater         uint64_t xscom_core_base;
1974d2fd9612SCédric Le Goater 
1975d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1976d2fd9612SCédric Le Goater             continue;
1977d2fd9612SCédric Le Goater         }
1978d2fd9612SCédric Le Goater 
19794fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
19804fa28f23SGreg Kurz 
1981d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1982d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
19834fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
19845325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
19855325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
19865325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
19875325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
19885325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
19895325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
19905325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
19915325cc34SMarkus Armbruster                                 &error_fatal);
19925325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1993158e17a6SGreg Kurz                                  &error_abort);
1994ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
199524ece072SCédric Le Goater 
199624ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1997c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1998c035851aSCédric Le Goater 
1999c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
20004fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
2001d2fd9612SCédric Le Goater         i++;
2002d2fd9612SCédric Le Goater     }
200351c04728SCédric Le Goater }
200451c04728SCédric Le Goater 
200551c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
200651c04728SCédric Le Goater {
200751c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
200851c04728SCédric Le Goater     Error *error = NULL;
200951c04728SCédric Le Goater 
201051c04728SCédric Le Goater     /* Cores */
201151c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
201251c04728SCédric Le Goater     if (error) {
201351c04728SCédric Le Goater         error_propagate(errp, error);
201451c04728SCédric Le Goater         return;
201551c04728SCédric Le Goater     }
2016e997040eSCédric Le Goater }
2017e997040eSCédric Le Goater 
2018e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
2019e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
2020e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
2021e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
2022397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
2023397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
2024764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
2025e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
2026e997040eSCédric Le Goater };
2027e997040eSCédric Le Goater 
2028e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
2029e997040eSCédric Le Goater {
2030e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
2031e997040eSCédric Le Goater 
20329d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
2033e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
20344f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
2035e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
2036e997040eSCédric Le Goater }
2037e997040eSCédric Le Goater 
2038119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
2039119eaa9dSCédric Le Goater {
2040119eaa9dSCédric Le Goater     int i, j;
2041119eaa9dSCédric Le Goater 
2042119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2043119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
2044119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
2045119eaa9dSCédric Le Goater 
2046119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
2047119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
2048119eaa9dSCédric Le Goater                 return pc->threads[j];
2049119eaa9dSCédric Le Goater             }
2050119eaa9dSCédric Le Goater         }
2051119eaa9dSCédric Le Goater     }
2052119eaa9dSCédric Le Goater     return NULL;
2053119eaa9dSCédric Le Goater }
2054119eaa9dSCédric Le Goater 
205554f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
205654f59d78SCédric Le Goater {
2057b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2058da6be501SDaniel Henrique Barboza     int i, j;
205954f59d78SCédric Le Goater 
206054f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
206177864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
206277864267SCédric Le Goater 
206377864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
206477864267SCédric Le Goater             return &chip8->psi.ics;
206554f59d78SCédric Le Goater         }
20662ff73ddaSCédric Le Goater 
2067da6be501SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
20680d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
20691f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2070da6be501SDaniel Henrique Barboza 
2071da6be501SDaniel Henrique Barboza             if (ics_valid_irq(&phb3->lsis, irq)) {
2072da6be501SDaniel Henrique Barboza                 return &phb3->lsis;
2073da6be501SDaniel Henrique Barboza             }
2074da6be501SDaniel Henrique Barboza 
2075da6be501SDaniel Henrique Barboza             if (ics_valid_irq(ICS(&phb3->msis), irq)) {
2076da6be501SDaniel Henrique Barboza                 return ICS(&phb3->msis);
2077da6be501SDaniel Henrique Barboza             }
20789ae1329eSCédric Le Goater         }
207954f59d78SCédric Le Goater     }
208054f59d78SCédric Le Goater     return NULL;
208154f59d78SCédric Le Goater }
208254f59d78SCédric Le Goater 
20831f6a88ffSCédric Le Goater PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id)
20841f6a88ffSCédric Le Goater {
20851f6a88ffSCédric Le Goater     int i;
20861f6a88ffSCédric Le Goater 
20871f6a88ffSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
20881f6a88ffSCédric Le Goater         PnvChip *chip = pnv->chips[i];
20891f6a88ffSCédric Le Goater         if (chip->chip_id == chip_id) {
20901f6a88ffSCédric Le Goater             return chip;
20911f6a88ffSCédric Le Goater         }
20921f6a88ffSCédric Le Goater     }
20931f6a88ffSCédric Le Goater     return NULL;
20941f6a88ffSCédric Le Goater }
20951f6a88ffSCédric Le Goater 
209654f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
209754f59d78SCédric Le Goater {
2098b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
2099ca459489SDaniel Henrique Barboza     int i, j;
210054f59d78SCédric Le Goater 
210154f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
210277864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
21039ae1329eSCédric Le Goater 
210477864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
2105ca459489SDaniel Henrique Barboza 
2106ca459489SDaniel Henrique Barboza         for (j = 0; j < chip8->num_phbs; j++) {
21070d512c71SDaniel Henrique Barboza             PnvPHB *phb = chip8->phbs[j];
21081f5d6b2aSDaniel Henrique Barboza             PnvPHB3 *phb3 = PNV_PHB3(phb->backend);
2109ca459489SDaniel Henrique Barboza 
2110ca459489SDaniel Henrique Barboza             ics_resend(&phb3->lsis);
2111ca459489SDaniel Henrique Barboza             ics_resend(ICS(&phb3->msis));
2112ca459489SDaniel Henrique Barboza         }
211354f59d78SCédric Le Goater     }
211454f59d78SCédric Le Goater }
211554f59d78SCédric Le Goater 
211636fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
211736fc6f08SCédric Le Goater {
211836fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
211936fc6f08SCédric Le Goater 
2120956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
212136fc6f08SCédric Le Goater }
212236fc6f08SCédric Le Goater 
212347fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
212447fea43aSCédric Le Goater                                Monitor *mon)
212547fea43aSCédric Le Goater {
2126b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
212754f59d78SCédric Le Goater     int i;
212847fea43aSCédric Le Goater     CPUState *cs;
212947fea43aSCédric Le Goater 
213047fea43aSCédric Le Goater     CPU_FOREACH(cs) {
213147fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
213247fea43aSCédric Le Goater 
213385913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
213485913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
213585913070SGreg Kurz                                                            mon);
2136d8e4aad5SCédric Le Goater     }
213754f59d78SCédric Le Goater 
213854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2139d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
214054f59d78SCédric Le Goater     }
214147fea43aSCédric Le Goater }
214247fea43aSCédric Le Goater 
2143c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
2144c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
2145c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
2146c722579eSCédric Le Goater                          uint32_t logic_serv,
2147c722579eSCédric Le Goater                          XiveTCTXMatch *match)
2148c722579eSCédric Le Goater {
2149c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2150c722579eSCédric Le Goater     int total_count = 0;
2151c722579eSCédric Le Goater     int i;
2152c722579eSCédric Le Goater 
2153c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2154c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
2155c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
2156c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2157c722579eSCédric Le Goater         int count;
2158c722579eSCédric Le Goater 
2159c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2160c722579eSCédric Le Goater                                priority, logic_serv, match);
2161c722579eSCédric Le Goater 
2162c722579eSCédric Le Goater         if (count < 0) {
2163c722579eSCédric Le Goater             return count;
2164c722579eSCédric Le Goater         }
2165c722579eSCédric Le Goater 
2166c722579eSCédric Le Goater         total_count += count;
2167c722579eSCédric Le Goater     }
2168c722579eSCédric Le Goater 
2169c722579eSCédric Le Goater     return total_count;
2170c722579eSCédric Le Goater }
2171c722579eSCédric Le Goater 
2172da71b7e3SCédric Le Goater static int pnv10_xive_match_nvt(XiveFabric *xfb, uint8_t format,
2173da71b7e3SCédric Le Goater                                 uint8_t nvt_blk, uint32_t nvt_idx,
2174da71b7e3SCédric Le Goater                                 bool cam_ignore, uint8_t priority,
2175da71b7e3SCédric Le Goater                                 uint32_t logic_serv,
2176da71b7e3SCédric Le Goater                                 XiveTCTXMatch *match)
2177da71b7e3SCédric Le Goater {
2178da71b7e3SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
2179da71b7e3SCédric Le Goater     int total_count = 0;
2180da71b7e3SCédric Le Goater     int i;
2181da71b7e3SCédric Le Goater 
2182da71b7e3SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
2183da71b7e3SCédric Le Goater         Pnv10Chip *chip10 = PNV10_CHIP(pnv->chips[i]);
2184da71b7e3SCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip10->xive);
2185da71b7e3SCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
2186da71b7e3SCédric Le Goater         int count;
2187da71b7e3SCédric Le Goater 
2188da71b7e3SCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
2189da71b7e3SCédric Le Goater                                priority, logic_serv, match);
2190da71b7e3SCédric Le Goater 
2191da71b7e3SCédric Le Goater         if (count < 0) {
2192da71b7e3SCédric Le Goater             return count;
2193da71b7e3SCédric Le Goater         }
2194da71b7e3SCédric Le Goater 
2195da71b7e3SCédric Le Goater         total_count += count;
2196da71b7e3SCédric Le Goater     }
2197da71b7e3SCédric Le Goater 
2198da71b7e3SCédric Le Goater     return total_count;
2199da71b7e3SCédric Le Goater }
2200da71b7e3SCédric Le Goater 
2201f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
22029e933f4aSBenjamin Herrenschmidt {
22039e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
220436fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
2205d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2206d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
2207f30c843cSCédric Le Goater 
22081f5d6b2aSDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
22091f5d6b2aSDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "3" },
221080515061SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "3" },
22111f5d6b2aSDaniel Henrique Barboza     };
22121f5d6b2aSDaniel Henrique Barboza 
2213f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
2214f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
22151f5d6b2aSDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2216f30c843cSCédric Le Goater 
2217f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
2218f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
2219f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
2220d76f2da7SGreg Kurz 
2221d76f2da7SGreg Kurz     pmc->compat = compat;
2222d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
2223892c3ad0SDaniel Henrique Barboza 
2224892c3ad0SDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2225f30c843cSCédric Le Goater }
2226f30c843cSCédric Le Goater 
2227f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
2228f30c843cSCédric Le Goater {
2229f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2230c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2231d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2232d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
2233f30c843cSCédric Le Goater 
2234210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2235210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "4" },
2236c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "4" },
2237210aacb3SDaniel Henrique Barboza     };
2238210aacb3SDaniel Henrique Barboza 
2239f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
2240277ee172SNicholas Piggin     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.2");
2241210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2242210aacb3SDaniel Henrique Barboza 
2243c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
2244f30c843cSCédric Le Goater 
2245f30c843cSCédric Le Goater     mc->alias = "powernv";
2246d76f2da7SGreg Kurz 
2247d76f2da7SGreg Kurz     pmc->compat = compat;
2248d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22497a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2250d786be3fSDaniel Henrique Barboza 
2251d786be3fSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
2252f30c843cSCédric Le Goater }
2253f30c843cSCédric Le Goater 
22542b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
22552b548a42SCédric Le Goater {
22562b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
2257d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
2258da71b7e3SCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
2259d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
22602b548a42SCédric Le Goater 
2261210aacb3SDaniel Henrique Barboza     static GlobalProperty phb_compat[] = {
2262210aacb3SDaniel Henrique Barboza         { TYPE_PNV_PHB, "version", "5" },
2263c8d14603SDaniel Henrique Barboza         { TYPE_PNV_PHB_ROOT_PORT, "version", "5" },
2264210aacb3SDaniel Henrique Barboza     };
2265210aacb3SDaniel Henrique Barboza 
22662b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
22676bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
2268210aacb3SDaniel Henrique Barboza     compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat));
2269d76f2da7SGreg Kurz 
2270d76f2da7SGreg Kurz     pmc->compat = compat;
2271d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
22727a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
2273da71b7e3SCédric Le Goater 
2274da71b7e3SCédric Le Goater     xfc->match_nvt = pnv10_xive_match_nvt;
2275f1327fdeSDaniel Henrique Barboza 
2276f1327fdeSDaniel Henrique Barboza     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB);
22772b548a42SCédric Le Goater }
22782b548a42SCédric Le Goater 
227908c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
228008c3f3a7SCédric Le Goater {
228108c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
228208c3f3a7SCédric Le Goater 
228308c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
228408c3f3a7SCédric Le Goater }
228508c3f3a7SCédric Le Goater 
228608c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
228708c3f3a7SCédric Le Goater {
228808c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
228908c3f3a7SCédric Le Goater 
229008c3f3a7SCédric Le Goater     if (value) {
229108c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
229208c3f3a7SCédric Le Goater     }
229308c3f3a7SCédric Le Goater }
229408c3f3a7SCédric Le Goater 
229501b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
229601b552b0SNicholas Piggin {
229701b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
229801b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
229901b552b0SNicholas Piggin 
230001b552b0SNicholas Piggin     cpu_synchronize_state(cs);
230101b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
23020911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
230301b552b0SNicholas Piggin         /*
2304fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
2305fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
2306fe837714SNicholas Piggin          * (PPC_BIT(43)).
230701b552b0SNicholas Piggin          */
23080911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
2309fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
23100911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
231101b552b0SNicholas Piggin         }
2312fe837714SNicholas Piggin     } else {
2313fe837714SNicholas Piggin         /*
2314fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
2315fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
2316fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
2317fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
2318fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
2319fe837714SNicholas Piggin          */
23200911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
2321fe837714SNicholas Piggin     }
2322fe837714SNicholas Piggin }
232301b552b0SNicholas Piggin 
232401b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
232501b552b0SNicholas Piggin {
232601b552b0SNicholas Piggin     CPUState *cs;
232701b552b0SNicholas Piggin 
232801b552b0SNicholas Piggin     CPU_FOREACH(cs) {
232901b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
233001b552b0SNicholas Piggin     }
233101b552b0SNicholas Piggin }
233201b552b0SNicholas Piggin 
2333f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
2334f30c843cSCédric Le Goater {
2335f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
233647fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
233701b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
23389e933f4aSBenjamin Herrenschmidt 
23399e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
2340b168a138SCédric Le Goater     mc->init = pnv_init;
2341b168a138SCédric Le Goater     mc->reset = pnv_reset;
23429e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
234359b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
234459b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
23459e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
23469e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2347f1d18b0aSJoel Stanley     /*
2348f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2349f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2350f1d18b0aSJoel Stanley      */
2351dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2352173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
235347fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
235401b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
235508c3f3a7SCédric Le Goater 
235608c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2357d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
235808c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
23597eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
23609e933f4aSBenjamin Herrenschmidt }
23619e933f4aSBenjamin Herrenschmidt 
236277864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2363beba5c0fSIgor Mammedov     {                                             \
2364beba5c0fSIgor Mammedov         .name          = type,                    \
2365beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
236677864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
236777864267SCédric Le Goater     }
236877864267SCédric Le Goater 
236977864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
237077864267SCédric Le Goater     {                                             \
237177864267SCédric Le Goater         .name          = type,                    \
237277864267SCédric Le Goater         .class_init    = class_initfn,            \
237377864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2374beba5c0fSIgor Mammedov     }
2375beba5c0fSIgor Mammedov 
23762b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
23772b548a42SCédric Le Goater     {                                              \
23782b548a42SCédric Le Goater         .name          = type,                     \
23792b548a42SCédric Le Goater         .class_init    = class_initfn,             \
23802b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
23812b548a42SCédric Le Goater     }
23822b548a42SCédric Le Goater 
2383beba5c0fSIgor Mammedov static const TypeInfo types[] = {
23841aba8716SCédric Le Goater     {
23852b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
23862b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23872b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
2388da71b7e3SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2389da71b7e3SCédric Le Goater             { TYPE_XIVE_FABRIC },
2390da71b7e3SCédric Le Goater             { },
2391da71b7e3SCédric Le Goater         },
23922b548a42SCédric Le Goater     },
23932b548a42SCédric Le Goater     {
23941aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
23951aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
23961aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2397c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2398c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2399c722579eSCédric Le Goater             { },
2400c722579eSCédric Le Goater         },
24011aba8716SCédric Le Goater     },
24021aba8716SCédric Le Goater     {
24031aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
24041aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
24051aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
24061aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
24071aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
24081aba8716SCédric Le Goater             { },
24091aba8716SCédric Le Goater         },
24101aba8716SCédric Le Goater     },
2411beba5c0fSIgor Mammedov     {
2412b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
24139e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2414f30c843cSCédric Le Goater         .abstract       = true,
24159e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2416b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2417d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
241836fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
241947fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
242001b552b0SNicholas Piggin             { TYPE_NMI },
242136fc6f08SCédric Le Goater             { },
242236fc6f08SCédric Le Goater         },
2423beba5c0fSIgor Mammedov     },
2424beba5c0fSIgor Mammedov     {
2425beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2426beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2427beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2428beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2429beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2430beba5c0fSIgor Mammedov         .abstract      = true,
2431beba5c0fSIgor Mammedov     },
243277864267SCédric Le Goater 
243377864267SCédric Le Goater     /*
24342b548a42SCédric Le Goater      * P10 chip and variants
24352b548a42SCédric Le Goater      */
24362b548a42SCédric Le Goater     {
24372b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
24382b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
24392b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
24402b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
24412b548a42SCédric Le Goater     },
24422b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
24432b548a42SCédric Le Goater 
24442b548a42SCédric Le Goater     /*
244577864267SCédric Le Goater      * P9 chip and variants
244677864267SCédric Le Goater      */
244777864267SCédric Le Goater     {
244877864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
244977864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
245077864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
245177864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
245277864267SCédric Le Goater     },
245377864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
245477864267SCédric Le Goater 
245577864267SCédric Le Goater     /*
245677864267SCédric Le Goater      * P8 chip and variants
245777864267SCédric Le Goater      */
245877864267SCédric Le Goater     {
245977864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
246077864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
246177864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
246277864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
246377864267SCédric Le Goater     },
246477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
246577864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
246677864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2467beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
24689e933f4aSBenjamin Herrenschmidt };
24699e933f4aSBenjamin Herrenschmidt 
2470beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2471