xref: /qemu/hw/ppc/pnv.c (revision 173a36d8)
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
99e933f4aSBenjamin Herrenschmidt  * version 2 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"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2671e8a915SMarkus Armbruster #include "sysemu/reset.h"
2754d31236SMarkus Armbruster #include "sysemu/runstate.h"
28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
298d409261SCédric Le Goater #include "sysemu/device_tree.h"
30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
38e997040eSCédric Le Goater #include "qapi/visitor.h"
3947fea43aSCédric Le Goater #include "monitor/monitor.h"
4047fea43aSCédric Le Goater #include "hw/intc/intc.h"
41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
434f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h"
449e933f4aSBenjamin Herrenschmidt 
4536fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
46a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
47967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
4835dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
49967b7523SCédric Le Goater 
503495b6b6SCédric Le Goater #include "hw/isa/isa.h"
5112e9493dSMarkus Armbruster #include "hw/boards.h"
523495b6b6SCédric Le Goater #include "hw/char/serial.h"
53bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
543495b6b6SCédric Le Goater 
559e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
569e933f4aSBenjamin Herrenschmidt 
57b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
589e933f4aSBenjamin Herrenschmidt 
599e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
609e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
61b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
629e933f4aSBenjamin Herrenschmidt 
639e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
64b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
65fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
66584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
679e933f4aSBenjamin Herrenschmidt 
6840abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
6940abf43fSIgor Mammedov {
7040abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7140abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7240abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7340abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7440abf43fSIgor Mammedov     g_free(s);
7540abf43fSIgor Mammedov     return core_type;
7640abf43fSIgor Mammedov }
7740abf43fSIgor Mammedov 
789e933f4aSBenjamin Herrenschmidt /*
799e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
809e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
819e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
829e933f4aSBenjamin Herrenschmidt  */
839e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
849e933f4aSBenjamin Herrenschmidt 
859e933f4aSBenjamin Herrenschmidt /*
869e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
879e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
889e933f4aSBenjamin Herrenschmidt  * per chip.
899e933f4aSBenjamin Herrenschmidt  */
90b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
919e933f4aSBenjamin Herrenschmidt {
929e933f4aSBenjamin Herrenschmidt     char *mem_name;
939e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
949e933f4aSBenjamin Herrenschmidt     int off;
959e933f4aSBenjamin Herrenschmidt 
969e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
979e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
989e933f4aSBenjamin Herrenschmidt 
999e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1009e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1019e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1029e933f4aSBenjamin Herrenschmidt 
1039e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1049e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1059e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1069e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1079e933f4aSBenjamin Herrenschmidt }
1089e933f4aSBenjamin Herrenschmidt 
109d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
110d2fd9612SCédric Le Goater {
111d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
112d2fd9612SCédric Le Goater 
113d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
114a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
115d2fd9612SCédric Le Goater         if (cpus_offset) {
116d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
117d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
118d2fd9612SCédric Le Goater         }
119d2fd9612SCédric Le Goater     }
120d2fd9612SCédric Le Goater     _FDT(cpus_offset);
121d2fd9612SCédric Le Goater     return cpus_offset;
122d2fd9612SCédric Le Goater }
123d2fd9612SCédric Le Goater 
124d2fd9612SCédric Le Goater /*
125d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
126d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
127d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
128d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
129d2fd9612SCédric Le Goater  * servers.
130d2fd9612SCédric Le Goater  */
131b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
132d2fd9612SCédric Le Goater {
13308304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13408304a86SDavid Gibson     CPUState *cs = CPU(cpu);
135d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1368bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
137d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
138d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
139d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
140d2fd9612SCédric Le Goater     int i;
141d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
142d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
143d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
144d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
145d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
146d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
147d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
148d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
149d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
150d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
151d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
152d2fd9612SCédric Le Goater     int offset;
153d2fd9612SCédric Le Goater     char *nodename;
154d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
155d2fd9612SCédric Le Goater 
156d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
157d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
158d2fd9612SCédric Le Goater     _FDT(offset);
159d2fd9612SCédric Le Goater     g_free(nodename);
160d2fd9612SCédric Le Goater 
161d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
162d2fd9612SCédric Le Goater 
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
164d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
166d2fd9612SCédric Le Goater 
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
168d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
169d2fd9612SCédric Le Goater                             env->dcache_line_size)));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
171d2fd9612SCédric Le Goater                             env->dcache_line_size)));
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
173d2fd9612SCédric Le Goater                             env->icache_line_size)));
174d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
175d2fd9612SCédric Le Goater                             env->icache_line_size)));
176d2fd9612SCédric Le Goater 
177d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
178d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
179d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
180d2fd9612SCédric Le Goater     } else {
1813dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
182d2fd9612SCédric Le Goater     }
183d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
184d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
185d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
186d2fd9612SCédric Le Goater     } else {
1873dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
188d2fd9612SCédric Le Goater     }
189d2fd9612SCédric Le Goater 
190d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
191d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19259b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19359b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
194d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
195d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
196d2fd9612SCédric Le Goater 
197d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
198d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
199d2fd9612SCédric Le Goater     }
200d2fd9612SCédric Le Goater 
20158969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
202d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
203d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
204d2fd9612SCédric Le Goater     }
205d2fd9612SCédric Le Goater 
20659b7c1c2SBalamuruhan S     /*
20759b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
208d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
209d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21059b7c1c2SBalamuruhan S      *   2               == VSX available
21159b7c1c2SBalamuruhan S      */
212d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
213d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
214d2fd9612SCédric Le Goater 
215d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
216d2fd9612SCédric Le Goater     }
217d2fd9612SCédric Le Goater 
21859b7c1c2SBalamuruhan S     /*
21959b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
220d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22159b7c1c2SBalamuruhan S      *   1               == DFP available
22259b7c1c2SBalamuruhan S      */
223d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
224d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
225d2fd9612SCédric Le Goater     }
226d2fd9612SCédric Le Goater 
227644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
228d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
229d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
230d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
231d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
232d2fd9612SCédric Le Goater     }
233d2fd9612SCédric Le Goater 
234d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
235d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
236d2fd9612SCédric Le Goater 
237d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
238d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
239d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
240d2fd9612SCédric Le Goater     }
241d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
242d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
243d2fd9612SCédric Le Goater }
244d2fd9612SCédric Le Goater 
245b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
246bf5615e7SCédric Le Goater                        uint32_t nr_threads)
247bf5615e7SCédric Le Goater {
248bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
249bf5615e7SCédric Le Goater     char *name;
250bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
251bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
252bf5615e7SCédric Le Goater     uint64_t *reg;
253bf5615e7SCédric Le Goater     int offset;
254bf5615e7SCédric Le Goater 
255bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
256bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
257bf5615e7SCédric Le Goater 
258bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
259bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
260bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
261bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
262bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
263bf5615e7SCédric Le Goater     }
264bf5615e7SCédric Le Goater 
265bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
266bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
267bf5615e7SCédric Le Goater     _FDT(offset);
268bf5615e7SCédric Le Goater     g_free(name);
269bf5615e7SCédric Le Goater 
270bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
271bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
272bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
273bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
275bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
276bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
278bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
279bf5615e7SCédric Le Goater     g_free(reg);
280bf5615e7SCédric Le Goater }
281bf5615e7SCédric Le Goater 
282eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
283e997040eSCédric Le Goater {
284c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
285d2fd9612SCédric Le Goater     int i;
286d2fd9612SCédric Le Goater 
2873f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2883f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
289c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
290c396c58aSGreg Kurz                  compat, sizeof(compat));
291967b7523SCédric Le Goater 
292d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2934fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
294d2fd9612SCédric Le Goater 
295b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
296bf5615e7SCédric Le Goater 
297bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
298b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
299d2fd9612SCédric Le Goater     }
300d2fd9612SCédric Le Goater 
301e997040eSCédric Le Goater     if (chip->ram_size) {
302b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
303e997040eSCédric Le Goater     }
304e997040eSCédric Le Goater }
305e997040eSCédric Le Goater 
306eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
307eb859a27SCédric Le Goater {
308c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
309eb859a27SCédric Le Goater     int i;
310eb859a27SCédric Le Goater 
3113f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3123f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
313c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
314c396c58aSGreg Kurz                  compat, sizeof(compat));
315eb859a27SCédric Le Goater 
316eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3174fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
318eb859a27SCédric Le Goater 
319eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
320eb859a27SCédric Le Goater     }
321eb859a27SCédric Le Goater 
322eb859a27SCédric Le Goater     if (chip->ram_size) {
323eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
324eb859a27SCédric Le Goater     }
32515376c66SCédric Le Goater 
3262661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
327eb859a27SCédric Le Goater }
328eb859a27SCédric Le Goater 
3292b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3302b548a42SCédric Le Goater {
331c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3322b548a42SCédric Le Goater     int i;
3332b548a42SCédric Le Goater 
3343f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3353f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
336c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
337c396c58aSGreg Kurz                  compat, sizeof(compat));
3382b548a42SCédric Le Goater 
3392b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3402b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3412b548a42SCédric Le Goater 
3422b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3432b548a42SCédric Le Goater     }
3442b548a42SCédric Le Goater 
3452b548a42SCédric Le Goater     if (chip->ram_size) {
3462b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3472b548a42SCédric Le Goater     }
3482661f6abSCédric Le Goater 
3492661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3502b548a42SCédric Le Goater }
3512b548a42SCédric Le Goater 
352b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
353c5ffdcaeSCédric Le Goater {
354c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
355c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
356c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
357c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
358c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
359c5ffdcaeSCédric Le Goater     };
360c5ffdcaeSCédric Le Goater     char *name;
361c5ffdcaeSCédric Le Goater     int node;
362c5ffdcaeSCédric Le Goater 
363c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
364c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
365c5ffdcaeSCédric Le Goater     _FDT(node);
366c5ffdcaeSCédric Le Goater     g_free(name);
367c5ffdcaeSCédric Le Goater 
368c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
369c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
370c5ffdcaeSCédric Le Goater }
371c5ffdcaeSCédric Le Goater 
372b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
373cb228f5aSCédric Le Goater {
374cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
375cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
376cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
377cb228f5aSCédric Le Goater         cpu_to_be32(1),
378cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
379cb228f5aSCédric Le Goater         cpu_to_be32(8)
380cb228f5aSCédric Le Goater     };
381cb228f5aSCédric Le Goater     char *name;
382cb228f5aSCédric Le Goater     int node;
383cb228f5aSCédric Le Goater 
384cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
385cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
386cb228f5aSCédric Le Goater     _FDT(node);
387cb228f5aSCédric Le Goater     g_free(name);
388cb228f5aSCédric Le Goater 
389cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
390cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
391cb228f5aSCédric Le Goater                       sizeof(compatible))));
392cb228f5aSCédric Le Goater 
393cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
394cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
395cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
396cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
397cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
398cb228f5aSCédric Le Goater 
399cb228f5aSCédric Le Goater     /* This is needed by Linux */
400cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
401cb228f5aSCédric Le Goater }
402cb228f5aSCédric Le Goater 
403b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40404f6c8b2SCédric Le Goater {
40504f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
40604f6c8b2SCédric Le Goater     uint32_t io_base;
40704f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
40804f6c8b2SCédric Le Goater         cpu_to_be32(1),
40904f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41004f6c8b2SCédric Le Goater         cpu_to_be32(3)
41104f6c8b2SCédric Le Goater     };
41204f6c8b2SCédric Le Goater     uint32_t irq;
41304f6c8b2SCédric Le Goater     char *name;
41404f6c8b2SCédric Le Goater     int node;
41504f6c8b2SCédric Le Goater 
41604f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
41704f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
41804f6c8b2SCédric Le Goater 
41904f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42004f6c8b2SCédric Le Goater 
42104f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42204f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42304f6c8b2SCédric Le Goater     _FDT(node);
42404f6c8b2SCédric Le Goater     g_free(name);
42504f6c8b2SCédric Le Goater 
4267032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4277032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4287032d92aSCédric Le Goater                       sizeof(compatible))));
42904f6c8b2SCédric Le Goater 
43004f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43104f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43204f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43304f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43404f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
43504f6c8b2SCédric Le Goater }
43604f6c8b2SCédric Le Goater 
437e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
438e7a3fee3SCédric Le Goater     void *fdt;
439e7a3fee3SCédric Le Goater     int offset;
440e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
441e7a3fee3SCédric Le Goater 
442b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
443e7a3fee3SCédric Le Goater {
444c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
445c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
446c5ffdcaeSCédric Le Goater 
447c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
448b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
449cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
450b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45104f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
452b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
453c5ffdcaeSCédric Le Goater     } else {
454c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
455c5ffdcaeSCédric Le Goater                      d->ioport_id);
456c5ffdcaeSCédric Le Goater     }
457c5ffdcaeSCédric Le Goater 
458e7a3fee3SCédric Le Goater     return 0;
459e7a3fee3SCédric Le Goater }
460e7a3fee3SCédric Le Goater 
46159b7c1c2SBalamuruhan S /*
46259b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
463bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
464bb7ab95cSCédric Le Goater  */
465bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
466bb7ab95cSCédric Le Goater {
46764d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
468e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
469e7a3fee3SCédric Le Goater         .fdt = fdt,
470bb7ab95cSCédric Le Goater         .offset = isa_offset,
471e7a3fee3SCédric Le Goater     };
472f47a08d1SCédric Le Goater     uint32_t phandle;
473e7a3fee3SCédric Le Goater 
474bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
475bb7ab95cSCédric Le Goater 
476f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
477f47a08d1SCédric Le Goater     assert(phandle > 0);
478f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
479f47a08d1SCédric Le Goater 
48059b7c1c2SBalamuruhan S     /*
48159b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48259b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48359b7c1c2SBalamuruhan S      */
484bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
485bb7ab95cSCédric Le Goater                        &args);
486e7a3fee3SCédric Le Goater }
487e7a3fee3SCédric Le Goater 
4887a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
489e5694793SCédric Le Goater {
490e5694793SCédric Le Goater     int off;
491e5694793SCédric Le Goater 
492e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
493e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
494e5694793SCédric Le Goater 
495e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
496e5694793SCédric Le Goater }
497e5694793SCédric Le Goater 
498b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4999e933f4aSBenjamin Herrenschmidt {
500d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
501b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5029e933f4aSBenjamin Herrenschmidt     void *fdt;
5039e933f4aSBenjamin Herrenschmidt     char *buf;
5049e933f4aSBenjamin Herrenschmidt     int off;
505e997040eSCédric Le Goater     int i;
5069e933f4aSBenjamin Herrenschmidt 
5079e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5089e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5099e933f4aSBenjamin Herrenschmidt 
510ccb099b3SCédric Le Goater     /* /qemu node */
511ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
512ccb099b3SCédric Le Goater 
5139e933f4aSBenjamin Herrenschmidt     /* Root node */
5149e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5159e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5169e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5179e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
518d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5199e933f4aSBenjamin Herrenschmidt 
5209e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5219e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5229e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5239e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5249e933f4aSBenjamin Herrenschmidt     }
5259e933f4aSBenjamin Herrenschmidt     g_free(buf);
5269e933f4aSBenjamin Herrenschmidt 
5279e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5289e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5299e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5309e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5319e933f4aSBenjamin Herrenschmidt     }
5329e933f4aSBenjamin Herrenschmidt 
5339e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5349e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5359e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5369e933f4aSBenjamin Herrenschmidt 
5379e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5389e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5399e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5409e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5419e933f4aSBenjamin Herrenschmidt     }
5429e933f4aSBenjamin Herrenschmidt 
543e997040eSCédric Le Goater     /* Populate device tree for each chip */
544e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
545eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
546e997040eSCédric Le Goater     }
547e7a3fee3SCédric Le Goater 
548e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
549bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
550aeaef83dSCédric Le Goater 
551aeaef83dSCédric Le Goater     if (pnv->bmc) {
552b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
553aeaef83dSCédric Le Goater     }
554aeaef83dSCédric Le Goater 
5557a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5567a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5577a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
558e5694793SCédric Le Goater     }
559e5694793SCédric Le Goater 
5609e933f4aSBenjamin Herrenschmidt     return fdt;
5619e933f4aSBenjamin Herrenschmidt }
5629e933f4aSBenjamin Herrenschmidt 
563bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
564bce0b691SCédric Le Goater {
5658f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
566bce0b691SCédric Le Goater 
567bce0b691SCédric Le Goater     if (pnv->bmc) {
568bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
569bce0b691SCédric Le Goater     }
570bce0b691SCédric Le Goater }
571bce0b691SCédric Le Goater 
572a0628599SLike Xu static void pnv_reset(MachineState *machine)
5739e933f4aSBenjamin Herrenschmidt {
5749e933f4aSBenjamin Herrenschmidt     void *fdt;
5759e933f4aSBenjamin Herrenschmidt 
5769e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5779e933f4aSBenjamin Herrenschmidt 
578b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5799e933f4aSBenjamin Herrenschmidt 
5809e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5819e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5829e933f4aSBenjamin Herrenschmidt 
5838d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5849e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5859e933f4aSBenjamin Herrenschmidt }
5869e933f4aSBenjamin Herrenschmidt 
58704026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5883495b6b6SCédric Le Goater {
58977864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
59077864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
59104026890SCédric Le Goater }
5923495b6b6SCédric Le Goater 
59304026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
59404026890SCédric Le Goater {
59577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
59677864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
59704026890SCédric Le Goater }
5983495b6b6SCédric Le Goater 
59904026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
60004026890SCédric Le Goater {
60115376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
60215376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
60304026890SCédric Le Goater }
6043495b6b6SCédric Le Goater 
6052b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6062b548a42SCédric Le Goater {
6072661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6082661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6092b548a42SCédric Le Goater }
6102b548a42SCédric Le Goater 
61104026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
61204026890SCédric Le Goater {
61304026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6143495b6b6SCédric Le Goater }
6153495b6b6SCédric Le Goater 
616d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
617d8e4aad5SCédric Le Goater {
618d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6199ae1329eSCédric Le Goater     int i;
620d8e4aad5SCédric Le Goater 
621d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6229ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
6239ae1329eSCédric Le Goater         pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
6249ae1329eSCédric Le Goater         ics_pic_print_info(&chip8->phbs[i].lsis, mon);
6259ae1329eSCédric Le Goater     }
626d8e4aad5SCédric Le Goater }
627d8e4aad5SCédric Le Goater 
628d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
629d8e4aad5SCédric Le Goater {
630d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
6314f9924c4SBenjamin Herrenschmidt     int i, j;
632d8e4aad5SCédric Le Goater 
633d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
634c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6354f9924c4SBenjamin Herrenschmidt 
6364f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
6374f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
6384f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks; j++) {
6394f9924c4SBenjamin Herrenschmidt             pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
6404f9924c4SBenjamin Herrenschmidt         }
6414f9924c4SBenjamin Herrenschmidt     }
642d8e4aad5SCédric Le Goater }
643d8e4aad5SCédric Le Goater 
644c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
645c4b2c40cSGreg Kurz                                                 uint32_t core_id)
646c4b2c40cSGreg Kurz {
647c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
648c4b2c40cSGreg Kurz }
649c4b2c40cSGreg Kurz 
650c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
651c4b2c40cSGreg Kurz                                                 uint32_t core_id)
652c4b2c40cSGreg Kurz {
653c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
654c4b2c40cSGreg Kurz }
655c4b2c40cSGreg Kurz 
656c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
657c4b2c40cSGreg Kurz                                                  uint32_t core_id)
658c4b2c40cSGreg Kurz {
659c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
660c4b2c40cSGreg Kurz }
661c4b2c40cSGreg Kurz 
662f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
663f30c843cSCédric Le Goater {
664f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
665f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
666f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
667f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
668f30c843cSCédric Le Goater 
669f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
670f30c843cSCédric Le Goater }
671f30c843cSCédric Le Goater 
672e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
673e2392d43SCédric Le Goater {
674e2392d43SCédric Le Goater     Object *obj;
675e2392d43SCédric Le Goater 
676e2392d43SCédric Le Goater     obj = OBJECT(isa_create(bus, "isa-ipmi-bt"));
677e2392d43SCédric Le Goater     object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal);
678e2392d43SCédric Le Goater     object_property_set_int(obj, irq, "irq", &error_fatal);
679e2392d43SCédric Le Goater     object_property_set_bool(obj, true, "realized", &error_fatal);
680e2392d43SCédric Le Goater }
681e2392d43SCédric Le Goater 
6822b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
6832b548a42SCédric Le Goater {
6848b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6858b50ce85SCédric Le Goater 
6868b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
6872b548a42SCédric Le Goater }
6882b548a42SCédric Le Goater 
689b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6909e933f4aSBenjamin Herrenschmidt {
691b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
692f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6939e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6949e933f4aSBenjamin Herrenschmidt     long fw_size;
695e997040eSCédric Le Goater     int i;
696e997040eSCédric Le Goater     char *chip_typename;
69735dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
69835dde576SCédric Le Goater     DeviceState *dev;
6999e933f4aSBenjamin Herrenschmidt 
7009e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
701d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
7023dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
7039e933f4aSBenjamin Herrenschmidt     }
704*173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7059e933f4aSBenjamin Herrenschmidt 
70635dde576SCédric Le Goater     /*
70735dde576SCédric Le Goater      * Create our simple PNOR device
70835dde576SCédric Le Goater      */
70935dde576SCédric Le Goater     dev = qdev_create(NULL, TYPE_PNV_PNOR);
71035dde576SCédric Le Goater     if (pnor) {
71135dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
71235dde576SCédric Le Goater                             &error_abort);
71335dde576SCédric Le Goater     }
71435dde576SCédric Le Goater     qdev_init_nofail(dev);
71535dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
71635dde576SCédric Le Goater 
7179e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7189e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
7199e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
7209e933f4aSBenjamin Herrenschmidt     }
7219e933f4aSBenjamin Herrenschmidt 
7229e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
72315fcedb2SCédric Le Goater     if (!fw_filename) {
72415fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
72515fcedb2SCédric Le Goater         exit(1);
72615fcedb2SCédric Le Goater     }
7279e933f4aSBenjamin Herrenschmidt 
72808c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
7299e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
73015fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7319e933f4aSBenjamin Herrenschmidt         exit(1);
7329e933f4aSBenjamin Herrenschmidt     }
7339e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7349e933f4aSBenjamin Herrenschmidt 
7359e933f4aSBenjamin Herrenschmidt     /* load kernel */
7369e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7379e933f4aSBenjamin Herrenschmidt         long kernel_size;
7389e933f4aSBenjamin Herrenschmidt 
7399e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
740b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7419e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
742802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7439e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7449e933f4aSBenjamin Herrenschmidt             exit(1);
7459e933f4aSBenjamin Herrenschmidt         }
7469e933f4aSBenjamin Herrenschmidt     }
7479e933f4aSBenjamin Herrenschmidt 
7489e933f4aSBenjamin Herrenschmidt     /* load initrd */
7499e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7509e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7519e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
752584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7539e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
754802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7559e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7569e933f4aSBenjamin Herrenschmidt             exit(1);
7579e933f4aSBenjamin Herrenschmidt         }
7589e933f4aSBenjamin Herrenschmidt     }
759e997040eSCédric Le Goater 
7604f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
7614f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
7624f9924c4SBenjamin Herrenschmidt 
763f30c843cSCédric Le Goater     /*
764f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
765f30c843cSCédric Le Goater      * default.
766f30c843cSCédric Le Goater      */
767f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
768f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
769f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
770f30c843cSCédric Le Goater         exit(1);
771f30c843cSCédric Le Goater     }
772f30c843cSCédric Le Goater 
773e997040eSCédric Le Goater     /* Create the processor chips */
7744a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7757fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7764a12c699SIgor Mammedov                                     i, machine->cpu_type);
777e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
778f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
779f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
780e997040eSCédric Le Goater         exit(1);
781e997040eSCédric Le Goater     }
782e997040eSCédric Le Goater 
783e44acde2SGreg Kurz     pnv->num_chips =
784e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
785e44acde2SGreg Kurz     /*
786e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
787e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
788e44acde2SGreg Kurz      */
789e44acde2SGreg Kurz     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 4) {
790e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
791e44acde2SGreg Kurz         error_printf("Try '-smp sockets=N'. Valid values are : 1, 2 or 4.\n");
792e44acde2SGreg Kurz         exit(1);
793e44acde2SGreg Kurz     }
794e44acde2SGreg Kurz 
795e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
796e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
797e997040eSCédric Le Goater         char chip_name[32];
798e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
799e997040eSCédric Le Goater 
800e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
801e997040eSCédric Le Goater 
80259b7c1c2SBalamuruhan S         /*
80359b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
804e997040eSCédric Le Goater          * way to specify different ranges for each chip
805e997040eSCédric Le Goater          */
806e997040eSCédric Le Goater         if (i == 0) {
807e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
808e997040eSCédric Le Goater                                     &error_fatal);
809e997040eSCédric Le Goater         }
810e997040eSCédric Le Goater 
811e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
812e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
813e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
814e997040eSCédric Le Goater                                 &error_fatal);
815fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
816fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
817764f9b25SGreg Kurz         object_property_set_int(chip, machine->smp.threads,
818764f9b25SGreg Kurz                                 "nr-threads", &error_fatal);
819245cdb7fSCédric Le Goater         /*
820245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
821245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
822245cdb7fSCédric Le Goater          */
823245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
824245cdb7fSCédric Le Goater             object_property_set_link(chip, OBJECT(pnv), "xics", &error_abort);
825245cdb7fSCédric Le Goater         }
826d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
827d1214b81SGreg Kurz             object_property_set_link(chip, OBJECT(pnv), "xive-fabric",
828d1214b81SGreg Kurz                                      &error_abort);
829d1214b81SGreg Kurz         }
830e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
831e997040eSCédric Le Goater     }
832e997040eSCédric Le Goater     g_free(chip_typename);
8333495b6b6SCédric Le Goater 
834e2392d43SCédric Le Goater     /* Create the machine BMC simulator */
835d8137bb7SGreg Kurz     pnv->bmc = pnv_bmc_create(pnv->pnor);
836e2392d43SCédric Le Goater 
8373495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
83804026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
8393495b6b6SCédric Le Goater 
8403495b6b6SCédric Le Goater     /* Create serial port */
841def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
8423495b6b6SCédric Le Goater 
8433495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8446c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
845bce0b691SCédric Le Goater 
846e2392d43SCédric Le Goater     /* Create the IPMI BT device for communication with the BMC */
847e2392d43SCédric Le Goater     pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
848e2392d43SCédric Le Goater 
84959b7c1c2SBalamuruhan S     /*
85059b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
85159b7c1c2SBalamuruhan S      * host to powerdown
85259b7c1c2SBalamuruhan S      */
853bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
854bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
855e997040eSCédric Le Goater }
856e997040eSCédric Le Goater 
857631adaffSCédric Le Goater /*
858631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
859631adaffSCédric Le Goater  *   22:24  Chip ID
860631adaffSCédric Le Goater  *   25:28  Core number
861631adaffSCédric Le Goater  *   29:31  Thread ID
862631adaffSCédric Le Goater  */
863631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
864631adaffSCédric Le Goater {
865631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
866631adaffSCédric Le Goater }
867631adaffSCédric Le Goater 
8688fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
869d35aefa9SCédric Le Goater                                         Error **errp)
870d35aefa9SCédric Le Goater {
871245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
8728fa1f4efSCédric Le Goater     Error *local_err = NULL;
8738fa1f4efSCédric Le Goater     Object *obj;
8748907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8758fa1f4efSCédric Le Goater 
876245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
8778fa1f4efSCédric Le Goater     if (local_err) {
8788fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
8798fa1f4efSCédric Le Goater         return;
8808fa1f4efSCédric Le Goater     }
8818fa1f4efSCédric Le Goater 
882956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
883d35aefa9SCédric Le Goater }
884d35aefa9SCédric Le Goater 
8850990ce6aSGreg Kurz 
886d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
887d49e8a9bSCédric Le Goater {
888d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
889d49e8a9bSCédric Le Goater 
890d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
891d49e8a9bSCédric Le Goater }
892d49e8a9bSCédric Le Goater 
8930990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8940990ce6aSGreg Kurz {
8950990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8960990ce6aSGreg Kurz 
8970990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
8980990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8990990ce6aSGreg Kurz }
9000990ce6aSGreg Kurz 
90185913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
90285913070SGreg Kurz                                             Monitor *mon)
90385913070SGreg Kurz {
90485913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
90585913070SGreg Kurz }
90685913070SGreg Kurz 
907631adaffSCédric Le Goater /*
908631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
909631adaffSCédric Le Goater  *   49:52  Node ID
910631adaffSCédric Le Goater  *   53:55  Chip ID
911631adaffSCédric Le Goater  *   56     Reserved - Read as zero
912631adaffSCédric Le Goater  *   57:61  Core number
913631adaffSCédric Le Goater  *   62:63  Thread ID
914631adaffSCédric Le Goater  *
915631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
916631adaffSCédric Le Goater  */
917631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
918631adaffSCédric Le Goater {
919631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
920631adaffSCédric Le Goater }
921631adaffSCédric Le Goater 
9222b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
9232b548a42SCédric Le Goater {
9242b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
9252b548a42SCédric Le Goater }
9262b548a42SCédric Le Goater 
9278fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
928d35aefa9SCédric Le Goater                                         Error **errp)
929d35aefa9SCédric Le Goater {
9302dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
9312dfa91a2SCédric Le Goater     Error *local_err = NULL;
9322dfa91a2SCédric Le Goater     Object *obj;
9332dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9342dfa91a2SCédric Le Goater 
9352dfa91a2SCédric Le Goater     /*
9362dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
9372dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
9382dfa91a2SCédric Le Goater      * only used at runtime.
9392dfa91a2SCédric Le Goater      */
94047950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
94147950946SCédric Le Goater                            &local_err);
9422dfa91a2SCédric Le Goater     if (local_err) {
9432dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9448fa1f4efSCédric Le Goater         return;
945d35aefa9SCédric Le Goater     }
946d35aefa9SCédric Le Goater 
9472dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
9482dfa91a2SCédric Le Goater }
9492dfa91a2SCédric Le Goater 
950d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
951d49e8a9bSCédric Le Goater {
952d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
953d49e8a9bSCédric Le Goater 
954d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
955d49e8a9bSCédric Le Goater }
956d49e8a9bSCédric Le Goater 
9570990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9580990ce6aSGreg Kurz {
9590990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9600990ce6aSGreg Kurz 
9610990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
9620990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9630990ce6aSGreg Kurz }
9640990ce6aSGreg Kurz 
96585913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
96685913070SGreg Kurz                                             Monitor *mon)
96785913070SGreg Kurz {
96885913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
96985913070SGreg Kurz }
97085913070SGreg Kurz 
9712b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
9722b548a42SCédric Le Goater                                         Error **errp)
9732b548a42SCédric Le Goater {
9742b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9752b548a42SCédric Le Goater 
9762b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
9772b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9782b548a42SCédric Le Goater }
9792b548a42SCédric Le Goater 
9802b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
9812b548a42SCédric Le Goater {
9822b548a42SCédric Le Goater     ;
9832b548a42SCédric Le Goater }
9842b548a42SCédric Le Goater 
9852b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9862b548a42SCédric Le Goater {
9872b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9882b548a42SCédric Le Goater 
9892b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9902b548a42SCédric Le Goater }
9912b548a42SCédric Le Goater 
99285913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
99385913070SGreg Kurz                                              Monitor *mon)
99485913070SGreg Kurz {
99585913070SGreg Kurz }
99685913070SGreg Kurz 
99759b7c1c2SBalamuruhan S /*
99859b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
999397a79e7SCédric Le Goater  *
1000397a79e7SCédric Le Goater  * <EX0 reserved>
1001397a79e7SCédric Le Goater  *  EX1  - Venice only
1002397a79e7SCédric Le Goater  *  EX2  - Venice only
1003397a79e7SCédric Le Goater  *  EX3  - Venice only
1004397a79e7SCédric Le Goater  *  EX4
1005397a79e7SCédric Le Goater  *  EX5
1006397a79e7SCédric Le Goater  *  EX6
1007397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1008397a79e7SCédric Le Goater  *  EX9  - Venice only
1009397a79e7SCédric Le Goater  *  EX10 - Venice only
1010397a79e7SCédric Le Goater  *  EX11 - Venice only
1011397a79e7SCédric Le Goater  *  EX12
1012397a79e7SCédric Le Goater  *  EX13
1013397a79e7SCédric Le Goater  *  EX14
1014397a79e7SCédric Le Goater  * <EX15 reserved>
1015397a79e7SCédric Le Goater  */
1016397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1017397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1018397a79e7SCédric Le Goater 
1019397a79e7SCédric Le Goater /*
102009279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1021397a79e7SCédric Le Goater  */
102209279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1023397a79e7SCédric Le Goater 
10242b548a42SCédric Le Goater 
10252b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
10262b548a42SCédric Le Goater 
102777864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
102877864267SCédric Le Goater {
10299ae1329eSCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
103077864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
10319ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
10329ae1329eSCédric Le Goater     int i;
103377864267SCédric Le Goater 
1034245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1035245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1036245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1037245cdb7fSCédric Le Goater                              OBJ_PROP_LINK_STRONG,
1038245cdb7fSCédric Le Goater                              &error_abort);
1039245cdb7fSCédric Le Goater 
1040f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
1041ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
104277864267SCédric Le Goater 
1043f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
104482514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
104577864267SCédric Le Goater 
1046f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
10473233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
10483887d241SBalamuruhan S 
10493887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
10503887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
10519ae1329eSCédric Le Goater 
10529ae1329eSCédric Le Goater     for (i = 0; i < pcc->num_phbs; i++) {
10539ae1329eSCédric Le Goater         object_initialize_child(obj, "phb[*]", &chip8->phbs[i],
10549ae1329eSCédric Le Goater                                 sizeof(chip8->phbs[i]), TYPE_PNV_PHB3,
10559ae1329eSCédric Le Goater                                 &error_abort, NULL);
10569ae1329eSCédric Le Goater     }
10579ae1329eSCédric Le Goater 
10589ae1329eSCédric Le Goater     /*
10599ae1329eSCédric Le Goater      * Number of PHBs is the chip default
10609ae1329eSCédric Le Goater      */
10619ae1329eSCédric Le Goater     chip->num_phbs = pcc->num_phbs;
106277864267SCédric Le Goater }
106377864267SCédric Le Goater 
106477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
106577864267SCédric Le Goater  {
106677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
106777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
106877864267SCédric Le Goater     int i, j;
106977864267SCédric Le Goater     char *name;
107077864267SCédric Le Goater 
107177864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
107277864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
107377864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
107477864267SCédric Le Goater     g_free(name);
107577864267SCédric Le Goater 
107677864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
107777864267SCédric Le Goater 
107877864267SCédric Le Goater     /* Map the ICP registers for each thread */
107977864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
10804fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
108177864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
108277864267SCédric Le Goater 
108377864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
108477864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1085245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
108677864267SCédric Le Goater 
108777864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
108877864267SCédric Le Goater                                         &icp->mmio);
108977864267SCédric Le Goater         }
109077864267SCédric Le Goater     }
109177864267SCédric Le Goater }
109277864267SCédric Le Goater 
109377864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
109477864267SCédric Le Goater {
109577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
109677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
109777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1098ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
109977864267SCédric Le Goater     Error *local_err = NULL;
11009ae1329eSCédric Le Goater     int i;
110177864267SCédric Le Goater 
1102245cdb7fSCédric Le Goater     assert(chip8->xics);
1103245cdb7fSCédric Le Goater 
1104709044fdSCédric Le Goater     /* XSCOM bridge is first */
1105709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1106709044fdSCédric Le Goater     if (local_err) {
1107709044fdSCédric Le Goater         error_propagate(errp, local_err);
1108709044fdSCédric Le Goater         return;
1109709044fdSCédric Le Goater     }
1110709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1111709044fdSCédric Le Goater 
111277864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
111377864267SCédric Le Goater     if (local_err) {
111477864267SCédric Le Goater         error_propagate(errp, local_err);
111577864267SCédric Le Goater         return;
111677864267SCédric Le Goater     }
111777864267SCédric Le Goater 
111877864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
111977864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
112077864267SCédric Le Goater                             "bar", &error_fatal);
1121245cdb7fSCédric Le Goater     object_property_set_link(OBJECT(&chip8->psi), OBJECT(chip8->xics),
112234bdca8fSCédric Le Goater                              ICS_PROP_XICS, &error_abort);
112377864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
112477864267SCédric Le Goater     if (local_err) {
112577864267SCédric Le Goater         error_propagate(errp, local_err);
112677864267SCédric Le Goater         return;
112777864267SCédric Le Goater     }
1128ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1129ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
113077864267SCédric Le Goater 
113177864267SCédric Le Goater     /* Create LPC controller */
1132b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi",
1133b63f3893SGreg Kurz                              &error_abort);
113477864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
113577864267SCédric Le Goater                              &error_fatal);
113677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
113777864267SCédric Le Goater 
113864d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
113964d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
114064d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
114164d011d5SCédric Le Goater 
114259b7c1c2SBalamuruhan S     /*
114359b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
114459b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
114559b7c1c2SBalamuruhan S      */
114677864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
114777864267SCédric Le Goater     if (local_err) {
114877864267SCédric Le Goater         error_propagate(errp, local_err);
114977864267SCédric Le Goater         return;
115077864267SCédric Le Goater     }
115177864267SCédric Le Goater 
115277864267SCédric Le Goater     /* Create the simplified OCC model */
1153ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi",
1154ee3d2713SGreg Kurz                              &error_abort);
115577864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
115677864267SCédric Le Goater     if (local_err) {
115777864267SCédric Le Goater         error_propagate(errp, local_err);
115877864267SCédric Le Goater         return;
115977864267SCédric Le Goater     }
116077864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1161f3db8266SBalamuruhan S 
1162f3db8266SBalamuruhan S     /* OCC SRAM model */
11633a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1164f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
11653887d241SBalamuruhan S 
11663887d241SBalamuruhan S     /* HOMER */
1167f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip",
1168f2582acfSGreg Kurz                              &error_abort);
11693887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
11703887d241SBalamuruhan S                              &local_err);
11713887d241SBalamuruhan S     if (local_err) {
11723887d241SBalamuruhan S         error_propagate(errp, local_err);
11733887d241SBalamuruhan S         return;
11743887d241SBalamuruhan S     }
11758f092316SCédric Le Goater     /* Homer Xscom region */
11768f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
11778f092316SCédric Le Goater 
11788f092316SCédric Le Goater     /* Homer mmio region */
11793887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
11803887d241SBalamuruhan S                                 &chip8->homer.regs);
11819ae1329eSCédric Le Goater 
11829ae1329eSCédric Le Goater     /* PHB3 controllers */
11839ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
11849ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
11859ae1329eSCédric Le Goater         PnvPBCQState *pbcq = &phb->pbcq;
11869ae1329eSCédric Le Goater 
11879ae1329eSCédric Le Goater         object_property_set_int(OBJECT(phb), i, "index", &error_fatal);
11889ae1329eSCédric Le Goater         object_property_set_int(OBJECT(phb), chip->chip_id, "chip-id",
11899ae1329eSCédric Le Goater                                 &error_fatal);
11909ae1329eSCédric Le Goater         object_property_set_bool(OBJECT(phb), true, "realized", &local_err);
11919ae1329eSCédric Le Goater         if (local_err) {
11929ae1329eSCédric Le Goater             error_propagate(errp, local_err);
11939ae1329eSCédric Le Goater             return;
11949ae1329eSCédric Le Goater         }
11959ae1329eSCédric Le Goater         qdev_set_parent_bus(DEVICE(phb), sysbus_get_default());
11969ae1329eSCédric Le Goater 
11979ae1329eSCédric Le Goater         /* Populate the XSCOM address space. */
11989ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
11999ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
12009ae1329eSCédric Le Goater                                 &pbcq->xscom_nest_regs);
12019ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12029ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
12039ae1329eSCédric Le Goater                                 &pbcq->xscom_pci_regs);
12049ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12059ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
12069ae1329eSCédric Le Goater                                 &pbcq->xscom_spci_regs);
12079ae1329eSCédric Le Goater     }
120877864267SCédric Le Goater }
120977864267SCédric Le Goater 
121070c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
121170c059e9SGreg Kurz {
121270c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
121370c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
121470c059e9SGreg Kurz }
121570c059e9SGreg Kurz 
1216e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1217e997040eSCédric Le Goater {
1218e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1219e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1220e997040eSCédric Le Goater 
1221e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1222397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
12239ae1329eSCédric Le Goater     k->num_phbs = 3;
1224631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1225d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1226d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12270990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
122885913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
122904026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1230eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1231d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1232c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
123370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1234e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
123577864267SCédric Le Goater 
123677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
123777864267SCédric Le Goater                                     &k->parent_realize);
1238e997040eSCédric Le Goater }
1239e997040eSCédric Le Goater 
1240e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1241e997040eSCédric Le Goater {
1242e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1243e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1244e997040eSCédric Le Goater 
1245e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1246397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12479ae1329eSCédric Le Goater     k->num_phbs = 3;
1248631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1249d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1250d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12510990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
125285913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
125304026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1254eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1255d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1256c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
125770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1258e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
125977864267SCédric Le Goater 
126077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
126177864267SCédric Le Goater                                     &k->parent_realize);
1262e997040eSCédric Le Goater }
1263e997040eSCédric Le Goater 
1264e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1265e997040eSCédric Le Goater {
1266e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1267e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1268e997040eSCédric Le Goater 
1269e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1270397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12719ae1329eSCédric Le Goater     k->num_phbs = 3;
1272631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1273d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1274d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12750990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
127685913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
127704026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1278eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1279d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1280c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
128170c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1282e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
128377864267SCédric Le Goater 
128477864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
128577864267SCédric Le Goater                                     &k->parent_realize);
128677864267SCédric Le Goater }
128777864267SCédric Le Goater 
128877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
128977864267SCédric Le Goater {
12904f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
12912dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
12924f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
12934f9924c4SBenjamin Herrenschmidt     int i;
12942dfa91a2SCédric Le Goater 
12952dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
12962dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
1297d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1298d1214b81SGreg Kurz                               "xive-fabric", &error_abort);
1299c38536bcSCédric Le Goater 
1300c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1301c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
130215376c66SCédric Le Goater 
130315376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
130415376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
13056598a70dSCédric Le Goater 
13066598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
13076598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
13083887d241SBalamuruhan S 
13093887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
13103887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
13114f9924c4SBenjamin Herrenschmidt 
13124f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13134f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
13144f9924c4SBenjamin Herrenschmidt                                 sizeof(chip9->pecs[i]), TYPE_PNV_PHB4_PEC,
13154f9924c4SBenjamin Herrenschmidt                                 &error_abort, NULL);
13164f9924c4SBenjamin Herrenschmidt     }
13174f9924c4SBenjamin Herrenschmidt 
13184f9924c4SBenjamin Herrenschmidt     /*
13194f9924c4SBenjamin Herrenschmidt      * Number of PHBs is the chip default
13204f9924c4SBenjamin Herrenschmidt      */
13214f9924c4SBenjamin Herrenschmidt     chip->num_phbs = pcc->num_phbs;
132277864267SCédric Le Goater }
132377864267SCédric Le Goater 
13245dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
13255dad902cSCédric Le Goater {
13265dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
13275dad902cSCédric Le Goater     int i;
13285dad902cSCédric Le Goater 
13295dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
13305dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
13315dad902cSCédric Le Goater 
13325dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
13335dad902cSCédric Le Goater         char eq_name[32];
13345dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
13354fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
13365dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
13375dad902cSCédric Le Goater 
13385dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1339bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1340bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
13415dad902cSCédric Le Goater 
13425dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
13435dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
13445dad902cSCédric Le Goater 
13455dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
13465dad902cSCédric Le Goater                                 &eq->xscom_regs);
13475dad902cSCédric Le Goater     }
13485dad902cSCédric Le Goater }
13495dad902cSCédric Le Goater 
13504f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
13514f9924c4SBenjamin Herrenschmidt {
13524f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
13534f9924c4SBenjamin Herrenschmidt     Error *local_err = NULL;
13544f9924c4SBenjamin Herrenschmidt     int i, j;
13554f9924c4SBenjamin Herrenschmidt     int phb_id = 0;
13564f9924c4SBenjamin Herrenschmidt 
13574f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13584f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
13594f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
13604f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
13614f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
13624f9924c4SBenjamin Herrenschmidt 
13634f9924c4SBenjamin Herrenschmidt         object_property_set_int(OBJECT(pec), i, "index", &error_fatal);
13644f9924c4SBenjamin Herrenschmidt         /*
13654f9924c4SBenjamin Herrenschmidt          * PEC0 -> 1 stack
13664f9924c4SBenjamin Herrenschmidt          * PEC1 -> 2 stacks
13674f9924c4SBenjamin Herrenschmidt          * PEC2 -> 3 stacks
13684f9924c4SBenjamin Herrenschmidt          */
13694f9924c4SBenjamin Herrenschmidt         object_property_set_int(OBJECT(pec), i + 1, "num-stacks",
13704f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
13714f9924c4SBenjamin Herrenschmidt         object_property_set_int(OBJECT(pec), chip->chip_id, "chip-id",
13724f9924c4SBenjamin Herrenschmidt                                  &error_fatal);
13734f9924c4SBenjamin Herrenschmidt         object_property_set_link(OBJECT(pec), OBJECT(get_system_memory()),
13744f9924c4SBenjamin Herrenschmidt                                  "system-memory", &error_abort);
13754f9924c4SBenjamin Herrenschmidt         object_property_set_bool(OBJECT(pec), true, "realized", &local_err);
13764f9924c4SBenjamin Herrenschmidt         if (local_err) {
13774f9924c4SBenjamin Herrenschmidt             error_propagate(errp, local_err);
13784f9924c4SBenjamin Herrenschmidt             return;
13794f9924c4SBenjamin Herrenschmidt         }
13804f9924c4SBenjamin Herrenschmidt 
13814f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
13824f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
13834f9924c4SBenjamin Herrenschmidt 
13844f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
13854f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
13864f9924c4SBenjamin Herrenschmidt 
13874f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs;
13884f9924c4SBenjamin Herrenschmidt              j++, phb_id++) {
13894f9924c4SBenjamin Herrenschmidt             PnvPhb4PecStack *stack = &pec->stacks[j];
13904f9924c4SBenjamin Herrenschmidt             Object *obj = OBJECT(&stack->phb);
13914f9924c4SBenjamin Herrenschmidt 
13924f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, phb_id, "index", &error_fatal);
13934f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, chip->chip_id, "chip-id",
13944f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
13954f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, PNV_PHB4_VERSION, "version",
13964f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
13974f9924c4SBenjamin Herrenschmidt             object_property_set_int(obj, PNV_PHB4_DEVICE_ID, "device-id",
13984f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
13994f9924c4SBenjamin Herrenschmidt             object_property_set_link(obj, OBJECT(stack), "stack", &error_abort);
14004f9924c4SBenjamin Herrenschmidt             object_property_set_bool(obj, true, "realized", &local_err);
14014f9924c4SBenjamin Herrenschmidt             if (local_err) {
14024f9924c4SBenjamin Herrenschmidt                 error_propagate(errp, local_err);
14034f9924c4SBenjamin Herrenschmidt                 return;
14044f9924c4SBenjamin Herrenschmidt             }
14054f9924c4SBenjamin Herrenschmidt             qdev_set_parent_bus(DEVICE(obj), sysbus_get_default());
14064f9924c4SBenjamin Herrenschmidt 
14074f9924c4SBenjamin Herrenschmidt             /* Populate the XSCOM address space. */
14084f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14094f9924c4SBenjamin Herrenschmidt                                    pec_nest_base + 0x40 * (stack->stack_no + 1),
14104f9924c4SBenjamin Herrenschmidt                                    &stack->nest_regs_mr);
14114f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14124f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + 0x40 * (stack->stack_no + 1),
14134f9924c4SBenjamin Herrenschmidt                                     &stack->pci_regs_mr);
14144f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14154f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
14164f9924c4SBenjamin Herrenschmidt                                     0x40 * stack->stack_no,
14174f9924c4SBenjamin Herrenschmidt                                     &stack->phb_regs_mr);
14184f9924c4SBenjamin Herrenschmidt         }
14194f9924c4SBenjamin Herrenschmidt     }
14204f9924c4SBenjamin Herrenschmidt }
14214f9924c4SBenjamin Herrenschmidt 
142277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
142377864267SCédric Le Goater {
142477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14252dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14262dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1427c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
142877864267SCédric Le Goater     Error *local_err = NULL;
142977864267SCédric Le Goater 
1430709044fdSCédric Le Goater     /* XSCOM bridge is first */
1431709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1432709044fdSCédric Le Goater     if (local_err) {
1433709044fdSCédric Le Goater         error_propagate(errp, local_err);
1434709044fdSCédric Le Goater         return;
1435709044fdSCédric Le Goater     }
1436709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1437709044fdSCédric Le Goater 
143877864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
143977864267SCédric Le Goater     if (local_err) {
144077864267SCédric Le Goater         error_propagate(errp, local_err);
144177864267SCédric Le Goater         return;
144277864267SCédric Le Goater     }
14432dfa91a2SCédric Le Goater 
14445dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14455dad902cSCédric Le Goater     if (local_err) {
14465dad902cSCédric Le Goater         error_propagate(errp, local_err);
14475dad902cSCédric Le Goater         return;
14485dad902cSCédric Le Goater     }
14495dad902cSCédric Le Goater 
14502dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
14512dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
14522dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
14532dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
14542dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
14552dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
14562dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
14572dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
14582dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
14597ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
14607ae54cc3SGreg Kurz                              &error_abort);
14612dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
14622dfa91a2SCédric Le Goater                              &local_err);
14632dfa91a2SCédric Le Goater     if (local_err) {
14642dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
14652dfa91a2SCédric Le Goater         return;
14662dfa91a2SCédric Le Goater     }
14672dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
14682dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1469c38536bcSCédric Le Goater 
1470c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1471c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1472c38536bcSCédric Le Goater                             "bar", &error_fatal);
1473c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1474c38536bcSCédric Le Goater     if (local_err) {
1475c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1476c38536bcSCédric Le Goater         return;
1477c38536bcSCédric Le Goater     }
1478c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1479c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
148015376c66SCédric Le Goater 
148115376c66SCédric Le Goater     /* LPC */
1482b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1483b63f3893SGreg Kurz                              &error_abort);
148415376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
148515376c66SCédric Le Goater     if (local_err) {
148615376c66SCédric Le Goater         error_propagate(errp, local_err);
148715376c66SCédric Le Goater         return;
148815376c66SCédric Le Goater     }
148915376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
149015376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
149115376c66SCédric Le Goater 
149215376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
149315376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
14946598a70dSCédric Le Goater 
14956598a70dSCédric Le Goater     /* Create the simplified OCC model */
1496ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1497ee3d2713SGreg Kurz                              &error_abort);
14986598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
14996598a70dSCédric Le Goater     if (local_err) {
15006598a70dSCédric Le Goater         error_propagate(errp, local_err);
15016598a70dSCédric Le Goater         return;
15026598a70dSCédric Le Goater     }
15036598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1504f3db8266SBalamuruhan S 
1505f3db8266SBalamuruhan S     /* OCC SRAM model */
15063a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1507f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
15083887d241SBalamuruhan S 
15093887d241SBalamuruhan S     /* HOMER */
1510f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1511f2582acfSGreg Kurz                              &error_abort);
15123887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
15133887d241SBalamuruhan S                              &local_err);
15143887d241SBalamuruhan S     if (local_err) {
15153887d241SBalamuruhan S         error_propagate(errp, local_err);
15163887d241SBalamuruhan S         return;
15173887d241SBalamuruhan S     }
15188f092316SCédric Le Goater     /* Homer Xscom region */
15198f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15208f092316SCédric Le Goater 
15218f092316SCédric Le Goater     /* Homer mmio region */
15223887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15233887d241SBalamuruhan S                                 &chip9->homer.regs);
15244f9924c4SBenjamin Herrenschmidt 
15254f9924c4SBenjamin Herrenschmidt     /* PHBs */
15264f9924c4SBenjamin Herrenschmidt     pnv_chip_power9_phb_realize(chip, &local_err);
15274f9924c4SBenjamin Herrenschmidt     if (local_err) {
15284f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15294f9924c4SBenjamin Herrenschmidt         return;
15304f9924c4SBenjamin Herrenschmidt     }
1531e997040eSCédric Le Goater }
1532e997040eSCédric Le Goater 
153370c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
153470c059e9SGreg Kurz {
153570c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
153670c059e9SGreg Kurz     return addr >> 3;
153770c059e9SGreg Kurz }
153870c059e9SGreg Kurz 
1539e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1540e997040eSCédric Le Goater {
1541e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1542e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1543e997040eSCédric Le Goater 
154483028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1545397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1546631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1547d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1548d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15490990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
155085913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
155104026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1552eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1553d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1554c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
155570c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1556e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
15574f9924c4SBenjamin Herrenschmidt     k->num_phbs = 6;
155877864267SCédric Le Goater 
155977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
156077864267SCédric Le Goater                                     &k->parent_realize);
1561e997040eSCédric Le Goater }
1562e997040eSCédric Le Goater 
15632b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
15642b548a42SCédric Le Goater {
15658b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
15668b50ce85SCédric Le Goater 
15678b50ce85SCédric Le Goater     object_initialize_child(obj, "psi",  &chip10->psi, sizeof(chip10->psi),
15688b50ce85SCédric Le Goater                             TYPE_PNV10_PSI, &error_abort, NULL);
15692661f6abSCédric Le Goater     object_initialize_child(obj, "lpc",  &chip10->lpc, sizeof(chip10->lpc),
15702661f6abSCédric Le Goater                             TYPE_PNV10_LPC, &error_abort, NULL);
15712b548a42SCédric Le Goater }
15722b548a42SCédric Le Goater 
15732b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
15742b548a42SCédric Le Goater {
15752b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15762b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
15778b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
15782b548a42SCédric Le Goater     Error *local_err = NULL;
15792b548a42SCédric Le Goater 
15802b548a42SCédric Le Goater     /* XSCOM bridge is first */
15812b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
15822b548a42SCédric Le Goater     if (local_err) {
15832b548a42SCédric Le Goater         error_propagate(errp, local_err);
15842b548a42SCédric Le Goater         return;
15852b548a42SCédric Le Goater     }
15862b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
15872b548a42SCédric Le Goater 
15882b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
15892b548a42SCédric Le Goater     if (local_err) {
15902b548a42SCédric Le Goater         error_propagate(errp, local_err);
15912b548a42SCédric Le Goater         return;
15922b548a42SCédric Le Goater     }
15938b50ce85SCédric Le Goater 
15948b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15958b50ce85SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip),
15968b50ce85SCédric Le Goater                             "bar", &error_fatal);
15978b50ce85SCédric Le Goater     object_property_set_bool(OBJECT(&chip10->psi), true, "realized",
15988b50ce85SCédric Le Goater                              &local_err);
15998b50ce85SCédric Le Goater     if (local_err) {
16008b50ce85SCédric Le Goater         error_propagate(errp, local_err);
16018b50ce85SCédric Le Goater         return;
16028b50ce85SCédric Le Goater     }
16038b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
16048b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
16052661f6abSCédric Le Goater 
16062661f6abSCédric Le Goater     /* LPC */
16072661f6abSCédric Le Goater     object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi",
16082661f6abSCédric Le Goater                              &error_abort);
16092661f6abSCédric Le Goater     object_property_set_bool(OBJECT(&chip10->lpc), true, "realized",
16102661f6abSCédric Le Goater                              &local_err);
16112661f6abSCédric Le Goater     if (local_err) {
16122661f6abSCédric Le Goater         error_propagate(errp, local_err);
16132661f6abSCédric Le Goater         return;
16142661f6abSCédric Le Goater     }
16152661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
16162661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
16172661f6abSCédric Le Goater 
16182661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
16192661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
16202b548a42SCédric Le Goater }
16212b548a42SCédric Le Goater 
162270c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
162370c059e9SGreg Kurz {
162470c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
162570c059e9SGreg Kurz     return addr >> 3;
162670c059e9SGreg Kurz }
162770c059e9SGreg Kurz 
16282b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
16292b548a42SCédric Le Goater {
16302b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
16312b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16322b548a42SCédric Le Goater 
16332b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
16342b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
16352b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
16362b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
16372b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
16382b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
163985913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
16402b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
16412b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
16422b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1643c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
164470c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
16452b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
16462b548a42SCédric Le Goater 
16472b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
16482b548a42SCédric Le Goater                                     &k->parent_realize);
16492b548a42SCédric Le Goater }
16502b548a42SCédric Le Goater 
1651397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1652397a79e7SCédric Le Goater {
1653397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1654397a79e7SCédric Le Goater     int cores_max;
1655397a79e7SCédric Le Goater 
1656397a79e7SCédric Le Goater     /*
1657397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1658397a79e7SCédric Le Goater      * the chip class
1659397a79e7SCédric Le Goater      */
1660397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1661397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1662397a79e7SCédric Le Goater     }
1663397a79e7SCédric Le Goater 
1664397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1665397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1666397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1667397a79e7SCédric Le Goater                    chip->cores_mask);
1668397a79e7SCédric Le Goater         return;
1669397a79e7SCédric Le Goater     }
1670397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1671397a79e7SCédric Le Goater 
1672397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
167327d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1674397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1675397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1676397a79e7SCédric Le Goater                    cores_max);
1677397a79e7SCédric Le Goater         return;
1678397a79e7SCédric Le Goater     }
1679397a79e7SCédric Le Goater }
1680397a79e7SCédric Le Goater 
168151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1682e997040eSCédric Le Goater {
1683397a79e7SCédric Le Goater     Error *error = NULL;
1684d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
168540abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1686d2fd9612SCédric Le Goater     int i, core_hwid;
168708c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1688397a79e7SCédric Le Goater 
1689d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1690d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1691d2fd9612SCédric Le Goater         return;
1692d2fd9612SCédric Le Goater     }
1693d2fd9612SCédric Le Goater 
1694d2fd9612SCédric Le Goater     /* Cores */
1695397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1696397a79e7SCédric Le Goater     if (error) {
1697397a79e7SCédric Le Goater         error_propagate(errp, error);
1698397a79e7SCédric Le Goater         return;
1699397a79e7SCédric Le Goater     }
1700d2fd9612SCédric Le Goater 
17014fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1702d2fd9612SCédric Le Goater 
1703d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1704d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1705d2fd9612SCédric Le Goater         char core_name[32];
17064fa28f23SGreg Kurz         PnvCore *pnv_core;
1707c035851aSCédric Le Goater         uint64_t xscom_core_base;
1708d2fd9612SCédric Le Goater 
1709d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1710d2fd9612SCédric Le Goater             continue;
1711d2fd9612SCédric Le Goater         }
1712d2fd9612SCédric Le Goater 
17134fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
17144fa28f23SGreg Kurz 
1715d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
17164fa28f23SGreg Kurz         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
17174fa28f23SGreg Kurz                                   &error_abort);
17184fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1719764f9b25SGreg Kurz         object_property_set_int(OBJECT(pnv_core), chip->nr_threads,
1720764f9b25SGreg Kurz                                 "nr-threads", &error_fatal);
1721d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1722d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1723d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1724d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1725d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
172608c3f3a7SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), pnv->fw_load_addr,
172708c3f3a7SCédric Le Goater                                 "hrmor", &error_fatal);
1728158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1729158e17a6SGreg Kurz                                  &error_abort);
1730d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1731d2fd9612SCédric Le Goater                                  &error_fatal);
173224ece072SCédric Le Goater 
173324ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1734c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1735c035851aSCédric Le Goater 
1736c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
17374fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1738d2fd9612SCédric Le Goater         i++;
1739d2fd9612SCédric Le Goater     }
174051c04728SCédric Le Goater }
174151c04728SCédric Le Goater 
174251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
174351c04728SCédric Le Goater {
174451c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
174551c04728SCédric Le Goater     Error *error = NULL;
174651c04728SCédric Le Goater 
174751c04728SCédric Le Goater     /* Cores */
174851c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
174951c04728SCédric Le Goater     if (error) {
175051c04728SCédric Le Goater         error_propagate(errp, error);
175151c04728SCédric Le Goater         return;
175251c04728SCédric Le Goater     }
1753e997040eSCédric Le Goater }
1754e997040eSCédric Le Goater 
1755e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1756e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1757e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1758e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1759397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1760397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1761764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
17624f9924c4SBenjamin Herrenschmidt     DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
1763e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1764e997040eSCédric Le Goater };
1765e997040eSCédric Le Goater 
1766e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1767e997040eSCédric Le Goater {
1768e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1769e997040eSCédric Le Goater 
17709d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1771e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
17724f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1773e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1774e997040eSCédric Le Goater }
1775e997040eSCédric Le Goater 
1776119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1777119eaa9dSCédric Le Goater {
1778119eaa9dSCédric Le Goater     int i, j;
1779119eaa9dSCédric Le Goater 
1780119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1781119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1782119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1783119eaa9dSCédric Le Goater 
1784119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1785119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1786119eaa9dSCédric Le Goater                 return pc->threads[j];
1787119eaa9dSCédric Le Goater             }
1788119eaa9dSCédric Le Goater         }
1789119eaa9dSCédric Le Goater     }
1790119eaa9dSCédric Le Goater     return NULL;
1791119eaa9dSCédric Le Goater }
1792119eaa9dSCédric Le Goater 
179354f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
179454f59d78SCédric Le Goater {
1795b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
17969ae1329eSCédric Le Goater     int i, j;
179754f59d78SCédric Le Goater 
179854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
17999ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
180077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
180177864267SCédric Le Goater 
180277864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
180377864267SCédric Le Goater             return &chip8->psi.ics;
180454f59d78SCédric Le Goater         }
18059ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18069ae1329eSCédric Le Goater             if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
18079ae1329eSCédric Le Goater                 return &chip8->phbs[j].lsis;
18089ae1329eSCédric Le Goater             }
18099ae1329eSCédric Le Goater             if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
18109ae1329eSCédric Le Goater                 return ICS(&chip8->phbs[j].msis);
18119ae1329eSCédric Le Goater             }
18129ae1329eSCédric Le Goater         }
181354f59d78SCédric Le Goater     }
181454f59d78SCédric Le Goater     return NULL;
181554f59d78SCédric Le Goater }
181654f59d78SCédric Le Goater 
181754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
181854f59d78SCédric Le Goater {
1819b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18209ae1329eSCédric Le Goater     int i, j;
182154f59d78SCédric Le Goater 
182254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18239ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
182477864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
18259ae1329eSCédric Le Goater 
182677864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
18279ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18289ae1329eSCédric Le Goater             ics_resend(&chip8->phbs[j].lsis);
18299ae1329eSCédric Le Goater             ics_resend(ICS(&chip8->phbs[j].msis));
18309ae1329eSCédric Le Goater         }
183154f59d78SCédric Le Goater     }
183254f59d78SCédric Le Goater }
183354f59d78SCédric Le Goater 
183436fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
183536fc6f08SCédric Le Goater {
183636fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
183736fc6f08SCédric Le Goater 
1838956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
183936fc6f08SCédric Le Goater }
184036fc6f08SCédric Le Goater 
184147fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
184247fea43aSCédric Le Goater                                Monitor *mon)
184347fea43aSCédric Le Goater {
1844b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
184554f59d78SCédric Le Goater     int i;
184647fea43aSCédric Le Goater     CPUState *cs;
184747fea43aSCédric Le Goater 
184847fea43aSCédric Le Goater     CPU_FOREACH(cs) {
184947fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
185047fea43aSCédric Le Goater 
185185913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
185285913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
185385913070SGreg Kurz                                                            mon);
1854d8e4aad5SCédric Le Goater     }
185554f59d78SCédric Le Goater 
185654f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1857d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
185854f59d78SCédric Le Goater     }
185947fea43aSCédric Le Goater }
186047fea43aSCédric Le Goater 
1861c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1862c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1863c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1864c722579eSCédric Le Goater                          uint32_t logic_serv,
1865c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1866c722579eSCédric Le Goater {
1867c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1868c722579eSCédric Le Goater     int total_count = 0;
1869c722579eSCédric Le Goater     int i;
1870c722579eSCédric Le Goater 
1871c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1872c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1873c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1874c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1875c722579eSCédric Le Goater         int count;
1876c722579eSCédric Le Goater 
1877c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1878c722579eSCédric Le Goater                                priority, logic_serv, match);
1879c722579eSCédric Le Goater 
1880c722579eSCédric Le Goater         if (count < 0) {
1881c722579eSCédric Le Goater             return count;
1882c722579eSCédric Le Goater         }
1883c722579eSCédric Le Goater 
1884c722579eSCédric Le Goater         total_count += count;
1885c722579eSCédric Le Goater     }
1886c722579eSCédric Le Goater 
1887c722579eSCédric Le Goater     return total_count;
1888c722579eSCédric Le Goater }
1889c722579eSCédric Le Goater 
1890f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
18919e933f4aSBenjamin Herrenschmidt {
18929e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
189336fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1894d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1895d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1896f30c843cSCédric Le Goater 
1897f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1898f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1899f30c843cSCédric Le Goater 
1900f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1901f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1902f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1903d76f2da7SGreg Kurz 
1904d76f2da7SGreg Kurz     pmc->compat = compat;
1905d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1906f30c843cSCédric Le Goater }
1907f30c843cSCédric Le Goater 
1908f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1909f30c843cSCédric Le Goater {
1910f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1911c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1912d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1913d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1914f30c843cSCédric Le Goater 
1915f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1916f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1917c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1918f30c843cSCédric Le Goater 
1919f30c843cSCédric Le Goater     mc->alias = "powernv";
1920d76f2da7SGreg Kurz 
1921d76f2da7SGreg Kurz     pmc->compat = compat;
1922d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19237a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1924f30c843cSCédric Le Goater }
1925f30c843cSCédric Le Goater 
19262b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
19272b548a42SCédric Le Goater {
19282b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1929d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1930d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
19312b548a42SCédric Le Goater 
19322b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
19332b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
1934d76f2da7SGreg Kurz 
1935d76f2da7SGreg Kurz     pmc->compat = compat;
1936d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19377a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
19382b548a42SCédric Le Goater }
19392b548a42SCédric Le Goater 
194008c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
194108c3f3a7SCédric Le Goater {
194208c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
194308c3f3a7SCédric Le Goater 
194408c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
194508c3f3a7SCédric Le Goater }
194608c3f3a7SCédric Le Goater 
194708c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
194808c3f3a7SCédric Le Goater {
194908c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
195008c3f3a7SCédric Le Goater 
195108c3f3a7SCédric Le Goater     if (value) {
195208c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
195308c3f3a7SCédric Le Goater     }
195408c3f3a7SCédric Le Goater }
195508c3f3a7SCédric Le Goater 
1956f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1957f30c843cSCédric Le Goater {
1958f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
195947fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
19609e933f4aSBenjamin Herrenschmidt 
19619e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1962b168a138SCédric Le Goater     mc->init = pnv_init;
1963b168a138SCédric Le Goater     mc->reset = pnv_reset;
19649e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
196559b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
196659b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
19679e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
19689e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1969f1d18b0aSJoel Stanley     /*
1970f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1971f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1972f1d18b0aSJoel Stanley      */
1973f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
1974*173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
197547fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
197608c3f3a7SCédric Le Goater 
197708c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
197808c3f3a7SCédric Le Goater                                    pnv_machine_get_hb, pnv_machine_set_hb,
197908c3f3a7SCédric Le Goater                                    &error_abort);
198008c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
198108c3f3a7SCédric Le Goater                               "Use a hostboot like boot loader",
198208c3f3a7SCédric Le Goater                               NULL);
19839e933f4aSBenjamin Herrenschmidt }
19849e933f4aSBenjamin Herrenschmidt 
198577864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1986beba5c0fSIgor Mammedov     {                                             \
1987beba5c0fSIgor Mammedov         .name          = type,                    \
1988beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
198977864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
199077864267SCédric Le Goater     }
199177864267SCédric Le Goater 
199277864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
199377864267SCédric Le Goater     {                                             \
199477864267SCédric Le Goater         .name          = type,                    \
199577864267SCédric Le Goater         .class_init    = class_initfn,            \
199677864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1997beba5c0fSIgor Mammedov     }
1998beba5c0fSIgor Mammedov 
19992b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
20002b548a42SCédric Le Goater     {                                              \
20012b548a42SCédric Le Goater         .name          = type,                     \
20022b548a42SCédric Le Goater         .class_init    = class_initfn,             \
20032b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
20042b548a42SCédric Le Goater     }
20052b548a42SCédric Le Goater 
2006beba5c0fSIgor Mammedov static const TypeInfo types[] = {
20071aba8716SCédric Le Goater     {
20082b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
20092b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20102b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
20112b548a42SCédric Le Goater     },
20122b548a42SCédric Le Goater     {
20131aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
20141aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20151aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2016c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2017c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2018c722579eSCédric Le Goater             { },
2019c722579eSCédric Le Goater         },
20201aba8716SCédric Le Goater     },
20211aba8716SCédric Le Goater     {
20221aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
20231aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20241aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
20251aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
20261aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
20271aba8716SCédric Le Goater             { },
20281aba8716SCédric Le Goater         },
20291aba8716SCédric Le Goater     },
2030beba5c0fSIgor Mammedov     {
2031b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
20329e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2033f30c843cSCédric Le Goater         .abstract       = true,
20349e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2035b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2036d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
203736fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
203847fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
203936fc6f08SCédric Le Goater             { },
204036fc6f08SCédric Le Goater         },
2041beba5c0fSIgor Mammedov     },
2042beba5c0fSIgor Mammedov     {
2043beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2044beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2045beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2046beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2047beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2048beba5c0fSIgor Mammedov         .abstract      = true,
2049beba5c0fSIgor Mammedov     },
205077864267SCédric Le Goater 
205177864267SCédric Le Goater     /*
20522b548a42SCédric Le Goater      * P10 chip and variants
20532b548a42SCédric Le Goater      */
20542b548a42SCédric Le Goater     {
20552b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
20562b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
20572b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
20582b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
20592b548a42SCédric Le Goater     },
20602b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
20612b548a42SCédric Le Goater 
20622b548a42SCédric Le Goater     /*
206377864267SCédric Le Goater      * P9 chip and variants
206477864267SCédric Le Goater      */
206577864267SCédric Le Goater     {
206677864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
206777864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
206877864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
206977864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
207077864267SCédric Le Goater     },
207177864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
207277864267SCédric Le Goater 
207377864267SCédric Le Goater     /*
207477864267SCédric Le Goater      * P8 chip and variants
207577864267SCédric Le Goater      */
207677864267SCédric Le Goater     {
207777864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
207877864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
207977864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
208077864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
208177864267SCédric Le Goater     },
208277864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
208377864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
208477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2085beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
20869e933f4aSBenjamin Herrenschmidt };
20879e933f4aSBenjamin Herrenschmidt 
2088beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2089