xref: /qemu/hw/ppc/pnv.c (revision ae856055)
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 
570d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
571d8e4aad5SCédric Le Goater {
572d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
573d8e4aad5SCédric Le Goater 
574d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
575d8e4aad5SCédric Le Goater }
576d8e4aad5SCédric Le Goater 
577d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
578d8e4aad5SCédric Le Goater {
579d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
580d8e4aad5SCédric Le Goater 
581d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
582d8e4aad5SCédric Le Goater }
583d8e4aad5SCé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),
791*ae856055SCédric Le Goater                             TYPE_PNV8_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);
843*ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
84477864267SCédric Le Goater     Error *local_err = NULL;
84577864267SCédric Le Goater 
84677864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
84777864267SCédric Le Goater     if (local_err) {
84877864267SCédric Le Goater         error_propagate(errp, local_err);
84977864267SCédric Le Goater         return;
85077864267SCédric Le Goater     }
85177864267SCédric Le Goater 
85277864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
85377864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
85477864267SCédric Le Goater                             "bar", &error_fatal);
85577864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
85677864267SCédric Le Goater     if (local_err) {
85777864267SCédric Le Goater         error_propagate(errp, local_err);
85877864267SCédric Le Goater         return;
85977864267SCédric Le Goater     }
860*ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
861*ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
86277864267SCédric Le Goater 
86377864267SCédric Le Goater     /* Create LPC controller */
86477864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
86577864267SCédric Le Goater                              &error_fatal);
86677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
86777864267SCédric Le Goater 
86877864267SCédric Le Goater     /* Interrupt Management Area. This is the memory region holding
86977864267SCédric Le Goater      * all the Interrupt Control Presenter (ICP) registers */
87077864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
87177864267SCédric Le Goater     if (local_err) {
87277864267SCédric Le Goater         error_propagate(errp, local_err);
87377864267SCédric Le Goater         return;
87477864267SCédric Le Goater     }
87577864267SCédric Le Goater 
87677864267SCédric Le Goater     /* Create the simplified OCC model */
87777864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
87877864267SCédric Le Goater     if (local_err) {
87977864267SCédric Le Goater         error_propagate(errp, local_err);
88077864267SCédric Le Goater         return;
88177864267SCédric Le Goater     }
88277864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
88377864267SCédric Le Goater }
88477864267SCédric Le Goater 
885e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
886e997040eSCédric Le Goater {
887e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
888e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
889e997040eSCédric Le Goater 
890e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
891e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
892397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
893631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
894d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
89504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
896eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
897d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
898967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
899e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
90077864267SCédric Le Goater 
90177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
90277864267SCédric Le Goater                                     &k->parent_realize);
903e997040eSCédric Le Goater }
904e997040eSCédric Le Goater 
905e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
906e997040eSCédric Le Goater {
907e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
908e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
909e997040eSCédric Le Goater 
910e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
911e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
912397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
913631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
914d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
91504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
916eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
917d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
918967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
919e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
92077864267SCédric Le Goater 
92177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
92277864267SCédric Le Goater                                     &k->parent_realize);
923e997040eSCédric Le Goater }
924e997040eSCédric Le Goater 
925e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
926e997040eSCédric Le Goater {
927e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
928e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
929e997040eSCédric Le Goater 
930e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
931e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
932397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
933631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
934d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
93504026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
936eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
937d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
938967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
939e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
94077864267SCédric Le Goater 
94177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
94277864267SCédric Le Goater                                     &k->parent_realize);
94377864267SCédric Le Goater }
94477864267SCédric Le Goater 
94577864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
94677864267SCédric Le Goater {
9472dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
9482dfa91a2SCédric Le Goater 
9492dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
9502dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
9512dfa91a2SCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj,
9522dfa91a2SCédric Le Goater                                    &error_abort);
95377864267SCédric Le Goater }
95477864267SCédric Le Goater 
95577864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
95677864267SCédric Le Goater {
95777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
9582dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
9592dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
96077864267SCédric Le Goater     Error *local_err = NULL;
96177864267SCédric Le Goater 
96277864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
96377864267SCédric Le Goater     if (local_err) {
96477864267SCédric Le Goater         error_propagate(errp, local_err);
96577864267SCédric Le Goater         return;
96677864267SCédric Le Goater     }
9672dfa91a2SCédric Le Goater 
9682dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
9692dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
9702dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
9712dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
9722dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
9732dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
9742dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
9752dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
9762dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
9772dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
9782dfa91a2SCédric Le Goater                              &local_err);
9792dfa91a2SCédric Le Goater     if (local_err) {
9802dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9812dfa91a2SCédric Le Goater         return;
9822dfa91a2SCédric Le Goater     }
9832dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
9842dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
985e997040eSCédric Le Goater }
986e997040eSCédric Le Goater 
987e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
988e997040eSCédric Le Goater {
989e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
990e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
991e997040eSCédric Le Goater 
992e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
99383028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
994397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
995631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
996d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
99704026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
998eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
999d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1000967b7523SCédric Le Goater     k->xscom_base = 0x00603fc00000000ull;
1001e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
100277864267SCédric Le Goater 
100377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
100477864267SCédric Le Goater                                     &k->parent_realize);
1005e997040eSCédric Le Goater }
1006e997040eSCédric Le Goater 
1007397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1008397a79e7SCédric Le Goater {
1009397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1010397a79e7SCédric Le Goater     int cores_max;
1011397a79e7SCédric Le Goater 
1012397a79e7SCédric Le Goater     /*
1013397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1014397a79e7SCédric Le Goater      * the chip class
1015397a79e7SCédric Le Goater      */
1016397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1017397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1018397a79e7SCédric Le Goater     }
1019397a79e7SCédric Le Goater 
1020397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1021397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1022397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1023397a79e7SCédric Le Goater                    chip->cores_mask);
1024397a79e7SCédric Le Goater         return;
1025397a79e7SCédric Le Goater     }
1026397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1027397a79e7SCédric Le Goater 
1028397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
102927d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1030397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1031397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1032397a79e7SCédric Le Goater                    cores_max);
1033397a79e7SCédric Le Goater         return;
1034397a79e7SCédric Le Goater     }
1035397a79e7SCédric Le Goater }
1036397a79e7SCédric Le Goater 
103777864267SCédric Le Goater static void pnv_chip_instance_init(Object *obj)
1038967b7523SCédric Le Goater {
103977864267SCédric Le Goater     PNV_CHIP(obj)->xscom_base = PNV_CHIP_GET_CLASS(obj)->xscom_base;
1040bf5615e7SCédric Le Goater }
1041bf5615e7SCédric Le Goater 
104251c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1043e997040eSCédric Le Goater {
1044397a79e7SCédric Le Goater     Error *error = NULL;
1045d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
104640abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1047d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
1048d2fd9612SCédric Le Goater     int i, core_hwid;
1049397a79e7SCédric Le Goater 
1050d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1051d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1052d2fd9612SCédric Le Goater         return;
1053d2fd9612SCédric Le Goater     }
1054d2fd9612SCédric Le Goater 
1055d2fd9612SCédric Le Goater     /* Cores */
1056397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1057397a79e7SCédric Le Goater     if (error) {
1058397a79e7SCédric Le Goater         error_propagate(errp, error);
1059397a79e7SCédric Le Goater         return;
1060397a79e7SCédric Le Goater     }
1061d2fd9612SCédric Le Goater 
1062d2fd9612SCédric Le Goater     chip->cores = g_malloc0(typesize * chip->nr_cores);
1063d2fd9612SCédric Le Goater 
1064d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1065d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1066d2fd9612SCédric Le Goater         char core_name[32];
1067d2fd9612SCédric Le Goater         void *pnv_core = chip->cores + i * typesize;
1068c035851aSCédric Le Goater         uint64_t xscom_core_base;
1069d2fd9612SCédric Le Goater 
1070d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1071d2fd9612SCédric Le Goater             continue;
1072d2fd9612SCédric Le Goater         }
1073d2fd9612SCédric Le Goater 
1074d2fd9612SCédric Le Goater         object_initialize(pnv_core, typesize, typename);
1075d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1076d2fd9612SCédric Le Goater         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
1077d2fd9612SCédric Le Goater                                   &error_fatal);
1078d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads",
1079d2fd9612SCédric Le Goater                                 &error_fatal);
1080d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1081d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1082d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1083d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1084d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1085d35aefa9SCédric Le Goater         object_property_add_const_link(OBJECT(pnv_core), "chip",
1086d35aefa9SCédric Le Goater                                        OBJECT(chip), &error_fatal);
1087d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1088d2fd9612SCédric Le Goater                                  &error_fatal);
1089d2fd9612SCédric Le Goater         object_unref(OBJECT(pnv_core));
109024ece072SCédric Le Goater 
109124ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1092c035851aSCédric Le Goater         if (!pnv_chip_is_power9(chip)) {
1093c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
1094c035851aSCédric Le Goater         } else {
1095c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_P9_EC_BASE(core_hwid);
1096c035851aSCédric Le Goater         }
1097c035851aSCédric Le Goater 
1098c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
109924ece072SCédric Le Goater                                 &PNV_CORE(pnv_core)->xscom_regs);
1100d2fd9612SCédric Le Goater         i++;
1101d2fd9612SCédric Le Goater     }
110251c04728SCédric Le Goater }
110351c04728SCédric Le Goater 
110451c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
110551c04728SCédric Le Goater {
110651c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
110751c04728SCédric Le Goater     Error *error = NULL;
110851c04728SCédric Le Goater 
110951c04728SCédric Le Goater     /* XSCOM bridge */
111051c04728SCédric Le Goater     pnv_xscom_realize(chip, &error);
111151c04728SCédric Le Goater     if (error) {
111251c04728SCédric Le Goater         error_propagate(errp, error);
111351c04728SCédric Le Goater         return;
111451c04728SCédric Le Goater     }
111551c04728SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
111651c04728SCédric Le Goater 
111751c04728SCédric Le Goater     /* Cores */
111851c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
111951c04728SCédric Le Goater     if (error) {
112051c04728SCédric Le Goater         error_propagate(errp, error);
112151c04728SCédric Le Goater         return;
112251c04728SCédric Le Goater     }
1123e997040eSCédric Le Goater }
1124e997040eSCédric Le Goater 
1125e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1126e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1127e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1128e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1129397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1130397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1131e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1132e997040eSCédric Le Goater };
1133e997040eSCédric Le Goater 
1134e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1135e997040eSCédric Le Goater {
1136e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1137e997040eSCédric Le Goater 
11389d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1139e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1140e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1141e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1142e997040eSCédric Le Goater }
1143e997040eSCédric Le Goater 
114454f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
114554f59d78SCédric Le Goater {
1146b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
114754f59d78SCédric Le Goater     int i;
114854f59d78SCédric Le Goater 
114954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
115077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
115177864267SCédric Le Goater 
115277864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
115377864267SCédric Le Goater             return &chip8->psi.ics;
115454f59d78SCédric Le Goater         }
115554f59d78SCédric Le Goater     }
115654f59d78SCédric Le Goater     return NULL;
115754f59d78SCédric Le Goater }
115854f59d78SCédric Le Goater 
115954f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
116054f59d78SCédric Le Goater {
1161b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
116254f59d78SCédric Le Goater     int i;
116354f59d78SCédric Le Goater 
116454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
116577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
116677864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
116754f59d78SCédric Le Goater     }
116854f59d78SCédric Le Goater }
116954f59d78SCédric Le Goater 
117036fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
117136fc6f08SCédric Le Goater {
117236fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
117336fc6f08SCédric Le Goater 
1174956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
117536fc6f08SCédric Le Goater }
117636fc6f08SCédric Le Goater 
117747fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
117847fea43aSCédric Le Goater                                Monitor *mon)
117947fea43aSCédric Le Goater {
1180b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
118154f59d78SCédric Le Goater     int i;
118247fea43aSCédric Le Goater     CPUState *cs;
118347fea43aSCédric Le Goater 
118447fea43aSCédric Le Goater     CPU_FOREACH(cs) {
118547fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
118647fea43aSCédric Le Goater 
1187d8e4aad5SCédric Le Goater         if (pnv_chip_is_power9(pnv->chips[0])) {
1188d8e4aad5SCédric Le Goater             xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
1189d8e4aad5SCédric Le Goater         } else {
1190956b8f46SCédric Le Goater             icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
119147fea43aSCédric Le Goater         }
1192d8e4aad5SCédric Le Goater     }
119354f59d78SCédric Le Goater 
119454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1195d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
119654f59d78SCédric Le Goater     }
119747fea43aSCédric Le Goater }
119847fea43aSCédric Le Goater 
1199e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1200e997040eSCédric Le Goater                               void *opaque, Error **errp)
1201e997040eSCédric Le Goater {
1202b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1203e997040eSCédric Le Goater }
1204e997040eSCédric Le Goater 
1205e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1206e997040eSCédric Le Goater                               void *opaque, Error **errp)
1207e997040eSCédric Le Goater {
1208b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1209e997040eSCédric Le Goater     uint32_t num_chips;
1210e997040eSCédric Le Goater     Error *local_err = NULL;
1211e997040eSCédric Le Goater 
1212e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1213e997040eSCédric Le Goater     if (local_err) {
1214e997040eSCédric Le Goater         error_propagate(errp, local_err);
1215e997040eSCédric Le Goater         return;
1216e997040eSCédric Le Goater     }
1217e997040eSCédric Le Goater 
1218e997040eSCédric Le Goater     /*
1219e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1220e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1221e997040eSCédric Le Goater      */
1222e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1223e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1224e997040eSCédric Le Goater         return;
1225e997040eSCédric Le Goater     }
1226e997040eSCédric Le Goater 
1227e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1228e997040eSCédric Le Goater }
1229e997040eSCédric Le Goater 
123077864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1231e997040eSCédric Le Goater {
1232b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1233e997040eSCédric Le Goater     pnv->num_chips = 1;
1234e997040eSCédric Le Goater }
1235e997040eSCédric Le Goater 
1236b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1237e997040eSCédric Le Goater {
12381e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1239e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1240e997040eSCédric Le Goater                               NULL, NULL, NULL);
1241e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1242e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1243e997040eSCédric Le Goater                               NULL);
12449e933f4aSBenjamin Herrenschmidt }
12459e933f4aSBenjamin Herrenschmidt 
1246b168a138SCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
12479e933f4aSBenjamin Herrenschmidt {
12489e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
124936fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
125047fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
12519e933f4aSBenjamin Herrenschmidt 
12529e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1253b168a138SCédric Le Goater     mc->init = pnv_init;
1254b168a138SCédric Le Goater     mc->reset = pnv_reset;
12559e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
12564a12c699SIgor Mammedov     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
12579e933f4aSBenjamin Herrenschmidt     mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
12589e933f4aSBenjamin Herrenschmidt                                       * storage */
12599e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
12609e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1261d23b6caaSPhilippe Mathieu-Daudé     mc->default_ram_size = 1 * GiB;
126236fc6f08SCédric Le Goater     xic->icp_get = pnv_icp_get;
126354f59d78SCédric Le Goater     xic->ics_get = pnv_ics_get;
126454f59d78SCédric Le Goater     xic->ics_resend = pnv_ics_resend;
126547fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1266e997040eSCédric Le Goater 
1267b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
12689e933f4aSBenjamin Herrenschmidt }
12699e933f4aSBenjamin Herrenschmidt 
127077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1271beba5c0fSIgor Mammedov     {                                             \
1272beba5c0fSIgor Mammedov         .name          = type,                    \
1273beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
127477864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
127577864267SCédric Le Goater     }
127677864267SCédric Le Goater 
127777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
127877864267SCédric Le Goater     {                                             \
127977864267SCédric Le Goater         .name          = type,                    \
128077864267SCédric Le Goater         .class_init    = class_initfn,            \
128177864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1282beba5c0fSIgor Mammedov     }
1283beba5c0fSIgor Mammedov 
1284beba5c0fSIgor Mammedov static const TypeInfo types[] = {
1285beba5c0fSIgor Mammedov     {
1286b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
12879e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
12889e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
128977864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1290b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
129136fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
129236fc6f08SCédric Le Goater             { TYPE_XICS_FABRIC },
129347fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
129436fc6f08SCédric Le Goater             { },
129536fc6f08SCédric Le Goater         },
1296beba5c0fSIgor Mammedov     },
1297beba5c0fSIgor Mammedov     {
1298beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1299beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1300beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
130177864267SCédric Le Goater         .instance_init = pnv_chip_instance_init,
1302beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1303beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1304beba5c0fSIgor Mammedov         .abstract      = true,
1305beba5c0fSIgor Mammedov     },
130677864267SCédric Le Goater 
130777864267SCédric Le Goater     /*
130877864267SCédric Le Goater      * P9 chip and variants
130977864267SCédric Le Goater      */
131077864267SCédric Le Goater     {
131177864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
131277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
131377864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
131477864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
131577864267SCédric Le Goater     },
131677864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
131777864267SCédric Le Goater 
131877864267SCédric Le Goater     /*
131977864267SCédric Le Goater      * P8 chip and variants
132077864267SCédric Le Goater      */
132177864267SCédric Le Goater     {
132277864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
132377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
132477864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
132577864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
132677864267SCédric Le Goater     },
132777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
132877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
132977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1330beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
13319e933f4aSBenjamin Herrenschmidt };
13329e933f4aSBenjamin Herrenschmidt 
1333beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1334