xref: /qemu/hw/ppc/pnv.c (revision c722579e)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
99e933f4aSBenjamin Herrenschmidt  * version 2 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2671e8a915SMarkus Armbruster #include "sysemu/reset.h"
2754d31236SMarkus Armbruster #include "sysemu/runstate.h"
28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
298d409261SCédric Le Goater #include "sysemu/device_tree.h"
30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
38e997040eSCédric Le Goater #include "qapi/visitor.h"
3947fea43aSCédric Le Goater #include "monitor/monitor.h"
4047fea43aSCédric Le Goater #include "hw/intc/intc.h"
41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
439e933f4aSBenjamin Herrenschmidt 
4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
4735dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
48967b7523SCédric Le Goater 
493495b6b6SCédric Le Goater #include "hw/isa/isa.h"
5012e9493dSMarkus Armbruster #include "hw/boards.h"
513495b6b6SCédric Le Goater #include "hw/char/serial.h"
52bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
533495b6b6SCédric Le Goater 
549e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
559e933f4aSBenjamin Herrenschmidt 
56b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
579e933f4aSBenjamin Herrenschmidt 
589e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
599e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
60b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
619e933f4aSBenjamin Herrenschmidt 
629e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
63b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
64fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
65584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
669e933f4aSBenjamin Herrenschmidt 
6740abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
6840abf43fSIgor Mammedov {
6940abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7040abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7140abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7240abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7340abf43fSIgor Mammedov     g_free(s);
7440abf43fSIgor Mammedov     return core_type;
7540abf43fSIgor Mammedov }
7640abf43fSIgor Mammedov 
779e933f4aSBenjamin Herrenschmidt /*
789e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
799e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
809e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
819e933f4aSBenjamin Herrenschmidt  */
829e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
839e933f4aSBenjamin Herrenschmidt 
849e933f4aSBenjamin Herrenschmidt /*
859e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
869e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
879e933f4aSBenjamin Herrenschmidt  * per chip.
889e933f4aSBenjamin Herrenschmidt  */
89b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
909e933f4aSBenjamin Herrenschmidt {
919e933f4aSBenjamin Herrenschmidt     char *mem_name;
929e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
939e933f4aSBenjamin Herrenschmidt     int off;
949e933f4aSBenjamin Herrenschmidt 
959e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
969e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
979e933f4aSBenjamin Herrenschmidt 
989e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
999e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1009e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1019e933f4aSBenjamin Herrenschmidt 
1029e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1039e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1049e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1069e933f4aSBenjamin Herrenschmidt }
1079e933f4aSBenjamin Herrenschmidt 
108d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
109d2fd9612SCédric Le Goater {
110d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
111d2fd9612SCédric Le Goater 
112d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
113a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
114d2fd9612SCédric Le Goater         if (cpus_offset) {
115d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
116d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
117d2fd9612SCédric Le Goater         }
118d2fd9612SCédric Le Goater     }
119d2fd9612SCédric Le Goater     _FDT(cpus_offset);
120d2fd9612SCédric Le Goater     return cpus_offset;
121d2fd9612SCédric Le Goater }
122d2fd9612SCédric Le Goater 
123d2fd9612SCédric Le Goater /*
124d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
125d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
126d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
127d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
128d2fd9612SCédric Le Goater  * servers.
129d2fd9612SCédric Le Goater  */
130b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
131d2fd9612SCédric Le Goater {
13208304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13308304a86SDavid Gibson     CPUState *cs = CPU(cpu);
134d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1358bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
136d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
137d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
138d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
139d2fd9612SCédric Le Goater     int i;
140d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
141d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
142d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
143d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
144d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
145d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
146d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
147d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
148d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
149d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
150d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
151d2fd9612SCédric Le Goater     int offset;
152d2fd9612SCédric Le Goater     char *nodename;
153d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
154d2fd9612SCédric Le Goater 
155d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
156d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
157d2fd9612SCédric Le Goater     _FDT(offset);
158d2fd9612SCédric Le Goater     g_free(nodename);
159d2fd9612SCédric Le Goater 
160d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
161d2fd9612SCédric Le Goater 
162d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
164d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
165d2fd9612SCédric Le Goater 
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
168d2fd9612SCédric Le Goater                             env->dcache_line_size)));
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
170d2fd9612SCédric Le Goater                             env->dcache_line_size)));
171d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
172d2fd9612SCédric Le Goater                             env->icache_line_size)));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
174d2fd9612SCédric Le Goater                             env->icache_line_size)));
175d2fd9612SCédric Le Goater 
176d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
177d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
178d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
179d2fd9612SCédric Le Goater     } else {
1803dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
181d2fd9612SCédric Le Goater     }
182d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
183d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
184d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
185d2fd9612SCédric Le Goater     } else {
1863dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
187d2fd9612SCédric Le Goater     }
188d2fd9612SCédric Le Goater 
189d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
190d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19159b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19259b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
194d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
195d2fd9612SCédric Le Goater 
196d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
197d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
198d2fd9612SCédric Le Goater     }
199d2fd9612SCédric Le Goater 
20058969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
201d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
202d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
203d2fd9612SCédric Le Goater     }
204d2fd9612SCédric Le Goater 
20559b7c1c2SBalamuruhan S     /*
20659b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
207d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
208d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
20959b7c1c2SBalamuruhan S      *   2               == VSX available
21059b7c1c2SBalamuruhan S      */
211d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
212d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
213d2fd9612SCédric Le Goater 
214d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
215d2fd9612SCédric Le Goater     }
216d2fd9612SCédric Le Goater 
21759b7c1c2SBalamuruhan S     /*
21859b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
219d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22059b7c1c2SBalamuruhan S      *   1               == DFP available
22159b7c1c2SBalamuruhan S      */
222d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
223d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
224d2fd9612SCédric Le Goater     }
225d2fd9612SCédric Le Goater 
226644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
227d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
228d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
229d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
230d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
231d2fd9612SCédric Le Goater     }
232d2fd9612SCédric Le Goater 
233d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
234d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
235d2fd9612SCédric Le Goater 
236d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
237d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
238d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
239d2fd9612SCédric Le Goater     }
240d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
241d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
242d2fd9612SCédric Le Goater }
243d2fd9612SCédric Le Goater 
244b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
245bf5615e7SCédric Le Goater                        uint32_t nr_threads)
246bf5615e7SCédric Le Goater {
247bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
248bf5615e7SCédric Le Goater     char *name;
249bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
250bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
251bf5615e7SCédric Le Goater     uint64_t *reg;
252bf5615e7SCédric Le Goater     int offset;
253bf5615e7SCédric Le Goater 
254bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
255bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
256bf5615e7SCédric Le Goater 
257bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
258bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
259bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
260bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
261bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
262bf5615e7SCédric Le Goater     }
263bf5615e7SCédric Le Goater 
264bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
265bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
266bf5615e7SCédric Le Goater     _FDT(offset);
267bf5615e7SCédric Le Goater     g_free(name);
268bf5615e7SCédric Le Goater 
269bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
270bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
271bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
272bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
275bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
278bf5615e7SCédric Le Goater     g_free(reg);
279bf5615e7SCédric Le Goater }
280bf5615e7SCédric Le Goater 
281eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
282e997040eSCédric Le Goater {
283d2fd9612SCédric Le Goater     int i;
284d2fd9612SCédric Le Goater 
285b168a138SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
286967b7523SCédric Le Goater 
287d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2884fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
289d2fd9612SCédric Le Goater 
290b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
291bf5615e7SCédric Le Goater 
292bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
293b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
294d2fd9612SCédric Le Goater     }
295d2fd9612SCédric Le Goater 
296e997040eSCédric Le Goater     if (chip->ram_size) {
297b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
298e997040eSCédric Le Goater     }
299e997040eSCédric Le Goater }
300e997040eSCédric Le Goater 
301eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
302eb859a27SCédric Le Goater {
303eb859a27SCédric Le Goater     int i;
304eb859a27SCédric Le Goater 
305eb859a27SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
306eb859a27SCédric Le Goater 
307eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3084fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
309eb859a27SCédric Le Goater 
310eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
311eb859a27SCédric Le Goater     }
312eb859a27SCédric Le Goater 
313eb859a27SCédric Le Goater     if (chip->ram_size) {
314eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
315eb859a27SCédric Le Goater     }
31615376c66SCédric Le Goater 
31715376c66SCédric Le Goater     pnv_dt_lpc(chip, fdt, 0);
318eb859a27SCédric Le Goater }
319eb859a27SCédric Le Goater 
320b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
321c5ffdcaeSCédric Le Goater {
322c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
323c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
324c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
325c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
326c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
327c5ffdcaeSCédric Le Goater     };
328c5ffdcaeSCédric Le Goater     char *name;
329c5ffdcaeSCédric Le Goater     int node;
330c5ffdcaeSCédric Le Goater 
331c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
332c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
333c5ffdcaeSCédric Le Goater     _FDT(node);
334c5ffdcaeSCédric Le Goater     g_free(name);
335c5ffdcaeSCédric Le Goater 
336c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
337c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
338c5ffdcaeSCédric Le Goater }
339c5ffdcaeSCédric Le Goater 
340b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
341cb228f5aSCédric Le Goater {
342cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
343cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
344cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
345cb228f5aSCédric Le Goater         cpu_to_be32(1),
346cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
347cb228f5aSCédric Le Goater         cpu_to_be32(8)
348cb228f5aSCédric Le Goater     };
349cb228f5aSCédric Le Goater     char *name;
350cb228f5aSCédric Le Goater     int node;
351cb228f5aSCédric Le Goater 
352cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
353cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
354cb228f5aSCédric Le Goater     _FDT(node);
355cb228f5aSCédric Le Goater     g_free(name);
356cb228f5aSCédric Le Goater 
357cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
358cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
359cb228f5aSCédric Le Goater                       sizeof(compatible))));
360cb228f5aSCédric Le Goater 
361cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
362cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
363cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
364cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
365cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
366cb228f5aSCédric Le Goater 
367cb228f5aSCédric Le Goater     /* This is needed by Linux */
368cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
369cb228f5aSCédric Le Goater }
370cb228f5aSCédric Le Goater 
371b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
37204f6c8b2SCédric Le Goater {
37304f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
37404f6c8b2SCédric Le Goater     uint32_t io_base;
37504f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
37604f6c8b2SCédric Le Goater         cpu_to_be32(1),
37704f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
37804f6c8b2SCédric Le Goater         cpu_to_be32(3)
37904f6c8b2SCédric Le Goater     };
38004f6c8b2SCédric Le Goater     uint32_t irq;
38104f6c8b2SCédric Le Goater     char *name;
38204f6c8b2SCédric Le Goater     int node;
38304f6c8b2SCédric Le Goater 
38404f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
38504f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
38604f6c8b2SCédric Le Goater 
38704f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
38804f6c8b2SCédric Le Goater 
38904f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
39004f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
39104f6c8b2SCédric Le Goater     _FDT(node);
39204f6c8b2SCédric Le Goater     g_free(name);
39304f6c8b2SCédric Le Goater 
3947032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
3957032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
3967032d92aSCédric Le Goater                       sizeof(compatible))));
39704f6c8b2SCédric Le Goater 
39804f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
39904f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
40004f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
40104f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
40204f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
40304f6c8b2SCédric Le Goater }
40404f6c8b2SCédric Le Goater 
405e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
406e7a3fee3SCédric Le Goater     void *fdt;
407e7a3fee3SCédric Le Goater     int offset;
408e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
409e7a3fee3SCédric Le Goater 
410b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
411e7a3fee3SCédric Le Goater {
412c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
413c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
414c5ffdcaeSCédric Le Goater 
415c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
416b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
417cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
418b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
41904f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
420b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
421c5ffdcaeSCédric Le Goater     } else {
422c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
423c5ffdcaeSCédric Le Goater                      d->ioport_id);
424c5ffdcaeSCédric Le Goater     }
425c5ffdcaeSCédric Le Goater 
426e7a3fee3SCédric Le Goater     return 0;
427e7a3fee3SCédric Le Goater }
428e7a3fee3SCédric Le Goater 
42959b7c1c2SBalamuruhan S /*
43059b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
431bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
432bb7ab95cSCédric Le Goater  */
433bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
434bb7ab95cSCédric Le Goater {
43564d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
436e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
437e7a3fee3SCédric Le Goater         .fdt = fdt,
438bb7ab95cSCédric Le Goater         .offset = isa_offset,
439e7a3fee3SCédric Le Goater     };
440f47a08d1SCédric Le Goater     uint32_t phandle;
441e7a3fee3SCédric Le Goater 
442bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
443bb7ab95cSCédric Le Goater 
444f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
445f47a08d1SCédric Le Goater     assert(phandle > 0);
446f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
447f47a08d1SCédric Le Goater 
44859b7c1c2SBalamuruhan S     /*
44959b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
45059b7c1c2SBalamuruhan S      * can not use object_child_foreach()
45159b7c1c2SBalamuruhan S      */
452bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
453bb7ab95cSCédric Le Goater                        &args);
454e7a3fee3SCédric Le Goater }
455e7a3fee3SCédric Le Goater 
456e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt)
457e5694793SCédric Le Goater {
458e5694793SCédric Le Goater     int off;
459e5694793SCédric Le Goater 
460e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
461e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
462e5694793SCédric Le Goater 
463e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
464e5694793SCédric Le Goater }
465e5694793SCédric Le Goater 
466b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4679e933f4aSBenjamin Herrenschmidt {
46883b90bf0SCédric Le Goater     const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
46983b90bf0SCédric Le Goater     const char plat_compat9[] = "qemu,powernv9\0ibm,powernv";
470b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
4719e933f4aSBenjamin Herrenschmidt     void *fdt;
4729e933f4aSBenjamin Herrenschmidt     char *buf;
4739e933f4aSBenjamin Herrenschmidt     int off;
474e997040eSCédric Le Goater     int i;
4759e933f4aSBenjamin Herrenschmidt 
4769e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
4779e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
4789e933f4aSBenjamin Herrenschmidt 
479ccb099b3SCédric Le Goater     /* /qemu node */
480ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
481ccb099b3SCédric Le Goater 
4829e933f4aSBenjamin Herrenschmidt     /* Root node */
4839e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
4849e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
4859e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
4869e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
48783b90bf0SCédric Le Goater     if (pnv_is_power9(pnv)) {
48883b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9,
48983b90bf0SCédric Le Goater                           sizeof(plat_compat9))));
49083b90bf0SCédric Le Goater     } else {
49183b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8,
49283b90bf0SCédric Le Goater                           sizeof(plat_compat8))));
49383b90bf0SCédric Le Goater     }
49483b90bf0SCédric Le Goater 
4959e933f4aSBenjamin Herrenschmidt 
4969e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
4979e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
4989e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
4999e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5009e933f4aSBenjamin Herrenschmidt     }
5019e933f4aSBenjamin Herrenschmidt     g_free(buf);
5029e933f4aSBenjamin Herrenschmidt 
5039e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5049e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5059e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5069e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5079e933f4aSBenjamin Herrenschmidt     }
5089e933f4aSBenjamin Herrenschmidt 
5099e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5109e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5119e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5129e933f4aSBenjamin Herrenschmidt 
5139e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5149e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5159e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5169e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5179e933f4aSBenjamin Herrenschmidt     }
5189e933f4aSBenjamin Herrenschmidt 
519e997040eSCédric Le Goater     /* Populate device tree for each chip */
520e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
521eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
522e997040eSCédric Le Goater     }
523e7a3fee3SCédric Le Goater 
524e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
525bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
526aeaef83dSCédric Le Goater 
527aeaef83dSCédric Le Goater     if (pnv->bmc) {
528b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
529aeaef83dSCédric Le Goater     }
530aeaef83dSCédric Le Goater 
531e5694793SCédric Le Goater     /* Create an extra node for power management on Power9 */
532e5694793SCédric Le Goater     if (pnv_is_power9(pnv)) {
533e5694793SCédric Le Goater         pnv_dt_power_mgt(fdt);
534e5694793SCédric Le Goater     }
535e5694793SCédric Le Goater 
5369e933f4aSBenjamin Herrenschmidt     return fdt;
5379e933f4aSBenjamin Herrenschmidt }
5389e933f4aSBenjamin Herrenschmidt 
539bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
540bce0b691SCédric Le Goater {
541b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
542bce0b691SCédric Le Goater 
543bce0b691SCédric Le Goater     if (pnv->bmc) {
544bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
545bce0b691SCédric Le Goater     }
546bce0b691SCédric Le Goater }
547bce0b691SCédric Le Goater 
548a0628599SLike Xu static void pnv_reset(MachineState *machine)
5499e933f4aSBenjamin Herrenschmidt {
5509e933f4aSBenjamin Herrenschmidt     void *fdt;
5519e933f4aSBenjamin Herrenschmidt 
5529e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5539e933f4aSBenjamin Herrenschmidt 
554b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5559e933f4aSBenjamin Herrenschmidt 
5569e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5579e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5589e933f4aSBenjamin Herrenschmidt 
5598d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5609e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5619e933f4aSBenjamin Herrenschmidt }
5629e933f4aSBenjamin Herrenschmidt 
56304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5643495b6b6SCédric Le Goater {
56577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
56677864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
56704026890SCédric Le Goater }
5683495b6b6SCédric Le Goater 
56904026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
57004026890SCédric Le Goater {
57177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
57277864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
57304026890SCédric Le Goater }
5743495b6b6SCédric Le Goater 
57504026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
57604026890SCédric Le Goater {
57715376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
57815376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
57904026890SCédric Le Goater }
5803495b6b6SCédric Le Goater 
58104026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
58204026890SCédric Le Goater {
58304026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
5843495b6b6SCédric Le Goater }
5853495b6b6SCédric Le Goater 
586d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
587d8e4aad5SCédric Le Goater {
588d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
589d8e4aad5SCédric Le Goater 
590d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
591d8e4aad5SCédric Le Goater }
592d8e4aad5SCédric Le Goater 
593d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
594d8e4aad5SCédric Le Goater {
595d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
596d8e4aad5SCédric Le Goater 
597d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
598c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
599d8e4aad5SCédric Le Goater }
600d8e4aad5SCédric Le Goater 
601f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
602f30c843cSCédric Le Goater {
603f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
604f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
605f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
606f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
607f30c843cSCédric Le Goater 
608f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
609f30c843cSCédric Le Goater }
610f30c843cSCédric Le Goater 
611e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
612e2392d43SCédric Le Goater {
613e2392d43SCédric Le Goater     Object *obj;
614e2392d43SCédric Le Goater 
615e2392d43SCédric Le Goater     obj = OBJECT(isa_create(bus, "isa-ipmi-bt"));
616e2392d43SCédric Le Goater     object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal);
617e2392d43SCédric Le Goater     object_property_set_int(obj, irq, "irq", &error_fatal);
618e2392d43SCédric Le Goater     object_property_set_bool(obj, true, "realized", &error_fatal);
619e2392d43SCédric Le Goater }
620e2392d43SCédric Le Goater 
621b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6229e933f4aSBenjamin Herrenschmidt {
623b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
624f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6259e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
6269e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6279e933f4aSBenjamin Herrenschmidt     long fw_size;
628e997040eSCédric Le Goater     int i;
629e997040eSCédric Le Goater     char *chip_typename;
63035dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
63135dde576SCédric Le Goater     DeviceState *dev;
6329e933f4aSBenjamin Herrenschmidt 
6339e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
634d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
6353dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
6369e933f4aSBenjamin Herrenschmidt     }
6379e933f4aSBenjamin Herrenschmidt 
6389e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
639b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6409e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6419e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6429e933f4aSBenjamin Herrenschmidt 
64335dde576SCédric Le Goater     /*
64435dde576SCédric Le Goater      * Create our simple PNOR device
64535dde576SCédric Le Goater      */
64635dde576SCédric Le Goater     dev = qdev_create(NULL, TYPE_PNV_PNOR);
64735dde576SCédric Le Goater     if (pnor) {
64835dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
64935dde576SCédric Le Goater                             &error_abort);
65035dde576SCédric Le Goater     }
65135dde576SCédric Le Goater     qdev_init_nofail(dev);
65235dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
65335dde576SCédric Le Goater 
6549e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
6559e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
6569e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
6579e933f4aSBenjamin Herrenschmidt     }
6589e933f4aSBenjamin Herrenschmidt 
6599e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
66015fcedb2SCédric Le Goater     if (!fw_filename) {
66115fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
66215fcedb2SCédric Le Goater         exit(1);
66315fcedb2SCédric Le Goater     }
6649e933f4aSBenjamin Herrenschmidt 
6659e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
6669e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
66715fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
6689e933f4aSBenjamin Herrenschmidt         exit(1);
6699e933f4aSBenjamin Herrenschmidt     }
6709e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
6719e933f4aSBenjamin Herrenschmidt 
6729e933f4aSBenjamin Herrenschmidt     /* load kernel */
6739e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
6749e933f4aSBenjamin Herrenschmidt         long kernel_size;
6759e933f4aSBenjamin Herrenschmidt 
6769e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
677b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
6789e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
679802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
6809e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
6819e933f4aSBenjamin Herrenschmidt             exit(1);
6829e933f4aSBenjamin Herrenschmidt         }
6839e933f4aSBenjamin Herrenschmidt     }
6849e933f4aSBenjamin Herrenschmidt 
6859e933f4aSBenjamin Herrenschmidt     /* load initrd */
6869e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
6879e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
6889e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
689584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
6909e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
691802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
6929e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
6939e933f4aSBenjamin Herrenschmidt             exit(1);
6949e933f4aSBenjamin Herrenschmidt         }
6959e933f4aSBenjamin Herrenschmidt     }
696e997040eSCédric Le Goater 
697f30c843cSCédric Le Goater     /*
698f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
699f30c843cSCédric Le Goater      * default.
700f30c843cSCédric Le Goater      */
701f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
702f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
703f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
704f30c843cSCédric Le Goater         exit(1);
705f30c843cSCédric Le Goater     }
706f30c843cSCédric Le Goater 
707e997040eSCédric Le Goater     /* Create the processor chips */
7084a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7097fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7104a12c699SIgor Mammedov                                     i, machine->cpu_type);
711e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
712f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
713f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
714e997040eSCédric Le Goater         exit(1);
715e997040eSCédric Le Goater     }
716e997040eSCédric Le Goater 
717e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
718e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
719e997040eSCédric Le Goater         char chip_name[32];
720e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
721e997040eSCédric Le Goater 
722e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
723e997040eSCédric Le Goater 
72459b7c1c2SBalamuruhan S         /*
72559b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
726e997040eSCédric Le Goater          * way to specify different ranges for each chip
727e997040eSCédric Le Goater          */
728e997040eSCédric Le Goater         if (i == 0) {
729e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
730e997040eSCédric Le Goater                                     &error_fatal);
731e997040eSCédric Le Goater         }
732e997040eSCédric Le Goater 
733e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
734e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
735e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
736e997040eSCédric Le Goater                                 &error_fatal);
737fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
738fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
739e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
740e997040eSCédric Le Goater     }
741e997040eSCédric Le Goater     g_free(chip_typename);
7423495b6b6SCédric Le Goater 
743e2392d43SCédric Le Goater     /* Create the machine BMC simulator */
744e2392d43SCédric Le Goater     pnv->bmc = pnv_bmc_create();
745e2392d43SCédric Le Goater 
7463495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
74704026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
7483495b6b6SCédric Le Goater 
7493495b6b6SCédric Le Goater     /* Create serial port */
750def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
7513495b6b6SCédric Le Goater 
7523495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
7536c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
754bce0b691SCédric Le Goater 
755e2392d43SCédric Le Goater     /* Create the IPMI BT device for communication with the BMC */
756e2392d43SCédric Le Goater     pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
757e2392d43SCédric Le Goater 
75859b7c1c2SBalamuruhan S     /*
75959b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
76059b7c1c2SBalamuruhan S      * host to powerdown
76159b7c1c2SBalamuruhan S      */
762bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
763bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
764e997040eSCédric Le Goater }
765e997040eSCédric Le Goater 
766631adaffSCédric Le Goater /*
767631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
768631adaffSCédric Le Goater  *   22:24  Chip ID
769631adaffSCédric Le Goater  *   25:28  Core number
770631adaffSCédric Le Goater  *   29:31  Thread ID
771631adaffSCédric Le Goater  */
772631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
773631adaffSCédric Le Goater {
774631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
775631adaffSCédric Le Goater }
776631adaffSCédric Le Goater 
7778fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
778d35aefa9SCédric Le Goater                                         Error **errp)
779d35aefa9SCédric Le Goater {
7808fa1f4efSCédric Le Goater     Error *local_err = NULL;
7818fa1f4efSCédric Le Goater     Object *obj;
7828907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
7838fa1f4efSCédric Le Goater 
7848fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
7858fa1f4efSCédric Le Goater                      &local_err);
7868fa1f4efSCédric Le Goater     if (local_err) {
7878fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
7888fa1f4efSCédric Le Goater         return;
7898fa1f4efSCédric Le Goater     }
7908fa1f4efSCédric Le Goater 
791956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
792d35aefa9SCédric Le Goater }
793d35aefa9SCédric Le Goater 
7940990ce6aSGreg Kurz 
795d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
796d49e8a9bSCédric Le Goater {
797d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
798d49e8a9bSCédric Le Goater 
799d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
800d49e8a9bSCédric Le Goater }
801d49e8a9bSCédric Le Goater 
8020990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8030990ce6aSGreg Kurz {
8040990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8050990ce6aSGreg Kurz 
8060990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
8070990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8080990ce6aSGreg Kurz }
8090990ce6aSGreg Kurz 
810631adaffSCédric Le Goater /*
811631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
812631adaffSCédric Le Goater  *   49:52  Node ID
813631adaffSCédric Le Goater  *   53:55  Chip ID
814631adaffSCédric Le Goater  *   56     Reserved - Read as zero
815631adaffSCédric Le Goater  *   57:61  Core number
816631adaffSCédric Le Goater  *   62:63  Thread ID
817631adaffSCédric Le Goater  *
818631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
819631adaffSCédric Le Goater  */
820631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
821631adaffSCédric Le Goater {
822631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
823631adaffSCédric Le Goater }
824631adaffSCédric Le Goater 
8258fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
826d35aefa9SCédric Le Goater                                         Error **errp)
827d35aefa9SCédric Le Goater {
8282dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
8292dfa91a2SCédric Le Goater     Error *local_err = NULL;
8302dfa91a2SCédric Le Goater     Object *obj;
8312dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8322dfa91a2SCédric Le Goater 
8332dfa91a2SCédric Le Goater     /*
8342dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
8352dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
8362dfa91a2SCédric Le Goater      * only used at runtime.
8372dfa91a2SCédric Le Goater      */
83826aa5b1eSGreg Kurz     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err);
8392dfa91a2SCédric Le Goater     if (local_err) {
8402dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
8418fa1f4efSCédric Le Goater         return;
842d35aefa9SCédric Le Goater     }
843d35aefa9SCédric Le Goater 
8442dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
8452dfa91a2SCédric Le Goater }
8462dfa91a2SCédric Le Goater 
847d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
848d49e8a9bSCédric Le Goater {
849d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
850d49e8a9bSCédric Le Goater 
851d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
852d49e8a9bSCédric Le Goater }
853d49e8a9bSCédric Le Goater 
8540990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8550990ce6aSGreg Kurz {
8560990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8570990ce6aSGreg Kurz 
8580990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
8590990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8600990ce6aSGreg Kurz }
8610990ce6aSGreg Kurz 
86259b7c1c2SBalamuruhan S /*
86359b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
864397a79e7SCédric Le Goater  *
865397a79e7SCédric Le Goater  * <EX0 reserved>
866397a79e7SCédric Le Goater  *  EX1  - Venice only
867397a79e7SCédric Le Goater  *  EX2  - Venice only
868397a79e7SCédric Le Goater  *  EX3  - Venice only
869397a79e7SCédric Le Goater  *  EX4
870397a79e7SCédric Le Goater  *  EX5
871397a79e7SCédric Le Goater  *  EX6
872397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
873397a79e7SCédric Le Goater  *  EX9  - Venice only
874397a79e7SCédric Le Goater  *  EX10 - Venice only
875397a79e7SCédric Le Goater  *  EX11 - Venice only
876397a79e7SCédric Le Goater  *  EX12
877397a79e7SCédric Le Goater  *  EX13
878397a79e7SCédric Le Goater  *  EX14
879397a79e7SCédric Le Goater  * <EX15 reserved>
880397a79e7SCédric Le Goater  */
881397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
882397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
883397a79e7SCédric Le Goater 
884397a79e7SCédric Le Goater /*
88509279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
886397a79e7SCédric Le Goater  */
88709279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
888397a79e7SCédric Le Goater 
88977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
89077864267SCédric Le Goater {
89177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
89277864267SCédric Le Goater 
893f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
894ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
89577864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
89677864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
89777864267SCédric Le Goater 
898f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
89982514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
90077864267SCédric Le Goater 
901f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
9023233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
9033887d241SBalamuruhan S 
9043887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
9053887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
90677864267SCédric Le Goater }
90777864267SCédric Le Goater 
90877864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
90977864267SCédric Le Goater  {
91077864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
91177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
91277864267SCédric Le Goater     int i, j;
91377864267SCédric Le Goater     char *name;
91477864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
91577864267SCédric Le Goater 
91677864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
91777864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
91877864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
91977864267SCédric Le Goater     g_free(name);
92077864267SCédric Le Goater 
92177864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
92277864267SCédric Le Goater 
92377864267SCédric Le Goater     /* Map the ICP registers for each thread */
92477864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
9254fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
92677864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
92777864267SCédric Le Goater 
92877864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
92977864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
93077864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
93177864267SCédric Le Goater 
93277864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
93377864267SCédric Le Goater                                         &icp->mmio);
93477864267SCédric Le Goater         }
93577864267SCédric Le Goater     }
93677864267SCédric Le Goater }
93777864267SCédric Le Goater 
93877864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
93977864267SCédric Le Goater {
94077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
94177864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
94277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
943ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
94477864267SCédric Le Goater     Error *local_err = NULL;
94577864267SCédric Le Goater 
946709044fdSCédric Le Goater     /* XSCOM bridge is first */
947709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
948709044fdSCédric Le Goater     if (local_err) {
949709044fdSCédric Le Goater         error_propagate(errp, local_err);
950709044fdSCédric Le Goater         return;
951709044fdSCédric Le Goater     }
952709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
953709044fdSCédric Le Goater 
95477864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
95577864267SCédric Le Goater     if (local_err) {
95677864267SCédric Le Goater         error_propagate(errp, local_err);
95777864267SCédric Le Goater         return;
95877864267SCédric Le Goater     }
95977864267SCédric Le Goater 
96077864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
96177864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
96277864267SCédric Le Goater                             "bar", &error_fatal);
96377864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
96477864267SCédric Le Goater     if (local_err) {
96577864267SCédric Le Goater         error_propagate(errp, local_err);
96677864267SCédric Le Goater         return;
96777864267SCédric Le Goater     }
968ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
969ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
97077864267SCédric Le Goater 
97177864267SCédric Le Goater     /* Create LPC controller */
972b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi",
973b63f3893SGreg Kurz                              &error_abort);
97477864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
97577864267SCédric Le Goater                              &error_fatal);
97677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
97777864267SCédric Le Goater 
97864d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
97964d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
98064d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
98164d011d5SCédric Le Goater 
98259b7c1c2SBalamuruhan S     /*
98359b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
98459b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
98559b7c1c2SBalamuruhan S      */
98677864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
98777864267SCédric Le Goater     if (local_err) {
98877864267SCédric Le Goater         error_propagate(errp, local_err);
98977864267SCédric Le Goater         return;
99077864267SCédric Le Goater     }
99177864267SCédric Le Goater 
99277864267SCédric Le Goater     /* Create the simplified OCC model */
993ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi",
994ee3d2713SGreg Kurz                              &error_abort);
99577864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
99677864267SCédric Le Goater     if (local_err) {
99777864267SCédric Le Goater         error_propagate(errp, local_err);
99877864267SCédric Le Goater         return;
99977864267SCédric Le Goater     }
100077864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1001f3db8266SBalamuruhan S 
1002f3db8266SBalamuruhan S     /* OCC SRAM model */
1003f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip),
1004f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
10053887d241SBalamuruhan S 
10063887d241SBalamuruhan S     /* HOMER */
1007f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip",
1008f2582acfSGreg Kurz                              &error_abort);
10093887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
10103887d241SBalamuruhan S                              &local_err);
10113887d241SBalamuruhan S     if (local_err) {
10123887d241SBalamuruhan S         error_propagate(errp, local_err);
10133887d241SBalamuruhan S         return;
10143887d241SBalamuruhan S     }
10153887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
10163887d241SBalamuruhan S                                 &chip8->homer.regs);
101777864267SCédric Le Goater }
101877864267SCédric Le Goater 
1019e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1020e997040eSCédric Le Goater {
1021e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1022e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1023e997040eSCédric Le Goater 
1024e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
1025e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1026397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
1027631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1028d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1029d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10300990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
103104026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1032eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1033d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1034e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
103577864267SCédric Le Goater 
103677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
103777864267SCédric Le Goater                                     &k->parent_realize);
1038e997040eSCédric Le Goater }
1039e997040eSCédric Le Goater 
1040e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1041e997040eSCédric Le Goater {
1042e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1043e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1044e997040eSCédric Le Goater 
1045e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
1046e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1047397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1048631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1049d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1050d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10510990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
105204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1053eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1054d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1055e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
105677864267SCédric Le Goater 
105777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
105877864267SCédric Le Goater                                     &k->parent_realize);
1059e997040eSCédric Le Goater }
1060e997040eSCédric Le Goater 
1061e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1062e997040eSCédric Le Goater {
1063e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1064e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1065e997040eSCédric Le Goater 
1066e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
1067e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1068397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1069631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1070d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1071d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10720990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
107304026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1074eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1075d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1076e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
107777864267SCédric Le Goater 
107877864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
107977864267SCédric Le Goater                                     &k->parent_realize);
108077864267SCédric Le Goater }
108177864267SCédric Le Goater 
108277864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
108377864267SCédric Le Goater {
10842dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
10852dfa91a2SCédric Le Goater 
10862dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
10872dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
1088c38536bcSCédric Le Goater 
1089c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1090c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
109115376c66SCédric Le Goater 
109215376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
109315376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
10946598a70dSCédric Le Goater 
10956598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
10966598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
10973887d241SBalamuruhan S 
10983887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
10993887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
110077864267SCédric Le Goater }
110177864267SCédric Le Goater 
11025dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
11035dad902cSCédric Le Goater {
11045dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
11055dad902cSCédric Le Goater     int i;
11065dad902cSCédric Le Goater 
11075dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
11085dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
11095dad902cSCédric Le Goater 
11105dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
11115dad902cSCédric Le Goater         char eq_name[32];
11125dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
11134fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
11145dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
11155dad902cSCédric Le Goater 
11165dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1117bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1118bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
11195dad902cSCédric Le Goater 
11205dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
11215dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
11225dad902cSCédric Le Goater 
11235dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
11245dad902cSCédric Le Goater                                 &eq->xscom_regs);
11255dad902cSCédric Le Goater     }
11265dad902cSCédric Le Goater }
11275dad902cSCédric Le Goater 
112877864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
112977864267SCédric Le Goater {
113077864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
11312dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
11322dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1133c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
113477864267SCédric Le Goater     Error *local_err = NULL;
113577864267SCédric Le Goater 
1136709044fdSCédric Le Goater     /* XSCOM bridge is first */
1137709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1138709044fdSCédric Le Goater     if (local_err) {
1139709044fdSCédric Le Goater         error_propagate(errp, local_err);
1140709044fdSCédric Le Goater         return;
1141709044fdSCédric Le Goater     }
1142709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1143709044fdSCédric Le Goater 
114477864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
114577864267SCédric Le Goater     if (local_err) {
114677864267SCédric Le Goater         error_propagate(errp, local_err);
114777864267SCédric Le Goater         return;
114877864267SCédric Le Goater     }
11492dfa91a2SCédric Le Goater 
11505dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
11515dad902cSCédric Le Goater     if (local_err) {
11525dad902cSCédric Le Goater         error_propagate(errp, local_err);
11535dad902cSCédric Le Goater         return;
11545dad902cSCédric Le Goater     }
11555dad902cSCédric Le Goater 
11562dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
11572dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
11582dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
11592dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
11602dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
11612dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
11622dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
11632dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
11642dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
11657ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
11667ae54cc3SGreg Kurz                              &error_abort);
11672dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
11682dfa91a2SCédric Le Goater                              &local_err);
11692dfa91a2SCédric Le Goater     if (local_err) {
11702dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
11712dfa91a2SCédric Le Goater         return;
11722dfa91a2SCédric Le Goater     }
11732dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
11742dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1175c38536bcSCédric Le Goater 
1176c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1177c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1178c38536bcSCédric Le Goater                             "bar", &error_fatal);
1179c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1180c38536bcSCédric Le Goater     if (local_err) {
1181c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1182c38536bcSCédric Le Goater         return;
1183c38536bcSCédric Le Goater     }
1184c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1185c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
118615376c66SCédric Le Goater 
118715376c66SCédric Le Goater     /* LPC */
1188b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1189b63f3893SGreg Kurz                              &error_abort);
119015376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
119115376c66SCédric Le Goater     if (local_err) {
119215376c66SCédric Le Goater         error_propagate(errp, local_err);
119315376c66SCédric Le Goater         return;
119415376c66SCédric Le Goater     }
119515376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
119615376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
119715376c66SCédric Le Goater 
119815376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
119915376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
12006598a70dSCédric Le Goater 
12016598a70dSCédric Le Goater     /* Create the simplified OCC model */
1202ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1203ee3d2713SGreg Kurz                              &error_abort);
12046598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
12056598a70dSCédric Le Goater     if (local_err) {
12066598a70dSCédric Le Goater         error_propagate(errp, local_err);
12076598a70dSCédric Le Goater         return;
12086598a70dSCédric Le Goater     }
12096598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1210f3db8266SBalamuruhan S 
1211f3db8266SBalamuruhan S     /* OCC SRAM model */
1212f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip),
1213f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
12143887d241SBalamuruhan S 
12153887d241SBalamuruhan S     /* HOMER */
1216f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1217f2582acfSGreg Kurz                              &error_abort);
12183887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
12193887d241SBalamuruhan S                              &local_err);
12203887d241SBalamuruhan S     if (local_err) {
12213887d241SBalamuruhan S         error_propagate(errp, local_err);
12223887d241SBalamuruhan S         return;
12233887d241SBalamuruhan S     }
12243887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
12253887d241SBalamuruhan S                                 &chip9->homer.regs);
1226e997040eSCédric Le Goater }
1227e997040eSCédric Le Goater 
1228e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1229e997040eSCédric Le Goater {
1230e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1231e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1232e997040eSCédric Le Goater 
1233e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
123483028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1235397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1236631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1237d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1238d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
12390990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
124004026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1241eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1242d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1243e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
124477864267SCédric Le Goater 
124577864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
124677864267SCédric Le Goater                                     &k->parent_realize);
1247e997040eSCédric Le Goater }
1248e997040eSCédric Le Goater 
1249397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1250397a79e7SCédric Le Goater {
1251397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1252397a79e7SCédric Le Goater     int cores_max;
1253397a79e7SCédric Le Goater 
1254397a79e7SCédric Le Goater     /*
1255397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1256397a79e7SCédric Le Goater      * the chip class
1257397a79e7SCédric Le Goater      */
1258397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1259397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1260397a79e7SCédric Le Goater     }
1261397a79e7SCédric Le Goater 
1262397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1263397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1264397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1265397a79e7SCédric Le Goater                    chip->cores_mask);
1266397a79e7SCédric Le Goater         return;
1267397a79e7SCédric Le Goater     }
1268397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1269397a79e7SCédric Le Goater 
1270397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
127127d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1272397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1273397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1274397a79e7SCédric Le Goater                    cores_max);
1275397a79e7SCédric Le Goater         return;
1276397a79e7SCédric Le Goater     }
1277397a79e7SCédric Le Goater }
1278397a79e7SCédric Le Goater 
127951c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1280e997040eSCédric Le Goater {
1281fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1282397a79e7SCédric Le Goater     Error *error = NULL;
1283d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
128440abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1285d2fd9612SCédric Le Goater     int i, core_hwid;
1286397a79e7SCédric Le Goater 
1287d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1288d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1289d2fd9612SCédric Le Goater         return;
1290d2fd9612SCédric Le Goater     }
1291d2fd9612SCédric Le Goater 
1292d2fd9612SCédric Le Goater     /* Cores */
1293397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1294397a79e7SCédric Le Goater     if (error) {
1295397a79e7SCédric Le Goater         error_propagate(errp, error);
1296397a79e7SCédric Le Goater         return;
1297397a79e7SCédric Le Goater     }
1298d2fd9612SCédric Le Goater 
12994fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1300d2fd9612SCédric Le Goater 
1301d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1302d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1303d2fd9612SCédric Le Goater         char core_name[32];
13044fa28f23SGreg Kurz         PnvCore *pnv_core;
1305c035851aSCédric Le Goater         uint64_t xscom_core_base;
1306d2fd9612SCédric Le Goater 
1307d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1308d2fd9612SCédric Le Goater             continue;
1309d2fd9612SCédric Le Goater         }
1310d2fd9612SCédric Le Goater 
13114fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
13124fa28f23SGreg Kurz 
1313d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
13144fa28f23SGreg Kurz         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
13154fa28f23SGreg Kurz                                   &error_abort);
13164fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1317fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1318d2fd9612SCédric Le Goater                                 &error_fatal);
1319d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1320d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1321d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1322d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1323d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1324158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1325158e17a6SGreg Kurz                                  &error_abort);
1326d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1327d2fd9612SCédric Le Goater                                  &error_fatal);
132824ece072SCédric Le Goater 
132924ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1330c035851aSCédric Le Goater         if (!pnv_chip_is_power9(chip)) {
1331c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
1332c035851aSCédric Le Goater         } else {
13335dad902cSCédric Le Goater             xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid);
1334c035851aSCédric Le Goater         }
1335c035851aSCédric Le Goater 
1336c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
13374fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1338d2fd9612SCédric Le Goater         i++;
1339d2fd9612SCédric Le Goater     }
134051c04728SCédric Le Goater }
134151c04728SCédric Le Goater 
134251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
134351c04728SCédric Le Goater {
134451c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
134551c04728SCédric Le Goater     Error *error = NULL;
134651c04728SCédric Le Goater 
134751c04728SCédric Le Goater     /* Cores */
134851c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
134951c04728SCédric Le Goater     if (error) {
135051c04728SCédric Le Goater         error_propagate(errp, error);
135151c04728SCédric Le Goater         return;
135251c04728SCédric Le Goater     }
1353e997040eSCédric Le Goater }
1354e997040eSCédric Le Goater 
1355e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1356e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1357e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1358e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1359397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1360397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1361e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1362e997040eSCédric Le Goater };
1363e997040eSCédric Le Goater 
1364e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1365e997040eSCédric Le Goater {
1366e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1367e997040eSCédric Le Goater 
13689d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1369e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1370e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1371e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1372e997040eSCédric Le Goater }
1373e997040eSCédric Le Goater 
1374119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1375119eaa9dSCédric Le Goater {
1376119eaa9dSCédric Le Goater     int i, j;
1377119eaa9dSCédric Le Goater 
1378119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1379119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1380119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1381119eaa9dSCédric Le Goater 
1382119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1383119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1384119eaa9dSCédric Le Goater                 return pc->threads[j];
1385119eaa9dSCédric Le Goater             }
1386119eaa9dSCédric Le Goater         }
1387119eaa9dSCédric Le Goater     }
1388119eaa9dSCédric Le Goater     return NULL;
1389119eaa9dSCédric Le Goater }
1390119eaa9dSCédric Le Goater 
139154f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
139254f59d78SCédric Le Goater {
1393b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
139454f59d78SCédric Le Goater     int i;
139554f59d78SCédric Le Goater 
139654f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
139777864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
139877864267SCédric Le Goater 
139977864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
140077864267SCédric Le Goater             return &chip8->psi.ics;
140154f59d78SCédric Le Goater         }
140254f59d78SCédric Le Goater     }
140354f59d78SCédric Le Goater     return NULL;
140454f59d78SCédric Le Goater }
140554f59d78SCédric Le Goater 
140654f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
140754f59d78SCédric Le Goater {
1408b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
140954f59d78SCédric Le Goater     int i;
141054f59d78SCédric Le Goater 
141154f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
141277864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
141377864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
141454f59d78SCédric Le Goater     }
141554f59d78SCédric Le Goater }
141654f59d78SCédric Le Goater 
141736fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
141836fc6f08SCédric Le Goater {
141936fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
142036fc6f08SCédric Le Goater 
1421956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
142236fc6f08SCédric Le Goater }
142336fc6f08SCédric Le Goater 
142447fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
142547fea43aSCédric Le Goater                                Monitor *mon)
142647fea43aSCédric Le Goater {
1427b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
142854f59d78SCédric Le Goater     int i;
142947fea43aSCédric Le Goater     CPUState *cs;
143047fea43aSCédric Le Goater 
143147fea43aSCédric Le Goater     CPU_FOREACH(cs) {
143247fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
143347fea43aSCédric Le Goater 
1434d8e4aad5SCédric Le Goater         if (pnv_chip_is_power9(pnv->chips[0])) {
1435d8e4aad5SCédric Le Goater             xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
1436d8e4aad5SCédric Le Goater         } else {
1437956b8f46SCédric Le Goater             icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
143847fea43aSCédric Le Goater         }
1439d8e4aad5SCédric Le Goater     }
144054f59d78SCédric Le Goater 
144154f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1442d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
144354f59d78SCédric Le Goater     }
144447fea43aSCédric Le Goater }
144547fea43aSCédric Le Goater 
1446*c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1447*c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1448*c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1449*c722579eSCédric Le Goater                          uint32_t logic_serv,
1450*c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1451*c722579eSCédric Le Goater {
1452*c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1453*c722579eSCédric Le Goater     int total_count = 0;
1454*c722579eSCédric Le Goater     int i;
1455*c722579eSCédric Le Goater 
1456*c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1457*c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1458*c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1459*c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1460*c722579eSCédric Le Goater         int count;
1461*c722579eSCédric Le Goater 
1462*c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1463*c722579eSCédric Le Goater                                priority, logic_serv, match);
1464*c722579eSCédric Le Goater 
1465*c722579eSCédric Le Goater         if (count < 0) {
1466*c722579eSCédric Le Goater             return count;
1467*c722579eSCédric Le Goater         }
1468*c722579eSCédric Le Goater 
1469*c722579eSCédric Le Goater         total_count += count;
1470*c722579eSCédric Le Goater     }
1471*c722579eSCédric Le Goater 
1472*c722579eSCédric Le Goater     return total_count;
1473*c722579eSCédric Le Goater }
1474*c722579eSCédric Le Goater 
1475e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1476e997040eSCédric Le Goater                               void *opaque, Error **errp)
1477e997040eSCédric Le Goater {
1478b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1479e997040eSCédric Le Goater }
1480e997040eSCédric Le Goater 
1481e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1482e997040eSCédric Le Goater                               void *opaque, Error **errp)
1483e997040eSCédric Le Goater {
1484b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1485e997040eSCédric Le Goater     uint32_t num_chips;
1486e997040eSCédric Le Goater     Error *local_err = NULL;
1487e997040eSCédric Le Goater 
1488e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1489e997040eSCédric Le Goater     if (local_err) {
1490e997040eSCédric Le Goater         error_propagate(errp, local_err);
1491e997040eSCédric Le Goater         return;
1492e997040eSCédric Le Goater     }
1493e997040eSCédric Le Goater 
1494e997040eSCédric Le Goater     /*
1495e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1496e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1497e997040eSCédric Le Goater      */
1498e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1499e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1500e997040eSCédric Le Goater         return;
1501e997040eSCédric Le Goater     }
1502e997040eSCédric Le Goater 
1503e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1504e997040eSCédric Le Goater }
1505e997040eSCédric Le Goater 
150677864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1507e997040eSCédric Le Goater {
1508b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1509e997040eSCédric Le Goater     pnv->num_chips = 1;
1510e997040eSCédric Le Goater }
1511e997040eSCédric Le Goater 
1512b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1513e997040eSCédric Le Goater {
15141e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1515e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1516e997040eSCédric Le Goater                               NULL, NULL, NULL);
1517e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1518e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1519e997040eSCédric Le Goater                               NULL);
15209e933f4aSBenjamin Herrenschmidt }
15219e933f4aSBenjamin Herrenschmidt 
1522f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
15239e933f4aSBenjamin Herrenschmidt {
15249e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
152536fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1526f30c843cSCédric Le Goater 
1527f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1528f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1529f30c843cSCédric Le Goater 
1530f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1531f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1532f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1533f30c843cSCédric Le Goater }
1534f30c843cSCédric Le Goater 
1535f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1536f30c843cSCédric Le Goater {
1537f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1538*c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1539f30c843cSCédric Le Goater 
1540f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1541f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1542*c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1543f30c843cSCédric Le Goater 
1544f30c843cSCédric Le Goater     mc->alias = "powernv";
1545f30c843cSCédric Le Goater }
1546f30c843cSCédric Le Goater 
1547f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1548f30c843cSCédric Le Goater {
1549f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
155047fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
15519e933f4aSBenjamin Herrenschmidt 
15529e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1553b168a138SCédric Le Goater     mc->init = pnv_init;
1554b168a138SCédric Le Goater     mc->reset = pnv_reset;
15559e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
155659b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
155759b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
15589e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
15599e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1560f1d18b0aSJoel Stanley     /*
1561f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1562f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1563f1d18b0aSJoel Stanley      */
1564f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
156547fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1566e997040eSCédric Le Goater 
1567b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
15689e933f4aSBenjamin Herrenschmidt }
15699e933f4aSBenjamin Herrenschmidt 
157077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1571beba5c0fSIgor Mammedov     {                                             \
1572beba5c0fSIgor Mammedov         .name          = type,                    \
1573beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
157477864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
157577864267SCédric Le Goater     }
157677864267SCédric Le Goater 
157777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
157877864267SCédric Le Goater     {                                             \
157977864267SCédric Le Goater         .name          = type,                    \
158077864267SCédric Le Goater         .class_init    = class_initfn,            \
158177864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1582beba5c0fSIgor Mammedov     }
1583beba5c0fSIgor Mammedov 
1584beba5c0fSIgor Mammedov static const TypeInfo types[] = {
15851aba8716SCédric Le Goater     {
15861aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
15871aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
15881aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
1589*c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
1590*c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
1591*c722579eSCédric Le Goater             { },
1592*c722579eSCédric Le Goater         },
15931aba8716SCédric Le Goater     },
15941aba8716SCédric Le Goater     {
15951aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
15961aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
15971aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
15981aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
15991aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
16001aba8716SCédric Le Goater             { },
16011aba8716SCédric Le Goater         },
16021aba8716SCédric Le Goater     },
1603beba5c0fSIgor Mammedov     {
1604b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
16059e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1606f30c843cSCédric Le Goater         .abstract       = true,
16079e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
160877864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1609b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
161036fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
161147fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
161236fc6f08SCédric Le Goater             { },
161336fc6f08SCédric Le Goater         },
1614beba5c0fSIgor Mammedov     },
1615beba5c0fSIgor Mammedov     {
1616beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1617beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1618beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1619beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1620beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1621beba5c0fSIgor Mammedov         .abstract      = true,
1622beba5c0fSIgor Mammedov     },
162377864267SCédric Le Goater 
162477864267SCédric Le Goater     /*
162577864267SCédric Le Goater      * P9 chip and variants
162677864267SCédric Le Goater      */
162777864267SCédric Le Goater     {
162877864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
162977864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
163077864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
163177864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
163277864267SCédric Le Goater     },
163377864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
163477864267SCédric Le Goater 
163577864267SCédric Le Goater     /*
163677864267SCédric Le Goater      * P8 chip and variants
163777864267SCédric Le Goater      */
163877864267SCédric Le Goater     {
163977864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
164077864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
164177864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
164277864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
164377864267SCédric Le Goater     },
164477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
164577864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
164677864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1647beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
16489e933f4aSBenjamin Herrenschmidt };
16499e933f4aSBenjamin Herrenschmidt 
1650beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1651