xref: /qemu/hw/ppc/pnv.c (revision 13480fc5)
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
9f70c5966SChetan Pant  * version 2.1 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"
222c65db5eSPaolo Bonzini #include "qemu/datadir.h"
23fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
24dd7ef911SCédric Le Goater #include "qemu/cutils.h"
259e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
2638d2448aSGreg Kurz #include "sysemu/qtest.h"
279e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
289e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2971e8a915SMarkus Armbruster #include "sysemu/reset.h"
3054d31236SMarkus Armbruster #include "sysemu/runstate.h"
31d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
328d409261SCédric Le Goater #include "sysemu/device_tree.h"
3301b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
34fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
379e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
38d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
399e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
4001b552b0SNicholas Piggin #include "hw/nmi.h"
41e997040eSCédric Le Goater #include "qapi/visitor.h"
4247fea43aSCédric Le Goater #include "monitor/monitor.h"
4347fea43aSCédric Le Goater #include "hw/intc/intc.h"
44aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4558969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
464f9924c4SBenjamin Herrenschmidt #include "hw/pci/msi.h"
479e933f4aSBenjamin Herrenschmidt 
4836fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
49a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
50967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
5135dde576SCédric Le Goater #include "hw/ppc/pnv_pnor.h"
52967b7523SCédric Le Goater 
533495b6b6SCédric Le Goater #include "hw/isa/isa.h"
543495b6b6SCédric Le Goater #include "hw/char/serial.h"
55bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
563495b6b6SCédric Le Goater 
579e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
589e933f4aSBenjamin Herrenschmidt 
59b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
609e933f4aSBenjamin Herrenschmidt 
619e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
629e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
6383fa6e2aSCédric Le Goater #define FW_MAX_SIZE             (16 * MiB)
649e933f4aSBenjamin Herrenschmidt 
659e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
6605ce9b73SCédric Le Goater #define KERNEL_MAX_SIZE         (128 * MiB)
6705ce9b73SCédric Le Goater #define INITRD_LOAD_ADDR        0x28000000
6805ce9b73SCédric Le Goater #define INITRD_MAX_SIZE         (128 * MiB)
699e933f4aSBenjamin Herrenschmidt 
7040abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7140abf43fSIgor Mammedov {
7240abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7340abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7440abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7540abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7640abf43fSIgor Mammedov     g_free(s);
7740abf43fSIgor Mammedov     return core_type;
7840abf43fSIgor Mammedov }
7940abf43fSIgor Mammedov 
809e933f4aSBenjamin Herrenschmidt /*
819e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
829e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
839e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
849e933f4aSBenjamin Herrenschmidt  */
859e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
869e933f4aSBenjamin Herrenschmidt 
879e933f4aSBenjamin Herrenschmidt /*
889e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
899e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
909e933f4aSBenjamin Herrenschmidt  * per chip.
919e933f4aSBenjamin Herrenschmidt  */
92b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
939e933f4aSBenjamin Herrenschmidt {
949e933f4aSBenjamin Herrenschmidt     char *mem_name;
959e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
969e933f4aSBenjamin Herrenschmidt     int off;
979e933f4aSBenjamin Herrenschmidt 
989e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
999e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
1009e933f4aSBenjamin Herrenschmidt 
1019e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1029e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1039e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1049e933f4aSBenjamin Herrenschmidt 
1059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1069e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1079e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1089e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1099e933f4aSBenjamin Herrenschmidt }
1109e933f4aSBenjamin Herrenschmidt 
111d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
112d2fd9612SCédric Le Goater {
113d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
114d2fd9612SCédric Le Goater 
115d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
116a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
117d2fd9612SCédric Le Goater         if (cpus_offset) {
118d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
119d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
120d2fd9612SCédric Le Goater         }
121d2fd9612SCédric Le Goater     }
122d2fd9612SCédric Le Goater     _FDT(cpus_offset);
123d2fd9612SCédric Le Goater     return cpus_offset;
124d2fd9612SCédric Le Goater }
125d2fd9612SCédric Le Goater 
126d2fd9612SCédric Le Goater /*
127d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
128d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
129d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
130d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
131d2fd9612SCédric Le Goater  * servers.
132d2fd9612SCédric Le Goater  */
133b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
134d2fd9612SCédric Le Goater {
13508304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13608304a86SDavid Gibson     CPUState *cs = CPU(cpu);
137d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1388bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
139d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
140d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
141d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
142d2fd9612SCédric Le Goater     int i;
143d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
144d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
145d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
146d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
147d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
148d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
149d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
150d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
151d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
152d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
153d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
154d2fd9612SCédric Le Goater     int offset;
155d2fd9612SCédric Le Goater     char *nodename;
156d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
157d2fd9612SCédric Le Goater 
158d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
159d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
160d2fd9612SCédric Le Goater     _FDT(offset);
161d2fd9612SCédric Le Goater     g_free(nodename);
162d2fd9612SCédric Le Goater 
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
164d2fd9612SCédric Le Goater 
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
168d2fd9612SCédric Le Goater 
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
171d2fd9612SCédric Le Goater                             env->dcache_line_size)));
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
173d2fd9612SCédric Le Goater                             env->dcache_line_size)));
174d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
175d2fd9612SCédric Le Goater                             env->icache_line_size)));
176d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
177d2fd9612SCédric Le Goater                             env->icache_line_size)));
178d2fd9612SCédric Le Goater 
179d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
180d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
181d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
182d2fd9612SCédric Le Goater     } else {
1833dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
184d2fd9612SCédric Le Goater     }
185d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
186d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
187d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
188d2fd9612SCédric Le Goater     } else {
1893dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
190d2fd9612SCédric Le Goater     }
191d2fd9612SCédric Le Goater 
192d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19459b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19559b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
196d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
197d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
198d2fd9612SCédric Le Goater 
19903282a3aSLucas Mateus Castro (alqotel)     if (ppc_has_spr(cpu, SPR_PURR)) {
200d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
201d2fd9612SCédric Le Goater     }
202d2fd9612SCédric Le Goater 
20358969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
204d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
205d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
206d2fd9612SCédric Le Goater     }
207d2fd9612SCédric Le Goater 
20859b7c1c2SBalamuruhan S     /*
20959b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
210d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
211d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21259b7c1c2SBalamuruhan S      *   2               == VSX available
21359b7c1c2SBalamuruhan S      */
214d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
215d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
216d2fd9612SCédric Le Goater 
217d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
218d2fd9612SCédric Le Goater     }
219d2fd9612SCédric Le Goater 
22059b7c1c2SBalamuruhan S     /*
22159b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
222d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22359b7c1c2SBalamuruhan S      *   1               == DFP available
22459b7c1c2SBalamuruhan S      */
225d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
226d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
227d2fd9612SCédric Le Goater     }
228d2fd9612SCédric Le Goater 
229644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
230d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
231d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
232d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
233d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
234d2fd9612SCédric Le Goater     }
235d2fd9612SCédric Le Goater 
236d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
237d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
238d2fd9612SCédric Le Goater 
239d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
240d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
241d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
242d2fd9612SCédric Le Goater     }
243d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
244d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
245d2fd9612SCédric Le Goater }
246d2fd9612SCédric Le Goater 
247b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
248bf5615e7SCédric Le Goater                        uint32_t nr_threads)
249bf5615e7SCédric Le Goater {
250bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
251bf5615e7SCédric Le Goater     char *name;
252bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
253bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
254bf5615e7SCédric Le Goater     uint64_t *reg;
255bf5615e7SCédric Le Goater     int offset;
256bf5615e7SCédric Le Goater 
257bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
258bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
259bf5615e7SCédric Le Goater 
260bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
261bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
262bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
263bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
264bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
265bf5615e7SCédric Le Goater     }
266bf5615e7SCédric Le Goater 
267bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
268bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
269bf5615e7SCédric Le Goater     _FDT(offset);
270bf5615e7SCédric Le Goater     g_free(name);
271bf5615e7SCédric Le Goater 
272bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
275bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
278bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
279bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
280bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
281bf5615e7SCédric Le Goater     g_free(reg);
282bf5615e7SCédric Le Goater }
283bf5615e7SCédric Le Goater 
284eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
285e997040eSCédric Le Goater {
286c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
287d2fd9612SCédric Le Goater     int i;
288d2fd9612SCédric Le Goater 
2893f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2903f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
291c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
292c396c58aSGreg Kurz                  compat, sizeof(compat));
293967b7523SCédric Le Goater 
294d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2954fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
296d2fd9612SCédric Le Goater 
297b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
298bf5615e7SCédric Le Goater 
299bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
300b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
301d2fd9612SCédric Le Goater     }
302d2fd9612SCédric Le Goater 
303e997040eSCédric Le Goater     if (chip->ram_size) {
304b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
305e997040eSCédric Le Goater     }
306e997040eSCédric Le Goater }
307e997040eSCédric Le Goater 
308eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
309eb859a27SCédric Le Goater {
310c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
311eb859a27SCédric Le Goater     int i;
312eb859a27SCédric Le Goater 
3133f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3143f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
315c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
316c396c58aSGreg Kurz                  compat, sizeof(compat));
317eb859a27SCédric Le Goater 
318eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3194fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
320eb859a27SCédric Le Goater 
321eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
322eb859a27SCédric Le Goater     }
323eb859a27SCédric Le Goater 
324eb859a27SCédric Le Goater     if (chip->ram_size) {
325eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
326eb859a27SCédric Le Goater     }
32715376c66SCédric Le Goater 
3282661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
329eb859a27SCédric Le Goater }
330eb859a27SCédric Le Goater 
3312b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3322b548a42SCédric Le Goater {
333c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3342b548a42SCédric Le Goater     int i;
3352b548a42SCédric Le Goater 
3363f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3373f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
338c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
339c396c58aSGreg Kurz                  compat, sizeof(compat));
3402b548a42SCédric Le Goater 
3412b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3422b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3432b548a42SCédric Le Goater 
3442b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3452b548a42SCédric Le Goater     }
3462b548a42SCédric Le Goater 
3472b548a42SCédric Le Goater     if (chip->ram_size) {
3482b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3492b548a42SCédric Le Goater     }
3502661f6abSCédric Le Goater 
3512661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3522b548a42SCédric Le Goater }
3532b548a42SCédric Le Goater 
354b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
355c5ffdcaeSCédric Le Goater {
356c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
357c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
358c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
359c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
360c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
361c5ffdcaeSCédric Le Goater     };
362c5ffdcaeSCédric Le Goater     char *name;
363c5ffdcaeSCédric Le Goater     int node;
364c5ffdcaeSCédric Le Goater 
365c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
366c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
367c5ffdcaeSCédric Le Goater     _FDT(node);
368c5ffdcaeSCédric Le Goater     g_free(name);
369c5ffdcaeSCédric Le Goater 
370c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
371c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
372c5ffdcaeSCédric Le Goater }
373c5ffdcaeSCédric Le Goater 
374b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
375cb228f5aSCédric Le Goater {
376cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
377cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
378cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
379cb228f5aSCédric Le Goater         cpu_to_be32(1),
380cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
381cb228f5aSCédric Le Goater         cpu_to_be32(8)
382cb228f5aSCédric Le Goater     };
383cb228f5aSCédric Le Goater     char *name;
384cb228f5aSCédric Le Goater     int node;
385cb228f5aSCédric Le Goater 
386cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
387cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
388cb228f5aSCédric Le Goater     _FDT(node);
389cb228f5aSCédric Le Goater     g_free(name);
390cb228f5aSCédric Le Goater 
391cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
392cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
393cb228f5aSCédric Le Goater                       sizeof(compatible))));
394cb228f5aSCédric Le Goater 
395cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
396cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
397cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
398cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
399cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
400cb228f5aSCédric Le Goater 
401cb228f5aSCédric Le Goater     /* This is needed by Linux */
402cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
403cb228f5aSCédric Le Goater }
404cb228f5aSCédric Le Goater 
405b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40604f6c8b2SCédric Le Goater {
40704f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
40804f6c8b2SCédric Le Goater     uint32_t io_base;
40904f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
41004f6c8b2SCédric Le Goater         cpu_to_be32(1),
41104f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41204f6c8b2SCédric Le Goater         cpu_to_be32(3)
41304f6c8b2SCédric Le Goater     };
41404f6c8b2SCédric Le Goater     uint32_t irq;
41504f6c8b2SCédric Le Goater     char *name;
41604f6c8b2SCédric Le Goater     int node;
41704f6c8b2SCédric Le Goater 
41804f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
41904f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
42004f6c8b2SCédric Le Goater 
42104f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42204f6c8b2SCédric Le Goater 
42304f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42404f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42504f6c8b2SCédric Le Goater     _FDT(node);
42604f6c8b2SCédric Le Goater     g_free(name);
42704f6c8b2SCédric Le Goater 
4287032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4297032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4307032d92aSCédric Le Goater                       sizeof(compatible))));
43104f6c8b2SCédric Le Goater 
43204f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43304f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43604f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
43704f6c8b2SCédric Le Goater }
43804f6c8b2SCédric Le Goater 
439e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
440e7a3fee3SCédric Le Goater     void *fdt;
441e7a3fee3SCédric Le Goater     int offset;
442e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
443e7a3fee3SCédric Le Goater 
444b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
445e7a3fee3SCédric Le Goater {
446c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
447c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
448c5ffdcaeSCédric Le Goater 
449c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
450b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
451cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
452b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45304f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
454b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
455c5ffdcaeSCédric Le Goater     } else {
456c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
457c5ffdcaeSCédric Le Goater                      d->ioport_id);
458c5ffdcaeSCédric Le Goater     }
459c5ffdcaeSCédric Le Goater 
460e7a3fee3SCédric Le Goater     return 0;
461e7a3fee3SCédric Le Goater }
462e7a3fee3SCédric Le Goater 
46359b7c1c2SBalamuruhan S /*
46459b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
465bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
466bb7ab95cSCédric Le Goater  */
467bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
468bb7ab95cSCédric Le Goater {
46964d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
470e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
471e7a3fee3SCédric Le Goater         .fdt = fdt,
472bb7ab95cSCédric Le Goater         .offset = isa_offset,
473e7a3fee3SCédric Le Goater     };
474f47a08d1SCédric Le Goater     uint32_t phandle;
475e7a3fee3SCédric Le Goater 
476bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
477bb7ab95cSCédric Le Goater 
478f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
479f47a08d1SCédric Le Goater     assert(phandle > 0);
480f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
481f47a08d1SCédric Le Goater 
48259b7c1c2SBalamuruhan S     /*
48359b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48459b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48559b7c1c2SBalamuruhan S      */
486bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
487bb7ab95cSCédric Le Goater                        &args);
488e7a3fee3SCédric Le Goater }
489e7a3fee3SCédric Le Goater 
4907a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
491e5694793SCédric Le Goater {
492e5694793SCédric Le Goater     int off;
493e5694793SCédric Le Goater 
494e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
495e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
496e5694793SCédric Le Goater 
497e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
498e5694793SCédric Le Goater }
499e5694793SCédric Le Goater 
500b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5019e933f4aSBenjamin Herrenschmidt {
502d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
503b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5049e933f4aSBenjamin Herrenschmidt     void *fdt;
5059e933f4aSBenjamin Herrenschmidt     char *buf;
5069e933f4aSBenjamin Herrenschmidt     int off;
507e997040eSCédric Le Goater     int i;
5089e933f4aSBenjamin Herrenschmidt 
5099e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5109e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5119e933f4aSBenjamin Herrenschmidt 
512ccb099b3SCédric Le Goater     /* /qemu node */
513ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
514ccb099b3SCédric Le Goater 
5159e933f4aSBenjamin Herrenschmidt     /* Root node */
5169e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5179e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5189e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5199e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
520d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5219e933f4aSBenjamin Herrenschmidt 
5229e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5239e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5249e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
525bbfbbff5SDaniel Henrique Barboza         _FDT((fdt_setprop_string(fdt, 0, "system-id", buf)));
5269e933f4aSBenjamin Herrenschmidt     }
5279e933f4aSBenjamin Herrenschmidt     g_free(buf);
5289e933f4aSBenjamin Herrenschmidt 
5299e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5309e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5319e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5329e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5339e933f4aSBenjamin Herrenschmidt     }
5349e933f4aSBenjamin Herrenschmidt 
5359e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5369e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5379e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5389e933f4aSBenjamin Herrenschmidt 
5399e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5409e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5419e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5429e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5439e933f4aSBenjamin Herrenschmidt     }
5449e933f4aSBenjamin Herrenschmidt 
545e997040eSCédric Le Goater     /* Populate device tree for each chip */
546e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
547eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
548e997040eSCédric Le Goater     }
549e7a3fee3SCédric Le Goater 
550e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
551bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
552aeaef83dSCédric Le Goater 
553aeaef83dSCédric Le Goater     if (pnv->bmc) {
554b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
555aeaef83dSCédric Le Goater     }
556aeaef83dSCédric Le Goater 
5577a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5587a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5597a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
560e5694793SCédric Le Goater     }
561e5694793SCédric Le Goater 
5629e933f4aSBenjamin Herrenschmidt     return fdt;
5639e933f4aSBenjamin Herrenschmidt }
5649e933f4aSBenjamin Herrenschmidt 
565bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
566bce0b691SCédric Le Goater {
5678f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
568bce0b691SCédric Le Goater 
569bce0b691SCédric Le Goater     if (pnv->bmc) {
570bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
571bce0b691SCédric Le Goater     }
572bce0b691SCédric Le Goater }
573bce0b691SCédric Le Goater 
574a0628599SLike Xu static void pnv_reset(MachineState *machine)
5759e933f4aSBenjamin Herrenschmidt {
57625f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
57725f3170bSCédric Le Goater     IPMIBmc *bmc;
5789e933f4aSBenjamin Herrenschmidt     void *fdt;
5799e933f4aSBenjamin Herrenschmidt 
5809e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5819e933f4aSBenjamin Herrenschmidt 
58225f3170bSCédric Le Goater     /*
58325f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
58425f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
58525f3170bSCédric Le Goater      * line.
58625f3170bSCédric Le Goater      */
58725f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
58825f3170bSCédric Le Goater     if (!pnv->bmc) {
58925f3170bSCédric Le Goater         if (!bmc) {
59038d2448aSGreg Kurz             if (!qtest_enabled()) {
59125f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
59225f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59325f3170bSCédric Le Goater                             "to define one");
59438d2448aSGreg Kurz             }
59525f3170bSCédric Le Goater         } else {
59625f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
59725f3170bSCédric Le Goater             pnv->bmc = bmc;
59825f3170bSCédric Le Goater         }
59925f3170bSCédric Le Goater     }
60025f3170bSCédric Le Goater 
601b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6029e933f4aSBenjamin Herrenschmidt 
6039e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6049e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6059e933f4aSBenjamin Herrenschmidt 
6068d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6079e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
608b2fb7a43SPan Nengyuan 
609b2fb7a43SPan Nengyuan     g_free(fdt);
6109e933f4aSBenjamin Herrenschmidt }
6119e933f4aSBenjamin Herrenschmidt 
61204026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6133495b6b6SCédric Le Goater {
61477864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
61577864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
61604026890SCédric Le Goater }
6173495b6b6SCédric Le Goater 
61804026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
61904026890SCédric Le Goater {
62077864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
62177864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
62204026890SCédric Le Goater }
6233495b6b6SCédric Le Goater 
62404026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
62504026890SCédric Le Goater {
62615376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
62715376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
62804026890SCédric Le Goater }
6293495b6b6SCédric Le Goater 
6302b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6312b548a42SCédric Le Goater {
6322661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6332661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6342b548a42SCédric Le Goater }
6352b548a42SCédric Le Goater 
63604026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
63704026890SCédric Le Goater {
63804026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6393495b6b6SCédric Le Goater }
6403495b6b6SCédric Le Goater 
6412ff73ddaSCédric Le Goater static int pnv_chip_power8_pic_print_info_child(Object *child, void *opaque)
6422ff73ddaSCédric Le Goater {
6432ff73ddaSCédric Le Goater     Monitor *mon = opaque;
6442ff73ddaSCédric Le Goater     PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
6452ff73ddaSCédric Le Goater 
6462ff73ddaSCédric Le Goater     if (phb3) {
6472ff73ddaSCédric Le Goater         pnv_phb3_msi_pic_print_info(&phb3->msis, mon);
6482ff73ddaSCédric Le Goater         ics_pic_print_info(&phb3->lsis, mon);
6492ff73ddaSCédric Le Goater     }
6502ff73ddaSCédric Le Goater     return 0;
6512ff73ddaSCédric Le Goater }
6522ff73ddaSCédric Le Goater 
653d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
654d8e4aad5SCédric Le Goater {
655d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
656d8e4aad5SCédric Le Goater 
657d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6582ff73ddaSCédric Le Goater     object_child_foreach(OBJECT(chip),
6592ff73ddaSCédric Le Goater                          pnv_chip_power8_pic_print_info_child, mon);
660d8e4aad5SCédric Le Goater }
661d8e4aad5SCédric Le Goater 
662d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
663d8e4aad5SCédric Le Goater {
664d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
6654f9924c4SBenjamin Herrenschmidt     int i, j;
666d8e4aad5SCédric Le Goater 
667d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
668c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6694f9924c4SBenjamin Herrenschmidt 
670422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
6714f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
6724f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks; j++) {
6734f9924c4SBenjamin Herrenschmidt             pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
6744f9924c4SBenjamin Herrenschmidt         }
6754f9924c4SBenjamin Herrenschmidt     }
676d8e4aad5SCédric Le Goater }
677d8e4aad5SCédric Le Goater 
678c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
679c4b2c40cSGreg Kurz                                                 uint32_t core_id)
680c4b2c40cSGreg Kurz {
681c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
682c4b2c40cSGreg Kurz }
683c4b2c40cSGreg Kurz 
684c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
685c4b2c40cSGreg Kurz                                                 uint32_t core_id)
686c4b2c40cSGreg Kurz {
687c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
688c4b2c40cSGreg Kurz }
689c4b2c40cSGreg Kurz 
690c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
691c4b2c40cSGreg Kurz                                                  uint32_t core_id)
692c4b2c40cSGreg Kurz {
693c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
694c4b2c40cSGreg Kurz }
695c4b2c40cSGreg Kurz 
696f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
697f30c843cSCédric Le Goater {
698f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
699f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
700f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
701f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
702f30c843cSCédric Le Goater 
703f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
704f30c843cSCédric Le Goater }
705f30c843cSCédric Le Goater 
706e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
707e2392d43SCédric Le Goater {
708c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
709e2392d43SCédric Le Goater 
7105325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7115325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
712c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
713e2392d43SCédric Le Goater }
714e2392d43SCédric Le Goater 
7152b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7162b548a42SCédric Le Goater {
7178b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7188b50ce85SCédric Le Goater 
7198b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
7202b548a42SCédric Le Goater }
7212b548a42SCédric Le Goater 
722458c6f01SCédric Le Goater /* Always give the first 1GB to chip 0 else we won't boot */
723458c6f01SCédric Le Goater static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
724458c6f01SCédric Le Goater {
725458c6f01SCédric Le Goater     MachineState *machine = MACHINE(pnv);
726458c6f01SCédric Le Goater     uint64_t ram_per_chip;
727458c6f01SCédric Le Goater 
728458c6f01SCédric Le Goater     assert(machine->ram_size >= 1 * GiB);
729458c6f01SCédric Le Goater 
730458c6f01SCédric Le Goater     ram_per_chip = machine->ram_size / pnv->num_chips;
731458c6f01SCédric Le Goater     if (ram_per_chip >= 1 * GiB) {
732458c6f01SCédric Le Goater         return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
733458c6f01SCédric Le Goater     }
734458c6f01SCédric Le Goater 
735f640afecSCédric Le Goater     assert(pnv->num_chips > 1);
736f640afecSCédric Le Goater 
737458c6f01SCédric Le Goater     ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
738458c6f01SCédric Le Goater     return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
739458c6f01SCédric Le Goater }
740458c6f01SCédric Le Goater 
741b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7429e933f4aSBenjamin Herrenschmidt {
743cd7b9498SPaolo Bonzini     const char *bios_name = machine->firmware ?: FW_FILE_NAME;
744b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
745f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7469e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7479e933f4aSBenjamin Herrenschmidt     long fw_size;
748458c6f01SCédric Le Goater     uint64_t chip_ram_start = 0;
749e997040eSCédric Le Goater     int i;
750e997040eSCédric Le Goater     char *chip_typename;
75135dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
75235dde576SCédric Le Goater     DeviceState *dev;
7539e933f4aSBenjamin Herrenschmidt 
754ebe6c3faSDaniel Henrique Barboza     if (kvm_enabled()) {
755ebe6c3faSDaniel Henrique Barboza         error_report("The powernv machine does not work with KVM acceleration");
756ebe6c3faSDaniel Henrique Barboza         exit(EXIT_FAILURE);
757ebe6c3faSDaniel Henrique Barboza     }
758ebe6c3faSDaniel Henrique Barboza 
7599e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
760dd7ef911SCédric Le Goater     if (machine->ram_size < mc->default_ram_size) {
761dd7ef911SCédric Le Goater         char *sz = size_to_str(mc->default_ram_size);
762dd7ef911SCédric Le Goater         error_report("Invalid RAM size, should be bigger than %s", sz);
763dd7ef911SCédric Le Goater         g_free(sz);
764dd7ef911SCédric Le Goater         exit(EXIT_FAILURE);
7659e933f4aSBenjamin Herrenschmidt     }
766173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7679e933f4aSBenjamin Herrenschmidt 
76835dde576SCédric Le Goater     /*
76935dde576SCédric Le Goater      * Create our simple PNOR device
77035dde576SCédric Le Goater      */
7713e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
77235dde576SCédric Le Goater     if (pnor) {
773934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
77435dde576SCédric Le Goater     }
7753c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
77635dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
77735dde576SCédric Le Goater 
7789e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7799e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
78015fcedb2SCédric Le Goater     if (!fw_filename) {
78115fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
78215fcedb2SCédric Le Goater         exit(1);
78315fcedb2SCédric Le Goater     }
7849e933f4aSBenjamin Herrenschmidt 
78508c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
7869e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
78715fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7889e933f4aSBenjamin Herrenschmidt         exit(1);
7899e933f4aSBenjamin Herrenschmidt     }
7909e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7919e933f4aSBenjamin Herrenschmidt 
7929e933f4aSBenjamin Herrenschmidt     /* load kernel */
7939e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7949e933f4aSBenjamin Herrenschmidt         long kernel_size;
7959e933f4aSBenjamin Herrenschmidt 
7969e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
797b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7989e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
799802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
8009e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
8019e933f4aSBenjamin Herrenschmidt             exit(1);
8029e933f4aSBenjamin Herrenschmidt         }
8039e933f4aSBenjamin Herrenschmidt     }
8049e933f4aSBenjamin Herrenschmidt 
8059e933f4aSBenjamin Herrenschmidt     /* load initrd */
8069e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
8079e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
8089e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
809584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
8109e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
811802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
8129e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
8139e933f4aSBenjamin Herrenschmidt             exit(1);
8149e933f4aSBenjamin Herrenschmidt         }
8159e933f4aSBenjamin Herrenschmidt     }
816e997040eSCédric Le Goater 
8174f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
8184f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
8194f9924c4SBenjamin Herrenschmidt 
820f30c843cSCédric Le Goater     /*
821f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
822f30c843cSCédric Le Goater      * default.
823f30c843cSCédric Le Goater      */
824f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
825f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
826f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
827f30c843cSCédric Le Goater         exit(1);
828f30c843cSCédric Le Goater     }
829f30c843cSCédric Le Goater 
830e997040eSCédric Le Goater     /* Create the processor chips */
8314a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
8327fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8334a12c699SIgor Mammedov                                     i, machine->cpu_type);
834e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
835f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
836f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
837e997040eSCédric Le Goater         exit(1);
838e997040eSCédric Le Goater     }
839e997040eSCédric Le Goater 
840e44acde2SGreg Kurz     pnv->num_chips =
841e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
842e44acde2SGreg Kurz     /*
843e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
844e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
845e44acde2SGreg Kurz      */
846ab17a3feSCédric Le Goater     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
847e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
848ab17a3feSCédric Le Goater         error_printf(
849ab17a3feSCédric Le Goater             "Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
850e44acde2SGreg Kurz         exit(1);
851e44acde2SGreg Kurz     }
852e44acde2SGreg Kurz 
853e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
854e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
855e997040eSCédric Le Goater         char chip_name[32];
856df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
8570e5e9ff4SCédric Le Goater         uint64_t chip_ram_size =  pnv_chip_get_ram_size(pnv, i);
858e997040eSCédric Le Goater 
859e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
860e997040eSCédric Le Goater 
861458c6f01SCédric Le Goater         /* Distribute RAM among the chips  */
862458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-start", chip_ram_start,
863e997040eSCédric Le Goater                                 &error_fatal);
864458c6f01SCédric Le Goater         object_property_set_int(chip, "ram-size", chip_ram_size,
865458c6f01SCédric Le Goater                                 &error_fatal);
866458c6f01SCédric Le Goater         chip_ram_start += chip_ram_size;
867e997040eSCédric Le Goater 
8680e5e9ff4SCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", i);
869d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
8700e5e9ff4SCédric Le Goater         object_property_set_int(chip, "chip-id", i, &error_fatal);
8715325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
8725325cc34SMarkus Armbruster                                 &error_fatal);
8735325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
8745325cc34SMarkus Armbruster                                 &error_fatal);
875245cdb7fSCédric Le Goater         /*
876245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
877245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
878245cdb7fSCédric Le Goater          */
879245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
8805325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
881245cdb7fSCédric Le Goater         }
882d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
8835325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
884d1214b81SGreg Kurz                                      &error_abort);
885d1214b81SGreg Kurz         }
8863c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
887e997040eSCédric Le Goater     }
888e997040eSCédric Le Goater     g_free(chip_typename);
8893495b6b6SCédric Le Goater 
8903495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
89104026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
8923495b6b6SCédric Le Goater 
8933495b6b6SCédric Le Goater     /* Create serial port */
894def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
8953495b6b6SCédric Le Goater 
8963495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8976c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
898bce0b691SCédric Le Goater 
89925f3170bSCédric Le Goater     /*
90025f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
90125f3170bSCédric Le Goater      * communication with the BMC
90225f3170bSCédric Le Goater      */
90325f3170bSCédric Le Goater     if (defaults_enabled()) {
90425f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
905e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
90625f3170bSCédric Le Goater     }
907e2392d43SCédric Le Goater 
90859b7c1c2SBalamuruhan S     /*
909032c226bSCédric Le Goater      * The PNOR is mapped on the LPC FW address space by the BMC.
910032c226bSCédric Le Goater      * Since we can not reach the remote BMC machine with LPC memops,
911032c226bSCédric Le Goater      * map it always for now.
912032c226bSCédric Le Goater      */
913032c226bSCédric Le Goater     memory_region_add_subregion(pnv->chips[0]->fw_mr, PNOR_SPI_OFFSET,
914032c226bSCédric Le Goater                                 &pnv->pnor->mmio);
915032c226bSCédric Le Goater 
916032c226bSCédric Le Goater     /*
91759b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
91859b7c1c2SBalamuruhan S      * host to powerdown
91959b7c1c2SBalamuruhan S      */
920bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
921bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
922e997040eSCédric Le Goater }
923e997040eSCédric Le Goater 
924631adaffSCédric Le Goater /*
925631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
926631adaffSCédric Le Goater  *   22:24  Chip ID
927631adaffSCédric Le Goater  *   25:28  Core number
928631adaffSCédric Le Goater  *   29:31  Thread ID
929631adaffSCédric Le Goater  */
930631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
931631adaffSCédric Le Goater {
932631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
933631adaffSCédric Le Goater }
934631adaffSCédric Le Goater 
9358fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
936d35aefa9SCédric Le Goater                                         Error **errp)
937d35aefa9SCédric Le Goater {
938245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
9398fa1f4efSCédric Le Goater     Error *local_err = NULL;
9408fa1f4efSCédric Le Goater     Object *obj;
9418907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9428fa1f4efSCédric Le Goater 
943245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9448fa1f4efSCédric Le Goater     if (local_err) {
9458fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9468fa1f4efSCédric Le Goater         return;
9478fa1f4efSCédric Le Goater     }
9488fa1f4efSCédric Le Goater 
949956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
950d35aefa9SCédric Le Goater }
951d35aefa9SCédric Le Goater 
9520990ce6aSGreg Kurz 
953d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
954d49e8a9bSCédric Le Goater {
955d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
956d49e8a9bSCédric Le Goater 
957d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
958d49e8a9bSCédric Le Goater }
959d49e8a9bSCédric Le Goater 
9600990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9610990ce6aSGreg Kurz {
9620990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9630990ce6aSGreg Kurz 
9640990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9650990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9660990ce6aSGreg Kurz }
9670990ce6aSGreg Kurz 
96885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
96985913070SGreg Kurz                                             Monitor *mon)
97085913070SGreg Kurz {
97185913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
97285913070SGreg Kurz }
97385913070SGreg Kurz 
974631adaffSCédric Le Goater /*
975631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
976631adaffSCédric Le Goater  *   49:52  Node ID
977631adaffSCédric Le Goater  *   53:55  Chip ID
978631adaffSCédric Le Goater  *   56     Reserved - Read as zero
979631adaffSCédric Le Goater  *   57:61  Core number
980631adaffSCédric Le Goater  *   62:63  Thread ID
981631adaffSCédric Le Goater  *
982631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
983631adaffSCédric Le Goater  */
984631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
985631adaffSCédric Le Goater {
986631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
987631adaffSCédric Le Goater }
988631adaffSCédric Le Goater 
9892b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
9902b548a42SCédric Le Goater {
9912b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
9922b548a42SCédric Le Goater }
9932b548a42SCédric Le Goater 
9948fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
995d35aefa9SCédric Le Goater                                         Error **errp)
996d35aefa9SCédric Le Goater {
9972dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
9982dfa91a2SCédric Le Goater     Error *local_err = NULL;
9992dfa91a2SCédric Le Goater     Object *obj;
10002dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10012dfa91a2SCédric Le Goater 
10022dfa91a2SCédric Le Goater     /*
10032dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
10042dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
10052dfa91a2SCédric Le Goater      * only used at runtime.
10062dfa91a2SCédric Le Goater      */
100747950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
100847950946SCédric Le Goater                            &local_err);
10092dfa91a2SCédric Le Goater     if (local_err) {
10102dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
10118fa1f4efSCédric Le Goater         return;
1012d35aefa9SCédric Le Goater     }
1013d35aefa9SCédric Le Goater 
10142dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
10152dfa91a2SCédric Le Goater }
10162dfa91a2SCédric Le Goater 
1017d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
1018d49e8a9bSCédric Le Goater {
1019d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
1020d49e8a9bSCédric Le Goater 
1021d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
1022d49e8a9bSCédric Le Goater }
1023d49e8a9bSCédric Le Goater 
10240990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10250990ce6aSGreg Kurz {
10260990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10270990ce6aSGreg Kurz 
10280990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
10290990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
10300990ce6aSGreg Kurz }
10310990ce6aSGreg Kurz 
103285913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
103385913070SGreg Kurz                                             Monitor *mon)
103485913070SGreg Kurz {
103585913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
103685913070SGreg Kurz }
103785913070SGreg Kurz 
10382b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
10392b548a42SCédric Le Goater                                         Error **errp)
10402b548a42SCédric Le Goater {
10412b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10422b548a42SCédric Le Goater 
10432b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
10442b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10452b548a42SCédric Le Goater }
10462b548a42SCédric Le Goater 
10472b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10482b548a42SCédric Le Goater {
10492b548a42SCédric Le Goater     ;
10502b548a42SCédric Le Goater }
10512b548a42SCédric Le Goater 
10522b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10532b548a42SCédric Le Goater {
10542b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10552b548a42SCédric Le Goater 
10562b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10572b548a42SCédric Le Goater }
10582b548a42SCédric Le Goater 
105985913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
106085913070SGreg Kurz                                              Monitor *mon)
106185913070SGreg Kurz {
106285913070SGreg Kurz }
106385913070SGreg Kurz 
106459b7c1c2SBalamuruhan S /*
106559b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1066397a79e7SCédric Le Goater  *
1067397a79e7SCédric Le Goater  * <EX0 reserved>
1068397a79e7SCédric Le Goater  *  EX1  - Venice only
1069397a79e7SCédric Le Goater  *  EX2  - Venice only
1070397a79e7SCédric Le Goater  *  EX3  - Venice only
1071397a79e7SCédric Le Goater  *  EX4
1072397a79e7SCédric Le Goater  *  EX5
1073397a79e7SCédric Le Goater  *  EX6
1074397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1075397a79e7SCédric Le Goater  *  EX9  - Venice only
1076397a79e7SCédric Le Goater  *  EX10 - Venice only
1077397a79e7SCédric Le Goater  *  EX11 - Venice only
1078397a79e7SCédric Le Goater  *  EX12
1079397a79e7SCédric Le Goater  *  EX13
1080397a79e7SCédric Le Goater  *  EX14
1081397a79e7SCédric Le Goater  * <EX15 reserved>
1082397a79e7SCédric Le Goater  */
1083397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1084397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1085397a79e7SCédric Le Goater 
1086397a79e7SCédric Le Goater /*
108709279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1088397a79e7SCédric Le Goater  */
108909279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1090397a79e7SCédric Le Goater 
10912b548a42SCédric Le Goater 
10922b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
10932b548a42SCédric Le Goater 
109477864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
109577864267SCédric Le Goater {
10969ae1329eSCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
109777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
10989ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
10999ae1329eSCédric Le Goater     int i;
110077864267SCédric Le Goater 
1101245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1102245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1103245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1104d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1105245cdb7fSCédric Le Goater 
11069fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
110777864267SCédric Le Goater 
11089fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
110977864267SCédric Le Goater 
11109fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
11113887d241SBalamuruhan S 
11129fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
11139ae1329eSCédric Le Goater 
11149ae1329eSCédric Le Goater     for (i = 0; i < pcc->num_phbs; i++) {
11159fc7fc4dSMarkus Armbruster         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
11169ae1329eSCédric Le Goater     }
11179ae1329eSCédric Le Goater 
11189ae1329eSCédric Le Goater     /*
11199ae1329eSCédric Le Goater      * Number of PHBs is the chip default
11209ae1329eSCédric Le Goater      */
11219ae1329eSCédric Le Goater     chip->num_phbs = pcc->num_phbs;
112277864267SCédric Le Goater }
112377864267SCédric Le Goater 
112477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
112577864267SCédric Le Goater  {
112677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
112777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
112877864267SCédric Le Goater     int i, j;
112977864267SCédric Le Goater     char *name;
113077864267SCédric Le Goater 
113177864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
113277864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
113377864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
113477864267SCédric Le Goater     g_free(name);
113577864267SCédric Le Goater 
113677864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
113777864267SCédric Le Goater 
113877864267SCédric Le Goater     /* Map the ICP registers for each thread */
113977864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
11404fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
114177864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
114277864267SCédric Le Goater 
114377864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
114477864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1145245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
114677864267SCédric Le Goater 
114777864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
114877864267SCédric Le Goater                                         &icp->mmio);
114977864267SCédric Le Goater         }
115077864267SCédric Le Goater     }
115177864267SCédric Le Goater }
115277864267SCédric Le Goater 
115377864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
115477864267SCédric Le Goater {
115577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
115677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
115777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1158ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
115977864267SCédric Le Goater     Error *local_err = NULL;
11609ae1329eSCédric Le Goater     int i;
116177864267SCédric Le Goater 
1162245cdb7fSCédric Le Goater     assert(chip8->xics);
1163245cdb7fSCédric Le Goater 
1164709044fdSCédric Le Goater     /* XSCOM bridge is first */
1165709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1166709044fdSCédric Le Goater     if (local_err) {
1167709044fdSCédric Le Goater         error_propagate(errp, local_err);
1168709044fdSCédric Le Goater         return;
1169709044fdSCédric Le Goater     }
1170709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1171709044fdSCédric Le Goater 
117277864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
117377864267SCédric Le Goater     if (local_err) {
117477864267SCédric Le Goater         error_propagate(errp, local_err);
117577864267SCédric Le Goater         return;
117677864267SCédric Le Goater     }
117777864267SCédric Le Goater 
117877864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
11795325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
11805325cc34SMarkus Armbruster                             &error_fatal);
11815325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
11825325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1183668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
118477864267SCédric Le Goater         return;
118577864267SCédric Le Goater     }
1186ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1187ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
118877864267SCédric Le Goater 
118977864267SCédric Le Goater     /* Create LPC controller */
11905325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi),
1191b63f3893SGreg Kurz                              &error_abort);
1192ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
119377864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
119477864267SCédric Le Goater 
1195032c226bSCédric Le Goater     chip->fw_mr = &chip8->lpc.isa_fw;
119664d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
119764d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
119864d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
119964d011d5SCédric Le Goater 
120059b7c1c2SBalamuruhan S     /*
120159b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
120259b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
120359b7c1c2SBalamuruhan S      */
120477864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
120577864267SCédric Le Goater     if (local_err) {
120677864267SCédric Le Goater         error_propagate(errp, local_err);
120777864267SCédric Le Goater         return;
120877864267SCédric Le Goater     }
120977864267SCédric Le Goater 
121077864267SCédric Le Goater     /* Create the simplified OCC model */
12115325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi),
1212ee3d2713SGreg Kurz                              &error_abort);
1213668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
121477864267SCédric Le Goater         return;
121577864267SCédric Le Goater     }
121677864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1217f3db8266SBalamuruhan S 
1218f3db8266SBalamuruhan S     /* OCC SRAM model */
12193a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1220f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
12213887d241SBalamuruhan S 
12223887d241SBalamuruhan S     /* HOMER */
12235325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1224f2582acfSGreg Kurz                              &error_abort);
1225668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
12263887d241SBalamuruhan S         return;
12273887d241SBalamuruhan S     }
12288f092316SCédric Le Goater     /* Homer Xscom region */
12298f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
12308f092316SCédric Le Goater 
12318f092316SCédric Le Goater     /* Homer mmio region */
12323887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
12333887d241SBalamuruhan S                                 &chip8->homer.regs);
12349ae1329eSCédric Le Goater 
12359ae1329eSCédric Le Goater     /* PHB3 controllers */
12369ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
12379ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
12389ae1329eSCédric Le Goater 
12395325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
12405325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
12419ae1329eSCédric Le Goater                                 &error_fatal);
12422c4d3a50SCédric Le Goater         object_property_set_link(OBJECT(phb), "chip", OBJECT(chip),
12432c4d3a50SCédric Le Goater                                  &error_fatal);
1244668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
12459ae1329eSCédric Le Goater             return;
12469ae1329eSCédric Le Goater         }
12479ae1329eSCédric Le Goater     }
124877864267SCédric Le Goater }
124977864267SCédric Le Goater 
125070c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
125170c059e9SGreg Kurz {
125270c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
125370c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
125470c059e9SGreg Kurz }
125570c059e9SGreg Kurz 
1256e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1257e997040eSCédric Le Goater {
1258e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1259e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1260e997040eSCédric Le Goater 
1261e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1262397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
12639ae1329eSCédric Le Goater     k->num_phbs = 3;
1264631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1265d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1266d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12670990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
126885913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
126904026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1270eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1271d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1272c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
127370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1274e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
127577864267SCédric Le Goater 
127677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
127777864267SCédric Le Goater                                     &k->parent_realize);
1278e997040eSCédric Le Goater }
1279e997040eSCédric Le Goater 
1280e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1281e997040eSCédric Le Goater {
1282e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1283e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1284e997040eSCédric Le Goater 
1285e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1286397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12879ae1329eSCédric Le Goater     k->num_phbs = 3;
1288631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1289d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1290d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12910990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
129285913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
129304026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1294eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1295d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1296c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
129770c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1298e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
129977864267SCédric Le Goater 
130077864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
130177864267SCédric Le Goater                                     &k->parent_realize);
1302e997040eSCédric Le Goater }
1303e997040eSCédric Le Goater 
1304e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1305e997040eSCédric Le Goater {
1306e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1307e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1308e997040eSCédric Le Goater 
1309e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1310397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
13119ae1329eSCédric Le Goater     k->num_phbs = 3;
1312631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1313d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1314d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
13150990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
131685913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
131704026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1318eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1319d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1320c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
132170c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1322e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
132377864267SCédric Le Goater 
132477864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
132577864267SCédric Le Goater                                     &k->parent_realize);
132677864267SCédric Le Goater }
132777864267SCédric Le Goater 
132877864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
132977864267SCédric Le Goater {
13304f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13312dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13324f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13334f9924c4SBenjamin Herrenschmidt     int i;
13342dfa91a2SCédric Le Goater 
1335db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1336d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1337d2623129SMarkus Armbruster                               "xive-fabric");
1338c38536bcSCédric Le Goater 
13399fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
134015376c66SCédric Le Goater 
13419fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
13426598a70dSCédric Le Goater 
13439fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
13443887d241SBalamuruhan S 
13459fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
13464f9924c4SBenjamin Herrenschmidt 
1347422fd92eSCédric Le Goater     /* Number of PECs is the chip default */
1348422fd92eSCédric Le Goater     chip->num_pecs = pcc->num_pecs;
1349422fd92eSCédric Le Goater 
1350422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
13514f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
13529fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
13534f9924c4SBenjamin Herrenschmidt     }
135477864267SCédric Le Goater }
135577864267SCédric Le Goater 
13565dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
13575dad902cSCédric Le Goater {
13585dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
13595dad902cSCédric Le Goater     int i;
13605dad902cSCédric Le Goater 
13615dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
13625dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
13635dad902cSCédric Le Goater 
13645dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
13655dad902cSCédric Le Goater         char eq_name[32];
13665dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
13674fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
13685dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
13695dad902cSCédric Le Goater 
13705dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
13719fc7fc4dSMarkus Armbruster         object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
13729fc7fc4dSMarkus Armbruster                                            sizeof(*eq), TYPE_PNV_QUAD,
13739fc7fc4dSMarkus Armbruster                                            &error_fatal, NULL);
13745dad902cSCédric Le Goater 
137592612f15SCédric Le Goater         object_property_set_int(OBJECT(eq), "quad-id", core_id, &error_fatal);
1376ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(eq), NULL, &error_fatal);
13775dad902cSCédric Le Goater 
137892612f15SCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->quad_id),
13795dad902cSCédric Le Goater                                 &eq->xscom_regs);
13805dad902cSCédric Le Goater     }
13815dad902cSCédric Le Goater }
13825dad902cSCédric Le Goater 
1383*13480fc5SCédric Le Goater static void pnv_chip_power9_pec_realize(PnvChip *chip, Error **errp)
13844f9924c4SBenjamin Herrenschmidt {
13854f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
1386*13480fc5SCédric Le Goater     int i;
13874f9924c4SBenjamin Herrenschmidt 
1388422fd92eSCédric Le Goater     for (i = 0; i < chip->num_pecs; i++) {
13894f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
13904f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
13914f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
13924f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
13934f9924c4SBenjamin Herrenschmidt 
13945325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
13955325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
13964f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
13976f43d255SCédric Le Goater         object_property_set_link(OBJECT(pec), "chip", OBJECT(chip),
13986f43d255SCédric Le Goater                                  &error_fatal);
1399668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
14004f9924c4SBenjamin Herrenschmidt             return;
14014f9924c4SBenjamin Herrenschmidt         }
14024f9924c4SBenjamin Herrenschmidt 
14034f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
14044f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
14054f9924c4SBenjamin Herrenschmidt 
14064f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
14074f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
14084f9924c4SBenjamin Herrenschmidt     }
14094f9924c4SBenjamin Herrenschmidt }
14104f9924c4SBenjamin Herrenschmidt 
141177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
141277864267SCédric Le Goater {
141377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14142dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14152dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1416c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
141777864267SCédric Le Goater     Error *local_err = NULL;
141877864267SCédric Le Goater 
1419709044fdSCédric Le Goater     /* XSCOM bridge is first */
1420709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1421709044fdSCédric Le Goater     if (local_err) {
1422709044fdSCédric Le Goater         error_propagate(errp, local_err);
1423709044fdSCédric Le Goater         return;
1424709044fdSCédric Le Goater     }
1425709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1426709044fdSCédric Le Goater 
142777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
142877864267SCédric Le Goater     if (local_err) {
142977864267SCédric Le Goater         error_propagate(errp, local_err);
143077864267SCédric Le Goater         return;
143177864267SCédric Le Goater     }
14322dfa91a2SCédric Le Goater 
14335dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14345dad902cSCédric Le Goater     if (local_err) {
14355dad902cSCédric Le Goater         error_propagate(errp, local_err);
14365dad902cSCédric Le Goater         return;
14375dad902cSCédric Le Goater     }
14385dad902cSCédric Le Goater 
14392dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
14405325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
14415325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
14425325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
14435325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
14445325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
14455325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
14465325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
14475325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
14485325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
14497ae54cc3SGreg Kurz                              &error_abort);
1450668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
14512dfa91a2SCédric Le Goater         return;
14522dfa91a2SCédric Le Goater     }
14532dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
14542dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1455c38536bcSCédric Le Goater 
1456c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
14575325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
14585325cc34SMarkus Armbruster                             &error_fatal);
1459668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1460c38536bcSCédric Le Goater         return;
1461c38536bcSCédric Le Goater     }
1462c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1463c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
146415376c66SCédric Le Goater 
146515376c66SCédric Le Goater     /* LPC */
14665325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi),
1467b63f3893SGreg Kurz                              &error_abort);
1468668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
146915376c66SCédric Le Goater         return;
147015376c66SCédric Le Goater     }
147115376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
147215376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
147315376c66SCédric Le Goater 
1474032c226bSCédric Le Goater     chip->fw_mr = &chip9->lpc.isa_fw;
147515376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
147615376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
14776598a70dSCédric Le Goater 
14786598a70dSCédric Le Goater     /* Create the simplified OCC model */
14795325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi),
1480ee3d2713SGreg Kurz                              &error_abort);
1481668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
14826598a70dSCédric Le Goater         return;
14836598a70dSCédric Le Goater     }
14846598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1485f3db8266SBalamuruhan S 
1486f3db8266SBalamuruhan S     /* OCC SRAM model */
14873a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1488f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
14893887d241SBalamuruhan S 
14903887d241SBalamuruhan S     /* HOMER */
14915325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1492f2582acfSGreg Kurz                              &error_abort);
1493668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
14943887d241SBalamuruhan S         return;
14953887d241SBalamuruhan S     }
14968f092316SCédric Le Goater     /* Homer Xscom region */
14978f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
14988f092316SCédric Le Goater 
14998f092316SCédric Le Goater     /* Homer mmio region */
15003887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15013887d241SBalamuruhan S                                 &chip9->homer.regs);
15024f9924c4SBenjamin Herrenschmidt 
1503*13480fc5SCédric Le Goater     /* PEC PHBs */
1504*13480fc5SCédric Le Goater     pnv_chip_power9_pec_realize(chip, &local_err);
15054f9924c4SBenjamin Herrenschmidt     if (local_err) {
15064f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15074f9924c4SBenjamin Herrenschmidt         return;
15084f9924c4SBenjamin Herrenschmidt     }
1509e997040eSCédric Le Goater }
1510e997040eSCédric Le Goater 
151170c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
151270c059e9SGreg Kurz {
151370c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
151470c059e9SGreg Kurz     return addr >> 3;
151570c059e9SGreg Kurz }
151670c059e9SGreg Kurz 
1517e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1518e997040eSCédric Le Goater {
1519e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1520e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1521e997040eSCédric Le Goater 
152283028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1523397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1524631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1525d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1526d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15270990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
152885913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
152904026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1530eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1531d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1532c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
153370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1534e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
1535422fd92eSCédric Le Goater     k->num_pecs = PNV9_CHIP_MAX_PEC;
153677864267SCédric Le Goater 
153777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
153877864267SCédric Le Goater                                     &k->parent_realize);
1539e997040eSCédric Le Goater }
1540e997040eSCédric Le Goater 
15412b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
15422b548a42SCédric Le Goater {
15438b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
15448b50ce85SCédric Le Goater 
15459fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
15469fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
15472b548a42SCédric Le Goater }
15482b548a42SCédric Le Goater 
15492b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
15502b548a42SCédric Le Goater {
15512b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15522b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
15538b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
15542b548a42SCédric Le Goater     Error *local_err = NULL;
15552b548a42SCédric Le Goater 
15562b548a42SCédric Le Goater     /* XSCOM bridge is first */
15572b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
15582b548a42SCédric Le Goater     if (local_err) {
15592b548a42SCédric Le Goater         error_propagate(errp, local_err);
15602b548a42SCédric Le Goater         return;
15612b548a42SCédric Le Goater     }
15622b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
15632b548a42SCédric Le Goater 
15642b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
15652b548a42SCédric Le Goater     if (local_err) {
15662b548a42SCédric Le Goater         error_propagate(errp, local_err);
15672b548a42SCédric Le Goater         return;
15682b548a42SCédric Le Goater     }
15698b50ce85SCédric Le Goater 
15708b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15715325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
15725325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
1573668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
15748b50ce85SCédric Le Goater         return;
15758b50ce85SCédric Le Goater     }
15768b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
15778b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
15782661f6abSCédric Le Goater 
15792661f6abSCédric Le Goater     /* LPC */
15805325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip10->lpc), "psi",
15815325cc34SMarkus Armbruster                              OBJECT(&chip10->psi), &error_abort);
1582668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
15832661f6abSCédric Le Goater         return;
15842661f6abSCédric Le Goater     }
15852661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
15862661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
15872661f6abSCédric Le Goater 
1588032c226bSCédric Le Goater     chip->fw_mr = &chip10->lpc.isa_fw;
15892661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
15902661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
15912b548a42SCédric Le Goater }
15922b548a42SCédric Le Goater 
159370c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
159470c059e9SGreg Kurz {
159570c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
159670c059e9SGreg Kurz     return addr >> 3;
159770c059e9SGreg Kurz }
159870c059e9SGreg Kurz 
15992b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
16002b548a42SCédric Le Goater {
16012b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
16022b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16032b548a42SCédric Le Goater 
16042b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
16052b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
16062b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
16072b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
16082b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
16092b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
161085913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
16112b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
16122b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
16132b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1614c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
161570c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
16162b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
16172b548a42SCédric Le Goater 
16182b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
16192b548a42SCédric Le Goater                                     &k->parent_realize);
16202b548a42SCédric Le Goater }
16212b548a42SCédric Le Goater 
1622397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1623397a79e7SCédric Le Goater {
1624397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1625397a79e7SCédric Le Goater     int cores_max;
1626397a79e7SCédric Le Goater 
1627397a79e7SCédric Le Goater     /*
1628397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1629397a79e7SCédric Le Goater      * the chip class
1630397a79e7SCédric Le Goater      */
1631397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1632397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1633397a79e7SCédric Le Goater     }
1634397a79e7SCédric Le Goater 
1635397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1636397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1637397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1638397a79e7SCédric Le Goater                    chip->cores_mask);
1639397a79e7SCédric Le Goater         return;
1640397a79e7SCédric Le Goater     }
1641397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1642397a79e7SCédric Le Goater 
1643397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
164427d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1645397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1646397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1647397a79e7SCédric Le Goater                    cores_max);
1648397a79e7SCédric Le Goater         return;
1649397a79e7SCédric Le Goater     }
1650397a79e7SCédric Le Goater }
1651397a79e7SCédric Le Goater 
165251c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1653e997040eSCédric Le Goater {
1654397a79e7SCédric Le Goater     Error *error = NULL;
1655d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
165640abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1657d2fd9612SCédric Le Goater     int i, core_hwid;
165808c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1659397a79e7SCédric Le Goater 
1660d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1661d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1662d2fd9612SCédric Le Goater         return;
1663d2fd9612SCédric Le Goater     }
1664d2fd9612SCédric Le Goater 
1665d2fd9612SCédric Le Goater     /* Cores */
1666397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1667397a79e7SCédric Le Goater     if (error) {
1668397a79e7SCédric Le Goater         error_propagate(errp, error);
1669397a79e7SCédric Le Goater         return;
1670397a79e7SCédric Le Goater     }
1671d2fd9612SCédric Le Goater 
16724fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1673d2fd9612SCédric Le Goater 
1674d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1675d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1676d2fd9612SCédric Le Goater         char core_name[32];
16774fa28f23SGreg Kurz         PnvCore *pnv_core;
1678c035851aSCédric Le Goater         uint64_t xscom_core_base;
1679d2fd9612SCédric Le Goater 
1680d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1681d2fd9612SCédric Le Goater             continue;
1682d2fd9612SCédric Le Goater         }
1683d2fd9612SCédric Le Goater 
16844fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
16854fa28f23SGreg Kurz 
1686d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1687d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
16884fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
16895325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
16905325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
16915325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
16925325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
16935325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
16945325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
16955325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
16965325cc34SMarkus Armbruster                                 &error_fatal);
16975325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1698158e17a6SGreg Kurz                                  &error_abort);
1699ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
170024ece072SCédric Le Goater 
170124ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1702c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1703c035851aSCédric Le Goater 
1704c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
17054fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1706d2fd9612SCédric Le Goater         i++;
1707d2fd9612SCédric Le Goater     }
170851c04728SCédric Le Goater }
170951c04728SCédric Le Goater 
171051c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
171151c04728SCédric Le Goater {
171251c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
171351c04728SCédric Le Goater     Error *error = NULL;
171451c04728SCédric Le Goater 
171551c04728SCédric Le Goater     /* Cores */
171651c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
171751c04728SCédric Le Goater     if (error) {
171851c04728SCédric Le Goater         error_propagate(errp, error);
171951c04728SCédric Le Goater         return;
172051c04728SCédric Le Goater     }
1721e997040eSCédric Le Goater }
1722e997040eSCédric Le Goater 
1723e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1724e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1725e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1726e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1727397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1728397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1729764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
1730e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1731e997040eSCédric Le Goater };
1732e997040eSCédric Le Goater 
1733e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1734e997040eSCédric Le Goater {
1735e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1736e997040eSCédric Le Goater 
17379d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1738e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
17394f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1740e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1741e997040eSCédric Le Goater }
1742e997040eSCédric Le Goater 
1743119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1744119eaa9dSCédric Le Goater {
1745119eaa9dSCédric Le Goater     int i, j;
1746119eaa9dSCédric Le Goater 
1747119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1748119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1749119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1750119eaa9dSCédric Le Goater 
1751119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1752119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1753119eaa9dSCédric Le Goater                 return pc->threads[j];
1754119eaa9dSCédric Le Goater             }
1755119eaa9dSCédric Le Goater         }
1756119eaa9dSCédric Le Goater     }
1757119eaa9dSCédric Le Goater     return NULL;
1758119eaa9dSCédric Le Goater }
1759119eaa9dSCédric Le Goater 
17602ff73ddaSCédric Le Goater typedef struct ForeachPhb3Args {
17612ff73ddaSCédric Le Goater     int irq;
17622ff73ddaSCédric Le Goater     ICSState *ics;
17632ff73ddaSCédric Le Goater } ForeachPhb3Args;
17642ff73ddaSCédric Le Goater 
17652ff73ddaSCédric Le Goater static int pnv_ics_get_child(Object *child, void *opaque)
17662ff73ddaSCédric Le Goater {
17672ff73ddaSCédric Le Goater     ForeachPhb3Args *args = opaque;
17682ff73ddaSCédric Le Goater     PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
17692ff73ddaSCédric Le Goater 
17702ff73ddaSCédric Le Goater     if (phb3) {
17712ff73ddaSCédric Le Goater         if (ics_valid_irq(&phb3->lsis, args->irq)) {
17722ff73ddaSCédric Le Goater             args->ics = &phb3->lsis;
17732ff73ddaSCédric Le Goater         }
17742ff73ddaSCédric Le Goater         if (ics_valid_irq(ICS(&phb3->msis), args->irq)) {
17752ff73ddaSCédric Le Goater             args->ics = ICS(&phb3->msis);
17762ff73ddaSCédric Le Goater         }
17772ff73ddaSCédric Le Goater     }
17782ff73ddaSCédric Le Goater     return args->ics ? 1 : 0;
17792ff73ddaSCédric Le Goater }
17802ff73ddaSCédric Le Goater 
178154f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
178254f59d78SCédric Le Goater {
1783b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
17842ff73ddaSCédric Le Goater     ForeachPhb3Args args = { irq, NULL };
17852ff73ddaSCédric Le Goater     int i;
178654f59d78SCédric Le Goater 
178754f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
17889ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
178977864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
179077864267SCédric Le Goater 
179177864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
179277864267SCédric Le Goater             return &chip8->psi.ics;
179354f59d78SCédric Le Goater         }
17942ff73ddaSCédric Le Goater 
17952ff73ddaSCédric Le Goater         object_child_foreach(OBJECT(chip), pnv_ics_get_child, &args);
17962ff73ddaSCédric Le Goater         if (args.ics) {
17972ff73ddaSCédric Le Goater             return args.ics;
17989ae1329eSCédric Le Goater         }
179954f59d78SCédric Le Goater     }
180054f59d78SCédric Le Goater     return NULL;
180154f59d78SCédric Le Goater }
180254f59d78SCédric Le Goater 
18032ff73ddaSCédric Le Goater static int pnv_ics_resend_child(Object *child, void *opaque)
18042ff73ddaSCédric Le Goater {
18052ff73ddaSCédric Le Goater     PnvPHB3 *phb3 = (PnvPHB3 *) object_dynamic_cast(child, TYPE_PNV_PHB3);
18062ff73ddaSCédric Le Goater 
18072ff73ddaSCédric Le Goater     if (phb3) {
18082ff73ddaSCédric Le Goater         ics_resend(&phb3->lsis);
18092ff73ddaSCédric Le Goater         ics_resend(ICS(&phb3->msis));
18102ff73ddaSCédric Le Goater     }
18112ff73ddaSCédric Le Goater     return 0;
18122ff73ddaSCédric Le Goater }
18132ff73ddaSCédric Le Goater 
181454f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
181554f59d78SCédric Le Goater {
1816b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
18172ff73ddaSCédric Le Goater     int i;
181854f59d78SCédric Le Goater 
181954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
18209ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
182177864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
18229ae1329eSCédric Le Goater 
182377864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
18242ff73ddaSCédric Le Goater         object_child_foreach(OBJECT(chip), pnv_ics_resend_child, NULL);
182554f59d78SCédric Le Goater     }
182654f59d78SCédric Le Goater }
182754f59d78SCédric Le Goater 
182836fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
182936fc6f08SCédric Le Goater {
183036fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
183136fc6f08SCédric Le Goater 
1832956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
183336fc6f08SCédric Le Goater }
183436fc6f08SCédric Le Goater 
183547fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
183647fea43aSCédric Le Goater                                Monitor *mon)
183747fea43aSCédric Le Goater {
1838b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
183954f59d78SCédric Le Goater     int i;
184047fea43aSCédric Le Goater     CPUState *cs;
184147fea43aSCédric Le Goater 
184247fea43aSCédric Le Goater     CPU_FOREACH(cs) {
184347fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
184447fea43aSCédric Le Goater 
184585913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
184685913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
184785913070SGreg Kurz                                                            mon);
1848d8e4aad5SCédric Le Goater     }
184954f59d78SCédric Le Goater 
185054f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1851d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
185254f59d78SCédric Le Goater     }
185347fea43aSCédric Le Goater }
185447fea43aSCédric Le Goater 
1855c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1856c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1857c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1858c722579eSCédric Le Goater                          uint32_t logic_serv,
1859c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1860c722579eSCédric Le Goater {
1861c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1862c722579eSCédric Le Goater     int total_count = 0;
1863c722579eSCédric Le Goater     int i;
1864c722579eSCédric Le Goater 
1865c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1866c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1867c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1868c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1869c722579eSCédric Le Goater         int count;
1870c722579eSCédric Le Goater 
1871c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1872c722579eSCédric Le Goater                                priority, logic_serv, match);
1873c722579eSCédric Le Goater 
1874c722579eSCédric Le Goater         if (count < 0) {
1875c722579eSCédric Le Goater             return count;
1876c722579eSCédric Le Goater         }
1877c722579eSCédric Le Goater 
1878c722579eSCédric Le Goater         total_count += count;
1879c722579eSCédric Le Goater     }
1880c722579eSCédric Le Goater 
1881c722579eSCédric Le Goater     return total_count;
1882c722579eSCédric Le Goater }
1883c722579eSCédric Le Goater 
1884f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
18859e933f4aSBenjamin Herrenschmidt {
18869e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
188736fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1888d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1889d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1890f30c843cSCédric Le Goater 
1891f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1892f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1893f30c843cSCédric Le Goater 
1894f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1895f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1896f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1897d76f2da7SGreg Kurz 
1898d76f2da7SGreg Kurz     pmc->compat = compat;
1899d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1900f30c843cSCédric Le Goater }
1901f30c843cSCédric Le Goater 
1902f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1903f30c843cSCédric Le Goater {
1904f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1905c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1906d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1907d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1908f30c843cSCédric Le Goater 
1909f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1910f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1911c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1912f30c843cSCédric Le Goater 
1913f30c843cSCédric Le Goater     mc->alias = "powernv";
1914d76f2da7SGreg Kurz 
1915d76f2da7SGreg Kurz     pmc->compat = compat;
1916d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19177a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1918f30c843cSCédric Le Goater }
1919f30c843cSCédric Le Goater 
19202b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
19212b548a42SCédric Le Goater {
19222b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1923d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1924d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
19252b548a42SCédric Le Goater 
19262b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
19276bc8c046SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
1928d76f2da7SGreg Kurz 
1929d76f2da7SGreg Kurz     pmc->compat = compat;
1930d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19317a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
19322b548a42SCédric Le Goater }
19332b548a42SCédric Le Goater 
193408c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
193508c3f3a7SCédric Le Goater {
193608c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
193708c3f3a7SCédric Le Goater 
193808c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
193908c3f3a7SCédric Le Goater }
194008c3f3a7SCédric Le Goater 
194108c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
194208c3f3a7SCédric Le Goater {
194308c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
194408c3f3a7SCédric Le Goater 
194508c3f3a7SCédric Le Goater     if (value) {
194608c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
194708c3f3a7SCédric Le Goater     }
194808c3f3a7SCédric Le Goater }
194908c3f3a7SCédric Le Goater 
195001b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
195101b552b0SNicholas Piggin {
195201b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
195301b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
195401b552b0SNicholas Piggin 
195501b552b0SNicholas Piggin     cpu_synchronize_state(cs);
195601b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
19570911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
195801b552b0SNicholas Piggin         /*
1959fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
1960fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
1961fe837714SNicholas Piggin          * (PPC_BIT(43)).
196201b552b0SNicholas Piggin          */
19630911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
1964fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
19650911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
196601b552b0SNicholas Piggin         }
1967fe837714SNicholas Piggin     } else {
1968fe837714SNicholas Piggin         /*
1969fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
1970fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
1971fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
1972fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
1973fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
1974fe837714SNicholas Piggin          */
19750911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
1976fe837714SNicholas Piggin     }
1977fe837714SNicholas Piggin }
197801b552b0SNicholas Piggin 
197901b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
198001b552b0SNicholas Piggin {
198101b552b0SNicholas Piggin     CPUState *cs;
198201b552b0SNicholas Piggin 
198301b552b0SNicholas Piggin     CPU_FOREACH(cs) {
198401b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
198501b552b0SNicholas Piggin     }
198601b552b0SNicholas Piggin }
198701b552b0SNicholas Piggin 
1988f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1989f30c843cSCédric Le Goater {
1990f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
199147fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
199201b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
19939e933f4aSBenjamin Herrenschmidt 
19949e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1995b168a138SCédric Le Goater     mc->init = pnv_init;
1996b168a138SCédric Le Goater     mc->reset = pnv_reset;
19979e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
199859b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
199959b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
20009e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
20019e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
2002f1d18b0aSJoel Stanley     /*
2003f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
2004f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
2005f1d18b0aSJoel Stanley      */
2006dd7ef911SCédric Le Goater     mc->default_ram_size = 1 * GiB;
2007173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
200847fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
200901b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
201008c3f3a7SCédric Le Goater 
201108c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
2012d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
201308c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
20147eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
20159e933f4aSBenjamin Herrenschmidt }
20169e933f4aSBenjamin Herrenschmidt 
201777864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2018beba5c0fSIgor Mammedov     {                                             \
2019beba5c0fSIgor Mammedov         .name          = type,                    \
2020beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
202177864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
202277864267SCédric Le Goater     }
202377864267SCédric Le Goater 
202477864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
202577864267SCédric Le Goater     {                                             \
202677864267SCédric Le Goater         .name          = type,                    \
202777864267SCédric Le Goater         .class_init    = class_initfn,            \
202877864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2029beba5c0fSIgor Mammedov     }
2030beba5c0fSIgor Mammedov 
20312b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
20322b548a42SCédric Le Goater     {                                              \
20332b548a42SCédric Le Goater         .name          = type,                     \
20342b548a42SCédric Le Goater         .class_init    = class_initfn,             \
20352b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
20362b548a42SCédric Le Goater     }
20372b548a42SCédric Le Goater 
2038beba5c0fSIgor Mammedov static const TypeInfo types[] = {
20391aba8716SCédric Le Goater     {
20402b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
20412b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20422b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
20432b548a42SCédric Le Goater     },
20442b548a42SCédric Le Goater     {
20451aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
20461aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20471aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2048c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2049c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2050c722579eSCédric Le Goater             { },
2051c722579eSCédric Le Goater         },
20521aba8716SCédric Le Goater     },
20531aba8716SCédric Le Goater     {
20541aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
20551aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20561aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
20571aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
20581aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
20591aba8716SCédric Le Goater             { },
20601aba8716SCédric Le Goater         },
20611aba8716SCédric Le Goater     },
2062beba5c0fSIgor Mammedov     {
2063b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
20649e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2065f30c843cSCédric Le Goater         .abstract       = true,
20669e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2067b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2068d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
206936fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
207047fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
207101b552b0SNicholas Piggin             { TYPE_NMI },
207236fc6f08SCédric Le Goater             { },
207336fc6f08SCédric Le Goater         },
2074beba5c0fSIgor Mammedov     },
2075beba5c0fSIgor Mammedov     {
2076beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2077beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2078beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2079beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2080beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2081beba5c0fSIgor Mammedov         .abstract      = true,
2082beba5c0fSIgor Mammedov     },
208377864267SCédric Le Goater 
208477864267SCédric Le Goater     /*
20852b548a42SCédric Le Goater      * P10 chip and variants
20862b548a42SCédric Le Goater      */
20872b548a42SCédric Le Goater     {
20882b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
20892b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
20902b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
20912b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
20922b548a42SCédric Le Goater     },
20932b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
20942b548a42SCédric Le Goater 
20952b548a42SCédric Le Goater     /*
209677864267SCédric Le Goater      * P9 chip and variants
209777864267SCédric Le Goater      */
209877864267SCédric Le Goater     {
209977864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
210077864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
210177864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
210277864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
210377864267SCédric Le Goater     },
210477864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
210577864267SCédric Le Goater 
210677864267SCédric Le Goater     /*
210777864267SCédric Le Goater      * P8 chip and variants
210877864267SCédric Le Goater      */
210977864267SCédric Le Goater     {
211077864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
211177864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
211277864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
211377864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
211477864267SCédric Le Goater     },
211577864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
211677864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
211777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2118beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
21199e933f4aSBenjamin Herrenschmidt };
21209e933f4aSBenjamin Herrenschmidt 
2121beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2122