xref: /qemu/hw/ppc/pnv.c (revision d8e4aad5)
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"
21fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
229e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
239e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
25d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
269e933f4aSBenjamin Herrenschmidt #include "hw/hw.h"
27fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
289e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
299e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
309e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
319e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
32d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
349e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
35e997040eSCédric Le Goater #include "qapi/visitor.h"
3647fea43aSCédric Le Goater #include "monitor/monitor.h"
3747fea43aSCédric Le Goater #include "hw/intc/intc.h"
38aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
3958969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
409e933f4aSBenjamin Herrenschmidt 
4136fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
42967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
43967b7523SCédric Le Goater 
443495b6b6SCédric Le Goater #include "hw/isa/isa.h"
453495b6b6SCédric Le Goater #include "hw/char/serial.h"
463495b6b6SCédric Le Goater #include "hw/timer/mc146818rtc.h"
473495b6b6SCédric Le Goater 
489e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
499e933f4aSBenjamin Herrenschmidt 
50b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
519e933f4aSBenjamin Herrenschmidt 
529e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
539e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
54b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
559e933f4aSBenjamin Herrenschmidt 
569e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
57b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
58fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
59584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
609e933f4aSBenjamin Herrenschmidt 
6140abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
6240abf43fSIgor Mammedov {
6340abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
6440abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
6540abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
6640abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
6740abf43fSIgor Mammedov     g_free(s);
6840abf43fSIgor Mammedov     return core_type;
6940abf43fSIgor Mammedov }
7040abf43fSIgor Mammedov 
719e933f4aSBenjamin Herrenschmidt /*
729e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
739e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
749e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
759e933f4aSBenjamin Herrenschmidt  */
769e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
779e933f4aSBenjamin Herrenschmidt 
789e933f4aSBenjamin Herrenschmidt /*
799e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
809e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
819e933f4aSBenjamin Herrenschmidt  * per chip.
829e933f4aSBenjamin Herrenschmidt  */
83b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
849e933f4aSBenjamin Herrenschmidt {
859e933f4aSBenjamin Herrenschmidt     char *mem_name;
869e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
879e933f4aSBenjamin Herrenschmidt     int off;
889e933f4aSBenjamin Herrenschmidt 
899e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
909e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
919e933f4aSBenjamin Herrenschmidt 
929e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
939e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
949e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
959e933f4aSBenjamin Herrenschmidt 
969e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
979e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
989e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
999e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1009e933f4aSBenjamin Herrenschmidt }
1019e933f4aSBenjamin Herrenschmidt 
102d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
103d2fd9612SCédric Le Goater {
104d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
105d2fd9612SCédric Le Goater 
106d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
107a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
108d2fd9612SCédric Le Goater         if (cpus_offset) {
109d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
110d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
111d2fd9612SCédric Le Goater         }
112d2fd9612SCédric Le Goater     }
113d2fd9612SCédric Le Goater     _FDT(cpus_offset);
114d2fd9612SCédric Le Goater     return cpus_offset;
115d2fd9612SCédric Le Goater }
116d2fd9612SCédric Le Goater 
117d2fd9612SCédric Le Goater /*
118d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
119d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
120d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
121d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
122d2fd9612SCédric Le Goater  * servers.
123d2fd9612SCédric Le Goater  */
124b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
125d2fd9612SCédric Le Goater {
12608304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
12708304a86SDavid Gibson     CPUState *cs = CPU(cpu);
128d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1298bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
130d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
131d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
132d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
133d2fd9612SCédric Le Goater     int i;
134d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
135d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
136d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
137d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
138d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
139d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
140d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
141d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
142d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
143d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
144d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
145d2fd9612SCédric Le Goater     int offset;
146d2fd9612SCédric Le Goater     char *nodename;
147d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
148d2fd9612SCédric Le Goater 
149d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
150d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
151d2fd9612SCédric Le Goater     _FDT(offset);
152d2fd9612SCédric Le Goater     g_free(nodename);
153d2fd9612SCédric Le Goater 
154d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
155d2fd9612SCédric Le Goater 
156d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
157d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
158d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
159d2fd9612SCédric Le Goater 
160d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
161d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
162d2fd9612SCédric Le Goater                             env->dcache_line_size)));
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
164d2fd9612SCédric Le Goater                             env->dcache_line_size)));
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
166d2fd9612SCédric Le Goater                             env->icache_line_size)));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
168d2fd9612SCédric Le Goater                             env->icache_line_size)));
169d2fd9612SCédric Le Goater 
170d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
171d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
172d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
173d2fd9612SCédric Le Goater     } else {
1743dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
175d2fd9612SCédric Le Goater     }
176d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
177d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
178d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
179d2fd9612SCédric Le Goater     } else {
1803dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
181d2fd9612SCédric Le Goater     }
182d2fd9612SCédric Le Goater 
183d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
184d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
18567d7d66fSDavid Gibson     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", cpu->hash64_opts->slb_size)));
186d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
187d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
188d2fd9612SCédric Le Goater 
189d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
190d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
191d2fd9612SCédric Le Goater     }
192d2fd9612SCédric Le Goater 
19358969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
194d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
195d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
196d2fd9612SCédric Le Goater     }
197d2fd9612SCédric Le Goater 
198d2fd9612SCédric Le Goater     /* Advertise VMX/VSX (vector extensions) if available
199d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
200d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
201d2fd9612SCédric Le Goater      *   2               == VSX available */
202d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
203d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
204d2fd9612SCédric Le Goater 
205d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
206d2fd9612SCédric Le Goater     }
207d2fd9612SCédric Le Goater 
208d2fd9612SCédric Le Goater     /* Advertise DFP (Decimal Floating Point) if available
209d2fd9612SCédric Le Goater      *   0 / no property == no DFP
210d2fd9612SCédric Le Goater      *   1               == DFP available */
211d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
212d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
213d2fd9612SCédric Le Goater     }
214d2fd9612SCédric Le Goater 
215644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
216d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
217d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
218d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
219d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
220d2fd9612SCédric Le Goater     }
221d2fd9612SCédric Le Goater 
222d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
223d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
224d2fd9612SCédric Le Goater 
225d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
226d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
227d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
228d2fd9612SCédric Le Goater     }
229d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
230d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
231d2fd9612SCédric Le Goater }
232d2fd9612SCédric Le Goater 
233b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
234bf5615e7SCédric Le Goater                        uint32_t nr_threads)
235bf5615e7SCédric Le Goater {
236bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
237bf5615e7SCédric Le Goater     char *name;
238bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
239bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
240bf5615e7SCédric Le Goater     uint64_t *reg;
241bf5615e7SCédric Le Goater     int offset;
242bf5615e7SCédric Le Goater 
243bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
244bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
245bf5615e7SCédric Le Goater 
246bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
247bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
248bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
249bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
250bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
251bf5615e7SCédric Le Goater     }
252bf5615e7SCédric Le Goater 
253bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
254bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
255bf5615e7SCédric Le Goater     _FDT(offset);
256bf5615e7SCédric Le Goater     g_free(name);
257bf5615e7SCédric Le Goater 
258bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
259bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
260bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
261bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
262bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
263bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
264bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
265bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
266bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
267bf5615e7SCédric Le Goater     g_free(reg);
268bf5615e7SCédric Le Goater }
269bf5615e7SCédric Le Goater 
270eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
271e997040eSCédric Le Goater {
27240abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
273d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
274d2fd9612SCédric Le Goater     int i;
275d2fd9612SCédric Le Goater 
276b168a138SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
277967b7523SCédric Le Goater 
278d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
279d2fd9612SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
280d2fd9612SCédric Le Goater 
281b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
282bf5615e7SCédric Le Goater 
283bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
284b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
285d2fd9612SCédric Le Goater     }
286d2fd9612SCédric Le Goater 
287e997040eSCédric Le Goater     if (chip->ram_size) {
288b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
289e997040eSCédric Le Goater     }
290e997040eSCédric Le Goater }
291e997040eSCédric Le Goater 
292eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
293eb859a27SCédric Le Goater {
294eb859a27SCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
295eb859a27SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
296eb859a27SCédric Le Goater     int i;
297eb859a27SCédric Le Goater 
298eb859a27SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
299eb859a27SCédric Le Goater 
300eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
301eb859a27SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
302eb859a27SCédric Le Goater 
303eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
304eb859a27SCédric Le Goater     }
305eb859a27SCédric Le Goater 
306eb859a27SCédric Le Goater     if (chip->ram_size) {
307eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
308eb859a27SCédric Le Goater     }
309eb859a27SCédric Le Goater }
310eb859a27SCédric Le Goater 
311b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
312c5ffdcaeSCédric Le Goater {
313c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
314c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
315c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
316c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
317c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
318c5ffdcaeSCédric Le Goater     };
319c5ffdcaeSCédric Le Goater     char *name;
320c5ffdcaeSCédric Le Goater     int node;
321c5ffdcaeSCédric Le Goater 
322c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
323c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
324c5ffdcaeSCédric Le Goater     _FDT(node);
325c5ffdcaeSCédric Le Goater     g_free(name);
326c5ffdcaeSCédric Le Goater 
327c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
328c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
329c5ffdcaeSCédric Le Goater }
330c5ffdcaeSCédric Le Goater 
331b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
332cb228f5aSCédric Le Goater {
333cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
334cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
335cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
336cb228f5aSCédric Le Goater         cpu_to_be32(1),
337cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
338cb228f5aSCédric Le Goater         cpu_to_be32(8)
339cb228f5aSCédric Le Goater     };
340cb228f5aSCédric Le Goater     char *name;
341cb228f5aSCédric Le Goater     int node;
342cb228f5aSCédric Le Goater 
343cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
344cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
345cb228f5aSCédric Le Goater     _FDT(node);
346cb228f5aSCédric Le Goater     g_free(name);
347cb228f5aSCédric Le Goater 
348cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
349cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
350cb228f5aSCédric Le Goater                       sizeof(compatible))));
351cb228f5aSCédric Le Goater 
352cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
353cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
354cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
355cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
356cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
357cb228f5aSCédric Le Goater 
358cb228f5aSCédric Le Goater     /* This is needed by Linux */
359cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
360cb228f5aSCédric Le Goater }
361cb228f5aSCédric Le Goater 
362b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
36304f6c8b2SCédric Le Goater {
36404f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
36504f6c8b2SCédric Le Goater     uint32_t io_base;
36604f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
36704f6c8b2SCédric Le Goater         cpu_to_be32(1),
36804f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
36904f6c8b2SCédric Le Goater         cpu_to_be32(3)
37004f6c8b2SCédric Le Goater     };
37104f6c8b2SCédric Le Goater     uint32_t irq;
37204f6c8b2SCédric Le Goater     char *name;
37304f6c8b2SCédric Le Goater     int node;
37404f6c8b2SCédric Le Goater 
37504f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
37604f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
37704f6c8b2SCédric Le Goater 
37804f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
37904f6c8b2SCédric Le Goater 
38004f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
38104f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
38204f6c8b2SCédric Le Goater     _FDT(node);
38304f6c8b2SCédric Le Goater     g_free(name);
38404f6c8b2SCédric Le Goater 
3857032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
3867032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
3877032d92aSCédric Le Goater                       sizeof(compatible))));
38804f6c8b2SCédric Le Goater 
38904f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
39004f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
39104f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
39204f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
39304f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
39404f6c8b2SCédric Le Goater }
39504f6c8b2SCédric Le Goater 
396e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
397e7a3fee3SCédric Le Goater     void *fdt;
398e7a3fee3SCédric Le Goater     int offset;
399e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
400e7a3fee3SCédric Le Goater 
401b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
402e7a3fee3SCédric Le Goater {
403c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
404c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
405c5ffdcaeSCédric Le Goater 
406c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
407b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
408cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
409b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
41004f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
411b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
412c5ffdcaeSCédric Le Goater     } else {
413c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
414c5ffdcaeSCédric Le Goater                      d->ioport_id);
415c5ffdcaeSCédric Le Goater     }
416c5ffdcaeSCédric Le Goater 
417e7a3fee3SCédric Le Goater     return 0;
418e7a3fee3SCédric Le Goater }
419e7a3fee3SCédric Le Goater 
420bb7ab95cSCédric Le Goater static int pnv_chip_isa_offset(PnvChip *chip, void *fdt)
421e7a3fee3SCédric Le Goater {
422bb7ab95cSCédric Le Goater     char *name;
423bb7ab95cSCédric Le Goater     int offset;
424bb7ab95cSCédric Le Goater 
425bb7ab95cSCédric Le Goater     name = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
426bb7ab95cSCédric Le Goater                            (uint64_t) PNV_XSCOM_BASE(chip), PNV_XSCOM_LPC_BASE);
427bb7ab95cSCédric Le Goater     offset = fdt_path_offset(fdt, name);
428bb7ab95cSCédric Le Goater     g_free(name);
429bb7ab95cSCédric Le Goater     return offset;
430bb7ab95cSCédric Le Goater }
431bb7ab95cSCédric Le Goater 
432bb7ab95cSCédric Le Goater /* The default LPC bus of a multichip system is on chip 0. It's
433bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
434bb7ab95cSCédric Le Goater  */
435bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
436bb7ab95cSCédric Le Goater {
437bb7ab95cSCédric Le Goater     int isa_offset = pnv_chip_isa_offset(pnv->chips[0], fdt);
438e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
439e7a3fee3SCédric Le Goater         .fdt = fdt,
440bb7ab95cSCédric Le Goater         .offset = isa_offset,
441e7a3fee3SCédric Le Goater     };
442e7a3fee3SCédric Le Goater 
443bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
444bb7ab95cSCédric Le Goater 
445e7a3fee3SCédric Le Goater     /* ISA devices are not necessarily parented to the ISA bus so we
446e7a3fee3SCédric Le Goater      * can not use object_child_foreach() */
447bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
448bb7ab95cSCédric Le Goater                        &args);
449e7a3fee3SCédric Le Goater }
450e7a3fee3SCédric Le Goater 
451b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4529e933f4aSBenjamin Herrenschmidt {
4539e933f4aSBenjamin Herrenschmidt     const char plat_compat[] = "qemu,powernv\0ibm,powernv";
454b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
4559e933f4aSBenjamin Herrenschmidt     void *fdt;
4569e933f4aSBenjamin Herrenschmidt     char *buf;
4579e933f4aSBenjamin Herrenschmidt     int off;
458e997040eSCédric Le Goater     int i;
4599e933f4aSBenjamin Herrenschmidt 
4609e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
4619e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
4629e933f4aSBenjamin Herrenschmidt 
4639e933f4aSBenjamin Herrenschmidt     /* Root node */
4649e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
4659e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
4669e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
4679e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
4689e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat,
4699e933f4aSBenjamin Herrenschmidt                       sizeof(plat_compat))));
4709e933f4aSBenjamin Herrenschmidt 
4719e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
4729e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
4739e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
4749e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
4759e933f4aSBenjamin Herrenschmidt     }
4769e933f4aSBenjamin Herrenschmidt     g_free(buf);
4779e933f4aSBenjamin Herrenschmidt 
4789e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
4799e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
4809e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
4819e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
4829e933f4aSBenjamin Herrenschmidt     }
4839e933f4aSBenjamin Herrenschmidt 
4849e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
4859e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
4869e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
4879e933f4aSBenjamin Herrenschmidt 
4889e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
4899e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
4909e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
4919e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
4929e933f4aSBenjamin Herrenschmidt     }
4939e933f4aSBenjamin Herrenschmidt 
494e997040eSCédric Le Goater     /* Populate device tree for each chip */
495e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
496eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
497e997040eSCédric Le Goater     }
498e7a3fee3SCédric Le Goater 
499e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
500bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
501aeaef83dSCédric Le Goater 
502aeaef83dSCédric Le Goater     if (pnv->bmc) {
503b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
504aeaef83dSCédric Le Goater     }
505aeaef83dSCédric Le Goater 
5069e933f4aSBenjamin Herrenschmidt     return fdt;
5079e933f4aSBenjamin Herrenschmidt }
5089e933f4aSBenjamin Herrenschmidt 
509bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
510bce0b691SCédric Le Goater {
511b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
512bce0b691SCédric Le Goater 
513bce0b691SCédric Le Goater     if (pnv->bmc) {
514bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
515bce0b691SCédric Le Goater     }
516bce0b691SCédric Le Goater }
517bce0b691SCédric Le Goater 
518b168a138SCédric Le Goater static void pnv_reset(void)
5199e933f4aSBenjamin Herrenschmidt {
5209e933f4aSBenjamin Herrenschmidt     MachineState *machine = MACHINE(qdev_get_machine());
521b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5229e933f4aSBenjamin Herrenschmidt     void *fdt;
523aeaef83dSCédric Le Goater     Object *obj;
5249e933f4aSBenjamin Herrenschmidt 
5259e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5269e933f4aSBenjamin Herrenschmidt 
527aeaef83dSCédric Le Goater     /* OpenPOWER systems have a BMC, which can be defined on the
528aeaef83dSCédric Le Goater      * command line with:
529aeaef83dSCédric Le Goater      *
530aeaef83dSCédric Le Goater      *   -device ipmi-bmc-sim,id=bmc0
531aeaef83dSCédric Le Goater      *
532aeaef83dSCédric Le Goater      * This is the internal simulator but it could also be an external
533aeaef83dSCédric Le Goater      * BMC.
534aeaef83dSCédric Le Goater      */
535a1a636b8SCédric Le Goater     obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL);
536aeaef83dSCédric Le Goater     if (obj) {
537aeaef83dSCédric Le Goater         pnv->bmc = IPMI_BMC(obj);
538aeaef83dSCédric Le Goater     }
539aeaef83dSCédric Le Goater 
540b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5419e933f4aSBenjamin Herrenschmidt 
5429e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5439e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5449e933f4aSBenjamin Herrenschmidt 
5459e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5469e933f4aSBenjamin Herrenschmidt }
5479e933f4aSBenjamin Herrenschmidt 
54804026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5493495b6b6SCédric Le Goater {
55077864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
55177864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
55204026890SCédric Le Goater }
5533495b6b6SCédric Le Goater 
55404026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
55504026890SCédric Le Goater {
55677864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
55777864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
55804026890SCédric Le Goater }
5593495b6b6SCédric Le Goater 
56004026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
56104026890SCédric Le Goater {
56204026890SCédric Le Goater     return NULL;
56304026890SCédric Le Goater }
5643495b6b6SCédric Le Goater 
56504026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
56604026890SCédric Le Goater {
56704026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
5683495b6b6SCédric Le Goater }
5693495b6b6SCédric Le Goater 
570*d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
571*d8e4aad5SCédric Le Goater {
572*d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
573*d8e4aad5SCédric Le Goater 
574*d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
575*d8e4aad5SCédric Le Goater }
576*d8e4aad5SCédric Le Goater 
577*d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
578*d8e4aad5SCédric Le Goater {
579*d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
580*d8e4aad5SCédric Le Goater 
581*d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
582*d8e4aad5SCédric Le Goater }
583*d8e4aad5SCédric Le Goater 
584b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
5859e933f4aSBenjamin Herrenschmidt {
586b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5879e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
5889e933f4aSBenjamin Herrenschmidt     char *fw_filename;
5899e933f4aSBenjamin Herrenschmidt     long fw_size;
590e997040eSCédric Le Goater     int i;
591e997040eSCédric Le Goater     char *chip_typename;
5929e933f4aSBenjamin Herrenschmidt 
5939e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
594d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
5953dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
5969e933f4aSBenjamin Herrenschmidt     }
5979e933f4aSBenjamin Herrenschmidt 
5989e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
599b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6009e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6019e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6029e933f4aSBenjamin Herrenschmidt 
6039e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
6049e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
6059e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
6069e933f4aSBenjamin Herrenschmidt     }
6079e933f4aSBenjamin Herrenschmidt 
6089e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
60915fcedb2SCédric Le Goater     if (!fw_filename) {
61015fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
61115fcedb2SCédric Le Goater         exit(1);
61215fcedb2SCédric Le Goater     }
6139e933f4aSBenjamin Herrenschmidt 
6149e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
6159e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
61615fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
6179e933f4aSBenjamin Herrenschmidt         exit(1);
6189e933f4aSBenjamin Herrenschmidt     }
6199e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
6209e933f4aSBenjamin Herrenschmidt 
6219e933f4aSBenjamin Herrenschmidt     /* load kernel */
6229e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
6239e933f4aSBenjamin Herrenschmidt         long kernel_size;
6249e933f4aSBenjamin Herrenschmidt 
6259e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
626b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
6279e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
628802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
6299e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
6309e933f4aSBenjamin Herrenschmidt             exit(1);
6319e933f4aSBenjamin Herrenschmidt         }
6329e933f4aSBenjamin Herrenschmidt     }
6339e933f4aSBenjamin Herrenschmidt 
6349e933f4aSBenjamin Herrenschmidt     /* load initrd */
6359e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
6369e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
6379e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
638584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
6399e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
640802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
6419e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
6429e933f4aSBenjamin Herrenschmidt             exit(1);
6439e933f4aSBenjamin Herrenschmidt         }
6449e933f4aSBenjamin Herrenschmidt     }
645e997040eSCédric Le Goater 
646e997040eSCédric Le Goater     /* Create the processor chips */
6474a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
6487fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
6494a12c699SIgor Mammedov                                     i, machine->cpu_type);
650e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
6514a12c699SIgor Mammedov         error_report("invalid CPU model '%.*s' for %s machine",
6524a12c699SIgor Mammedov                      i, machine->cpu_type, MACHINE_GET_CLASS(machine)->name);
653e997040eSCédric Le Goater         exit(1);
654e997040eSCédric Le Goater     }
655e997040eSCédric Le Goater 
656e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
657e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
658e997040eSCédric Le Goater         char chip_name[32];
659e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
660e997040eSCédric Le Goater 
661e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
662e997040eSCédric Le Goater 
663e997040eSCédric Le Goater         /* TODO: put all the memory in one node on chip 0 until we find a
664e997040eSCédric Le Goater          * way to specify different ranges for each chip
665e997040eSCédric Le Goater          */
666e997040eSCédric Le Goater         if (i == 0) {
667e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
668e997040eSCédric Le Goater                                     &error_fatal);
669e997040eSCédric Le Goater         }
670e997040eSCédric Le Goater 
671e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
672e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
673e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
674e997040eSCédric Le Goater                                 &error_fatal);
675397a79e7SCédric Le Goater         object_property_set_int(chip, smp_cores, "nr-cores", &error_fatal);
676e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
677e997040eSCédric Le Goater     }
678e997040eSCédric Le Goater     g_free(chip_typename);
6793495b6b6SCédric Le Goater 
6803495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
68104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
6823495b6b6SCédric Le Goater 
6833495b6b6SCédric Le Goater     /* Create serial port */
684def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
6853495b6b6SCédric Le Goater 
6863495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
6876c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
688bce0b691SCédric Le Goater 
689bce0b691SCédric Le Goater     /* OpenPOWER systems use a IPMI SEL Event message to notify the
690bce0b691SCédric Le Goater      * host to powerdown */
691bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
692bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
693e997040eSCédric Le Goater }
694e997040eSCédric Le Goater 
695631adaffSCédric Le Goater /*
696631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
697631adaffSCédric Le Goater  *   22:24  Chip ID
698631adaffSCédric Le Goater  *   25:28  Core number
699631adaffSCédric Le Goater  *   29:31  Thread ID
700631adaffSCédric Le Goater  */
701631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
702631adaffSCédric Le Goater {
703631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
704631adaffSCédric Le Goater }
705631adaffSCédric Le Goater 
7068fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
707d35aefa9SCédric Le Goater                                         Error **errp)
708d35aefa9SCédric Le Goater {
7098fa1f4efSCédric Le Goater     Error *local_err = NULL;
7108fa1f4efSCédric Le Goater     Object *obj;
7118907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
7128fa1f4efSCédric Le Goater 
7138fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
7148fa1f4efSCédric Le Goater                      &local_err);
7158fa1f4efSCédric Le Goater     if (local_err) {
7168fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
7178fa1f4efSCédric Le Goater         return;
7188fa1f4efSCédric Le Goater     }
7198fa1f4efSCédric Le Goater 
720956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
721d35aefa9SCédric Le Goater }
722d35aefa9SCédric Le Goater 
723631adaffSCédric Le Goater /*
724631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
725631adaffSCédric Le Goater  *   49:52  Node ID
726631adaffSCédric Le Goater  *   53:55  Chip ID
727631adaffSCédric Le Goater  *   56     Reserved - Read as zero
728631adaffSCédric Le Goater  *   57:61  Core number
729631adaffSCédric Le Goater  *   62:63  Thread ID
730631adaffSCédric Le Goater  *
731631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
732631adaffSCédric Le Goater  */
733631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
734631adaffSCédric Le Goater {
735631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
736631adaffSCédric Le Goater }
737631adaffSCédric Le Goater 
7388fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
739d35aefa9SCédric Le Goater                                         Error **errp)
740d35aefa9SCédric Le Goater {
7412dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
7422dfa91a2SCédric Le Goater     Error *local_err = NULL;
7432dfa91a2SCédric Le Goater     Object *obj;
7442dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
7452dfa91a2SCédric Le Goater 
7462dfa91a2SCédric Le Goater     /*
7472dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
7482dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
7492dfa91a2SCédric Le Goater      * only used at runtime.
7502dfa91a2SCédric Le Goater      */
7512dfa91a2SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), errp);
7522dfa91a2SCédric Le Goater     if (local_err) {
7532dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
7548fa1f4efSCédric Le Goater         return;
755d35aefa9SCédric Le Goater     }
756d35aefa9SCédric Le Goater 
7572dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
7582dfa91a2SCédric Le Goater }
7592dfa91a2SCédric Le Goater 
760397a79e7SCédric Le Goater /* Allowed core identifiers on a POWER8 Processor Chip :
761397a79e7SCédric Le Goater  *
762397a79e7SCédric Le Goater  * <EX0 reserved>
763397a79e7SCédric Le Goater  *  EX1  - Venice only
764397a79e7SCédric Le Goater  *  EX2  - Venice only
765397a79e7SCédric Le Goater  *  EX3  - Venice only
766397a79e7SCédric Le Goater  *  EX4
767397a79e7SCédric Le Goater  *  EX5
768397a79e7SCédric Le Goater  *  EX6
769397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
770397a79e7SCédric Le Goater  *  EX9  - Venice only
771397a79e7SCédric Le Goater  *  EX10 - Venice only
772397a79e7SCédric Le Goater  *  EX11 - Venice only
773397a79e7SCédric Le Goater  *  EX12
774397a79e7SCédric Le Goater  *  EX13
775397a79e7SCédric Le Goater  *  EX14
776397a79e7SCédric Le Goater  * <EX15 reserved>
777397a79e7SCédric Le Goater  */
778397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
779397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
780397a79e7SCédric Le Goater 
781397a79e7SCédric Le Goater /*
78209279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
783397a79e7SCédric Le Goater  */
78409279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
785397a79e7SCédric Le Goater 
78677864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
78777864267SCédric Le Goater {
78877864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
78977864267SCédric Le Goater 
790f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
791f6d4dca8SThomas Huth                             TYPE_PNV_PSI, &error_abort, NULL);
79277864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
79377864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
79477864267SCédric Le Goater 
795f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
796f6d4dca8SThomas Huth                             TYPE_PNV_LPC, &error_abort, NULL);
79777864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
79877864267SCédric Le Goater                                    OBJECT(&chip8->psi), &error_abort);
79977864267SCédric Le Goater 
800f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
801f6d4dca8SThomas Huth                             TYPE_PNV_OCC, &error_abort, NULL);
80277864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->occ), "psi",
80377864267SCédric Le Goater                                    OBJECT(&chip8->psi), &error_abort);
80477864267SCédric Le Goater }
80577864267SCédric Le Goater 
80677864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
80777864267SCédric Le Goater  {
80877864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
80977864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
81077864267SCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
81177864267SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
81277864267SCédric Le Goater     int i, j;
81377864267SCédric Le Goater     char *name;
81477864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
81577864267SCédric Le Goater 
81677864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
81777864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
81877864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
81977864267SCédric Le Goater     g_free(name);
82077864267SCédric Le Goater 
82177864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
82277864267SCédric Le Goater 
82377864267SCédric Le Goater     /* Map the ICP registers for each thread */
82477864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
82577864267SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
82677864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
82777864267SCédric Le Goater 
82877864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
82977864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
83077864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
83177864267SCédric Le Goater 
83277864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
83377864267SCédric Le Goater                                         &icp->mmio);
83477864267SCédric Le Goater         }
83577864267SCédric Le Goater     }
83677864267SCédric Le Goater }
83777864267SCédric Le Goater 
83877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
83977864267SCédric Le Goater {
84077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
84177864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
84277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
84377864267SCédric Le Goater     Error *local_err = NULL;
84477864267SCédric Le Goater 
84577864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
84677864267SCédric Le Goater     if (local_err) {
84777864267SCédric Le Goater         error_propagate(errp, local_err);
84877864267SCédric Le Goater         return;
84977864267SCédric Le Goater     }
85077864267SCédric Le Goater 
85177864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
85277864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
85377864267SCédric Le Goater                             "bar", &error_fatal);
85477864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
85577864267SCédric Le Goater     if (local_err) {
85677864267SCédric Le Goater         error_propagate(errp, local_err);
85777864267SCédric Le Goater         return;
85877864267SCédric Le Goater     }
85977864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE, &chip8->psi.xscom_regs);
86077864267SCédric Le Goater 
86177864267SCédric Le Goater     /* Create LPC controller */
86277864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
86377864267SCédric Le Goater                              &error_fatal);
86477864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
86577864267SCédric Le Goater 
86677864267SCédric Le Goater     /* Interrupt Management Area. This is the memory region holding
86777864267SCédric Le Goater      * all the Interrupt Control Presenter (ICP) registers */
86877864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
86977864267SCédric Le Goater     if (local_err) {
87077864267SCédric Le Goater         error_propagate(errp, local_err);
87177864267SCédric Le Goater         return;
87277864267SCédric Le Goater     }
87377864267SCédric Le Goater 
87477864267SCédric Le Goater     /* Create the simplified OCC model */
87577864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
87677864267SCédric Le Goater     if (local_err) {
87777864267SCédric Le Goater         error_propagate(errp, local_err);
87877864267SCédric Le Goater         return;
87977864267SCédric Le Goater     }
88077864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
88177864267SCédric Le Goater }
88277864267SCédric Le Goater 
883e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
884e997040eSCédric Le Goater {
885e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
886e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
887e997040eSCédric Le Goater 
888e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
889e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
890397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
891631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
892d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
89304026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
894eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
895*d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
896967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
897e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
89877864267SCédric Le Goater 
89977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
90077864267SCédric Le Goater                                     &k->parent_realize);
901e997040eSCédric Le Goater }
902e997040eSCédric Le Goater 
903e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
904e997040eSCédric Le Goater {
905e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
906e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
907e997040eSCédric Le Goater 
908e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
909e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
910397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
911631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
912d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
91304026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
914eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
915*d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
916967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
917e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
91877864267SCédric Le Goater 
91977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
92077864267SCédric Le Goater                                     &k->parent_realize);
921e997040eSCédric Le Goater }
922e997040eSCédric Le Goater 
923e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
924e997040eSCédric Le Goater {
925e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
926e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
927e997040eSCédric Le Goater 
928e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
929e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
930397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
931631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
932d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
93304026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
934eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
935*d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
936967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
937e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
93877864267SCédric Le Goater 
93977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
94077864267SCédric Le Goater                                     &k->parent_realize);
94177864267SCédric Le Goater }
94277864267SCédric Le Goater 
94377864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
94477864267SCédric Le Goater {
9452dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
9462dfa91a2SCédric Le Goater 
9472dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
9482dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
9492dfa91a2SCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj,
9502dfa91a2SCédric Le Goater                                    &error_abort);
95177864267SCédric Le Goater }
95277864267SCédric Le Goater 
95377864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
95477864267SCédric Le Goater {
95577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
9562dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
9572dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
95877864267SCédric Le Goater     Error *local_err = NULL;
95977864267SCédric Le Goater 
96077864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
96177864267SCédric Le Goater     if (local_err) {
96277864267SCédric Le Goater         error_propagate(errp, local_err);
96377864267SCédric Le Goater         return;
96477864267SCédric Le Goater     }
9652dfa91a2SCédric Le Goater 
9662dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
9672dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
9682dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
9692dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
9702dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
9712dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
9722dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
9732dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
9742dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
9752dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
9762dfa91a2SCédric Le Goater                              &local_err);
9772dfa91a2SCédric Le Goater     if (local_err) {
9782dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9792dfa91a2SCédric Le Goater         return;
9802dfa91a2SCédric Le Goater     }
9812dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
9822dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
983e997040eSCédric Le Goater }
984e997040eSCédric Le Goater 
985e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
986e997040eSCédric Le Goater {
987e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
988e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
989e997040eSCédric Le Goater 
990e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
99183028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
992397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
993631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
994d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
99504026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
996eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
997*d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
998967b7523SCédric Le Goater     k->xscom_base = 0x00603fc00000000ull;
999e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
100077864267SCédric Le Goater 
100177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
100277864267SCédric Le Goater                                     &k->parent_realize);
1003e997040eSCédric Le Goater }
1004e997040eSCédric Le Goater 
1005397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1006397a79e7SCédric Le Goater {
1007397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1008397a79e7SCédric Le Goater     int cores_max;
1009397a79e7SCédric Le Goater 
1010397a79e7SCédric Le Goater     /*
1011397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1012397a79e7SCédric Le Goater      * the chip class
1013397a79e7SCédric Le Goater      */
1014397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1015397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1016397a79e7SCédric Le Goater     }
1017397a79e7SCédric Le Goater 
1018397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1019397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1020397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1021397a79e7SCédric Le Goater                    chip->cores_mask);
1022397a79e7SCédric Le Goater         return;
1023397a79e7SCédric Le Goater     }
1024397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1025397a79e7SCédric Le Goater 
1026397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
102727d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1028397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1029397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1030397a79e7SCédric Le Goater                    cores_max);
1031397a79e7SCédric Le Goater         return;
1032397a79e7SCédric Le Goater     }
1033397a79e7SCédric Le Goater }
1034397a79e7SCédric Le Goater 
103577864267SCédric Le Goater static void pnv_chip_instance_init(Object *obj)
1036967b7523SCédric Le Goater {
103777864267SCédric Le Goater     PNV_CHIP(obj)->xscom_base = PNV_CHIP_GET_CLASS(obj)->xscom_base;
1038bf5615e7SCédric Le Goater }
1039bf5615e7SCédric Le Goater 
104051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1041e997040eSCédric Le Goater {
1042397a79e7SCédric Le Goater     Error *error = NULL;
1043d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
104440abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1045d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
1046d2fd9612SCédric Le Goater     int i, core_hwid;
1047397a79e7SCédric Le Goater 
1048d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1049d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1050d2fd9612SCédric Le Goater         return;
1051d2fd9612SCédric Le Goater     }
1052d2fd9612SCédric Le Goater 
1053d2fd9612SCédric Le Goater     /* Cores */
1054397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1055397a79e7SCédric Le Goater     if (error) {
1056397a79e7SCédric Le Goater         error_propagate(errp, error);
1057397a79e7SCédric Le Goater         return;
1058397a79e7SCédric Le Goater     }
1059d2fd9612SCédric Le Goater 
1060d2fd9612SCédric Le Goater     chip->cores = g_malloc0(typesize * chip->nr_cores);
1061d2fd9612SCédric Le Goater 
1062d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1063d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1064d2fd9612SCédric Le Goater         char core_name[32];
1065d2fd9612SCédric Le Goater         void *pnv_core = chip->cores + i * typesize;
1066c035851aSCédric Le Goater         uint64_t xscom_core_base;
1067d2fd9612SCédric Le Goater 
1068d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1069d2fd9612SCédric Le Goater             continue;
1070d2fd9612SCédric Le Goater         }
1071d2fd9612SCédric Le Goater 
1072d2fd9612SCédric Le Goater         object_initialize(pnv_core, typesize, typename);
1073d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1074d2fd9612SCédric Le Goater         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
1075d2fd9612SCédric Le Goater                                   &error_fatal);
1076d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads",
1077d2fd9612SCédric Le Goater                                 &error_fatal);
1078d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1079d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1080d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1081d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1082d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1083d35aefa9SCédric Le Goater         object_property_add_const_link(OBJECT(pnv_core), "chip",
1084d35aefa9SCédric Le Goater                                        OBJECT(chip), &error_fatal);
1085d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1086d2fd9612SCédric Le Goater                                  &error_fatal);
1087d2fd9612SCédric Le Goater         object_unref(OBJECT(pnv_core));
108824ece072SCédric Le Goater 
108924ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1090c035851aSCédric Le Goater         if (!pnv_chip_is_power9(chip)) {
1091c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
1092c035851aSCédric Le Goater         } else {
1093c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_P9_EC_BASE(core_hwid);
1094c035851aSCédric Le Goater         }
1095c035851aSCédric Le Goater 
1096c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
109724ece072SCédric Le Goater                                 &PNV_CORE(pnv_core)->xscom_regs);
1098d2fd9612SCédric Le Goater         i++;
1099d2fd9612SCédric Le Goater     }
110051c04728SCédric Le Goater }
110151c04728SCédric Le Goater 
110251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
110351c04728SCédric Le Goater {
110451c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
110551c04728SCédric Le Goater     Error *error = NULL;
110651c04728SCédric Le Goater 
110751c04728SCédric Le Goater     /* XSCOM bridge */
110851c04728SCédric Le Goater     pnv_xscom_realize(chip, &error);
110951c04728SCédric Le Goater     if (error) {
111051c04728SCédric Le Goater         error_propagate(errp, error);
111151c04728SCédric Le Goater         return;
111251c04728SCédric Le Goater     }
111351c04728SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
111451c04728SCédric Le Goater 
111551c04728SCédric Le Goater     /* Cores */
111651c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
111751c04728SCédric Le Goater     if (error) {
111851c04728SCédric Le Goater         error_propagate(errp, error);
111951c04728SCédric Le Goater         return;
112051c04728SCédric Le Goater     }
1121e997040eSCédric Le Goater }
1122e997040eSCédric Le Goater 
1123e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1124e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1125e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1126e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1127397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1128397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1129e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1130e997040eSCédric Le Goater };
1131e997040eSCédric Le Goater 
1132e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1133e997040eSCédric Le Goater {
1134e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1135e997040eSCédric Le Goater 
11369d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1137e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1138e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1139e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1140e997040eSCédric Le Goater }
1141e997040eSCédric Le Goater 
114254f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
114354f59d78SCédric Le Goater {
1144b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
114554f59d78SCédric Le Goater     int i;
114654f59d78SCédric Le Goater 
114754f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
114877864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
114977864267SCédric Le Goater 
115077864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
115177864267SCédric Le Goater             return &chip8->psi.ics;
115254f59d78SCédric Le Goater         }
115354f59d78SCédric Le Goater     }
115454f59d78SCédric Le Goater     return NULL;
115554f59d78SCédric Le Goater }
115654f59d78SCédric Le Goater 
115754f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
115854f59d78SCédric Le Goater {
1159b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
116054f59d78SCédric Le Goater     int i;
116154f59d78SCédric Le Goater 
116254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
116377864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
116477864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
116554f59d78SCédric Le Goater     }
116654f59d78SCédric Le Goater }
116754f59d78SCédric Le Goater 
116836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
116936fc6f08SCédric Le Goater {
117036fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
117136fc6f08SCédric Le Goater 
1172956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
117336fc6f08SCédric Le Goater }
117436fc6f08SCédric Le Goater 
117547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
117647fea43aSCédric Le Goater                                Monitor *mon)
117747fea43aSCédric Le Goater {
1178b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
117954f59d78SCédric Le Goater     int i;
118047fea43aSCédric Le Goater     CPUState *cs;
118147fea43aSCédric Le Goater 
118247fea43aSCédric Le Goater     CPU_FOREACH(cs) {
118347fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
118447fea43aSCédric Le Goater 
1185*d8e4aad5SCédric Le Goater         if (pnv_chip_is_power9(pnv->chips[0])) {
1186*d8e4aad5SCédric Le Goater             xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
1187*d8e4aad5SCédric Le Goater         } else {
1188956b8f46SCédric Le Goater             icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
118947fea43aSCédric Le Goater         }
1190*d8e4aad5SCédric Le Goater     }
119154f59d78SCédric Le Goater 
119254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1193*d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
119454f59d78SCédric Le Goater     }
119547fea43aSCédric Le Goater }
119647fea43aSCédric Le Goater 
1197e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1198e997040eSCédric Le Goater                               void *opaque, Error **errp)
1199e997040eSCédric Le Goater {
1200b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1201e997040eSCédric Le Goater }
1202e997040eSCédric Le Goater 
1203e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1204e997040eSCédric Le Goater                               void *opaque, Error **errp)
1205e997040eSCédric Le Goater {
1206b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1207e997040eSCédric Le Goater     uint32_t num_chips;
1208e997040eSCédric Le Goater     Error *local_err = NULL;
1209e997040eSCédric Le Goater 
1210e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1211e997040eSCédric Le Goater     if (local_err) {
1212e997040eSCédric Le Goater         error_propagate(errp, local_err);
1213e997040eSCédric Le Goater         return;
1214e997040eSCédric Le Goater     }
1215e997040eSCédric Le Goater 
1216e997040eSCédric Le Goater     /*
1217e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1218e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1219e997040eSCédric Le Goater      */
1220e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1221e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1222e997040eSCédric Le Goater         return;
1223e997040eSCédric Le Goater     }
1224e997040eSCédric Le Goater 
1225e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1226e997040eSCédric Le Goater }
1227e997040eSCédric Le Goater 
122877864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1229e997040eSCédric Le Goater {
1230b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1231e997040eSCédric Le Goater     pnv->num_chips = 1;
1232e997040eSCédric Le Goater }
1233e997040eSCédric Le Goater 
1234b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1235e997040eSCédric Le Goater {
12361e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1237e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1238e997040eSCédric Le Goater                               NULL, NULL, NULL);
1239e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1240e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1241e997040eSCédric Le Goater                               NULL);
12429e933f4aSBenjamin Herrenschmidt }
12439e933f4aSBenjamin Herrenschmidt 
1244b168a138SCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
12459e933f4aSBenjamin Herrenschmidt {
12469e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
124736fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
124847fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
12499e933f4aSBenjamin Herrenschmidt 
12509e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1251b168a138SCédric Le Goater     mc->init = pnv_init;
1252b168a138SCédric Le Goater     mc->reset = pnv_reset;
12539e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
12544a12c699SIgor Mammedov     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
12559e933f4aSBenjamin Herrenschmidt     mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
12569e933f4aSBenjamin Herrenschmidt                                       * storage */
12579e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
12589e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1259d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 1 * GiB;
126036fc6f08SCédric Le Goater     xic->icp_get = pnv_icp_get;
126154f59d78SCédric Le Goater     xic->ics_get = pnv_ics_get;
126254f59d78SCédric Le Goater     xic->ics_resend = pnv_ics_resend;
126347fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1264e997040eSCédric Le Goater 
1265b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
12669e933f4aSBenjamin Herrenschmidt }
12679e933f4aSBenjamin Herrenschmidt 
126877864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1269beba5c0fSIgor Mammedov     {                                             \
1270beba5c0fSIgor Mammedov         .name          = type,                    \
1271beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
127277864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
127377864267SCédric Le Goater     }
127477864267SCédric Le Goater 
127577864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
127677864267SCédric Le Goater     {                                             \
127777864267SCédric Le Goater         .name          = type,                    \
127877864267SCédric Le Goater         .class_init    = class_initfn,            \
127977864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1280beba5c0fSIgor Mammedov     }
1281beba5c0fSIgor Mammedov 
1282beba5c0fSIgor Mammedov static const TypeInfo types[] = {
1283beba5c0fSIgor Mammedov     {
1284b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
12859e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
12869e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
128777864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1288b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
128936fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
129036fc6f08SCédric Le Goater             { TYPE_XICS_FABRIC },
129147fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
129236fc6f08SCédric Le Goater             { },
129336fc6f08SCédric Le Goater         },
1294beba5c0fSIgor Mammedov     },
1295beba5c0fSIgor Mammedov     {
1296beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1297beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1298beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
129977864267SCédric Le Goater         .instance_init = pnv_chip_instance_init,
1300beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1301beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1302beba5c0fSIgor Mammedov         .abstract      = true,
1303beba5c0fSIgor Mammedov     },
130477864267SCédric Le Goater 
130577864267SCédric Le Goater     /*
130677864267SCédric Le Goater      * P9 chip and variants
130777864267SCédric Le Goater      */
130877864267SCédric Le Goater     {
130977864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
131077864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
131177864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
131277864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
131377864267SCédric Le Goater     },
131477864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
131577864267SCédric Le Goater 
131677864267SCédric Le Goater     /*
131777864267SCédric Le Goater      * P8 chip and variants
131877864267SCédric Le Goater      */
131977864267SCédric Le Goater     {
132077864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
132177864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
132277864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
132377864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
132477864267SCédric Le Goater     },
132577864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
132677864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
132777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1328beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
13299e933f4aSBenjamin Herrenschmidt };
13309e933f4aSBenjamin Herrenschmidt 
1331beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1332