xref: /qemu/hw/ppc/pnv.c (revision 8b50ce85)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
99e933f4aSBenjamin Herrenschmidt  * version 2 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2671e8a915SMarkus Armbruster #include "sysemu/reset.h"
2754d31236SMarkus Armbruster #include "sysemu/runstate.h"
28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
298d409261SCédric Le Goater #include "sysemu/device_tree.h"
30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
38e997040eSCédric Le Goater #include "qapi/visitor.h"
3947fea43aSCédric Le Goater #include "monitor/monitor.h"
4047fea43aSCédric Le Goater #include "hw/intc/intc.h"
41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
439e933f4aSBenjamin Herrenschmidt 
4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
4735dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
48967b7523SCédric Le Goater 
493495b6b6SCédric Le Goater #include "hw/isa/isa.h"
5012e9493dSMarkus Armbruster #include "hw/boards.h"
513495b6b6SCédric Le Goater #include "hw/char/serial.h"
52bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
533495b6b6SCédric Le Goater 
549e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
559e933f4aSBenjamin Herrenschmidt 
56b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
579e933f4aSBenjamin Herrenschmidt 
589e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
599e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
60b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
619e933f4aSBenjamin Herrenschmidt 
629e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
63b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
64fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
65584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
669e933f4aSBenjamin Herrenschmidt 
6740abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
6840abf43fSIgor Mammedov {
6940abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7040abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7140abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7240abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7340abf43fSIgor Mammedov     g_free(s);
7440abf43fSIgor Mammedov     return core_type;
7540abf43fSIgor Mammedov }
7640abf43fSIgor Mammedov 
779e933f4aSBenjamin Herrenschmidt /*
789e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
799e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
809e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
819e933f4aSBenjamin Herrenschmidt  */
829e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
839e933f4aSBenjamin Herrenschmidt 
849e933f4aSBenjamin Herrenschmidt /*
859e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
869e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
879e933f4aSBenjamin Herrenschmidt  * per chip.
889e933f4aSBenjamin Herrenschmidt  */
89b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
909e933f4aSBenjamin Herrenschmidt {
919e933f4aSBenjamin Herrenschmidt     char *mem_name;
929e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
939e933f4aSBenjamin Herrenschmidt     int off;
949e933f4aSBenjamin Herrenschmidt 
959e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
969e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
979e933f4aSBenjamin Herrenschmidt 
989e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
999e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1009e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1019e933f4aSBenjamin Herrenschmidt 
1029e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1039e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1049e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1069e933f4aSBenjamin Herrenschmidt }
1079e933f4aSBenjamin Herrenschmidt 
108d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
109d2fd9612SCédric Le Goater {
110d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
111d2fd9612SCédric Le Goater 
112d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
113a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
114d2fd9612SCédric Le Goater         if (cpus_offset) {
115d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
116d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
117d2fd9612SCédric Le Goater         }
118d2fd9612SCédric Le Goater     }
119d2fd9612SCédric Le Goater     _FDT(cpus_offset);
120d2fd9612SCédric Le Goater     return cpus_offset;
121d2fd9612SCédric Le Goater }
122d2fd9612SCédric Le Goater 
123d2fd9612SCédric Le Goater /*
124d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
125d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
126d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
127d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
128d2fd9612SCédric Le Goater  * servers.
129d2fd9612SCédric Le Goater  */
130b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
131d2fd9612SCédric Le Goater {
13208304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13308304a86SDavid Gibson     CPUState *cs = CPU(cpu);
134d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1358bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
136d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
137d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
138d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
139d2fd9612SCédric Le Goater     int i;
140d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
141d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
142d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
143d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
144d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
145d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
146d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
147d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
148d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
149d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
150d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
151d2fd9612SCédric Le Goater     int offset;
152d2fd9612SCédric Le Goater     char *nodename;
153d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
154d2fd9612SCédric Le Goater 
155d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
156d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
157d2fd9612SCédric Le Goater     _FDT(offset);
158d2fd9612SCédric Le Goater     g_free(nodename);
159d2fd9612SCédric Le Goater 
160d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
161d2fd9612SCédric Le Goater 
162d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
164d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
165d2fd9612SCédric Le Goater 
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
168d2fd9612SCédric Le Goater                             env->dcache_line_size)));
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
170d2fd9612SCédric Le Goater                             env->dcache_line_size)));
171d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
172d2fd9612SCédric Le Goater                             env->icache_line_size)));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
174d2fd9612SCédric Le Goater                             env->icache_line_size)));
175d2fd9612SCédric Le Goater 
176d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
177d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
178d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
179d2fd9612SCédric Le Goater     } else {
1803dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
181d2fd9612SCédric Le Goater     }
182d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
183d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
184d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
185d2fd9612SCédric Le Goater     } else {
1863dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
187d2fd9612SCédric Le Goater     }
188d2fd9612SCédric Le Goater 
189d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
190d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19159b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19259b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
194d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
195d2fd9612SCédric Le Goater 
196d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
197d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
198d2fd9612SCédric Le Goater     }
199d2fd9612SCédric Le Goater 
20058969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
201d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
202d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
203d2fd9612SCédric Le Goater     }
204d2fd9612SCédric Le Goater 
20559b7c1c2SBalamuruhan S     /*
20659b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
207d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
208d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
20959b7c1c2SBalamuruhan S      *   2               == VSX available
21059b7c1c2SBalamuruhan S      */
211d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
212d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
213d2fd9612SCédric Le Goater 
214d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
215d2fd9612SCédric Le Goater     }
216d2fd9612SCédric Le Goater 
21759b7c1c2SBalamuruhan S     /*
21859b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
219d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22059b7c1c2SBalamuruhan S      *   1               == DFP available
22159b7c1c2SBalamuruhan S      */
222d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
223d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
224d2fd9612SCédric Le Goater     }
225d2fd9612SCédric Le Goater 
226644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
227d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
228d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
229d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
230d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
231d2fd9612SCédric Le Goater     }
232d2fd9612SCédric Le Goater 
233d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
234d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
235d2fd9612SCédric Le Goater 
236d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
237d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
238d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
239d2fd9612SCédric Le Goater     }
240d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
241d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
242d2fd9612SCédric Le Goater }
243d2fd9612SCédric Le Goater 
244b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
245bf5615e7SCédric Le Goater                        uint32_t nr_threads)
246bf5615e7SCédric Le Goater {
247bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
248bf5615e7SCédric Le Goater     char *name;
249bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
250bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
251bf5615e7SCédric Le Goater     uint64_t *reg;
252bf5615e7SCédric Le Goater     int offset;
253bf5615e7SCédric Le Goater 
254bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
255bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
256bf5615e7SCédric Le Goater 
257bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
258bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
259bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
260bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
261bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
262bf5615e7SCédric Le Goater     }
263bf5615e7SCédric Le Goater 
264bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
265bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
266bf5615e7SCédric Le Goater     _FDT(offset);
267bf5615e7SCédric Le Goater     g_free(name);
268bf5615e7SCédric Le Goater 
269bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
270bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
271bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
272bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
275bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
278bf5615e7SCédric Le Goater     g_free(reg);
279bf5615e7SCédric Le Goater }
280bf5615e7SCédric Le Goater 
281eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
282e997040eSCédric Le Goater {
283d2fd9612SCédric Le Goater     int i;
284d2fd9612SCédric Le Goater 
285b168a138SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
286967b7523SCédric Le Goater 
287d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2884fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
289d2fd9612SCédric Le Goater 
290b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
291bf5615e7SCédric Le Goater 
292bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
293b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
294d2fd9612SCédric Le Goater     }
295d2fd9612SCédric Le Goater 
296e997040eSCédric Le Goater     if (chip->ram_size) {
297b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
298e997040eSCédric Le Goater     }
299e997040eSCédric Le Goater }
300e997040eSCédric Le Goater 
301eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
302eb859a27SCédric Le Goater {
303eb859a27SCédric Le Goater     int i;
304eb859a27SCédric Le Goater 
305eb859a27SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
306eb859a27SCédric Le Goater 
307eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3084fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
309eb859a27SCédric Le Goater 
310eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
311eb859a27SCédric Le Goater     }
312eb859a27SCédric Le Goater 
313eb859a27SCédric Le Goater     if (chip->ram_size) {
314eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
315eb859a27SCédric Le Goater     }
31615376c66SCédric Le Goater 
31715376c66SCédric Le Goater     pnv_dt_lpc(chip, fdt, 0);
318eb859a27SCédric Le Goater }
319eb859a27SCédric Le Goater 
3202b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3212b548a42SCédric Le Goater {
3222b548a42SCédric Le Goater     int i;
3232b548a42SCédric Le Goater 
3242b548a42SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
3252b548a42SCédric Le Goater 
3262b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3272b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3282b548a42SCédric Le Goater 
3292b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3302b548a42SCédric Le Goater     }
3312b548a42SCédric Le Goater 
3322b548a42SCédric Le Goater     if (chip->ram_size) {
3332b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3342b548a42SCédric Le Goater     }
3352b548a42SCédric Le Goater }
3362b548a42SCédric Le Goater 
337b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
338c5ffdcaeSCédric Le Goater {
339c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
340c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
341c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
342c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
343c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
344c5ffdcaeSCédric Le Goater     };
345c5ffdcaeSCédric Le Goater     char *name;
346c5ffdcaeSCédric Le Goater     int node;
347c5ffdcaeSCédric Le Goater 
348c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
349c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
350c5ffdcaeSCédric Le Goater     _FDT(node);
351c5ffdcaeSCédric Le Goater     g_free(name);
352c5ffdcaeSCédric Le Goater 
353c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
354c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
355c5ffdcaeSCédric Le Goater }
356c5ffdcaeSCédric Le Goater 
357b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
358cb228f5aSCédric Le Goater {
359cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
360cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
361cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
362cb228f5aSCédric Le Goater         cpu_to_be32(1),
363cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
364cb228f5aSCédric Le Goater         cpu_to_be32(8)
365cb228f5aSCédric Le Goater     };
366cb228f5aSCédric Le Goater     char *name;
367cb228f5aSCédric Le Goater     int node;
368cb228f5aSCédric Le Goater 
369cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
370cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
371cb228f5aSCédric Le Goater     _FDT(node);
372cb228f5aSCédric Le Goater     g_free(name);
373cb228f5aSCédric Le Goater 
374cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
375cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
376cb228f5aSCédric Le Goater                       sizeof(compatible))));
377cb228f5aSCédric Le Goater 
378cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
379cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
380cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
381cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
382cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
383cb228f5aSCédric Le Goater 
384cb228f5aSCédric Le Goater     /* This is needed by Linux */
385cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
386cb228f5aSCédric Le Goater }
387cb228f5aSCédric Le Goater 
388b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
38904f6c8b2SCédric Le Goater {
39004f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
39104f6c8b2SCédric Le Goater     uint32_t io_base;
39204f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
39304f6c8b2SCédric Le Goater         cpu_to_be32(1),
39404f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
39504f6c8b2SCédric Le Goater         cpu_to_be32(3)
39604f6c8b2SCédric Le Goater     };
39704f6c8b2SCédric Le Goater     uint32_t irq;
39804f6c8b2SCédric Le Goater     char *name;
39904f6c8b2SCédric Le Goater     int node;
40004f6c8b2SCédric Le Goater 
40104f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
40204f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
40304f6c8b2SCédric Le Goater 
40404f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
40504f6c8b2SCédric Le Goater 
40604f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
40704f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
40804f6c8b2SCédric Le Goater     _FDT(node);
40904f6c8b2SCédric Le Goater     g_free(name);
41004f6c8b2SCédric Le Goater 
4117032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4127032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4137032d92aSCédric Le Goater                       sizeof(compatible))));
41404f6c8b2SCédric Le Goater 
41504f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
41604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
41704f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
41804f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
41904f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
42004f6c8b2SCédric Le Goater }
42104f6c8b2SCédric Le Goater 
422e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
423e7a3fee3SCédric Le Goater     void *fdt;
424e7a3fee3SCédric Le Goater     int offset;
425e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
426e7a3fee3SCédric Le Goater 
427b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
428e7a3fee3SCédric Le Goater {
429c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
430c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
431c5ffdcaeSCédric Le Goater 
432c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
433b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
434cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
435b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
43604f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
437b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
438c5ffdcaeSCédric Le Goater     } else {
439c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
440c5ffdcaeSCédric Le Goater                      d->ioport_id);
441c5ffdcaeSCédric Le Goater     }
442c5ffdcaeSCédric Le Goater 
443e7a3fee3SCédric Le Goater     return 0;
444e7a3fee3SCédric Le Goater }
445e7a3fee3SCédric Le Goater 
44659b7c1c2SBalamuruhan S /*
44759b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
448bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
449bb7ab95cSCédric Le Goater  */
450bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
451bb7ab95cSCédric Le Goater {
45264d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
453e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
454e7a3fee3SCédric Le Goater         .fdt = fdt,
455bb7ab95cSCédric Le Goater         .offset = isa_offset,
456e7a3fee3SCédric Le Goater     };
457f47a08d1SCédric Le Goater     uint32_t phandle;
458e7a3fee3SCédric Le Goater 
459bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
460bb7ab95cSCédric Le Goater 
461f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
462f47a08d1SCédric Le Goater     assert(phandle > 0);
463f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
464f47a08d1SCédric Le Goater 
46559b7c1c2SBalamuruhan S     /*
46659b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
46759b7c1c2SBalamuruhan S      * can not use object_child_foreach()
46859b7c1c2SBalamuruhan S      */
469bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
470bb7ab95cSCédric Le Goater                        &args);
471e7a3fee3SCédric Le Goater }
472e7a3fee3SCédric Le Goater 
473e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt)
474e5694793SCédric Le Goater {
475e5694793SCédric Le Goater     int off;
476e5694793SCédric Le Goater 
477e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
478e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
479e5694793SCédric Le Goater 
480e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
481e5694793SCédric Le Goater }
482e5694793SCédric Le Goater 
483b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4849e933f4aSBenjamin Herrenschmidt {
48583b90bf0SCédric Le Goater     const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
48683b90bf0SCédric Le Goater     const char plat_compat9[] = "qemu,powernv9\0ibm,powernv";
4872b548a42SCédric Le Goater     const char plat_compat10[] = "qemu,powernv10\0ibm,powernv";
488b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
4899e933f4aSBenjamin Herrenschmidt     void *fdt;
4909e933f4aSBenjamin Herrenschmidt     char *buf;
4919e933f4aSBenjamin Herrenschmidt     int off;
492e997040eSCédric Le Goater     int i;
4939e933f4aSBenjamin Herrenschmidt 
4949e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
4959e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
4969e933f4aSBenjamin Herrenschmidt 
497ccb099b3SCédric Le Goater     /* /qemu node */
498ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
499ccb099b3SCédric Le Goater 
5009e933f4aSBenjamin Herrenschmidt     /* Root node */
5019e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5029e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5039e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5049e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
5052b548a42SCédric Le Goater     if (pnv_is_power10(pnv)) {
5062b548a42SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat10,
5072b548a42SCédric Le Goater                           sizeof(plat_compat10))));
5082b548a42SCédric Le Goater     } else if (pnv_is_power9(pnv)) {
50983b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9,
51083b90bf0SCédric Le Goater                           sizeof(plat_compat9))));
51183b90bf0SCédric Le Goater     } else {
51283b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8,
51383b90bf0SCédric Le Goater                           sizeof(plat_compat8))));
51483b90bf0SCédric Le Goater     }
51583b90bf0SCédric Le Goater 
5169e933f4aSBenjamin Herrenschmidt 
5179e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5189e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5199e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5209e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5219e933f4aSBenjamin Herrenschmidt     }
5229e933f4aSBenjamin Herrenschmidt     g_free(buf);
5239e933f4aSBenjamin Herrenschmidt 
5249e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5259e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5269e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5279e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5289e933f4aSBenjamin Herrenschmidt     }
5299e933f4aSBenjamin Herrenschmidt 
5309e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5319e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5329e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5339e933f4aSBenjamin Herrenschmidt 
5349e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5359e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5369e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5379e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5389e933f4aSBenjamin Herrenschmidt     }
5399e933f4aSBenjamin Herrenschmidt 
540e997040eSCédric Le Goater     /* Populate device tree for each chip */
541e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
542eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
543e997040eSCédric Le Goater     }
544e7a3fee3SCédric Le Goater 
545e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
546bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
547aeaef83dSCédric Le Goater 
548aeaef83dSCédric Le Goater     if (pnv->bmc) {
549b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
550aeaef83dSCédric Le Goater     }
551aeaef83dSCédric Le Goater 
5522b548a42SCédric Le Goater     /* Create an extra node for power management on Power9 and Power10 */
5532b548a42SCédric Le Goater     if (pnv_is_power9(pnv) || pnv_is_power10(pnv)) {
554e5694793SCédric Le Goater         pnv_dt_power_mgt(fdt);
555e5694793SCédric Le Goater     }
556e5694793SCédric Le Goater 
5579e933f4aSBenjamin Herrenschmidt     return fdt;
5589e933f4aSBenjamin Herrenschmidt }
5599e933f4aSBenjamin Herrenschmidt 
560bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
561bce0b691SCédric Le Goater {
562b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
563bce0b691SCédric Le Goater 
564bce0b691SCédric Le Goater     if (pnv->bmc) {
565bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
566bce0b691SCédric Le Goater     }
567bce0b691SCédric Le Goater }
568bce0b691SCédric Le Goater 
569a0628599SLike Xu static void pnv_reset(MachineState *machine)
5709e933f4aSBenjamin Herrenschmidt {
5719e933f4aSBenjamin Herrenschmidt     void *fdt;
5729e933f4aSBenjamin Herrenschmidt 
5739e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5749e933f4aSBenjamin Herrenschmidt 
575b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5769e933f4aSBenjamin Herrenschmidt 
5779e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5789e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5799e933f4aSBenjamin Herrenschmidt 
5808d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5819e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5829e933f4aSBenjamin Herrenschmidt }
5839e933f4aSBenjamin Herrenschmidt 
58404026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5853495b6b6SCédric Le Goater {
58677864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58777864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
58804026890SCédric Le Goater }
5893495b6b6SCédric Le Goater 
59004026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
59104026890SCédric Le Goater {
59277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
59377864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
59404026890SCédric Le Goater }
5953495b6b6SCédric Le Goater 
59604026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
59704026890SCédric Le Goater {
59815376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
59915376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
60004026890SCédric Le Goater }
6013495b6b6SCédric Le Goater 
6022b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6032b548a42SCédric Le Goater {
6042b548a42SCédric Le Goater     error_setg(errp, "No ISA bus!");
6052b548a42SCédric Le Goater     return NULL;
6062b548a42SCédric Le Goater }
6072b548a42SCédric Le Goater 
60804026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
60904026890SCédric Le Goater {
61004026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6113495b6b6SCédric Le Goater }
6123495b6b6SCédric Le Goater 
613d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
614d8e4aad5SCédric Le Goater {
615d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
616d8e4aad5SCédric Le Goater 
617d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
618d8e4aad5SCédric Le Goater }
619d8e4aad5SCédric Le Goater 
620d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
621d8e4aad5SCédric Le Goater {
622d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
623d8e4aad5SCédric Le Goater 
624d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
625c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
626d8e4aad5SCédric Le Goater }
627d8e4aad5SCédric Le Goater 
628f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
629f30c843cSCédric Le Goater {
630f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
631f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
632f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
633f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
634f30c843cSCédric Le Goater 
635f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
636f30c843cSCédric Le Goater }
637f30c843cSCédric Le Goater 
638e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
639e2392d43SCédric Le Goater {
640e2392d43SCédric Le Goater     Object *obj;
641e2392d43SCédric Le Goater 
642e2392d43SCédric Le Goater     obj = OBJECT(isa_create(bus, "isa-ipmi-bt"));
643e2392d43SCédric Le Goater     object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal);
644e2392d43SCédric Le Goater     object_property_set_int(obj, irq, "irq", &error_fatal);
645e2392d43SCédric Le Goater     object_property_set_bool(obj, true, "realized", &error_fatal);
646e2392d43SCédric Le Goater }
647e2392d43SCédric Le Goater 
6482b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
6492b548a42SCédric Le Goater {
650*8b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
651*8b50ce85SCédric Le Goater 
652*8b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
6532b548a42SCédric Le Goater }
6542b548a42SCédric Le Goater 
655b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6569e933f4aSBenjamin Herrenschmidt {
657b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
658f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6599e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
6609e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6619e933f4aSBenjamin Herrenschmidt     long fw_size;
662e997040eSCédric Le Goater     int i;
663e997040eSCédric Le Goater     char *chip_typename;
66435dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
66535dde576SCédric Le Goater     DeviceState *dev;
6669e933f4aSBenjamin Herrenschmidt 
6679e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
668d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
6693dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
6709e933f4aSBenjamin Herrenschmidt     }
6719e933f4aSBenjamin Herrenschmidt 
6729e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
673b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6749e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6759e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6769e933f4aSBenjamin Herrenschmidt 
67735dde576SCédric Le Goater     /*
67835dde576SCédric Le Goater      * Create our simple PNOR device
67935dde576SCédric Le Goater      */
68035dde576SCédric Le Goater     dev = qdev_create(NULL, TYPE_PNV_PNOR);
68135dde576SCédric Le Goater     if (pnor) {
68235dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
68335dde576SCédric Le Goater                             &error_abort);
68435dde576SCédric Le Goater     }
68535dde576SCédric Le Goater     qdev_init_nofail(dev);
68635dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
68735dde576SCédric Le Goater 
6889e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
6899e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
6909e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
6919e933f4aSBenjamin Herrenschmidt     }
6929e933f4aSBenjamin Herrenschmidt 
6939e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
69415fcedb2SCédric Le Goater     if (!fw_filename) {
69515fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
69615fcedb2SCédric Le Goater         exit(1);
69715fcedb2SCédric Le Goater     }
6989e933f4aSBenjamin Herrenschmidt 
6999e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
7009e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
70115fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7029e933f4aSBenjamin Herrenschmidt         exit(1);
7039e933f4aSBenjamin Herrenschmidt     }
7049e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7059e933f4aSBenjamin Herrenschmidt 
7069e933f4aSBenjamin Herrenschmidt     /* load kernel */
7079e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7089e933f4aSBenjamin Herrenschmidt         long kernel_size;
7099e933f4aSBenjamin Herrenschmidt 
7109e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
711b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7129e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
713802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7149e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7159e933f4aSBenjamin Herrenschmidt             exit(1);
7169e933f4aSBenjamin Herrenschmidt         }
7179e933f4aSBenjamin Herrenschmidt     }
7189e933f4aSBenjamin Herrenschmidt 
7199e933f4aSBenjamin Herrenschmidt     /* load initrd */
7209e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7219e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7229e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
723584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7249e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
725802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7269e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7279e933f4aSBenjamin Herrenschmidt             exit(1);
7289e933f4aSBenjamin Herrenschmidt         }
7299e933f4aSBenjamin Herrenschmidt     }
730e997040eSCédric Le Goater 
731f30c843cSCédric Le Goater     /*
732f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
733f30c843cSCédric Le Goater      * default.
734f30c843cSCédric Le Goater      */
735f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
736f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
737f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
738f30c843cSCédric Le Goater         exit(1);
739f30c843cSCédric Le Goater     }
740f30c843cSCédric Le Goater 
741e997040eSCédric Le Goater     /* Create the processor chips */
7424a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7437fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7444a12c699SIgor Mammedov                                     i, machine->cpu_type);
745e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
746f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
747f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
748e997040eSCédric Le Goater         exit(1);
749e997040eSCédric Le Goater     }
750e997040eSCédric Le Goater 
751e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
752e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
753e997040eSCédric Le Goater         char chip_name[32];
754e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
755e997040eSCédric Le Goater 
756e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
757e997040eSCédric Le Goater 
75859b7c1c2SBalamuruhan S         /*
75959b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
760e997040eSCédric Le Goater          * way to specify different ranges for each chip
761e997040eSCédric Le Goater          */
762e997040eSCédric Le Goater         if (i == 0) {
763e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
764e997040eSCédric Le Goater                                     &error_fatal);
765e997040eSCédric Le Goater         }
766e997040eSCédric Le Goater 
767e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
768e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
769e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
770e997040eSCédric Le Goater                                 &error_fatal);
771fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
772fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
773e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
774e997040eSCédric Le Goater     }
775e997040eSCédric Le Goater     g_free(chip_typename);
7763495b6b6SCédric Le Goater 
777e2392d43SCédric Le Goater     /* Create the machine BMC simulator */
778e2392d43SCédric Le Goater     pnv->bmc = pnv_bmc_create();
779e2392d43SCédric Le Goater 
7803495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
78104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
7823495b6b6SCédric Le Goater 
7833495b6b6SCédric Le Goater     /* Create serial port */
784def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
7853495b6b6SCédric Le Goater 
7863495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
7876c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
788bce0b691SCédric Le Goater 
789e2392d43SCédric Le Goater     /* Create the IPMI BT device for communication with the BMC */
790e2392d43SCédric Le Goater     pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
791e2392d43SCédric Le Goater 
79259b7c1c2SBalamuruhan S     /*
79359b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
79459b7c1c2SBalamuruhan S      * host to powerdown
79559b7c1c2SBalamuruhan S      */
796bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
797bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
798e997040eSCédric Le Goater }
799e997040eSCédric Le Goater 
800631adaffSCédric Le Goater /*
801631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
802631adaffSCédric Le Goater  *   22:24  Chip ID
803631adaffSCédric Le Goater  *   25:28  Core number
804631adaffSCédric Le Goater  *   29:31  Thread ID
805631adaffSCédric Le Goater  */
806631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
807631adaffSCédric Le Goater {
808631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
809631adaffSCédric Le Goater }
810631adaffSCédric Le Goater 
8118fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
812d35aefa9SCédric Le Goater                                         Error **errp)
813d35aefa9SCédric Le Goater {
8148fa1f4efSCédric Le Goater     Error *local_err = NULL;
8158fa1f4efSCédric Le Goater     Object *obj;
8168907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8178fa1f4efSCédric Le Goater 
8188fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
8198fa1f4efSCédric Le Goater                      &local_err);
8208fa1f4efSCédric Le Goater     if (local_err) {
8218fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
8228fa1f4efSCédric Le Goater         return;
8238fa1f4efSCédric Le Goater     }
8248fa1f4efSCédric Le Goater 
825956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
826d35aefa9SCédric Le Goater }
827d35aefa9SCédric Le Goater 
8280990ce6aSGreg Kurz 
829d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
830d49e8a9bSCédric Le Goater {
831d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
832d49e8a9bSCédric Le Goater 
833d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
834d49e8a9bSCédric Le Goater }
835d49e8a9bSCédric Le Goater 
8360990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8370990ce6aSGreg Kurz {
8380990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8390990ce6aSGreg Kurz 
8400990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
8410990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8420990ce6aSGreg Kurz }
8430990ce6aSGreg Kurz 
844631adaffSCédric Le Goater /*
845631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
846631adaffSCédric Le Goater  *   49:52  Node ID
847631adaffSCédric Le Goater  *   53:55  Chip ID
848631adaffSCédric Le Goater  *   56     Reserved - Read as zero
849631adaffSCédric Le Goater  *   57:61  Core number
850631adaffSCédric Le Goater  *   62:63  Thread ID
851631adaffSCédric Le Goater  *
852631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
853631adaffSCédric Le Goater  */
854631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
855631adaffSCédric Le Goater {
856631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
857631adaffSCédric Le Goater }
858631adaffSCédric Le Goater 
8592b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
8602b548a42SCédric Le Goater {
8612b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
8622b548a42SCédric Le Goater }
8632b548a42SCédric Le Goater 
8648fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
865d35aefa9SCédric Le Goater                                         Error **errp)
866d35aefa9SCédric Le Goater {
8672dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
8682dfa91a2SCédric Le Goater     Error *local_err = NULL;
8692dfa91a2SCédric Le Goater     Object *obj;
8702dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8712dfa91a2SCédric Le Goater 
8722dfa91a2SCédric Le Goater     /*
8732dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
8742dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
8752dfa91a2SCédric Le Goater      * only used at runtime.
8762dfa91a2SCédric Le Goater      */
87726aa5b1eSGreg Kurz     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err);
8782dfa91a2SCédric Le Goater     if (local_err) {
8792dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
8808fa1f4efSCédric Le Goater         return;
881d35aefa9SCédric Le Goater     }
882d35aefa9SCédric Le Goater 
8832dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
8842dfa91a2SCédric Le Goater }
8852dfa91a2SCédric Le Goater 
886d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
887d49e8a9bSCédric Le Goater {
888d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
889d49e8a9bSCédric Le Goater 
890d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
891d49e8a9bSCédric Le Goater }
892d49e8a9bSCédric Le Goater 
8930990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8940990ce6aSGreg Kurz {
8950990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8960990ce6aSGreg Kurz 
8970990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
8980990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8990990ce6aSGreg Kurz }
9000990ce6aSGreg Kurz 
9012b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
9022b548a42SCédric Le Goater                                         Error **errp)
9032b548a42SCédric Le Goater {
9042b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9052b548a42SCédric Le Goater 
9062b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
9072b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9082b548a42SCédric Le Goater }
9092b548a42SCédric Le Goater 
9102b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
9112b548a42SCédric Le Goater {
9122b548a42SCédric Le Goater     ;
9132b548a42SCédric Le Goater }
9142b548a42SCédric Le Goater 
9152b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9162b548a42SCédric Le Goater {
9172b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9182b548a42SCédric Le Goater 
9192b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9202b548a42SCédric Le Goater }
9212b548a42SCédric Le Goater 
92259b7c1c2SBalamuruhan S /*
92359b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
924397a79e7SCédric Le Goater  *
925397a79e7SCédric Le Goater  * <EX0 reserved>
926397a79e7SCédric Le Goater  *  EX1  - Venice only
927397a79e7SCédric Le Goater  *  EX2  - Venice only
928397a79e7SCédric Le Goater  *  EX3  - Venice only
929397a79e7SCédric Le Goater  *  EX4
930397a79e7SCédric Le Goater  *  EX5
931397a79e7SCédric Le Goater  *  EX6
932397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
933397a79e7SCédric Le Goater  *  EX9  - Venice only
934397a79e7SCédric Le Goater  *  EX10 - Venice only
935397a79e7SCédric Le Goater  *  EX11 - Venice only
936397a79e7SCédric Le Goater  *  EX12
937397a79e7SCédric Le Goater  *  EX13
938397a79e7SCédric Le Goater  *  EX14
939397a79e7SCédric Le Goater  * <EX15 reserved>
940397a79e7SCédric Le Goater  */
941397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
942397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
943397a79e7SCédric Le Goater 
944397a79e7SCédric Le Goater /*
94509279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
946397a79e7SCédric Le Goater  */
94709279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
948397a79e7SCédric Le Goater 
9492b548a42SCédric Le Goater 
9502b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
9512b548a42SCédric Le Goater 
95277864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
95377864267SCédric Le Goater {
95477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
95577864267SCédric Le Goater 
956f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
957ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
95877864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
95977864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
96077864267SCédric Le Goater 
961f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
96282514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
96377864267SCédric Le Goater 
964f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
9653233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
9663887d241SBalamuruhan S 
9673887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
9683887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
96977864267SCédric Le Goater }
97077864267SCédric Le Goater 
97177864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
97277864267SCédric Le Goater  {
97377864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
97477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
97577864267SCédric Le Goater     int i, j;
97677864267SCédric Le Goater     char *name;
97777864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
97877864267SCédric Le Goater 
97977864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
98077864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
98177864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
98277864267SCédric Le Goater     g_free(name);
98377864267SCédric Le Goater 
98477864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
98577864267SCédric Le Goater 
98677864267SCédric Le Goater     /* Map the ICP registers for each thread */
98777864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
9884fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
98977864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
99077864267SCédric Le Goater 
99177864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
99277864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
99377864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
99477864267SCédric Le Goater 
99577864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
99677864267SCédric Le Goater                                         &icp->mmio);
99777864267SCédric Le Goater         }
99877864267SCédric Le Goater     }
99977864267SCédric Le Goater }
100077864267SCédric Le Goater 
100177864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
100277864267SCédric Le Goater {
100377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
100477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
100577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1006ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
100777864267SCédric Le Goater     Error *local_err = NULL;
100877864267SCédric Le Goater 
1009709044fdSCédric Le Goater     /* XSCOM bridge is first */
1010709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1011709044fdSCédric Le Goater     if (local_err) {
1012709044fdSCédric Le Goater         error_propagate(errp, local_err);
1013709044fdSCédric Le Goater         return;
1014709044fdSCédric Le Goater     }
1015709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1016709044fdSCédric Le Goater 
101777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
101877864267SCédric Le Goater     if (local_err) {
101977864267SCédric Le Goater         error_propagate(errp, local_err);
102077864267SCédric Le Goater         return;
102177864267SCédric Le Goater     }
102277864267SCédric Le Goater 
102377864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
102477864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
102577864267SCédric Le Goater                             "bar", &error_fatal);
102677864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
102777864267SCédric Le Goater     if (local_err) {
102877864267SCédric Le Goater         error_propagate(errp, local_err);
102977864267SCédric Le Goater         return;
103077864267SCédric Le Goater     }
1031ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1032ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
103377864267SCédric Le Goater 
103477864267SCédric Le Goater     /* Create LPC controller */
1035b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi",
1036b63f3893SGreg Kurz                              &error_abort);
103777864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
103877864267SCédric Le Goater                              &error_fatal);
103977864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
104077864267SCédric Le Goater 
104164d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
104264d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
104364d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
104464d011d5SCédric Le Goater 
104559b7c1c2SBalamuruhan S     /*
104659b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
104759b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
104859b7c1c2SBalamuruhan S      */
104977864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
105077864267SCédric Le Goater     if (local_err) {
105177864267SCédric Le Goater         error_propagate(errp, local_err);
105277864267SCédric Le Goater         return;
105377864267SCédric Le Goater     }
105477864267SCédric Le Goater 
105577864267SCédric Le Goater     /* Create the simplified OCC model */
1056ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi",
1057ee3d2713SGreg Kurz                              &error_abort);
105877864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
105977864267SCédric Le Goater     if (local_err) {
106077864267SCédric Le Goater         error_propagate(errp, local_err);
106177864267SCédric Le Goater         return;
106277864267SCédric Le Goater     }
106377864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1064f3db8266SBalamuruhan S 
1065f3db8266SBalamuruhan S     /* OCC SRAM model */
1066f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip),
1067f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
10683887d241SBalamuruhan S 
10693887d241SBalamuruhan S     /* HOMER */
1070f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip",
1071f2582acfSGreg Kurz                              &error_abort);
10723887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
10733887d241SBalamuruhan S                              &local_err);
10743887d241SBalamuruhan S     if (local_err) {
10753887d241SBalamuruhan S         error_propagate(errp, local_err);
10763887d241SBalamuruhan S         return;
10773887d241SBalamuruhan S     }
10783887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
10793887d241SBalamuruhan S                                 &chip8->homer.regs);
108077864267SCédric Le Goater }
108177864267SCédric Le Goater 
1082e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1083e997040eSCédric Le Goater {
1084e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1085e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1086e997040eSCédric Le Goater 
1087e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
1088e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1089397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
1090631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1091d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1092d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
10930990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
109404026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1095eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1096d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1097e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
109877864267SCédric Le Goater 
109977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
110077864267SCédric Le Goater                                     &k->parent_realize);
1101e997040eSCédric Le Goater }
1102e997040eSCédric Le Goater 
1103e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1104e997040eSCédric Le Goater {
1105e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1106e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1107e997040eSCédric Le Goater 
1108e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
1109e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1110397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1111631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1112d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1113d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11140990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
111504026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1116eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1117d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1118e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
111977864267SCédric Le Goater 
112077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
112177864267SCédric Le Goater                                     &k->parent_realize);
1122e997040eSCédric Le Goater }
1123e997040eSCédric Le Goater 
1124e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1125e997040eSCédric Le Goater {
1126e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1127e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1128e997040eSCédric Le Goater 
1129e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
1130e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1131397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1132631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1133d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1134d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11350990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
113604026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1137eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1138d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1139e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
114077864267SCédric Le Goater 
114177864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
114277864267SCédric Le Goater                                     &k->parent_realize);
114377864267SCédric Le Goater }
114477864267SCédric Le Goater 
114577864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
114677864267SCédric Le Goater {
11472dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
11482dfa91a2SCédric Le Goater 
11492dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
11502dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
1151c38536bcSCédric Le Goater 
1152c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1153c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
115415376c66SCédric Le Goater 
115515376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
115615376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
11576598a70dSCédric Le Goater 
11586598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
11596598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
11603887d241SBalamuruhan S 
11613887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
11623887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
116377864267SCédric Le Goater }
116477864267SCédric Le Goater 
11655dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
11665dad902cSCédric Le Goater {
11675dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
11685dad902cSCédric Le Goater     int i;
11695dad902cSCédric Le Goater 
11705dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
11715dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
11725dad902cSCédric Le Goater 
11735dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
11745dad902cSCédric Le Goater         char eq_name[32];
11755dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
11764fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
11775dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
11785dad902cSCédric Le Goater 
11795dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1180bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1181bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
11825dad902cSCédric Le Goater 
11835dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
11845dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
11855dad902cSCédric Le Goater 
11865dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
11875dad902cSCédric Le Goater                                 &eq->xscom_regs);
11885dad902cSCédric Le Goater     }
11895dad902cSCédric Le Goater }
11905dad902cSCédric Le Goater 
119177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
119277864267SCédric Le Goater {
119377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
11942dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
11952dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1196c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
119777864267SCédric Le Goater     Error *local_err = NULL;
119877864267SCédric Le Goater 
1199709044fdSCédric Le Goater     /* XSCOM bridge is first */
1200709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1201709044fdSCédric Le Goater     if (local_err) {
1202709044fdSCédric Le Goater         error_propagate(errp, local_err);
1203709044fdSCédric Le Goater         return;
1204709044fdSCédric Le Goater     }
1205709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1206709044fdSCédric Le Goater 
120777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
120877864267SCédric Le Goater     if (local_err) {
120977864267SCédric Le Goater         error_propagate(errp, local_err);
121077864267SCédric Le Goater         return;
121177864267SCédric Le Goater     }
12122dfa91a2SCédric Le Goater 
12135dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
12145dad902cSCédric Le Goater     if (local_err) {
12155dad902cSCédric Le Goater         error_propagate(errp, local_err);
12165dad902cSCédric Le Goater         return;
12175dad902cSCédric Le Goater     }
12185dad902cSCédric Le Goater 
12192dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
12202dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
12212dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
12222dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
12232dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
12242dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
12252dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
12262dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
12272dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
12287ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
12297ae54cc3SGreg Kurz                              &error_abort);
12302dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
12312dfa91a2SCédric Le Goater                              &local_err);
12322dfa91a2SCédric Le Goater     if (local_err) {
12332dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
12342dfa91a2SCédric Le Goater         return;
12352dfa91a2SCédric Le Goater     }
12362dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
12372dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1238c38536bcSCédric Le Goater 
1239c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1240c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1241c38536bcSCédric Le Goater                             "bar", &error_fatal);
1242c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1243c38536bcSCédric Le Goater     if (local_err) {
1244c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1245c38536bcSCédric Le Goater         return;
1246c38536bcSCédric Le Goater     }
1247c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1248c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
124915376c66SCédric Le Goater 
125015376c66SCédric Le Goater     /* LPC */
1251b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1252b63f3893SGreg Kurz                              &error_abort);
125315376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
125415376c66SCédric Le Goater     if (local_err) {
125515376c66SCédric Le Goater         error_propagate(errp, local_err);
125615376c66SCédric Le Goater         return;
125715376c66SCédric Le Goater     }
125815376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
125915376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
126015376c66SCédric Le Goater 
126115376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
126215376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
12636598a70dSCédric Le Goater 
12646598a70dSCédric Le Goater     /* Create the simplified OCC model */
1265ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1266ee3d2713SGreg Kurz                              &error_abort);
12676598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
12686598a70dSCédric Le Goater     if (local_err) {
12696598a70dSCédric Le Goater         error_propagate(errp, local_err);
12706598a70dSCédric Le Goater         return;
12716598a70dSCédric Le Goater     }
12726598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1273f3db8266SBalamuruhan S 
1274f3db8266SBalamuruhan S     /* OCC SRAM model */
1275f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip),
1276f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
12773887d241SBalamuruhan S 
12783887d241SBalamuruhan S     /* HOMER */
1279f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1280f2582acfSGreg Kurz                              &error_abort);
12813887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
12823887d241SBalamuruhan S                              &local_err);
12833887d241SBalamuruhan S     if (local_err) {
12843887d241SBalamuruhan S         error_propagate(errp, local_err);
12853887d241SBalamuruhan S         return;
12863887d241SBalamuruhan S     }
12873887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
12883887d241SBalamuruhan S                                 &chip9->homer.regs);
1289e997040eSCédric Le Goater }
1290e997040eSCédric Le Goater 
1291e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1292e997040eSCédric Le Goater {
1293e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1294e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1295e997040eSCédric Le Goater 
1296e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
129783028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1298397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1299631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1300d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1301d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
13020990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
130304026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1304eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1305d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1306e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
130777864267SCédric Le Goater 
130877864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
130977864267SCédric Le Goater                                     &k->parent_realize);
1310e997040eSCédric Le Goater }
1311e997040eSCédric Le Goater 
13122b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
13132b548a42SCédric Le Goater {
1314*8b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
1315*8b50ce85SCédric Le Goater 
1316*8b50ce85SCédric Le Goater     object_initialize_child(obj, "psi",  &chip10->psi, sizeof(chip10->psi),
1317*8b50ce85SCédric Le Goater                             TYPE_PNV10_PSI, &error_abort, NULL);
13182b548a42SCédric Le Goater }
13192b548a42SCédric Le Goater 
13202b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
13212b548a42SCédric Le Goater {
13222b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
13232b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1324*8b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
13252b548a42SCédric Le Goater     Error *local_err = NULL;
13262b548a42SCédric Le Goater 
13272b548a42SCédric Le Goater     /* XSCOM bridge is first */
13282b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
13292b548a42SCédric Le Goater     if (local_err) {
13302b548a42SCédric Le Goater         error_propagate(errp, local_err);
13312b548a42SCédric Le Goater         return;
13322b548a42SCédric Le Goater     }
13332b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
13342b548a42SCédric Le Goater 
13352b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
13362b548a42SCédric Le Goater     if (local_err) {
13372b548a42SCédric Le Goater         error_propagate(errp, local_err);
13382b548a42SCédric Le Goater         return;
13392b548a42SCédric Le Goater     }
1340*8b50ce85SCédric Le Goater 
1341*8b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1342*8b50ce85SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip),
1343*8b50ce85SCédric Le Goater                             "bar", &error_fatal);
1344*8b50ce85SCédric Le Goater     object_property_set_bool(OBJECT(&chip10->psi), true, "realized",
1345*8b50ce85SCédric Le Goater                              &local_err);
1346*8b50ce85SCédric Le Goater     if (local_err) {
1347*8b50ce85SCédric Le Goater         error_propagate(errp, local_err);
1348*8b50ce85SCédric Le Goater         return;
1349*8b50ce85SCédric Le Goater     }
1350*8b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
1351*8b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
13522b548a42SCédric Le Goater }
13532b548a42SCédric Le Goater 
13542b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
13552b548a42SCédric Le Goater {
13562b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
13572b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
13582b548a42SCédric Le Goater 
13592b548a42SCédric Le Goater     k->chip_type = PNV_CHIP_POWER10;
13602b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
13612b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
13622b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
13632b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
13642b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
13652b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
13662b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
13672b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
13682b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
13692b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
13702b548a42SCédric Le Goater 
13712b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
13722b548a42SCédric Le Goater                                     &k->parent_realize);
13732b548a42SCédric Le Goater }
13742b548a42SCédric Le Goater 
1375397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1376397a79e7SCédric Le Goater {
1377397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1378397a79e7SCédric Le Goater     int cores_max;
1379397a79e7SCédric Le Goater 
1380397a79e7SCédric Le Goater     /*
1381397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1382397a79e7SCédric Le Goater      * the chip class
1383397a79e7SCédric Le Goater      */
1384397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1385397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1386397a79e7SCédric Le Goater     }
1387397a79e7SCédric Le Goater 
1388397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1389397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1390397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1391397a79e7SCédric Le Goater                    chip->cores_mask);
1392397a79e7SCédric Le Goater         return;
1393397a79e7SCédric Le Goater     }
1394397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1395397a79e7SCédric Le Goater 
1396397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
139727d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1398397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1399397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1400397a79e7SCédric Le Goater                    cores_max);
1401397a79e7SCédric Le Goater         return;
1402397a79e7SCédric Le Goater     }
1403397a79e7SCédric Le Goater }
1404397a79e7SCédric Le Goater 
140551c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1406e997040eSCédric Le Goater {
1407fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1408397a79e7SCédric Le Goater     Error *error = NULL;
1409d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
141040abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1411d2fd9612SCédric Le Goater     int i, core_hwid;
1412397a79e7SCédric Le Goater 
1413d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1414d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1415d2fd9612SCédric Le Goater         return;
1416d2fd9612SCédric Le Goater     }
1417d2fd9612SCédric Le Goater 
1418d2fd9612SCédric Le Goater     /* Cores */
1419397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1420397a79e7SCédric Le Goater     if (error) {
1421397a79e7SCédric Le Goater         error_propagate(errp, error);
1422397a79e7SCédric Le Goater         return;
1423397a79e7SCédric Le Goater     }
1424d2fd9612SCédric Le Goater 
14254fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1426d2fd9612SCédric Le Goater 
1427d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1428d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1429d2fd9612SCédric Le Goater         char core_name[32];
14304fa28f23SGreg Kurz         PnvCore *pnv_core;
1431c035851aSCédric Le Goater         uint64_t xscom_core_base;
1432d2fd9612SCédric Le Goater 
1433d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1434d2fd9612SCédric Le Goater             continue;
1435d2fd9612SCédric Le Goater         }
1436d2fd9612SCédric Le Goater 
14374fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
14384fa28f23SGreg Kurz 
1439d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
14404fa28f23SGreg Kurz         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
14414fa28f23SGreg Kurz                                   &error_abort);
14424fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1443fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1444d2fd9612SCédric Le Goater                                 &error_fatal);
1445d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1446d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1447d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1448d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1449d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1450158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1451158e17a6SGreg Kurz                                  &error_abort);
1452d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1453d2fd9612SCédric Le Goater                                  &error_fatal);
145424ece072SCédric Le Goater 
145524ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
14562b548a42SCédric Le Goater         if (pnv_chip_is_power10(chip)) {
14572b548a42SCédric Le Goater             xscom_core_base = PNV10_XSCOM_EC_BASE(core_hwid);
14582b548a42SCédric Le Goater         } else if (pnv_chip_is_power9(chip)) {
14595dad902cSCédric Le Goater             xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid);
14602b548a42SCédric Le Goater         } else {
14612b548a42SCédric Le Goater             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
1462c035851aSCédric Le Goater         }
1463c035851aSCédric Le Goater 
1464c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
14654fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1466d2fd9612SCédric Le Goater         i++;
1467d2fd9612SCédric Le Goater     }
146851c04728SCédric Le Goater }
146951c04728SCédric Le Goater 
147051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
147151c04728SCédric Le Goater {
147251c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
147351c04728SCédric Le Goater     Error *error = NULL;
147451c04728SCédric Le Goater 
147551c04728SCédric Le Goater     /* Cores */
147651c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
147751c04728SCédric Le Goater     if (error) {
147851c04728SCédric Le Goater         error_propagate(errp, error);
147951c04728SCédric Le Goater         return;
148051c04728SCédric Le Goater     }
1481e997040eSCédric Le Goater }
1482e997040eSCédric Le Goater 
1483e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1484e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1485e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1486e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1487397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1488397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1489e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1490e997040eSCédric Le Goater };
1491e997040eSCédric Le Goater 
1492e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1493e997040eSCédric Le Goater {
1494e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1495e997040eSCédric Le Goater 
14969d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1497e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1498e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1499e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1500e997040eSCédric Le Goater }
1501e997040eSCédric Le Goater 
1502119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1503119eaa9dSCédric Le Goater {
1504119eaa9dSCédric Le Goater     int i, j;
1505119eaa9dSCédric Le Goater 
1506119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1507119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1508119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1509119eaa9dSCédric Le Goater 
1510119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1511119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1512119eaa9dSCédric Le Goater                 return pc->threads[j];
1513119eaa9dSCédric Le Goater             }
1514119eaa9dSCédric Le Goater         }
1515119eaa9dSCédric Le Goater     }
1516119eaa9dSCédric Le Goater     return NULL;
1517119eaa9dSCédric Le Goater }
1518119eaa9dSCédric Le Goater 
151954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
152054f59d78SCédric Le Goater {
1521b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
152254f59d78SCédric Le Goater     int i;
152354f59d78SCédric Le Goater 
152454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
152577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
152677864267SCédric Le Goater 
152777864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
152877864267SCédric Le Goater             return &chip8->psi.ics;
152954f59d78SCédric Le Goater         }
153054f59d78SCédric Le Goater     }
153154f59d78SCédric Le Goater     return NULL;
153254f59d78SCédric Le Goater }
153354f59d78SCédric Le Goater 
153454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
153554f59d78SCédric Le Goater {
1536b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
153754f59d78SCédric Le Goater     int i;
153854f59d78SCédric Le Goater 
153954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
154077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
154177864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
154254f59d78SCédric Le Goater     }
154354f59d78SCédric Le Goater }
154454f59d78SCédric Le Goater 
154536fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
154636fc6f08SCédric Le Goater {
154736fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
154836fc6f08SCédric Le Goater 
1549956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
155036fc6f08SCédric Le Goater }
155136fc6f08SCédric Le Goater 
155247fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
155347fea43aSCédric Le Goater                                Monitor *mon)
155447fea43aSCédric Le Goater {
1555b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
155654f59d78SCédric Le Goater     int i;
155747fea43aSCédric Le Goater     CPUState *cs;
155847fea43aSCédric Le Goater 
155947fea43aSCédric Le Goater     CPU_FOREACH(cs) {
156047fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
156147fea43aSCédric Le Goater 
1562d8e4aad5SCédric Le Goater         if (pnv_chip_is_power9(pnv->chips[0])) {
1563d8e4aad5SCédric Le Goater             xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
1564d8e4aad5SCédric Le Goater         } else {
1565956b8f46SCédric Le Goater             icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
156647fea43aSCédric Le Goater         }
1567d8e4aad5SCédric Le Goater     }
156854f59d78SCédric Le Goater 
156954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1570d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
157154f59d78SCédric Le Goater     }
157247fea43aSCédric Le Goater }
157347fea43aSCédric Le Goater 
1574c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1575c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1576c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1577c722579eSCédric Le Goater                          uint32_t logic_serv,
1578c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1579c722579eSCédric Le Goater {
1580c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1581c722579eSCédric Le Goater     int total_count = 0;
1582c722579eSCédric Le Goater     int i;
1583c722579eSCédric Le Goater 
1584c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1585c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1586c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1587c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1588c722579eSCédric Le Goater         int count;
1589c722579eSCédric Le Goater 
1590c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1591c722579eSCédric Le Goater                                priority, logic_serv, match);
1592c722579eSCédric Le Goater 
1593c722579eSCédric Le Goater         if (count < 0) {
1594c722579eSCédric Le Goater             return count;
1595c722579eSCédric Le Goater         }
1596c722579eSCédric Le Goater 
1597c722579eSCédric Le Goater         total_count += count;
1598c722579eSCédric Le Goater     }
1599c722579eSCédric Le Goater 
1600c722579eSCédric Le Goater     return total_count;
1601c722579eSCédric Le Goater }
1602c722579eSCédric Le Goater 
16035373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id)
16045373c61dSCédric Le Goater {
16055373c61dSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
16065373c61dSCédric Le Goater     int i;
16075373c61dSCédric Le Goater 
16085373c61dSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
16095373c61dSCédric Le Goater         PnvChip *chip = pnv->chips[i];
16105373c61dSCédric Le Goater         if (chip->chip_id == chip_id) {
16115373c61dSCédric Le Goater             return chip;
16125373c61dSCédric Le Goater         }
16135373c61dSCédric Le Goater     }
16145373c61dSCédric Le Goater     return NULL;
16155373c61dSCédric Le Goater }
16165373c61dSCédric Le Goater 
1617e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1618e997040eSCédric Le Goater                               void *opaque, Error **errp)
1619e997040eSCédric Le Goater {
1620b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1621e997040eSCédric Le Goater }
1622e997040eSCédric Le Goater 
1623e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1624e997040eSCédric Le Goater                               void *opaque, Error **errp)
1625e997040eSCédric Le Goater {
1626b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1627e997040eSCédric Le Goater     uint32_t num_chips;
1628e997040eSCédric Le Goater     Error *local_err = NULL;
1629e997040eSCédric Le Goater 
1630e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1631e997040eSCédric Le Goater     if (local_err) {
1632e997040eSCédric Le Goater         error_propagate(errp, local_err);
1633e997040eSCédric Le Goater         return;
1634e997040eSCédric Le Goater     }
1635e997040eSCédric Le Goater 
1636e997040eSCédric Le Goater     /*
1637e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1638e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1639e997040eSCédric Le Goater      */
1640e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1641e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1642e997040eSCédric Le Goater         return;
1643e997040eSCédric Le Goater     }
1644e997040eSCédric Le Goater 
1645e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1646e997040eSCédric Le Goater }
1647e997040eSCédric Le Goater 
164877864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1649e997040eSCédric Le Goater {
1650b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1651e997040eSCédric Le Goater     pnv->num_chips = 1;
1652e997040eSCédric Le Goater }
1653e997040eSCédric Le Goater 
1654b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1655e997040eSCédric Le Goater {
16561e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1657e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1658e997040eSCédric Le Goater                               NULL, NULL, NULL);
1659e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1660e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1661e997040eSCédric Le Goater                               NULL);
16629e933f4aSBenjamin Herrenschmidt }
16639e933f4aSBenjamin Herrenschmidt 
1664f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
16659e933f4aSBenjamin Herrenschmidt {
16669e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
166736fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1668f30c843cSCédric Le Goater 
1669f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1670f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1671f30c843cSCédric Le Goater 
1672f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1673f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1674f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1675f30c843cSCédric Le Goater }
1676f30c843cSCédric Le Goater 
1677f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1678f30c843cSCédric Le Goater {
1679f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1680c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1681f30c843cSCédric Le Goater 
1682f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1683f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1684c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1685f30c843cSCédric Le Goater 
1686f30c843cSCédric Le Goater     mc->alias = "powernv";
1687f30c843cSCédric Le Goater }
1688f30c843cSCédric Le Goater 
16892b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
16902b548a42SCédric Le Goater {
16912b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
16922b548a42SCédric Le Goater 
16932b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
16942b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
16952b548a42SCédric Le Goater }
16962b548a42SCédric Le Goater 
1697f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1698f30c843cSCédric Le Goater {
1699f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
170047fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
17019e933f4aSBenjamin Herrenschmidt 
17029e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1703b168a138SCédric Le Goater     mc->init = pnv_init;
1704b168a138SCédric Le Goater     mc->reset = pnv_reset;
17059e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
170659b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
170759b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
17089e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
17099e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1710f1d18b0aSJoel Stanley     /*
1711f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1712f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1713f1d18b0aSJoel Stanley      */
1714f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
171547fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1716e997040eSCédric Le Goater 
1717b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
17189e933f4aSBenjamin Herrenschmidt }
17199e933f4aSBenjamin Herrenschmidt 
172077864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1721beba5c0fSIgor Mammedov     {                                             \
1722beba5c0fSIgor Mammedov         .name          = type,                    \
1723beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
172477864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
172577864267SCédric Le Goater     }
172677864267SCédric Le Goater 
172777864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
172877864267SCédric Le Goater     {                                             \
172977864267SCédric Le Goater         .name          = type,                    \
173077864267SCédric Le Goater         .class_init    = class_initfn,            \
173177864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1732beba5c0fSIgor Mammedov     }
1733beba5c0fSIgor Mammedov 
17342b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
17352b548a42SCédric Le Goater     {                                              \
17362b548a42SCédric Le Goater         .name          = type,                     \
17372b548a42SCédric Le Goater         .class_init    = class_initfn,             \
17382b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
17392b548a42SCédric Le Goater     }
17402b548a42SCédric Le Goater 
1741beba5c0fSIgor Mammedov static const TypeInfo types[] = {
17421aba8716SCédric Le Goater     {
17432b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
17442b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
17452b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
17462b548a42SCédric Le Goater     },
17472b548a42SCédric Le Goater     {
17481aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
17491aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
17501aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
1751c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
1752c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
1753c722579eSCédric Le Goater             { },
1754c722579eSCédric Le Goater         },
17551aba8716SCédric Le Goater     },
17561aba8716SCédric Le Goater     {
17571aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
17581aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
17591aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
17601aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
17611aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
17621aba8716SCédric Le Goater             { },
17631aba8716SCédric Le Goater         },
17641aba8716SCédric Le Goater     },
1765beba5c0fSIgor Mammedov     {
1766b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
17679e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1768f30c843cSCédric Le Goater         .abstract       = true,
17699e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
177077864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1771b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
177236fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
177347fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
177436fc6f08SCédric Le Goater             { },
177536fc6f08SCédric Le Goater         },
1776beba5c0fSIgor Mammedov     },
1777beba5c0fSIgor Mammedov     {
1778beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1779beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1780beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1781beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1782beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1783beba5c0fSIgor Mammedov         .abstract      = true,
1784beba5c0fSIgor Mammedov     },
178577864267SCédric Le Goater 
178677864267SCédric Le Goater     /*
17872b548a42SCédric Le Goater      * P10 chip and variants
17882b548a42SCédric Le Goater      */
17892b548a42SCédric Le Goater     {
17902b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
17912b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
17922b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
17932b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
17942b548a42SCédric Le Goater     },
17952b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
17962b548a42SCédric Le Goater 
17972b548a42SCédric Le Goater     /*
179877864267SCédric Le Goater      * P9 chip and variants
179977864267SCédric Le Goater      */
180077864267SCédric Le Goater     {
180177864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
180277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
180377864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
180477864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
180577864267SCédric Le Goater     },
180677864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
180777864267SCédric Le Goater 
180877864267SCédric Le Goater     /*
180977864267SCédric Le Goater      * P8 chip and variants
181077864267SCédric Le Goater      */
181177864267SCédric Le Goater     {
181277864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
181377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
181477864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
181577864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
181677864267SCédric Le Goater     },
181777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
181877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
181977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1820beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
18219e933f4aSBenjamin Herrenschmidt };
18229e933f4aSBenjamin Herrenschmidt 
1823beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1824