xref: /qemu/hw/ppc/pnv.c (revision 3f5b45ca)
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 
285*3f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
286*3f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
287*3f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE));
288967b7523SCédric Le Goater 
289d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2904fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
291d2fd9612SCédric Le Goater 
292b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
293bf5615e7SCédric Le Goater 
294bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
295b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
296d2fd9612SCédric Le Goater     }
297d2fd9612SCédric Le Goater 
298e997040eSCédric Le Goater     if (chip->ram_size) {
299b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
300e997040eSCédric Le Goater     }
301e997040eSCédric Le Goater }
302e997040eSCédric Le Goater 
303eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
304eb859a27SCédric Le Goater {
305eb859a27SCédric Le Goater     int i;
306eb859a27SCédric Le Goater 
307*3f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
308*3f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
309*3f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE));
310eb859a27SCédric Le Goater 
311eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3124fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
313eb859a27SCédric Le Goater 
314eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
315eb859a27SCédric Le Goater     }
316eb859a27SCédric Le Goater 
317eb859a27SCédric Le Goater     if (chip->ram_size) {
318eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
319eb859a27SCédric Le Goater     }
32015376c66SCédric Le Goater 
3212661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
322eb859a27SCédric Le Goater }
323eb859a27SCédric Le Goater 
3242b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3252b548a42SCédric Le Goater {
3262b548a42SCédric Le Goater     int i;
3272b548a42SCédric Le Goater 
328*3f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
329*3f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
330*3f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE));
3312b548a42SCédric Le Goater 
3322b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3332b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3342b548a42SCédric Le Goater 
3352b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3362b548a42SCédric Le Goater     }
3372b548a42SCédric Le Goater 
3382b548a42SCédric Le Goater     if (chip->ram_size) {
3392b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3402b548a42SCédric Le Goater     }
3412661f6abSCédric Le Goater 
3422661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3432b548a42SCédric Le Goater }
3442b548a42SCédric Le Goater 
345b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
346c5ffdcaeSCédric Le Goater {
347c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
348c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
349c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
350c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
351c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
352c5ffdcaeSCédric Le Goater     };
353c5ffdcaeSCédric Le Goater     char *name;
354c5ffdcaeSCédric Le Goater     int node;
355c5ffdcaeSCédric Le Goater 
356c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
357c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
358c5ffdcaeSCédric Le Goater     _FDT(node);
359c5ffdcaeSCédric Le Goater     g_free(name);
360c5ffdcaeSCédric Le Goater 
361c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
362c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
363c5ffdcaeSCédric Le Goater }
364c5ffdcaeSCédric Le Goater 
365b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
366cb228f5aSCédric Le Goater {
367cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
368cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
369cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
370cb228f5aSCédric Le Goater         cpu_to_be32(1),
371cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
372cb228f5aSCédric Le Goater         cpu_to_be32(8)
373cb228f5aSCédric Le Goater     };
374cb228f5aSCédric Le Goater     char *name;
375cb228f5aSCédric Le Goater     int node;
376cb228f5aSCédric Le Goater 
377cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
378cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
379cb228f5aSCédric Le Goater     _FDT(node);
380cb228f5aSCédric Le Goater     g_free(name);
381cb228f5aSCédric Le Goater 
382cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
383cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
384cb228f5aSCédric Le Goater                       sizeof(compatible))));
385cb228f5aSCédric Le Goater 
386cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
387cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
388cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
389cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
390cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
391cb228f5aSCédric Le Goater 
392cb228f5aSCédric Le Goater     /* This is needed by Linux */
393cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
394cb228f5aSCédric Le Goater }
395cb228f5aSCédric Le Goater 
396b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
39704f6c8b2SCédric Le Goater {
39804f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
39904f6c8b2SCédric Le Goater     uint32_t io_base;
40004f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
40104f6c8b2SCédric Le Goater         cpu_to_be32(1),
40204f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
40304f6c8b2SCédric Le Goater         cpu_to_be32(3)
40404f6c8b2SCédric Le Goater     };
40504f6c8b2SCédric Le Goater     uint32_t irq;
40604f6c8b2SCédric Le Goater     char *name;
40704f6c8b2SCédric Le Goater     int node;
40804f6c8b2SCédric Le Goater 
40904f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
41004f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
41104f6c8b2SCédric Le Goater 
41204f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
41304f6c8b2SCédric Le Goater 
41404f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
41504f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
41604f6c8b2SCédric Le Goater     _FDT(node);
41704f6c8b2SCédric Le Goater     g_free(name);
41804f6c8b2SCédric Le Goater 
4197032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4207032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4217032d92aSCédric Le Goater                       sizeof(compatible))));
42204f6c8b2SCédric Le Goater 
42304f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
42404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
42504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
42604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
42704f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
42804f6c8b2SCédric Le Goater }
42904f6c8b2SCédric Le Goater 
430e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
431e7a3fee3SCédric Le Goater     void *fdt;
432e7a3fee3SCédric Le Goater     int offset;
433e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
434e7a3fee3SCédric Le Goater 
435b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
436e7a3fee3SCédric Le Goater {
437c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
438c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
439c5ffdcaeSCédric Le Goater 
440c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
441b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
442cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
443b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
44404f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
445b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
446c5ffdcaeSCédric Le Goater     } else {
447c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
448c5ffdcaeSCédric Le Goater                      d->ioport_id);
449c5ffdcaeSCédric Le Goater     }
450c5ffdcaeSCédric Le Goater 
451e7a3fee3SCédric Le Goater     return 0;
452e7a3fee3SCédric Le Goater }
453e7a3fee3SCédric Le Goater 
45459b7c1c2SBalamuruhan S /*
45559b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
456bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
457bb7ab95cSCédric Le Goater  */
458bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
459bb7ab95cSCédric Le Goater {
46064d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
461e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
462e7a3fee3SCédric Le Goater         .fdt = fdt,
463bb7ab95cSCédric Le Goater         .offset = isa_offset,
464e7a3fee3SCédric Le Goater     };
465f47a08d1SCédric Le Goater     uint32_t phandle;
466e7a3fee3SCédric Le Goater 
467bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
468bb7ab95cSCédric Le Goater 
469f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
470f47a08d1SCédric Le Goater     assert(phandle > 0);
471f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
472f47a08d1SCédric Le Goater 
47359b7c1c2SBalamuruhan S     /*
47459b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
47559b7c1c2SBalamuruhan S      * can not use object_child_foreach()
47659b7c1c2SBalamuruhan S      */
477bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
478bb7ab95cSCédric Le Goater                        &args);
479e7a3fee3SCédric Le Goater }
480e7a3fee3SCédric Le Goater 
4817a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
482e5694793SCédric Le Goater {
483e5694793SCédric Le Goater     int off;
484e5694793SCédric Le Goater 
485e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
486e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
487e5694793SCédric Le Goater 
488e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
489e5694793SCédric Le Goater }
490e5694793SCédric Le Goater 
491b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4929e933f4aSBenjamin Herrenschmidt {
493d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
494b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
4959e933f4aSBenjamin Herrenschmidt     void *fdt;
4969e933f4aSBenjamin Herrenschmidt     char *buf;
4979e933f4aSBenjamin Herrenschmidt     int off;
498e997040eSCédric Le Goater     int i;
4999e933f4aSBenjamin Herrenschmidt 
5009e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5019e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5029e933f4aSBenjamin Herrenschmidt 
503ccb099b3SCédric Le Goater     /* /qemu node */
504ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
505ccb099b3SCédric Le Goater 
5069e933f4aSBenjamin Herrenschmidt     /* Root node */
5079e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5089e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5099e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5109e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
511d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5129e933f4aSBenjamin Herrenschmidt 
5139e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5149e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5159e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5169e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5179e933f4aSBenjamin Herrenschmidt     }
5189e933f4aSBenjamin Herrenschmidt     g_free(buf);
5199e933f4aSBenjamin Herrenschmidt 
5209e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5219e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5229e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5239e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5249e933f4aSBenjamin Herrenschmidt     }
5259e933f4aSBenjamin Herrenschmidt 
5269e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5279e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5289e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5299e933f4aSBenjamin Herrenschmidt 
5309e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5319e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5329e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5339e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5349e933f4aSBenjamin Herrenschmidt     }
5359e933f4aSBenjamin Herrenschmidt 
536e997040eSCédric Le Goater     /* Populate device tree for each chip */
537e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
538eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
539e997040eSCédric Le Goater     }
540e7a3fee3SCédric Le Goater 
541e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
542bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
543aeaef83dSCédric Le Goater 
544aeaef83dSCédric Le Goater     if (pnv->bmc) {
545b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
546aeaef83dSCédric Le Goater     }
547aeaef83dSCédric Le Goater 
5487a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5497a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5507a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
551e5694793SCédric Le Goater     }
552e5694793SCédric Le Goater 
5539e933f4aSBenjamin Herrenschmidt     return fdt;
5549e933f4aSBenjamin Herrenschmidt }
5559e933f4aSBenjamin Herrenschmidt 
556bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
557bce0b691SCédric Le Goater {
558b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
559bce0b691SCédric Le Goater 
560bce0b691SCédric Le Goater     if (pnv->bmc) {
561bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
562bce0b691SCédric Le Goater     }
563bce0b691SCédric Le Goater }
564bce0b691SCédric Le Goater 
565a0628599SLike Xu static void pnv_reset(MachineState *machine)
5669e933f4aSBenjamin Herrenschmidt {
5679e933f4aSBenjamin Herrenschmidt     void *fdt;
5689e933f4aSBenjamin Herrenschmidt 
5699e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5709e933f4aSBenjamin Herrenschmidt 
571b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5729e933f4aSBenjamin Herrenschmidt 
5739e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5749e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5759e933f4aSBenjamin Herrenschmidt 
5768d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5779e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5789e933f4aSBenjamin Herrenschmidt }
5799e933f4aSBenjamin Herrenschmidt 
58004026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5813495b6b6SCédric Le Goater {
58277864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58377864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
58404026890SCédric Le Goater }
5853495b6b6SCédric Le Goater 
58604026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
58704026890SCédric Le Goater {
58877864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58977864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
59004026890SCédric Le Goater }
5913495b6b6SCédric Le Goater 
59204026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
59304026890SCédric Le Goater {
59415376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
59515376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
59604026890SCédric Le Goater }
5973495b6b6SCédric Le Goater 
5982b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
5992b548a42SCédric Le Goater {
6002661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6012661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6022b548a42SCédric Le Goater }
6032b548a42SCédric Le Goater 
60404026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
60504026890SCédric Le Goater {
60604026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6073495b6b6SCédric Le Goater }
6083495b6b6SCédric Le Goater 
609d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
610d8e4aad5SCédric Le Goater {
611d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
612d8e4aad5SCédric Le Goater 
613d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
614d8e4aad5SCédric Le Goater }
615d8e4aad5SCédric Le Goater 
616d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
617d8e4aad5SCédric Le Goater {
618d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
619d8e4aad5SCédric Le Goater 
620d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
621c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
622d8e4aad5SCédric Le Goater }
623d8e4aad5SCédric Le Goater 
624c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
625c4b2c40cSGreg Kurz                                                 uint32_t core_id)
626c4b2c40cSGreg Kurz {
627c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
628c4b2c40cSGreg Kurz }
629c4b2c40cSGreg Kurz 
630c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
631c4b2c40cSGreg Kurz                                                 uint32_t core_id)
632c4b2c40cSGreg Kurz {
633c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
634c4b2c40cSGreg Kurz }
635c4b2c40cSGreg Kurz 
636c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
637c4b2c40cSGreg Kurz                                                  uint32_t core_id)
638c4b2c40cSGreg Kurz {
639c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
640c4b2c40cSGreg Kurz }
641c4b2c40cSGreg Kurz 
642f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
643f30c843cSCédric Le Goater {
644f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
645f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
646f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
647f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
648f30c843cSCédric Le Goater 
649f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
650f30c843cSCédric Le Goater }
651f30c843cSCédric Le Goater 
652e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
653e2392d43SCédric Le Goater {
654e2392d43SCédric Le Goater     Object *obj;
655e2392d43SCédric Le Goater 
656e2392d43SCédric Le Goater     obj = OBJECT(isa_create(bus, "isa-ipmi-bt"));
657e2392d43SCédric Le Goater     object_property_set_link(obj, OBJECT(bmc), "bmc", &error_fatal);
658e2392d43SCédric Le Goater     object_property_set_int(obj, irq, "irq", &error_fatal);
659e2392d43SCédric Le Goater     object_property_set_bool(obj, true, "realized", &error_fatal);
660e2392d43SCédric Le Goater }
661e2392d43SCédric Le Goater 
6622b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
6632b548a42SCédric Le Goater {
6648b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6658b50ce85SCédric Le Goater 
6668b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
6672b548a42SCédric Le Goater }
6682b548a42SCédric Le Goater 
669b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6709e933f4aSBenjamin Herrenschmidt {
671b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
672f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6739e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
6749e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6759e933f4aSBenjamin Herrenschmidt     long fw_size;
676e997040eSCédric Le Goater     int i;
677e997040eSCédric Le Goater     char *chip_typename;
67835dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
67935dde576SCédric Le Goater     DeviceState *dev;
6809e933f4aSBenjamin Herrenschmidt 
6819e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
682d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
6833dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
6849e933f4aSBenjamin Herrenschmidt     }
6859e933f4aSBenjamin Herrenschmidt 
6869e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
687b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6889e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6899e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6909e933f4aSBenjamin Herrenschmidt 
69135dde576SCédric Le Goater     /*
69235dde576SCédric Le Goater      * Create our simple PNOR device
69335dde576SCédric Le Goater      */
69435dde576SCédric Le Goater     dev = qdev_create(NULL, TYPE_PNV_PNOR);
69535dde576SCédric Le Goater     if (pnor) {
69635dde576SCédric Le Goater         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor),
69735dde576SCédric Le Goater                             &error_abort);
69835dde576SCédric Le Goater     }
69935dde576SCédric Le Goater     qdev_init_nofail(dev);
70035dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
70135dde576SCédric Le Goater 
7029e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7039e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
7049e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
7059e933f4aSBenjamin Herrenschmidt     }
7069e933f4aSBenjamin Herrenschmidt 
7079e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
70815fcedb2SCédric Le Goater     if (!fw_filename) {
70915fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
71015fcedb2SCédric Le Goater         exit(1);
71115fcedb2SCédric Le Goater     }
7129e933f4aSBenjamin Herrenschmidt 
7139e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
7149e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
71515fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7169e933f4aSBenjamin Herrenschmidt         exit(1);
7179e933f4aSBenjamin Herrenschmidt     }
7189e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7199e933f4aSBenjamin Herrenschmidt 
7209e933f4aSBenjamin Herrenschmidt     /* load kernel */
7219e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7229e933f4aSBenjamin Herrenschmidt         long kernel_size;
7239e933f4aSBenjamin Herrenschmidt 
7249e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
725b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7269e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
727802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7289e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7299e933f4aSBenjamin Herrenschmidt             exit(1);
7309e933f4aSBenjamin Herrenschmidt         }
7319e933f4aSBenjamin Herrenschmidt     }
7329e933f4aSBenjamin Herrenschmidt 
7339e933f4aSBenjamin Herrenschmidt     /* load initrd */
7349e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7359e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7369e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
737584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7389e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
739802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7409e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7419e933f4aSBenjamin Herrenschmidt             exit(1);
7429e933f4aSBenjamin Herrenschmidt         }
7439e933f4aSBenjamin Herrenschmidt     }
744e997040eSCédric Le Goater 
745f30c843cSCédric Le Goater     /*
746f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
747f30c843cSCédric Le Goater      * default.
748f30c843cSCédric Le Goater      */
749f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
750f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
751f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
752f30c843cSCédric Le Goater         exit(1);
753f30c843cSCédric Le Goater     }
754f30c843cSCédric Le Goater 
755e997040eSCédric Le Goater     /* Create the processor chips */
7564a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7577fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7584a12c699SIgor Mammedov                                     i, machine->cpu_type);
759e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
760f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
761f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
762e997040eSCédric Le Goater         exit(1);
763e997040eSCédric Le Goater     }
764e997040eSCédric Le Goater 
765e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
766e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
767e997040eSCédric Le Goater         char chip_name[32];
768e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
769e997040eSCédric Le Goater 
770e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
771e997040eSCédric Le Goater 
77259b7c1c2SBalamuruhan S         /*
77359b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
774e997040eSCédric Le Goater          * way to specify different ranges for each chip
775e997040eSCédric Le Goater          */
776e997040eSCédric Le Goater         if (i == 0) {
777e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
778e997040eSCédric Le Goater                                     &error_fatal);
779e997040eSCédric Le Goater         }
780e997040eSCédric Le Goater 
781e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
782e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
783e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
784e997040eSCédric Le Goater                                 &error_fatal);
785fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
786fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
787e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
788e997040eSCédric Le Goater     }
789e997040eSCédric Le Goater     g_free(chip_typename);
7903495b6b6SCédric Le Goater 
791e2392d43SCédric Le Goater     /* Create the machine BMC simulator */
792e2392d43SCédric Le Goater     pnv->bmc = pnv_bmc_create();
793e2392d43SCédric Le Goater 
7943495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
79504026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
7963495b6b6SCédric Le Goater 
7973495b6b6SCédric Le Goater     /* Create serial port */
798def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
7993495b6b6SCédric Le Goater 
8003495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8016c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
802bce0b691SCédric Le Goater 
803e2392d43SCédric Le Goater     /* Create the IPMI BT device for communication with the BMC */
804e2392d43SCédric Le Goater     pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
805e2392d43SCédric Le Goater 
80659b7c1c2SBalamuruhan S     /*
80759b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
80859b7c1c2SBalamuruhan S      * host to powerdown
80959b7c1c2SBalamuruhan S      */
810bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
811bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
812e997040eSCédric Le Goater }
813e997040eSCédric Le Goater 
814631adaffSCédric Le Goater /*
815631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
816631adaffSCédric Le Goater  *   22:24  Chip ID
817631adaffSCédric Le Goater  *   25:28  Core number
818631adaffSCédric Le Goater  *   29:31  Thread ID
819631adaffSCédric Le Goater  */
820631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
821631adaffSCédric Le Goater {
822631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
823631adaffSCédric Le Goater }
824631adaffSCédric Le Goater 
8258fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
826d35aefa9SCédric Le Goater                                         Error **errp)
827d35aefa9SCédric Le Goater {
8288fa1f4efSCédric Le Goater     Error *local_err = NULL;
8298fa1f4efSCédric Le Goater     Object *obj;
8308907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8318fa1f4efSCédric Le Goater 
8328fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
8338fa1f4efSCédric Le Goater                      &local_err);
8348fa1f4efSCédric Le Goater     if (local_err) {
8358fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
8368fa1f4efSCédric Le Goater         return;
8378fa1f4efSCédric Le Goater     }
8388fa1f4efSCédric Le Goater 
839956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
840d35aefa9SCédric Le Goater }
841d35aefa9SCédric Le Goater 
8420990ce6aSGreg Kurz 
843d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
844d49e8a9bSCédric Le Goater {
845d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
846d49e8a9bSCédric Le Goater 
847d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
848d49e8a9bSCédric Le Goater }
849d49e8a9bSCédric Le Goater 
8500990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
8510990ce6aSGreg Kurz {
8520990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8530990ce6aSGreg Kurz 
8540990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
8550990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
8560990ce6aSGreg Kurz }
8570990ce6aSGreg Kurz 
85885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
85985913070SGreg Kurz                                             Monitor *mon)
86085913070SGreg Kurz {
86185913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
86285913070SGreg Kurz }
86385913070SGreg Kurz 
864631adaffSCédric Le Goater /*
865631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
866631adaffSCédric Le Goater  *   49:52  Node ID
867631adaffSCédric Le Goater  *   53:55  Chip ID
868631adaffSCédric Le Goater  *   56     Reserved - Read as zero
869631adaffSCédric Le Goater  *   57:61  Core number
870631adaffSCédric Le Goater  *   62:63  Thread ID
871631adaffSCédric Le Goater  *
872631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
873631adaffSCédric Le Goater  */
874631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
875631adaffSCédric Le Goater {
876631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
877631adaffSCédric Le Goater }
878631adaffSCédric Le Goater 
8792b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
8802b548a42SCédric Le Goater {
8812b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
8822b548a42SCédric Le Goater }
8832b548a42SCédric Le Goater 
8848fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
885d35aefa9SCédric Le Goater                                         Error **errp)
886d35aefa9SCédric Le Goater {
8872dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
8882dfa91a2SCédric Le Goater     Error *local_err = NULL;
8892dfa91a2SCédric Le Goater     Object *obj;
8902dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8912dfa91a2SCédric Le Goater 
8922dfa91a2SCédric Le Goater     /*
8932dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
8942dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
8952dfa91a2SCédric Le Goater      * only used at runtime.
8962dfa91a2SCédric Le Goater      */
89726aa5b1eSGreg Kurz     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err);
8982dfa91a2SCédric Le Goater     if (local_err) {
8992dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9008fa1f4efSCédric Le Goater         return;
901d35aefa9SCédric Le Goater     }
902d35aefa9SCédric Le Goater 
9032dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
9042dfa91a2SCédric Le Goater }
9052dfa91a2SCédric Le Goater 
906d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
907d49e8a9bSCédric Le Goater {
908d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
909d49e8a9bSCédric Le Goater 
910d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
911d49e8a9bSCédric Le Goater }
912d49e8a9bSCédric Le Goater 
9130990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9140990ce6aSGreg Kurz {
9150990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9160990ce6aSGreg Kurz 
9170990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
9180990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9190990ce6aSGreg Kurz }
9200990ce6aSGreg Kurz 
92185913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
92285913070SGreg Kurz                                             Monitor *mon)
92385913070SGreg Kurz {
92485913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
92585913070SGreg Kurz }
92685913070SGreg Kurz 
9272b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
9282b548a42SCédric Le Goater                                         Error **errp)
9292b548a42SCédric Le Goater {
9302b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9312b548a42SCédric Le Goater 
9322b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
9332b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9342b548a42SCédric Le Goater }
9352b548a42SCédric Le Goater 
9362b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
9372b548a42SCédric Le Goater {
9382b548a42SCédric Le Goater     ;
9392b548a42SCédric Le Goater }
9402b548a42SCédric Le Goater 
9412b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9422b548a42SCédric Le Goater {
9432b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9442b548a42SCédric Le Goater 
9452b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
9462b548a42SCédric Le Goater }
9472b548a42SCédric Le Goater 
94885913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
94985913070SGreg Kurz                                              Monitor *mon)
95085913070SGreg Kurz {
95185913070SGreg Kurz }
95285913070SGreg Kurz 
95359b7c1c2SBalamuruhan S /*
95459b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
955397a79e7SCédric Le Goater  *
956397a79e7SCédric Le Goater  * <EX0 reserved>
957397a79e7SCédric Le Goater  *  EX1  - Venice only
958397a79e7SCédric Le Goater  *  EX2  - Venice only
959397a79e7SCédric Le Goater  *  EX3  - Venice only
960397a79e7SCédric Le Goater  *  EX4
961397a79e7SCédric Le Goater  *  EX5
962397a79e7SCédric Le Goater  *  EX6
963397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
964397a79e7SCédric Le Goater  *  EX9  - Venice only
965397a79e7SCédric Le Goater  *  EX10 - Venice only
966397a79e7SCédric Le Goater  *  EX11 - Venice only
967397a79e7SCédric Le Goater  *  EX12
968397a79e7SCédric Le Goater  *  EX13
969397a79e7SCédric Le Goater  *  EX14
970397a79e7SCédric Le Goater  * <EX15 reserved>
971397a79e7SCédric Le Goater  */
972397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
973397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
974397a79e7SCédric Le Goater 
975397a79e7SCédric Le Goater /*
97609279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
977397a79e7SCédric Le Goater  */
97809279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
979397a79e7SCédric Le Goater 
9802b548a42SCédric Le Goater 
9812b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
9822b548a42SCédric Le Goater 
98377864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
98477864267SCédric Le Goater {
98577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
98677864267SCédric Le Goater 
987f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
988ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
98977864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
99077864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
99177864267SCédric Le Goater 
992f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
99382514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
99477864267SCédric Le Goater 
995f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
9963233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
9973887d241SBalamuruhan S 
9983887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
9993887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
100077864267SCédric Le Goater }
100177864267SCédric Le Goater 
100277864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
100377864267SCédric Le Goater  {
100477864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
100577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
100677864267SCédric Le Goater     int i, j;
100777864267SCédric Le Goater     char *name;
100877864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
100977864267SCédric Le Goater 
101077864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
101177864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
101277864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
101377864267SCédric Le Goater     g_free(name);
101477864267SCédric Le Goater 
101577864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
101677864267SCédric Le Goater 
101777864267SCédric Le Goater     /* Map the ICP registers for each thread */
101877864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
10194fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
102077864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
102177864267SCédric Le Goater 
102277864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
102377864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
102477864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
102577864267SCédric Le Goater 
102677864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
102777864267SCédric Le Goater                                         &icp->mmio);
102877864267SCédric Le Goater         }
102977864267SCédric Le Goater     }
103077864267SCédric Le Goater }
103177864267SCédric Le Goater 
103277864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
103377864267SCédric Le Goater {
103477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
103577864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
103677864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1037ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
103877864267SCédric Le Goater     Error *local_err = NULL;
103977864267SCédric Le Goater 
1040709044fdSCédric Le Goater     /* XSCOM bridge is first */
1041709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1042709044fdSCédric Le Goater     if (local_err) {
1043709044fdSCédric Le Goater         error_propagate(errp, local_err);
1044709044fdSCédric Le Goater         return;
1045709044fdSCédric Le Goater     }
1046709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1047709044fdSCédric Le Goater 
104877864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
104977864267SCédric Le Goater     if (local_err) {
105077864267SCédric Le Goater         error_propagate(errp, local_err);
105177864267SCédric Le Goater         return;
105277864267SCédric Le Goater     }
105377864267SCédric Le Goater 
105477864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
105577864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
105677864267SCédric Le Goater                             "bar", &error_fatal);
105777864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
105877864267SCédric Le Goater     if (local_err) {
105977864267SCédric Le Goater         error_propagate(errp, local_err);
106077864267SCédric Le Goater         return;
106177864267SCédric Le Goater     }
1062ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1063ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
106477864267SCédric Le Goater 
106577864267SCédric Le Goater     /* Create LPC controller */
1066b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip8->lpc), OBJECT(&chip8->psi), "psi",
1067b63f3893SGreg Kurz                              &error_abort);
106877864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
106977864267SCédric Le Goater                              &error_fatal);
107077864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
107177864267SCédric Le Goater 
107264d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
107364d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
107464d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
107564d011d5SCédric Le Goater 
107659b7c1c2SBalamuruhan S     /*
107759b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
107859b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
107959b7c1c2SBalamuruhan S      */
108077864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
108177864267SCédric Le Goater     if (local_err) {
108277864267SCédric Le Goater         error_propagate(errp, local_err);
108377864267SCédric Le Goater         return;
108477864267SCédric Le Goater     }
108577864267SCédric Le Goater 
108677864267SCédric Le Goater     /* Create the simplified OCC model */
1087ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip8->occ), OBJECT(&chip8->psi), "psi",
1088ee3d2713SGreg Kurz                              &error_abort);
108977864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
109077864267SCédric Le Goater     if (local_err) {
109177864267SCédric Le Goater         error_propagate(errp, local_err);
109277864267SCédric Le Goater         return;
109377864267SCédric Le Goater     }
109477864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1095f3db8266SBalamuruhan S 
1096f3db8266SBalamuruhan S     /* OCC SRAM model */
10973a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1098f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
10993887d241SBalamuruhan S 
11003887d241SBalamuruhan S     /* HOMER */
1101f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip8->homer), OBJECT(chip), "chip",
1102f2582acfSGreg Kurz                              &error_abort);
11033887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
11043887d241SBalamuruhan S                              &local_err);
11053887d241SBalamuruhan S     if (local_err) {
11063887d241SBalamuruhan S         error_propagate(errp, local_err);
11073887d241SBalamuruhan S         return;
11083887d241SBalamuruhan S     }
11098f092316SCédric Le Goater     /* Homer Xscom region */
11108f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
11118f092316SCédric Le Goater 
11128f092316SCédric Le Goater     /* Homer mmio region */
11133887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
11143887d241SBalamuruhan S                                 &chip8->homer.regs);
111577864267SCédric Le Goater }
111677864267SCédric Le Goater 
1117e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1118e997040eSCédric Le Goater {
1119e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1120e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1121e997040eSCédric Le Goater 
1122e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
1123e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1124397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
1125631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1126d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1127d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11280990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
112985913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
113004026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1131eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1132d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1133c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
1134e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
113577864267SCédric Le Goater 
113677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
113777864267SCédric Le Goater                                     &k->parent_realize);
1138e997040eSCédric Le Goater }
1139e997040eSCédric Le Goater 
1140e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1141e997040eSCédric Le Goater {
1142e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1143e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1144e997040eSCédric Le Goater 
1145e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
1146e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1147397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1148631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1149d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1150d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11510990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
115285913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
115304026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1154eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1155d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1156c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
1157e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
115877864267SCédric Le Goater 
115977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
116077864267SCédric Le Goater                                     &k->parent_realize);
1161e997040eSCédric Le Goater }
1162e997040eSCédric Le Goater 
1163e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1164e997040eSCédric Le Goater {
1165e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1166e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1167e997040eSCédric Le Goater 
1168e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
1169e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1170397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1171631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1172d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1173d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
11740990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
117585913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
117604026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1177eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1178d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1179c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
1180e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
118177864267SCédric Le Goater 
118277864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
118377864267SCédric Le Goater                                     &k->parent_realize);
118477864267SCédric Le Goater }
118577864267SCédric Le Goater 
118677864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
118777864267SCédric Le Goater {
11882dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
11892dfa91a2SCédric Le Goater 
11902dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
11912dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
1192c38536bcSCédric Le Goater 
1193c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1194c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
119515376c66SCédric Le Goater 
119615376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
119715376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
11986598a70dSCédric Le Goater 
11996598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
12006598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
12013887d241SBalamuruhan S 
12023887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
12033887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
120477864267SCédric Le Goater }
120577864267SCédric Le Goater 
12065dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
12075dad902cSCédric Le Goater {
12085dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
12095dad902cSCédric Le Goater     int i;
12105dad902cSCédric Le Goater 
12115dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
12125dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
12135dad902cSCédric Le Goater 
12145dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
12155dad902cSCédric Le Goater         char eq_name[32];
12165dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
12174fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
12185dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
12195dad902cSCédric Le Goater 
12205dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1221bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1222bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
12235dad902cSCédric Le Goater 
12245dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
12255dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
12265dad902cSCédric Le Goater 
12275dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
12285dad902cSCédric Le Goater                                 &eq->xscom_regs);
12295dad902cSCédric Le Goater     }
12305dad902cSCédric Le Goater }
12315dad902cSCédric Le Goater 
123277864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
123377864267SCédric Le Goater {
123477864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
12352dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
12362dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1237c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
123877864267SCédric Le Goater     Error *local_err = NULL;
123977864267SCédric Le Goater 
1240709044fdSCédric Le Goater     /* XSCOM bridge is first */
1241709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1242709044fdSCédric Le Goater     if (local_err) {
1243709044fdSCédric Le Goater         error_propagate(errp, local_err);
1244709044fdSCédric Le Goater         return;
1245709044fdSCédric Le Goater     }
1246709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1247709044fdSCédric Le Goater 
124877864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
124977864267SCédric Le Goater     if (local_err) {
125077864267SCédric Le Goater         error_propagate(errp, local_err);
125177864267SCédric Le Goater         return;
125277864267SCédric Le Goater     }
12532dfa91a2SCédric Le Goater 
12545dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
12555dad902cSCédric Le Goater     if (local_err) {
12565dad902cSCédric Le Goater         error_propagate(errp, local_err);
12575dad902cSCédric Le Goater         return;
12585dad902cSCédric Le Goater     }
12595dad902cSCédric Le Goater 
12602dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
12612dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
12622dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
12632dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
12642dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
12652dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
12662dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
12672dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
12682dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
12697ae54cc3SGreg Kurz     object_property_set_link(OBJECT(&chip9->xive), OBJECT(chip), "chip",
12707ae54cc3SGreg Kurz                              &error_abort);
12712dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
12722dfa91a2SCédric Le Goater                              &local_err);
12732dfa91a2SCédric Le Goater     if (local_err) {
12742dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
12752dfa91a2SCédric Le Goater         return;
12762dfa91a2SCédric Le Goater     }
12772dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
12782dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1279c38536bcSCédric Le Goater 
1280c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1281c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1282c38536bcSCédric Le Goater                             "bar", &error_fatal);
1283c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1284c38536bcSCédric Le Goater     if (local_err) {
1285c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1286c38536bcSCédric Le Goater         return;
1287c38536bcSCédric Le Goater     }
1288c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1289c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
129015376c66SCédric Le Goater 
129115376c66SCédric Le Goater     /* LPC */
1292b63f3893SGreg Kurz     object_property_set_link(OBJECT(&chip9->lpc), OBJECT(&chip9->psi), "psi",
1293b63f3893SGreg Kurz                              &error_abort);
129415376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
129515376c66SCédric Le Goater     if (local_err) {
129615376c66SCédric Le Goater         error_propagate(errp, local_err);
129715376c66SCédric Le Goater         return;
129815376c66SCédric Le Goater     }
129915376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
130015376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
130115376c66SCédric Le Goater 
130215376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
130315376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
13046598a70dSCédric Le Goater 
13056598a70dSCédric Le Goater     /* Create the simplified OCC model */
1306ee3d2713SGreg Kurz     object_property_set_link(OBJECT(&chip9->occ), OBJECT(&chip9->psi), "psi",
1307ee3d2713SGreg Kurz                              &error_abort);
13086598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
13096598a70dSCédric Le Goater     if (local_err) {
13106598a70dSCédric Le Goater         error_propagate(errp, local_err);
13116598a70dSCédric Le Goater         return;
13126598a70dSCédric Le Goater     }
13136598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1314f3db8266SBalamuruhan S 
1315f3db8266SBalamuruhan S     /* OCC SRAM model */
13163a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1317f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
13183887d241SBalamuruhan S 
13193887d241SBalamuruhan S     /* HOMER */
1320f2582acfSGreg Kurz     object_property_set_link(OBJECT(&chip9->homer), OBJECT(chip), "chip",
1321f2582acfSGreg Kurz                              &error_abort);
13223887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
13233887d241SBalamuruhan S                              &local_err);
13243887d241SBalamuruhan S     if (local_err) {
13253887d241SBalamuruhan S         error_propagate(errp, local_err);
13263887d241SBalamuruhan S         return;
13273887d241SBalamuruhan S     }
13288f092316SCédric Le Goater     /* Homer Xscom region */
13298f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
13308f092316SCédric Le Goater 
13318f092316SCédric Le Goater     /* Homer mmio region */
13323887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
13333887d241SBalamuruhan S                                 &chip9->homer.regs);
1334e997040eSCédric Le Goater }
1335e997040eSCédric Le Goater 
1336e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1337e997040eSCédric Le Goater {
1338e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1339e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1340e997040eSCédric Le Goater 
1341e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
134283028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1343397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1344631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1345d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1346d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
13470990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
134885913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
134904026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1350eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1351d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1352c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
1353e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
135477864267SCédric Le Goater 
135577864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
135677864267SCédric Le Goater                                     &k->parent_realize);
1357e997040eSCédric Le Goater }
1358e997040eSCédric Le Goater 
13592b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
13602b548a42SCédric Le Goater {
13618b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
13628b50ce85SCédric Le Goater 
13638b50ce85SCédric Le Goater     object_initialize_child(obj, "psi",  &chip10->psi, sizeof(chip10->psi),
13648b50ce85SCédric Le Goater                             TYPE_PNV10_PSI, &error_abort, NULL);
13652661f6abSCédric Le Goater     object_initialize_child(obj, "lpc",  &chip10->lpc, sizeof(chip10->lpc),
13662661f6abSCédric Le Goater                             TYPE_PNV10_LPC, &error_abort, NULL);
13672b548a42SCédric Le Goater }
13682b548a42SCédric Le Goater 
13692b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
13702b548a42SCédric Le Goater {
13712b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
13722b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
13738b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
13742b548a42SCédric Le Goater     Error *local_err = NULL;
13752b548a42SCédric Le Goater 
13762b548a42SCédric Le Goater     /* XSCOM bridge is first */
13772b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
13782b548a42SCédric Le Goater     if (local_err) {
13792b548a42SCédric Le Goater         error_propagate(errp, local_err);
13802b548a42SCédric Le Goater         return;
13812b548a42SCédric Le Goater     }
13822b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
13832b548a42SCédric Le Goater 
13842b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
13852b548a42SCédric Le Goater     if (local_err) {
13862b548a42SCédric Le Goater         error_propagate(errp, local_err);
13872b548a42SCédric Le Goater         return;
13882b548a42SCédric Le Goater     }
13898b50ce85SCédric Le Goater 
13908b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
13918b50ce85SCédric Le Goater     object_property_set_int(OBJECT(&chip10->psi), PNV10_PSIHB_BASE(chip),
13928b50ce85SCédric Le Goater                             "bar", &error_fatal);
13938b50ce85SCédric Le Goater     object_property_set_bool(OBJECT(&chip10->psi), true, "realized",
13948b50ce85SCédric Le Goater                              &local_err);
13958b50ce85SCédric Le Goater     if (local_err) {
13968b50ce85SCédric Le Goater         error_propagate(errp, local_err);
13978b50ce85SCédric Le Goater         return;
13988b50ce85SCédric Le Goater     }
13998b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
14008b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
14012661f6abSCédric Le Goater 
14022661f6abSCédric Le Goater     /* LPC */
14032661f6abSCédric Le Goater     object_property_set_link(OBJECT(&chip10->lpc), OBJECT(&chip10->psi), "psi",
14042661f6abSCédric Le Goater                              &error_abort);
14052661f6abSCédric Le Goater     object_property_set_bool(OBJECT(&chip10->lpc), true, "realized",
14062661f6abSCédric Le Goater                              &local_err);
14072661f6abSCédric Le Goater     if (local_err) {
14082661f6abSCédric Le Goater         error_propagate(errp, local_err);
14092661f6abSCédric Le Goater         return;
14102661f6abSCédric Le Goater     }
14112661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
14122661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
14132661f6abSCédric Le Goater 
14142661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
14152661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
14162b548a42SCédric Le Goater }
14172b548a42SCédric Le Goater 
14182b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
14192b548a42SCédric Le Goater {
14202b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
14212b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
14222b548a42SCédric Le Goater 
14232b548a42SCédric Le Goater     k->chip_type = PNV_CHIP_POWER10;
14242b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
14252b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
14262b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
14272b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
14282b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
14292b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
143085913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
14312b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
14322b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
14332b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1434c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
14352b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
14362b548a42SCédric Le Goater 
14372b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
14382b548a42SCédric Le Goater                                     &k->parent_realize);
14392b548a42SCédric Le Goater }
14402b548a42SCédric Le Goater 
1441397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1442397a79e7SCédric Le Goater {
1443397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1444397a79e7SCédric Le Goater     int cores_max;
1445397a79e7SCédric Le Goater 
1446397a79e7SCédric Le Goater     /*
1447397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1448397a79e7SCédric Le Goater      * the chip class
1449397a79e7SCédric Le Goater      */
1450397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1451397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1452397a79e7SCédric Le Goater     }
1453397a79e7SCédric Le Goater 
1454397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1455397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1456397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1457397a79e7SCédric Le Goater                    chip->cores_mask);
1458397a79e7SCédric Le Goater         return;
1459397a79e7SCédric Le Goater     }
1460397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1461397a79e7SCédric Le Goater 
1462397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
146327d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1464397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1465397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1466397a79e7SCédric Le Goater                    cores_max);
1467397a79e7SCédric Le Goater         return;
1468397a79e7SCédric Le Goater     }
1469397a79e7SCédric Le Goater }
1470397a79e7SCédric Le Goater 
147151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1472e997040eSCédric Le Goater {
1473fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1474397a79e7SCédric Le Goater     Error *error = NULL;
1475d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
147640abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1477d2fd9612SCédric Le Goater     int i, core_hwid;
1478397a79e7SCédric Le Goater 
1479d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1480d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1481d2fd9612SCédric Le Goater         return;
1482d2fd9612SCédric Le Goater     }
1483d2fd9612SCédric Le Goater 
1484d2fd9612SCédric Le Goater     /* Cores */
1485397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1486397a79e7SCédric Le Goater     if (error) {
1487397a79e7SCédric Le Goater         error_propagate(errp, error);
1488397a79e7SCédric Le Goater         return;
1489397a79e7SCédric Le Goater     }
1490d2fd9612SCédric Le Goater 
14914fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1492d2fd9612SCédric Le Goater 
1493d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1494d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1495d2fd9612SCédric Le Goater         char core_name[32];
14964fa28f23SGreg Kurz         PnvCore *pnv_core;
1497c035851aSCédric Le Goater         uint64_t xscom_core_base;
1498d2fd9612SCédric Le Goater 
1499d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1500d2fd9612SCédric Le Goater             continue;
1501d2fd9612SCédric Le Goater         }
1502d2fd9612SCédric Le Goater 
15034fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
15044fa28f23SGreg Kurz 
1505d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
15064fa28f23SGreg Kurz         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
15074fa28f23SGreg Kurz                                   &error_abort);
15084fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
1509fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1510d2fd9612SCédric Le Goater                                 &error_fatal);
1511d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1512d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1513d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1514d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1515d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1516158e17a6SGreg Kurz         object_property_set_link(OBJECT(pnv_core), OBJECT(chip), "chip",
1517158e17a6SGreg Kurz                                  &error_abort);
1518d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1519d2fd9612SCédric Le Goater                                  &error_fatal);
152024ece072SCédric Le Goater 
152124ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1522c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1523c035851aSCédric Le Goater 
1524c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
15254fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1526d2fd9612SCédric Le Goater         i++;
1527d2fd9612SCédric Le Goater     }
152851c04728SCédric Le Goater }
152951c04728SCédric Le Goater 
153051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
153151c04728SCédric Le Goater {
153251c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
153351c04728SCédric Le Goater     Error *error = NULL;
153451c04728SCédric Le Goater 
153551c04728SCédric Le Goater     /* Cores */
153651c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
153751c04728SCédric Le Goater     if (error) {
153851c04728SCédric Le Goater         error_propagate(errp, error);
153951c04728SCédric Le Goater         return;
154051c04728SCédric Le Goater     }
1541e997040eSCédric Le Goater }
1542e997040eSCédric Le Goater 
1543e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1544e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1545e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1546e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1547397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1548397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1549e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1550e997040eSCédric Le Goater };
1551e997040eSCédric Le Goater 
1552e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1553e997040eSCédric Le Goater {
1554e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1555e997040eSCédric Le Goater 
15569d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1557e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1558e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1559e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1560e997040eSCédric Le Goater }
1561e997040eSCédric Le Goater 
1562119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1563119eaa9dSCédric Le Goater {
1564119eaa9dSCédric Le Goater     int i, j;
1565119eaa9dSCédric Le Goater 
1566119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1567119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1568119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1569119eaa9dSCédric Le Goater 
1570119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1571119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1572119eaa9dSCédric Le Goater                 return pc->threads[j];
1573119eaa9dSCédric Le Goater             }
1574119eaa9dSCédric Le Goater         }
1575119eaa9dSCédric Le Goater     }
1576119eaa9dSCédric Le Goater     return NULL;
1577119eaa9dSCédric Le Goater }
1578119eaa9dSCédric Le Goater 
157954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
158054f59d78SCédric Le Goater {
1581b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
158254f59d78SCédric Le Goater     int i;
158354f59d78SCédric Le Goater 
158454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
158577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
158677864267SCédric Le Goater 
158777864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
158877864267SCédric Le Goater             return &chip8->psi.ics;
158954f59d78SCédric Le Goater         }
159054f59d78SCédric Le Goater     }
159154f59d78SCédric Le Goater     return NULL;
159254f59d78SCédric Le Goater }
159354f59d78SCédric Le Goater 
159454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
159554f59d78SCédric Le Goater {
1596b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
159754f59d78SCédric Le Goater     int i;
159854f59d78SCédric Le Goater 
159954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
160077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
160177864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
160254f59d78SCédric Le Goater     }
160354f59d78SCédric Le Goater }
160454f59d78SCédric Le Goater 
160536fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
160636fc6f08SCédric Le Goater {
160736fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
160836fc6f08SCédric Le Goater 
1609956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
161036fc6f08SCédric Le Goater }
161136fc6f08SCédric Le Goater 
161247fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
161347fea43aSCédric Le Goater                                Monitor *mon)
161447fea43aSCédric Le Goater {
1615b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
161654f59d78SCédric Le Goater     int i;
161747fea43aSCédric Le Goater     CPUState *cs;
161847fea43aSCédric Le Goater 
161947fea43aSCédric Le Goater     CPU_FOREACH(cs) {
162047fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
162147fea43aSCédric Le Goater 
162285913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
162385913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
162485913070SGreg Kurz                                                            mon);
1625d8e4aad5SCédric Le Goater     }
162654f59d78SCédric Le Goater 
162754f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1628d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
162954f59d78SCédric Le Goater     }
163047fea43aSCédric Le Goater }
163147fea43aSCédric Le Goater 
1632c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1633c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1634c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1635c722579eSCédric Le Goater                          uint32_t logic_serv,
1636c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1637c722579eSCédric Le Goater {
1638c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1639c722579eSCédric Le Goater     int total_count = 0;
1640c722579eSCédric Le Goater     int i;
1641c722579eSCédric Le Goater 
1642c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1643c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1644c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1645c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1646c722579eSCédric Le Goater         int count;
1647c722579eSCédric Le Goater 
1648c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1649c722579eSCédric Le Goater                                priority, logic_serv, match);
1650c722579eSCédric Le Goater 
1651c722579eSCédric Le Goater         if (count < 0) {
1652c722579eSCédric Le Goater             return count;
1653c722579eSCédric Le Goater         }
1654c722579eSCédric Le Goater 
1655c722579eSCédric Le Goater         total_count += count;
1656c722579eSCédric Le Goater     }
1657c722579eSCédric Le Goater 
1658c722579eSCédric Le Goater     return total_count;
1659c722579eSCédric Le Goater }
1660c722579eSCédric Le Goater 
16615373c61dSCédric Le Goater PnvChip *pnv_get_chip(uint32_t chip_id)
16625373c61dSCédric Le Goater {
16635373c61dSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
16645373c61dSCédric Le Goater     int i;
16655373c61dSCédric Le Goater 
16665373c61dSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
16675373c61dSCédric Le Goater         PnvChip *chip = pnv->chips[i];
16685373c61dSCédric Le Goater         if (chip->chip_id == chip_id) {
16695373c61dSCédric Le Goater             return chip;
16705373c61dSCédric Le Goater         }
16715373c61dSCédric Le Goater     }
16725373c61dSCédric Le Goater     return NULL;
16735373c61dSCédric Le Goater }
16745373c61dSCédric Le Goater 
1675e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1676e997040eSCédric Le Goater                               void *opaque, Error **errp)
1677e997040eSCédric Le Goater {
1678b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1679e997040eSCédric Le Goater }
1680e997040eSCédric Le Goater 
1681e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1682e997040eSCédric Le Goater                               void *opaque, Error **errp)
1683e997040eSCédric Le Goater {
1684b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1685e997040eSCédric Le Goater     uint32_t num_chips;
1686e997040eSCédric Le Goater     Error *local_err = NULL;
1687e997040eSCédric Le Goater 
1688e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1689e997040eSCédric Le Goater     if (local_err) {
1690e997040eSCédric Le Goater         error_propagate(errp, local_err);
1691e997040eSCédric Le Goater         return;
1692e997040eSCédric Le Goater     }
1693e997040eSCédric Le Goater 
1694e997040eSCédric Le Goater     /*
1695e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1696e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1697e997040eSCédric Le Goater      */
1698e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1699e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1700e997040eSCédric Le Goater         return;
1701e997040eSCédric Le Goater     }
1702e997040eSCédric Le Goater 
1703e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1704e997040eSCédric Le Goater }
1705e997040eSCédric Le Goater 
170677864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1707e997040eSCédric Le Goater {
1708b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1709e997040eSCédric Le Goater     pnv->num_chips = 1;
1710e997040eSCédric Le Goater }
1711e997040eSCédric Le Goater 
1712b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1713e997040eSCédric Le Goater {
17141e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1715e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1716e997040eSCédric Le Goater                               NULL, NULL, NULL);
1717e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1718e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1719e997040eSCédric Le Goater                               NULL);
17209e933f4aSBenjamin Herrenschmidt }
17219e933f4aSBenjamin Herrenschmidt 
1722f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
17239e933f4aSBenjamin Herrenschmidt {
17249e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
172536fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1726d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1727d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1728f30c843cSCédric Le Goater 
1729f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1730f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1731f30c843cSCédric Le Goater 
1732f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1733f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1734f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1735d76f2da7SGreg Kurz 
1736d76f2da7SGreg Kurz     pmc->compat = compat;
1737d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1738f30c843cSCédric Le Goater }
1739f30c843cSCédric Le Goater 
1740f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1741f30c843cSCédric Le Goater {
1742f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1743c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1744d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1745d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1746f30c843cSCédric Le Goater 
1747f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1748f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1749c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1750f30c843cSCédric Le Goater 
1751f30c843cSCédric Le Goater     mc->alias = "powernv";
1752d76f2da7SGreg Kurz 
1753d76f2da7SGreg Kurz     pmc->compat = compat;
1754d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
17557a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1756f30c843cSCédric Le Goater }
1757f30c843cSCédric Le Goater 
17582b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
17592b548a42SCédric Le Goater {
17602b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1761d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1762d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
17632b548a42SCédric Le Goater 
17642b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
17652b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
1766d76f2da7SGreg Kurz 
1767d76f2da7SGreg Kurz     pmc->compat = compat;
1768d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
17697a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
17702b548a42SCédric Le Goater }
17712b548a42SCédric Le Goater 
1772f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1773f30c843cSCédric Le Goater {
1774f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
177547fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
17769e933f4aSBenjamin Herrenschmidt 
17779e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1778b168a138SCédric Le Goater     mc->init = pnv_init;
1779b168a138SCédric Le Goater     mc->reset = pnv_reset;
17809e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
178159b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
178259b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
17839e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
17849e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1785f1d18b0aSJoel Stanley     /*
1786f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1787f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1788f1d18b0aSJoel Stanley      */
1789f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
179047fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1791e997040eSCédric Le Goater 
1792b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
17939e933f4aSBenjamin Herrenschmidt }
17949e933f4aSBenjamin Herrenschmidt 
179577864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1796beba5c0fSIgor Mammedov     {                                             \
1797beba5c0fSIgor Mammedov         .name          = type,                    \
1798beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
179977864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
180077864267SCédric Le Goater     }
180177864267SCédric Le Goater 
180277864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
180377864267SCédric Le Goater     {                                             \
180477864267SCédric Le Goater         .name          = type,                    \
180577864267SCédric Le Goater         .class_init    = class_initfn,            \
180677864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1807beba5c0fSIgor Mammedov     }
1808beba5c0fSIgor Mammedov 
18092b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
18102b548a42SCédric Le Goater     {                                              \
18112b548a42SCédric Le Goater         .name          = type,                     \
18122b548a42SCédric Le Goater         .class_init    = class_initfn,             \
18132b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
18142b548a42SCédric Le Goater     }
18152b548a42SCédric Le Goater 
1816beba5c0fSIgor Mammedov static const TypeInfo types[] = {
18171aba8716SCédric Le Goater     {
18182b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
18192b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18202b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
18212b548a42SCédric Le Goater     },
18222b548a42SCédric Le Goater     {
18231aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
18241aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18251aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
1826c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
1827c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
1828c722579eSCédric Le Goater             { },
1829c722579eSCédric Le Goater         },
18301aba8716SCédric Le Goater     },
18311aba8716SCédric Le Goater     {
18321aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
18331aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
18341aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
18351aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
18361aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
18371aba8716SCédric Le Goater             { },
18381aba8716SCédric Le Goater         },
18391aba8716SCédric Le Goater     },
1840beba5c0fSIgor Mammedov     {
1841b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
18429e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1843f30c843cSCédric Le Goater         .abstract       = true,
18449e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
184577864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1846b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
1847d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
184836fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
184947fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
185036fc6f08SCédric Le Goater             { },
185136fc6f08SCédric Le Goater         },
1852beba5c0fSIgor Mammedov     },
1853beba5c0fSIgor Mammedov     {
1854beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1855beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1856beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1857beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1858beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1859beba5c0fSIgor Mammedov         .abstract      = true,
1860beba5c0fSIgor Mammedov     },
186177864267SCédric Le Goater 
186277864267SCédric Le Goater     /*
18632b548a42SCédric Le Goater      * P10 chip and variants
18642b548a42SCédric Le Goater      */
18652b548a42SCédric Le Goater     {
18662b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
18672b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
18682b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
18692b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
18702b548a42SCédric Le Goater     },
18712b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
18722b548a42SCédric Le Goater 
18732b548a42SCédric Le Goater     /*
187477864267SCédric Le Goater      * P9 chip and variants
187577864267SCédric Le Goater      */
187677864267SCédric Le Goater     {
187777864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
187877864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
187977864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
188077864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
188177864267SCédric Le Goater     },
188277864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
188377864267SCédric Le Goater 
188477864267SCédric Le Goater     /*
188577864267SCédric Le Goater      * P8 chip and variants
188677864267SCédric Le Goater      */
188777864267SCédric Le Goater     {
188877864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
188977864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
189077864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
189177864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
189277864267SCédric Le Goater     },
189377864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
189477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
189577864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1896beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
18979e933f4aSBenjamin Herrenschmidt };
18989e933f4aSBenjamin Herrenschmidt 
1899beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1900