xref: /qemu/hw/ppc/pnv.c (revision 35dde576)
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"
47*35dde576SCé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 {
28340abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
284d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
285d2fd9612SCédric Le Goater     int i;
286d2fd9612SCédric Le Goater 
287b168a138SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
288967b7523SCédric Le Goater 
289d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
290d2fd9612SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
291d2fd9612SCédric Le Goater 
292b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
293bf5615e7SCédric Le Goater 
294bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
295b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
296d2fd9612SCédric Le Goater     }
297d2fd9612SCédric Le Goater 
298e997040eSCédric Le Goater     if (chip->ram_size) {
299b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
300e997040eSCédric Le Goater     }
301e997040eSCédric Le Goater }
302e997040eSCédric Le Goater 
303eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
304eb859a27SCédric Le Goater {
305eb859a27SCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
306eb859a27SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
307eb859a27SCédric Le Goater     int i;
308eb859a27SCédric Le Goater 
309eb859a27SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
310eb859a27SCédric Le Goater 
311eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
312eb859a27SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
313eb859a27SCédric Le Goater 
314eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
315eb859a27SCédric Le Goater     }
316eb859a27SCédric Le Goater 
317eb859a27SCédric Le Goater     if (chip->ram_size) {
318eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
319eb859a27SCédric Le Goater     }
32015376c66SCédric Le Goater 
32115376c66SCédric Le Goater     pnv_dt_lpc(chip, fdt, 0);
322eb859a27SCédric Le Goater }
323eb859a27SCédric Le Goater 
324b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
325c5ffdcaeSCédric Le Goater {
326c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
327c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
328c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
329c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
330c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
331c5ffdcaeSCédric Le Goater     };
332c5ffdcaeSCédric Le Goater     char *name;
333c5ffdcaeSCédric Le Goater     int node;
334c5ffdcaeSCédric Le Goater 
335c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
336c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
337c5ffdcaeSCédric Le Goater     _FDT(node);
338c5ffdcaeSCédric Le Goater     g_free(name);
339c5ffdcaeSCédric Le Goater 
340c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
341c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
342c5ffdcaeSCédric Le Goater }
343c5ffdcaeSCédric Le Goater 
344b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
345cb228f5aSCédric Le Goater {
346cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
347cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
348cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
349cb228f5aSCédric Le Goater         cpu_to_be32(1),
350cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
351cb228f5aSCédric Le Goater         cpu_to_be32(8)
352cb228f5aSCédric Le Goater     };
353cb228f5aSCédric Le Goater     char *name;
354cb228f5aSCédric Le Goater     int node;
355cb228f5aSCédric Le Goater 
356cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
357cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
358cb228f5aSCédric Le Goater     _FDT(node);
359cb228f5aSCédric Le Goater     g_free(name);
360cb228f5aSCédric Le Goater 
361cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
362cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
363cb228f5aSCédric Le Goater                       sizeof(compatible))));
364cb228f5aSCédric Le Goater 
365cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
366cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
367cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
368cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
369cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
370cb228f5aSCédric Le Goater 
371cb228f5aSCédric Le Goater     /* This is needed by Linux */
372cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
373cb228f5aSCédric Le Goater }
374cb228f5aSCédric Le Goater 
375b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
37604f6c8b2SCédric Le Goater {
37704f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
37804f6c8b2SCédric Le Goater     uint32_t io_base;
37904f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
38004f6c8b2SCédric Le Goater         cpu_to_be32(1),
38104f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
38204f6c8b2SCédric Le Goater         cpu_to_be32(3)
38304f6c8b2SCédric Le Goater     };
38404f6c8b2SCédric Le Goater     uint32_t irq;
38504f6c8b2SCédric Le Goater     char *name;
38604f6c8b2SCédric Le Goater     int node;
38704f6c8b2SCédric Le Goater 
38804f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
38904f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
39004f6c8b2SCédric Le Goater 
39104f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
39204f6c8b2SCédric Le Goater 
39304f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
39404f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
39504f6c8b2SCédric Le Goater     _FDT(node);
39604f6c8b2SCédric Le Goater     g_free(name);
39704f6c8b2SCédric Le Goater 
3987032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
3997032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4007032d92aSCédric Le Goater                       sizeof(compatible))));
40104f6c8b2SCédric Le Goater 
40204f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
40304f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
40404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
40504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
40604f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
40704f6c8b2SCédric Le Goater }
40804f6c8b2SCédric Le Goater 
409e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
410e7a3fee3SCédric Le Goater     void *fdt;
411e7a3fee3SCédric Le Goater     int offset;
412e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
413e7a3fee3SCédric Le Goater 
414b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
415e7a3fee3SCédric Le Goater {
416c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
417c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
418c5ffdcaeSCédric Le Goater 
419c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
420b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
421cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
422b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
42304f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
424b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
425c5ffdcaeSCédric Le Goater     } else {
426c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
427c5ffdcaeSCédric Le Goater                      d->ioport_id);
428c5ffdcaeSCédric Le Goater     }
429c5ffdcaeSCédric Le Goater 
430e7a3fee3SCédric Le Goater     return 0;
431e7a3fee3SCédric Le Goater }
432e7a3fee3SCédric Le Goater 
43359b7c1c2SBalamuruhan S /*
43459b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
435bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
436bb7ab95cSCédric Le Goater  */
437bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
438bb7ab95cSCédric Le Goater {
43964d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
440e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
441e7a3fee3SCédric Le Goater         .fdt = fdt,
442bb7ab95cSCédric Le Goater         .offset = isa_offset,
443e7a3fee3SCédric Le Goater     };
444f47a08d1SCédric Le Goater     uint32_t phandle;
445e7a3fee3SCédric Le Goater 
446bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
447bb7ab95cSCédric Le Goater 
448f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
449f47a08d1SCédric Le Goater     assert(phandle > 0);
450f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
451f47a08d1SCédric Le Goater 
45259b7c1c2SBalamuruhan S     /*
45359b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
45459b7c1c2SBalamuruhan S      * can not use object_child_foreach()
45559b7c1c2SBalamuruhan S      */
456bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
457bb7ab95cSCédric Le Goater                        &args);
458e7a3fee3SCédric Le Goater }
459e7a3fee3SCédric Le Goater 
460e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt)
461e5694793SCédric Le Goater {
462e5694793SCédric Le Goater     int off;
463e5694793SCédric Le Goater 
464e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
465e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
466e5694793SCédric Le Goater 
467e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
468e5694793SCédric Le Goater }
469e5694793SCédric Le Goater 
470b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4719e933f4aSBenjamin Herrenschmidt {
47283b90bf0SCédric Le Goater     const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
47383b90bf0SCédric Le Goater     const char plat_compat9[] = "qemu,powernv9\0ibm,powernv";
474b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
4759e933f4aSBenjamin Herrenschmidt     void *fdt;
4769e933f4aSBenjamin Herrenschmidt     char *buf;
4779e933f4aSBenjamin Herrenschmidt     int off;
478e997040eSCédric Le Goater     int i;
4799e933f4aSBenjamin Herrenschmidt 
4809e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
4819e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
4829e933f4aSBenjamin Herrenschmidt 
4839e933f4aSBenjamin Herrenschmidt     /* Root node */
4849e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
4859e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
4869e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
4879e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
48883b90bf0SCédric Le Goater     if (pnv_is_power9(pnv)) {
48983b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9,
49083b90bf0SCédric Le Goater                           sizeof(plat_compat9))));
49183b90bf0SCédric Le Goater     } else {
49283b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8,
49383b90bf0SCédric Le Goater                           sizeof(plat_compat8))));
49483b90bf0SCédric Le Goater     }
49583b90bf0SCédric Le Goater 
4969e933f4aSBenjamin Herrenschmidt 
4979e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
4989e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
4999e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5009e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5019e933f4aSBenjamin Herrenschmidt     }
5029e933f4aSBenjamin Herrenschmidt     g_free(buf);
5039e933f4aSBenjamin Herrenschmidt 
5049e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5059e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5069e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5079e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5089e933f4aSBenjamin Herrenschmidt     }
5099e933f4aSBenjamin Herrenschmidt 
5109e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5119e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5129e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5139e933f4aSBenjamin Herrenschmidt 
5149e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5159e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5169e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5179e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5189e933f4aSBenjamin Herrenschmidt     }
5199e933f4aSBenjamin Herrenschmidt 
520e997040eSCédric Le Goater     /* Populate device tree for each chip */
521e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
522eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
523e997040eSCédric Le Goater     }
524e7a3fee3SCédric Le Goater 
525e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
526bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
527aeaef83dSCédric Le Goater 
528aeaef83dSCédric Le Goater     if (pnv->bmc) {
529b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
530aeaef83dSCédric Le Goater     }
531aeaef83dSCédric Le Goater 
532e5694793SCédric Le Goater     /* Create an extra node for power management on Power9 */
533e5694793SCédric Le Goater     if (pnv_is_power9(pnv)) {
534e5694793SCédric Le Goater         pnv_dt_power_mgt(fdt);
535e5694793SCédric Le Goater     }
536e5694793SCédric Le Goater 
5379e933f4aSBenjamin Herrenschmidt     return fdt;
5389e933f4aSBenjamin Herrenschmidt }
5399e933f4aSBenjamin Herrenschmidt 
540bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
541bce0b691SCédric Le Goater {
542b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
543bce0b691SCédric Le Goater 
544bce0b691SCédric Le Goater     if (pnv->bmc) {
545bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
546bce0b691SCédric Le Goater     }
547bce0b691SCédric Le Goater }
548bce0b691SCédric Le Goater 
549a0628599SLike Xu static void pnv_reset(MachineState *machine)
5509e933f4aSBenjamin Herrenschmidt {
551b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5529e933f4aSBenjamin Herrenschmidt     void *fdt;
553aeaef83dSCédric Le Goater     Object *obj;
5549e933f4aSBenjamin Herrenschmidt 
5559e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5569e933f4aSBenjamin Herrenschmidt 
55759b7c1c2SBalamuruhan S     /*
55859b7c1c2SBalamuruhan S      * OpenPOWER systems have a BMC, which can be defined on the
559aeaef83dSCédric Le Goater      * command line with:
560aeaef83dSCédric Le Goater      *
561aeaef83dSCédric Le Goater      *   -device ipmi-bmc-sim,id=bmc0
562aeaef83dSCédric Le Goater      *
563aeaef83dSCédric Le Goater      * This is the internal simulator but it could also be an external
564aeaef83dSCédric Le Goater      * BMC.
565aeaef83dSCédric Le Goater      */
566a1a636b8SCédric Le Goater     obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL);
567aeaef83dSCédric Le Goater     if (obj) {
568aeaef83dSCédric Le Goater         pnv->bmc = IPMI_BMC(obj);
569aeaef83dSCédric Le Goater     }
570aeaef83dSCédric Le Goater 
571b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5729e933f4aSBenjamin Herrenschmidt 
5739e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5749e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5759e933f4aSBenjamin Herrenschmidt 
5768d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5779e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5789e933f4aSBenjamin Herrenschmidt }
5799e933f4aSBenjamin Herrenschmidt 
58004026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5813495b6b6SCédric Le Goater {
58277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58377864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
58404026890SCédric Le Goater }
5853495b6b6SCédric Le Goater 
58604026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
58704026890SCédric Le Goater {
58877864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58977864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
59004026890SCédric Le Goater }
5913495b6b6SCédric Le Goater 
59204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
59304026890SCédric Le Goater {
59415376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
59515376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
59604026890SCédric Le Goater }
5973495b6b6SCédric Le Goater 
59804026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
59904026890SCédric Le Goater {
60004026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6013495b6b6SCédric Le Goater }
6023495b6b6SCédric Le Goater 
603d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
604d8e4aad5SCédric Le Goater {
605d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
606d8e4aad5SCédric Le Goater 
607d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
608d8e4aad5SCédric Le Goater }
609d8e4aad5SCédric Le Goater 
610d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
611d8e4aad5SCédric Le Goater {
612d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
613d8e4aad5SCédric Le Goater 
614d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
615c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
616d8e4aad5SCédric Le Goater }
617d8e4aad5SCédric Le Goater 
618f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
619f30c843cSCédric Le Goater {
620f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
621f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
622f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
623f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
624f30c843cSCédric Le Goater 
625f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
626f30c843cSCédric Le Goater }
627f30c843cSCédric Le Goater 
628b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6299e933f4aSBenjamin Herrenschmidt {
630b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
631f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6329e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
6339e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6349e933f4aSBenjamin Herrenschmidt     long fw_size;
635e997040eSCédric Le Goater     int i;
636e997040eSCédric Le Goater     char *chip_typename;
637*35dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
638*35dde576SCédric Le Goater     DeviceState *dev;
6399e933f4aSBenjamin Herrenschmidt 
6409e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
641d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
6423dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
6439e933f4aSBenjamin Herrenschmidt     }
6449e933f4aSBenjamin Herrenschmidt 
6459e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
646b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6479e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6489e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6499e933f4aSBenjamin Herrenschmidt 
650*35dde576SCédric Le Goater     /*
651*35dde576SCédric Le Goater      * Create our simple PNOR device
652*35dde576SCédric Le Goater      */
653*35dde576SCédric Le Goater     dev = qdev_create(NULL, TYPE_PNV_PNOR);
654*35dde576SCédric Le Goater     if (pnor) {
655*35dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
656*35dde576SCédric Le Goater                             &error_abort);
657*35dde576SCédric Le Goater     }
658*35dde576SCédric Le Goater     qdev_init_nofail(dev);
659*35dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
660*35dde576SCédric Le Goater 
6619e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
6629e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
6639e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
6649e933f4aSBenjamin Herrenschmidt     }
6659e933f4aSBenjamin Herrenschmidt 
6669e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
66715fcedb2SCédric Le Goater     if (!fw_filename) {
66815fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
66915fcedb2SCédric Le Goater         exit(1);
67015fcedb2SCédric Le Goater     }
6719e933f4aSBenjamin Herrenschmidt 
6729e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
6739e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
67415fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
6759e933f4aSBenjamin Herrenschmidt         exit(1);
6769e933f4aSBenjamin Herrenschmidt     }
6779e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
6789e933f4aSBenjamin Herrenschmidt 
6799e933f4aSBenjamin Herrenschmidt     /* load kernel */
6809e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
6819e933f4aSBenjamin Herrenschmidt         long kernel_size;
6829e933f4aSBenjamin Herrenschmidt 
6839e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
684b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
6859e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
686802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
6879e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
6889e933f4aSBenjamin Herrenschmidt             exit(1);
6899e933f4aSBenjamin Herrenschmidt         }
6909e933f4aSBenjamin Herrenschmidt     }
6919e933f4aSBenjamin Herrenschmidt 
6929e933f4aSBenjamin Herrenschmidt     /* load initrd */
6939e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
6949e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
6959e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
696584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
6979e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
698802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
6999e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7009e933f4aSBenjamin Herrenschmidt             exit(1);
7019e933f4aSBenjamin Herrenschmidt         }
7029e933f4aSBenjamin Herrenschmidt     }
703e997040eSCédric Le Goater 
704f30c843cSCédric Le Goater     /*
705f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
706f30c843cSCédric Le Goater      * default.
707f30c843cSCédric Le Goater      */
708f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
709f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
710f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
711f30c843cSCédric Le Goater         exit(1);
712f30c843cSCédric Le Goater     }
713f30c843cSCédric Le Goater 
714e997040eSCédric Le Goater     /* Create the processor chips */
7154a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7167fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7174a12c699SIgor Mammedov                                     i, machine->cpu_type);
718e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
719f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
720f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
721e997040eSCédric Le Goater         exit(1);
722e997040eSCédric Le Goater     }
723e997040eSCédric Le Goater 
724e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
725e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
726e997040eSCédric Le Goater         char chip_name[32];
727e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
728e997040eSCédric Le Goater 
729e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
730e997040eSCédric Le Goater 
73159b7c1c2SBalamuruhan S         /*
73259b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
733e997040eSCédric Le Goater          * way to specify different ranges for each chip
734e997040eSCédric Le Goater          */
735e997040eSCédric Le Goater         if (i == 0) {
736e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
737e997040eSCédric Le Goater                                     &error_fatal);
738e997040eSCédric Le Goater         }
739e997040eSCédric Le Goater 
740e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
741e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
742e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
743e997040eSCédric Le Goater                                 &error_fatal);
744fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
745fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
746e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
747e997040eSCédric Le Goater     }
748e997040eSCédric Le Goater     g_free(chip_typename);
7493495b6b6SCédric Le Goater 
7503495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
75104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
7523495b6b6SCédric Le Goater 
7533495b6b6SCédric Le Goater     /* Create serial port */
754def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
7553495b6b6SCédric Le Goater 
7563495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
7576c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
758bce0b691SCédric Le Goater 
75959b7c1c2SBalamuruhan S     /*
76059b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
76159b7c1c2SBalamuruhan S      * host to powerdown
76259b7c1c2SBalamuruhan S      */
763bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
764bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
765e997040eSCédric Le Goater }
766e997040eSCédric Le Goater 
767631adaffSCédric Le Goater /*
768631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
769631adaffSCédric Le Goater  *   22:24  Chip ID
770631adaffSCédric Le Goater  *   25:28  Core number
771631adaffSCédric Le Goater  *   29:31  Thread ID
772631adaffSCédric Le Goater  */
773631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
774631adaffSCédric Le Goater {
775631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
776631adaffSCédric Le Goater }
777631adaffSCédric Le Goater 
7788fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
779d35aefa9SCédric Le Goater                                         Error **errp)
780d35aefa9SCédric Le Goater {
7818fa1f4efSCédric Le Goater     Error *local_err = NULL;
7828fa1f4efSCédric Le Goater     Object *obj;
7838907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
7848fa1f4efSCédric Le Goater 
7858fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
7868fa1f4efSCédric Le Goater                      &local_err);
7878fa1f4efSCédric Le Goater     if (local_err) {
7888fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
7898fa1f4efSCédric Le Goater         return;
7908fa1f4efSCédric Le Goater     }
7918fa1f4efSCédric Le Goater 
792956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
793d35aefa9SCédric Le Goater }
794d35aefa9SCédric Le Goater 
7950990ce6aSGreg Kurz 
796d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
797d49e8a9bSCédric Le Goater {
798d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
799d49e8a9bSCédric Le Goater 
800d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
801d49e8a9bSCédric Le Goater }
802d49e8a9bSCédric Le Goater 
8030990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8040990ce6aSGreg Kurz {
8050990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8060990ce6aSGreg Kurz 
8070990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
8080990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8090990ce6aSGreg Kurz }
8100990ce6aSGreg Kurz 
811631adaffSCédric Le Goater /*
812631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
813631adaffSCédric Le Goater  *   49:52  Node ID
814631adaffSCédric Le Goater  *   53:55  Chip ID
815631adaffSCédric Le Goater  *   56     Reserved - Read as zero
816631adaffSCédric Le Goater  *   57:61  Core number
817631adaffSCédric Le Goater  *   62:63  Thread ID
818631adaffSCédric Le Goater  *
819631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
820631adaffSCédric Le Goater  */
821631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
822631adaffSCédric Le Goater {
823631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
824631adaffSCédric Le Goater }
825631adaffSCédric Le Goater 
8268fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
827d35aefa9SCédric Le Goater                                         Error **errp)
828d35aefa9SCédric Le Goater {
8292dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
8302dfa91a2SCédric Le Goater     Error *local_err = NULL;
8312dfa91a2SCédric Le Goater     Object *obj;
8322dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8332dfa91a2SCédric Le Goater 
8342dfa91a2SCédric Le Goater     /*
8352dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
8362dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
8372dfa91a2SCédric Le Goater      * only used at runtime.
8382dfa91a2SCédric Le Goater      */
83926aa5b1eSGreg Kurz     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err);
8402dfa91a2SCédric Le Goater     if (local_err) {
8412dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
8428fa1f4efSCédric Le Goater         return;
843d35aefa9SCédric Le Goater     }
844d35aefa9SCédric Le Goater 
8452dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
8462dfa91a2SCédric Le Goater }
8472dfa91a2SCédric Le Goater 
848d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
849d49e8a9bSCédric Le Goater {
850d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
851d49e8a9bSCédric Le Goater 
852d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
853d49e8a9bSCédric Le Goater }
854d49e8a9bSCédric Le Goater 
8550990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8560990ce6aSGreg Kurz {
8570990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8580990ce6aSGreg Kurz 
8590990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
8600990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8610990ce6aSGreg Kurz }
8620990ce6aSGreg Kurz 
86359b7c1c2SBalamuruhan S /*
86459b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
865397a79e7SCédric Le Goater  *
866397a79e7SCédric Le Goater  * <EX0 reserved>
867397a79e7SCédric Le Goater  *  EX1  - Venice only
868397a79e7SCédric Le Goater  *  EX2  - Venice only
869397a79e7SCédric Le Goater  *  EX3  - Venice only
870397a79e7SCédric Le Goater  *  EX4
871397a79e7SCédric Le Goater  *  EX5
872397a79e7SCédric Le Goater  *  EX6
873397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
874397a79e7SCédric Le Goater  *  EX9  - Venice only
875397a79e7SCédric Le Goater  *  EX10 - Venice only
876397a79e7SCédric Le Goater  *  EX11 - Venice only
877397a79e7SCédric Le Goater  *  EX12
878397a79e7SCédric Le Goater  *  EX13
879397a79e7SCédric Le Goater  *  EX14
880397a79e7SCédric Le Goater  * <EX15 reserved>
881397a79e7SCédric Le Goater  */
882397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
883397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
884397a79e7SCédric Le Goater 
885397a79e7SCédric Le Goater /*
88609279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
887397a79e7SCédric Le Goater  */
88809279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
889397a79e7SCédric Le Goater 
89077864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
89177864267SCédric Le Goater {
89277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
89377864267SCédric Le Goater 
894f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
895ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
89677864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
89777864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
89877864267SCédric Le Goater 
899f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
90082514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
90177864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
90277864267SCédric Le Goater                                    OBJECT(&chip8->psi), &error_abort);
90377864267SCédric Le Goater 
904f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
9053233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
90677864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->occ), "psi",
90777864267SCédric Le Goater                                    OBJECT(&chip8->psi), &error_abort);
9083887d241SBalamuruhan S 
9093887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
9103887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
9113887d241SBalamuruhan S     object_property_add_const_link(OBJECT(&chip8->homer), "chip", obj,
9123887d241SBalamuruhan S                                    &error_abort);
91377864267SCédric Le Goater }
91477864267SCédric Le Goater 
91577864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
91677864267SCédric Le Goater  {
91777864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
91877864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
91977864267SCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
92077864267SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
92177864267SCédric Le Goater     int i, j;
92277864267SCédric Le Goater     char *name;
92377864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
92477864267SCédric Le Goater 
92577864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
92677864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
92777864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
92877864267SCédric Le Goater     g_free(name);
92977864267SCédric Le Goater 
93077864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
93177864267SCédric Le Goater 
93277864267SCédric Le Goater     /* Map the ICP registers for each thread */
93377864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
93477864267SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
93577864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
93677864267SCédric Le Goater 
93777864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
93877864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
93977864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
94077864267SCédric Le Goater 
94177864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
94277864267SCédric Le Goater                                         &icp->mmio);
94377864267SCédric Le Goater         }
94477864267SCédric Le Goater     }
94577864267SCédric Le Goater }
94677864267SCédric Le Goater 
94777864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
94877864267SCédric Le Goater {
94977864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
95077864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
95177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
952ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
95377864267SCédric Le Goater     Error *local_err = NULL;
95477864267SCédric Le Goater 
955709044fdSCédric Le Goater     /* XSCOM bridge is first */
956709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
957709044fdSCédric Le Goater     if (local_err) {
958709044fdSCédric Le Goater         error_propagate(errp, local_err);
959709044fdSCédric Le Goater         return;
960709044fdSCédric Le Goater     }
961709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
962709044fdSCédric Le Goater 
96377864267SCédric Le Goater     pcc->parent_realize(dev, &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     }
96877864267SCédric Le Goater 
96977864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
97077864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
97177864267SCédric Le Goater                             "bar", &error_fatal);
97277864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
97377864267SCédric Le Goater     if (local_err) {
97477864267SCédric Le Goater         error_propagate(errp, local_err);
97577864267SCédric Le Goater         return;
97677864267SCédric Le Goater     }
977ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
978ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
97977864267SCédric Le Goater 
98077864267SCédric Le Goater     /* Create LPC controller */
98177864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
98277864267SCédric Le Goater                              &error_fatal);
98377864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
98477864267SCédric Le Goater 
98564d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
98664d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
98764d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
98864d011d5SCédric Le Goater 
98959b7c1c2SBalamuruhan S     /*
99059b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
99159b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
99259b7c1c2SBalamuruhan S      */
99377864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
99477864267SCédric Le Goater     if (local_err) {
99577864267SCédric Le Goater         error_propagate(errp, local_err);
99677864267SCédric Le Goater         return;
99777864267SCédric Le Goater     }
99877864267SCédric Le Goater 
99977864267SCédric Le Goater     /* Create the simplified OCC model */
100077864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
100177864267SCédric Le Goater     if (local_err) {
100277864267SCédric Le Goater         error_propagate(errp, local_err);
100377864267SCédric Le Goater         return;
100477864267SCédric Le Goater     }
100577864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1006f3db8266SBalamuruhan S 
1007f3db8266SBalamuruhan S     /* OCC SRAM model */
1008f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip),
1009f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
10103887d241SBalamuruhan S 
10113887d241SBalamuruhan S     /* HOMER */
10123887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
10133887d241SBalamuruhan S                              &local_err);
10143887d241SBalamuruhan S     if (local_err) {
10153887d241SBalamuruhan S         error_propagate(errp, local_err);
10163887d241SBalamuruhan S         return;
10173887d241SBalamuruhan S     }
10183887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
10193887d241SBalamuruhan S                                 &chip8->homer.regs);
102077864267SCédric Le Goater }
102177864267SCédric Le Goater 
1022e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1023e997040eSCédric Le Goater {
1024e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1025e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1026e997040eSCédric Le Goater 
1027e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
1028e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1029397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
1030631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1031d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1032d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10330990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
103404026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1035eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1036d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1037e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
103877864267SCédric Le Goater 
103977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
104077864267SCédric Le Goater                                     &k->parent_realize);
1041e997040eSCédric Le Goater }
1042e997040eSCédric Le Goater 
1043e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1044e997040eSCédric Le Goater {
1045e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1046e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1047e997040eSCédric Le Goater 
1048e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
1049e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1050397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1051631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1052d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1053d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10540990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
105504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1056eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1057d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1058e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
105977864267SCédric Le Goater 
106077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
106177864267SCédric Le Goater                                     &k->parent_realize);
1062e997040eSCédric Le Goater }
1063e997040eSCédric Le Goater 
1064e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1065e997040eSCédric Le Goater {
1066e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1067e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1068e997040eSCédric Le Goater 
1069e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
1070e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1071397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1072631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1073d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1074d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10750990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
107604026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1077eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1078d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1079e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
108077864267SCédric Le Goater 
108177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
108277864267SCédric Le Goater                                     &k->parent_realize);
108377864267SCédric Le Goater }
108477864267SCédric Le Goater 
108577864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
108677864267SCédric Le Goater {
10872dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
10882dfa91a2SCédric Le Goater 
10892dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
10902dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
10912dfa91a2SCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj,
10922dfa91a2SCédric Le Goater                                    &error_abort);
1093c38536bcSCédric Le Goater 
1094c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1095c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
1096c38536bcSCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj,
1097c38536bcSCédric Le Goater                                    &error_abort);
109815376c66SCédric Le Goater 
109915376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
110015376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
110115376c66SCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->lpc), "psi",
110215376c66SCédric Le Goater                                    OBJECT(&chip9->psi), &error_abort);
11036598a70dSCédric Le Goater 
11046598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
11056598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
11066598a70dSCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->occ), "psi",
11076598a70dSCédric Le Goater                                    OBJECT(&chip9->psi), &error_abort);
11083887d241SBalamuruhan S 
11093887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
11103887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
11113887d241SBalamuruhan S     object_property_add_const_link(OBJECT(&chip9->homer), "chip", obj,
11123887d241SBalamuruhan S                                    &error_abort);
111377864267SCédric Le Goater }
111477864267SCédric Le Goater 
11155dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
11165dad902cSCédric Le Goater {
11175dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
11185dad902cSCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
11195dad902cSCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
11205dad902cSCédric Le Goater     int i;
11215dad902cSCédric Le Goater 
11225dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
11235dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
11245dad902cSCédric Le Goater 
11255dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
11265dad902cSCédric Le Goater         char eq_name[32];
11275dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
11285dad902cSCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize);
11295dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
11305dad902cSCédric Le Goater 
11315dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1132bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1133bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
11345dad902cSCédric Le Goater 
11355dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
11365dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
11375dad902cSCédric Le Goater 
11385dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
11395dad902cSCédric Le Goater                                 &eq->xscom_regs);
11405dad902cSCédric Le Goater     }
11415dad902cSCédric Le Goater }
11425dad902cSCédric Le Goater 
114377864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
114477864267SCédric Le Goater {
114577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
11462dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
11472dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1148c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
114977864267SCédric Le Goater     Error *local_err = NULL;
115077864267SCédric Le Goater 
1151709044fdSCédric Le Goater     /* XSCOM bridge is first */
1152709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1153709044fdSCédric Le Goater     if (local_err) {
1154709044fdSCédric Le Goater         error_propagate(errp, local_err);
1155709044fdSCédric Le Goater         return;
1156709044fdSCédric Le Goater     }
1157709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1158709044fdSCédric Le Goater 
115977864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
116077864267SCédric Le Goater     if (local_err) {
116177864267SCédric Le Goater         error_propagate(errp, local_err);
116277864267SCédric Le Goater         return;
116377864267SCédric Le Goater     }
11642dfa91a2SCédric Le Goater 
11655dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
11665dad902cSCédric Le Goater     if (local_err) {
11675dad902cSCédric Le Goater         error_propagate(errp, local_err);
11685dad902cSCédric Le Goater         return;
11695dad902cSCédric Le Goater     }
11705dad902cSCédric Le Goater 
11712dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
11722dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
11732dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
11742dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
11752dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
11762dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
11772dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
11782dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
11792dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
11802dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
11812dfa91a2SCédric Le Goater                              &local_err);
11822dfa91a2SCédric Le Goater     if (local_err) {
11832dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
11842dfa91a2SCédric Le Goater         return;
11852dfa91a2SCédric Le Goater     }
11862dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
11872dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1188c38536bcSCédric Le Goater 
1189c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1190c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1191c38536bcSCédric Le Goater                             "bar", &error_fatal);
1192c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1193c38536bcSCédric Le Goater     if (local_err) {
1194c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1195c38536bcSCédric Le Goater         return;
1196c38536bcSCédric Le Goater     }
1197c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1198c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
119915376c66SCédric Le Goater 
120015376c66SCédric Le Goater     /* LPC */
120115376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
120215376c66SCédric Le Goater     if (local_err) {
120315376c66SCédric Le Goater         error_propagate(errp, local_err);
120415376c66SCédric Le Goater         return;
120515376c66SCédric Le Goater     }
120615376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
120715376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
120815376c66SCédric Le Goater 
120915376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
121015376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
12116598a70dSCédric Le Goater 
12126598a70dSCédric Le Goater     /* Create the simplified OCC model */
12136598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
12146598a70dSCédric Le Goater     if (local_err) {
12156598a70dSCédric Le Goater         error_propagate(errp, local_err);
12166598a70dSCédric Le Goater         return;
12176598a70dSCédric Le Goater     }
12186598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1219f3db8266SBalamuruhan S 
1220f3db8266SBalamuruhan S     /* OCC SRAM model */
1221f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip),
1222f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
12233887d241SBalamuruhan S 
12243887d241SBalamuruhan S     /* HOMER */
12253887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
12263887d241SBalamuruhan S                              &local_err);
12273887d241SBalamuruhan S     if (local_err) {
12283887d241SBalamuruhan S         error_propagate(errp, local_err);
12293887d241SBalamuruhan S         return;
12303887d241SBalamuruhan S     }
12313887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
12323887d241SBalamuruhan S                                 &chip9->homer.regs);
1233e997040eSCédric Le Goater }
1234e997040eSCédric Le Goater 
1235e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1236e997040eSCédric Le Goater {
1237e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1238e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1239e997040eSCédric Le Goater 
1240e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
124183028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1242397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1243631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1244d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1245d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
12460990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
124704026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1248eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1249d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1250e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
125177864267SCédric Le Goater 
125277864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
125377864267SCédric Le Goater                                     &k->parent_realize);
1254e997040eSCédric Le Goater }
1255e997040eSCédric Le Goater 
1256397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1257397a79e7SCédric Le Goater {
1258397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1259397a79e7SCédric Le Goater     int cores_max;
1260397a79e7SCédric Le Goater 
1261397a79e7SCédric Le Goater     /*
1262397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1263397a79e7SCédric Le Goater      * the chip class
1264397a79e7SCédric Le Goater      */
1265397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1266397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1267397a79e7SCédric Le Goater     }
1268397a79e7SCédric Le Goater 
1269397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1270397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1271397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1272397a79e7SCédric Le Goater                    chip->cores_mask);
1273397a79e7SCédric Le Goater         return;
1274397a79e7SCédric Le Goater     }
1275397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1276397a79e7SCédric Le Goater 
1277397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
127827d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1279397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1280397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1281397a79e7SCédric Le Goater                    cores_max);
1282397a79e7SCédric Le Goater         return;
1283397a79e7SCédric Le Goater     }
1284397a79e7SCédric Le Goater }
1285397a79e7SCédric Le Goater 
128651c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1287e997040eSCédric Le Goater {
1288fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1289397a79e7SCédric Le Goater     Error *error = NULL;
1290d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
129140abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1292d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
1293d2fd9612SCédric Le Goater     int i, core_hwid;
1294397a79e7SCédric Le Goater 
1295d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1296d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1297d2fd9612SCédric Le Goater         return;
1298d2fd9612SCédric Le Goater     }
1299d2fd9612SCédric Le Goater 
1300d2fd9612SCédric Le Goater     /* Cores */
1301397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1302397a79e7SCédric Le Goater     if (error) {
1303397a79e7SCédric Le Goater         error_propagate(errp, error);
1304397a79e7SCédric Le Goater         return;
1305397a79e7SCédric Le Goater     }
1306d2fd9612SCédric Le Goater 
1307d2fd9612SCédric Le Goater     chip->cores = g_malloc0(typesize * chip->nr_cores);
1308d2fd9612SCédric Le Goater 
1309d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1310d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1311d2fd9612SCédric Le Goater         char core_name[32];
1312d2fd9612SCédric Le Goater         void *pnv_core = chip->cores + i * typesize;
1313c035851aSCédric Le Goater         uint64_t xscom_core_base;
1314d2fd9612SCédric Le Goater 
1315d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1316d2fd9612SCédric Le Goater             continue;
1317d2fd9612SCédric Le Goater         }
1318d2fd9612SCédric Le Goater 
1319d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1320bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize,
1321bc4c406cSPhilippe Mathieu-Daudé                                 typename, &error_fatal, NULL);
1322fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1323d2fd9612SCédric Le Goater                                 &error_fatal);
1324d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1325d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1326d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1327d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1328d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1329d35aefa9SCédric Le Goater         object_property_add_const_link(OBJECT(pnv_core), "chip",
1330d35aefa9SCédric Le Goater                                        OBJECT(chip), &error_fatal);
1331d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1332d2fd9612SCédric Le Goater                                  &error_fatal);
133324ece072SCédric Le Goater 
133424ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1335c035851aSCédric Le Goater         if (!pnv_chip_is_power9(chip)) {
1336c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
1337c035851aSCédric Le Goater         } else {
13385dad902cSCédric Le Goater             xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid);
1339c035851aSCédric Le Goater         }
1340c035851aSCédric Le Goater 
1341c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
134224ece072SCédric Le Goater                                 &PNV_CORE(pnv_core)->xscom_regs);
1343d2fd9612SCédric Le Goater         i++;
1344d2fd9612SCédric Le Goater     }
134551c04728SCédric Le Goater }
134651c04728SCédric Le Goater 
134751c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
134851c04728SCédric Le Goater {
134951c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
135051c04728SCédric Le Goater     Error *error = NULL;
135151c04728SCédric Le Goater 
135251c04728SCédric Le Goater     /* Cores */
135351c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
135451c04728SCédric Le Goater     if (error) {
135551c04728SCédric Le Goater         error_propagate(errp, error);
135651c04728SCédric Le Goater         return;
135751c04728SCédric Le Goater     }
1358e997040eSCédric Le Goater }
1359e997040eSCédric Le Goater 
1360e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1361e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1362e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1363e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1364397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1365397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1366e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1367e997040eSCédric Le Goater };
1368e997040eSCédric Le Goater 
1369e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1370e997040eSCédric Le Goater {
1371e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1372e997040eSCédric Le Goater 
13739d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1374e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1375e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1376e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1377e997040eSCédric Le Goater }
1378e997040eSCédric Le Goater 
137954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
138054f59d78SCédric Le Goater {
1381b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
138254f59d78SCédric Le Goater     int i;
138354f59d78SCédric Le Goater 
138454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
138577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
138677864267SCédric Le Goater 
138777864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
138877864267SCédric Le Goater             return &chip8->psi.ics;
138954f59d78SCédric Le Goater         }
139054f59d78SCédric Le Goater     }
139154f59d78SCédric Le Goater     return NULL;
139254f59d78SCédric Le Goater }
139354f59d78SCédric Le Goater 
139454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
139554f59d78SCédric Le Goater {
1396b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
139754f59d78SCédric Le Goater     int i;
139854f59d78SCédric Le Goater 
139954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
140077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
140177864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
140254f59d78SCédric Le Goater     }
140354f59d78SCédric Le Goater }
140454f59d78SCédric Le Goater 
140536fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
140636fc6f08SCédric Le Goater {
140736fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
140836fc6f08SCédric Le Goater 
1409956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
141036fc6f08SCédric Le Goater }
141136fc6f08SCédric Le Goater 
141247fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
141347fea43aSCédric Le Goater                                Monitor *mon)
141447fea43aSCédric Le Goater {
1415b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
141654f59d78SCédric Le Goater     int i;
141747fea43aSCédric Le Goater     CPUState *cs;
141847fea43aSCédric Le Goater 
141947fea43aSCédric Le Goater     CPU_FOREACH(cs) {
142047fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
142147fea43aSCédric Le Goater 
1422d8e4aad5SCédric Le Goater         if (pnv_chip_is_power9(pnv->chips[0])) {
1423d8e4aad5SCédric Le Goater             xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
1424d8e4aad5SCédric Le Goater         } else {
1425956b8f46SCédric Le Goater             icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
142647fea43aSCédric Le Goater         }
1427d8e4aad5SCédric Le Goater     }
142854f59d78SCédric Le Goater 
142954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1430d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
143154f59d78SCédric Le Goater     }
143247fea43aSCédric Le Goater }
143347fea43aSCédric Le Goater 
1434e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1435e997040eSCédric Le Goater                               void *opaque, Error **errp)
1436e997040eSCédric Le Goater {
1437b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1438e997040eSCédric Le Goater }
1439e997040eSCédric Le Goater 
1440e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1441e997040eSCédric Le Goater                               void *opaque, Error **errp)
1442e997040eSCédric Le Goater {
1443b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1444e997040eSCédric Le Goater     uint32_t num_chips;
1445e997040eSCédric Le Goater     Error *local_err = NULL;
1446e997040eSCédric Le Goater 
1447e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1448e997040eSCédric Le Goater     if (local_err) {
1449e997040eSCédric Le Goater         error_propagate(errp, local_err);
1450e997040eSCédric Le Goater         return;
1451e997040eSCédric Le Goater     }
1452e997040eSCédric Le Goater 
1453e997040eSCédric Le Goater     /*
1454e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1455e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1456e997040eSCédric Le Goater      */
1457e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1458e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1459e997040eSCédric Le Goater         return;
1460e997040eSCédric Le Goater     }
1461e997040eSCédric Le Goater 
1462e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1463e997040eSCédric Le Goater }
1464e997040eSCédric Le Goater 
146577864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1466e997040eSCédric Le Goater {
1467b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1468e997040eSCédric Le Goater     pnv->num_chips = 1;
1469e997040eSCédric Le Goater }
1470e997040eSCédric Le Goater 
1471b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1472e997040eSCédric Le Goater {
14731e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1474e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1475e997040eSCédric Le Goater                               NULL, NULL, NULL);
1476e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1477e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1478e997040eSCédric Le Goater                               NULL);
14799e933f4aSBenjamin Herrenschmidt }
14809e933f4aSBenjamin Herrenschmidt 
1481f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
14829e933f4aSBenjamin Herrenschmidt {
14839e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
148436fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1485f30c843cSCédric Le Goater 
1486f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1487f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1488f30c843cSCédric Le Goater 
1489f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1490f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1491f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1492f30c843cSCédric Le Goater }
1493f30c843cSCédric Le Goater 
1494f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1495f30c843cSCédric Le Goater {
1496f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1497f30c843cSCédric Le Goater 
1498f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1499f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1500f30c843cSCédric Le Goater 
1501f30c843cSCédric Le Goater     mc->alias = "powernv";
1502f30c843cSCédric Le Goater }
1503f30c843cSCédric Le Goater 
1504f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1505f30c843cSCédric Le Goater {
1506f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
150747fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
15089e933f4aSBenjamin Herrenschmidt 
15099e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1510b168a138SCédric Le Goater     mc->init = pnv_init;
1511b168a138SCédric Le Goater     mc->reset = pnv_reset;
15129e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
151359b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
151459b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
15159e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
15169e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1517f1d18b0aSJoel Stanley     /*
1518f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1519f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1520f1d18b0aSJoel Stanley      */
1521f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
152247fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1523e997040eSCédric Le Goater 
1524b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
15259e933f4aSBenjamin Herrenschmidt }
15269e933f4aSBenjamin Herrenschmidt 
152777864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1528beba5c0fSIgor Mammedov     {                                             \
1529beba5c0fSIgor Mammedov         .name          = type,                    \
1530beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
153177864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
153277864267SCédric Le Goater     }
153377864267SCédric Le Goater 
153477864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
153577864267SCédric Le Goater     {                                             \
153677864267SCédric Le Goater         .name          = type,                    \
153777864267SCédric Le Goater         .class_init    = class_initfn,            \
153877864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1539beba5c0fSIgor Mammedov     }
1540beba5c0fSIgor Mammedov 
1541beba5c0fSIgor Mammedov static const TypeInfo types[] = {
15421aba8716SCédric Le Goater     {
15431aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
15441aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
15451aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
15461aba8716SCédric Le Goater     },
15471aba8716SCédric Le Goater     {
15481aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
15491aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
15501aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
15511aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
15521aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
15531aba8716SCédric Le Goater             { },
15541aba8716SCédric Le Goater         },
15551aba8716SCédric Le Goater     },
1556beba5c0fSIgor Mammedov     {
1557b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
15589e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1559f30c843cSCédric Le Goater         .abstract       = true,
15609e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
156177864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1562b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
156336fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
156447fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
156536fc6f08SCédric Le Goater             { },
156636fc6f08SCédric Le Goater         },
1567beba5c0fSIgor Mammedov     },
1568beba5c0fSIgor Mammedov     {
1569beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1570beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1571beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1572beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1573beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1574beba5c0fSIgor Mammedov         .abstract      = true,
1575beba5c0fSIgor Mammedov     },
157677864267SCédric Le Goater 
157777864267SCédric Le Goater     /*
157877864267SCédric Le Goater      * P9 chip and variants
157977864267SCédric Le Goater      */
158077864267SCédric Le Goater     {
158177864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
158277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
158377864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
158477864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
158577864267SCédric Le Goater     },
158677864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
158777864267SCédric Le Goater 
158877864267SCédric Le Goater     /*
158977864267SCédric Le Goater      * P8 chip and variants
159077864267SCédric Le Goater      */
159177864267SCédric Le Goater     {
159277864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
159377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
159477864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
159577864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
159677864267SCédric Le Goater     },
159777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
159877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
159977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1600beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
16019e933f4aSBenjamin Herrenschmidt };
16029e933f4aSBenjamin Herrenschmidt 
1603beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1604