xref: /qemu/hw/ppc/pnv.c (revision 83fa6e2a)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
99e933f4aSBenjamin Herrenschmidt  * version 2 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
2438d2448aSGreg Kurz #include "sysemu/qtest.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
269e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2771e8a915SMarkus Armbruster #include "sysemu/reset.h"
2854d31236SMarkus Armbruster #include "sysemu/runstate.h"
29d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
308d409261SCédric Le Goater #include "sysemu/device_tree.h"
3101b552b0SNicholas Piggin #include "sysemu/hw_accel.h"
32fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
339e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
359e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
37d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
389e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
3901b552b0SNicholas Piggin #include "hw/nmi.h"
409e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.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"
5412e9493dSMarkus Armbruster #include "hw/boards.h"
553495b6b6SCédric Le Goater #include "hw/char/serial.h"
56bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
573495b6b6SCédric Le Goater 
589e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
599e933f4aSBenjamin Herrenschmidt 
60b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
619e933f4aSBenjamin Herrenschmidt 
629e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
639e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
64*83fa6e2aSCédric Le Goater #define FW_MAX_SIZE             (16 * MiB)
659e933f4aSBenjamin Herrenschmidt 
669e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
67b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
68fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
69584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
709e933f4aSBenjamin Herrenschmidt 
7140abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
7240abf43fSIgor Mammedov {
7340abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
7440abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7540abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7640abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7740abf43fSIgor Mammedov     g_free(s);
7840abf43fSIgor Mammedov     return core_type;
7940abf43fSIgor Mammedov }
8040abf43fSIgor Mammedov 
819e933f4aSBenjamin Herrenschmidt /*
829e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
839e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
849e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
859e933f4aSBenjamin Herrenschmidt  */
869e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
879e933f4aSBenjamin Herrenschmidt 
889e933f4aSBenjamin Herrenschmidt /*
899e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
909e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
919e933f4aSBenjamin Herrenschmidt  * per chip.
929e933f4aSBenjamin Herrenschmidt  */
93b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
949e933f4aSBenjamin Herrenschmidt {
959e933f4aSBenjamin Herrenschmidt     char *mem_name;
969e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
979e933f4aSBenjamin Herrenschmidt     int off;
989e933f4aSBenjamin Herrenschmidt 
999e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
1009e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
1019e933f4aSBenjamin Herrenschmidt 
1029e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
1039e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
1049e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1059e933f4aSBenjamin Herrenschmidt 
1069e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1079e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1089e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1099e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1109e933f4aSBenjamin Herrenschmidt }
1119e933f4aSBenjamin Herrenschmidt 
112d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
113d2fd9612SCédric Le Goater {
114d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
115d2fd9612SCédric Le Goater 
116d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
117a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
118d2fd9612SCédric Le Goater         if (cpus_offset) {
119d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
120d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
121d2fd9612SCédric Le Goater         }
122d2fd9612SCédric Le Goater     }
123d2fd9612SCédric Le Goater     _FDT(cpus_offset);
124d2fd9612SCédric Le Goater     return cpus_offset;
125d2fd9612SCédric Le Goater }
126d2fd9612SCédric Le Goater 
127d2fd9612SCédric Le Goater /*
128d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
129d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
130d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
131d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
132d2fd9612SCédric Le Goater  * servers.
133d2fd9612SCédric Le Goater  */
134b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
135d2fd9612SCédric Le Goater {
13608304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13708304a86SDavid Gibson     CPUState *cs = CPU(cpu);
138d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1398bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
140d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
141d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
142d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
143d2fd9612SCédric Le Goater     int i;
144d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
145d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
146d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
147d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
148d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
149d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
150d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
151d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
152d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
153d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
154d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
155d2fd9612SCédric Le Goater     int offset;
156d2fd9612SCédric Le Goater     char *nodename;
157d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
158d2fd9612SCédric Le Goater 
159d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
160d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
161d2fd9612SCédric Le Goater     _FDT(offset);
162d2fd9612SCédric Le Goater     g_free(nodename);
163d2fd9612SCédric Le Goater 
164d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
165d2fd9612SCédric Le Goater 
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
167d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
168d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
169d2fd9612SCédric Le Goater 
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
171d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
172d2fd9612SCédric Le Goater                             env->dcache_line_size)));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
174d2fd9612SCédric Le Goater                             env->dcache_line_size)));
175d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
176d2fd9612SCédric Le Goater                             env->icache_line_size)));
177d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
178d2fd9612SCédric Le Goater                             env->icache_line_size)));
179d2fd9612SCédric Le Goater 
180d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
181d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
182d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
183d2fd9612SCédric Le Goater     } else {
1843dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
185d2fd9612SCédric Le Goater     }
186d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
187d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
188d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
189d2fd9612SCédric Le Goater     } else {
1903dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
191d2fd9612SCédric Le Goater     }
192d2fd9612SCédric Le Goater 
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
194d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19559b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19659b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
197d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
198d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
199d2fd9612SCédric Le Goater 
200d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
201d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
202d2fd9612SCédric Le Goater     }
203d2fd9612SCédric Le Goater 
20458969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
205d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
206d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
207d2fd9612SCédric Le Goater     }
208d2fd9612SCédric Le Goater 
20959b7c1c2SBalamuruhan S     /*
21059b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
211d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
212d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
21359b7c1c2SBalamuruhan S      *   2               == VSX available
21459b7c1c2SBalamuruhan S      */
215d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
216d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
217d2fd9612SCédric Le Goater 
218d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
219d2fd9612SCédric Le Goater     }
220d2fd9612SCédric Le Goater 
22159b7c1c2SBalamuruhan S     /*
22259b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
223d2fd9612SCédric Le Goater      *   0 / no property == no DFP
22459b7c1c2SBalamuruhan S      *   1               == DFP available
22559b7c1c2SBalamuruhan S      */
226d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
227d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
228d2fd9612SCédric Le Goater     }
229d2fd9612SCédric Le Goater 
230644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
231d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
232d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
233d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
234d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
235d2fd9612SCédric Le Goater     }
236d2fd9612SCédric Le Goater 
237d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
238d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
239d2fd9612SCédric Le Goater 
240d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
241d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
242d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
243d2fd9612SCédric Le Goater     }
244d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
245d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
246d2fd9612SCédric Le Goater }
247d2fd9612SCédric Le Goater 
248b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
249bf5615e7SCédric Le Goater                        uint32_t nr_threads)
250bf5615e7SCédric Le Goater {
251bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
252bf5615e7SCédric Le Goater     char *name;
253bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
254bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
255bf5615e7SCédric Le Goater     uint64_t *reg;
256bf5615e7SCédric Le Goater     int offset;
257bf5615e7SCédric Le Goater 
258bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
259bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
260bf5615e7SCédric Le Goater 
261bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
262bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
263bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
264bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
265bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
266bf5615e7SCédric Le Goater     }
267bf5615e7SCédric Le Goater 
268bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
269bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
270bf5615e7SCédric Le Goater     _FDT(offset);
271bf5615e7SCédric Le Goater     g_free(name);
272bf5615e7SCédric Le Goater 
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
274bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
275bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
276bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
277bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
278bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
279bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
280bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
281bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
282bf5615e7SCédric Le Goater     g_free(reg);
283bf5615e7SCédric Le Goater }
284bf5615e7SCédric Le Goater 
285eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
286e997040eSCédric Le Goater {
287c396c58aSGreg Kurz     static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
288d2fd9612SCédric Le Goater     int i;
289d2fd9612SCédric Le Goater 
2903f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
2913f5b45caSGreg Kurz                  cpu_to_be64(PNV_XSCOM_BASE(chip)),
292c396c58aSGreg Kurz                  cpu_to_be64(PNV_XSCOM_SIZE),
293c396c58aSGreg Kurz                  compat, sizeof(compat));
294967b7523SCédric Le Goater 
295d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
2964fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
297d2fd9612SCédric Le Goater 
298b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
299bf5615e7SCédric Le Goater 
300bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
301b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
302d2fd9612SCédric Le Goater     }
303d2fd9612SCédric Le Goater 
304e997040eSCédric Le Goater     if (chip->ram_size) {
305b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
306e997040eSCédric Le Goater     }
307e997040eSCédric Le Goater }
308e997040eSCédric Le Goater 
309eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
310eb859a27SCédric Le Goater {
311c396c58aSGreg Kurz     static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
312eb859a27SCédric Le Goater     int i;
313eb859a27SCédric Le Goater 
3143f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3153f5b45caSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_BASE(chip)),
316c396c58aSGreg Kurz                  cpu_to_be64(PNV9_XSCOM_SIZE),
317c396c58aSGreg Kurz                  compat, sizeof(compat));
318eb859a27SCédric Le Goater 
319eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3204fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
321eb859a27SCédric Le Goater 
322eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
323eb859a27SCédric Le Goater     }
324eb859a27SCédric Le Goater 
325eb859a27SCédric Le Goater     if (chip->ram_size) {
326eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
327eb859a27SCédric Le Goater     }
32815376c66SCédric Le Goater 
3292661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
330eb859a27SCédric Le Goater }
331eb859a27SCédric Le Goater 
3322b548a42SCédric Le Goater static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
3332b548a42SCédric Le Goater {
334c396c58aSGreg Kurz     static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
3352b548a42SCédric Le Goater     int i;
3362b548a42SCédric Le Goater 
3373f5b45caSGreg Kurz     pnv_dt_xscom(chip, fdt, 0,
3383f5b45caSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_BASE(chip)),
339c396c58aSGreg Kurz                  cpu_to_be64(PNV10_XSCOM_SIZE),
340c396c58aSGreg Kurz                  compat, sizeof(compat));
3412b548a42SCédric Le Goater 
3422b548a42SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
3432b548a42SCédric Le Goater         PnvCore *pnv_core = chip->cores[i];
3442b548a42SCédric Le Goater 
3452b548a42SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
3462b548a42SCédric Le Goater     }
3472b548a42SCédric Le Goater 
3482b548a42SCédric Le Goater     if (chip->ram_size) {
3492b548a42SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
3502b548a42SCédric Le Goater     }
3512661f6abSCédric Le Goater 
3522661f6abSCédric Le Goater     pnv_dt_lpc(chip, fdt, 0, PNV10_LPCM_BASE(chip), PNV10_LPCM_SIZE);
3532b548a42SCédric Le Goater }
3542b548a42SCédric Le Goater 
355b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
356c5ffdcaeSCédric Le Goater {
357c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
358c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
359c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
360c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
361c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
362c5ffdcaeSCédric Le Goater     };
363c5ffdcaeSCédric Le Goater     char *name;
364c5ffdcaeSCédric Le Goater     int node;
365c5ffdcaeSCédric Le Goater 
366c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
367c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
368c5ffdcaeSCédric Le Goater     _FDT(node);
369c5ffdcaeSCédric Le Goater     g_free(name);
370c5ffdcaeSCédric Le Goater 
371c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
372c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
373c5ffdcaeSCédric Le Goater }
374c5ffdcaeSCédric Le Goater 
375b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
376cb228f5aSCédric Le Goater {
377cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
378cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
379cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
380cb228f5aSCédric Le Goater         cpu_to_be32(1),
381cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
382cb228f5aSCédric Le Goater         cpu_to_be32(8)
383cb228f5aSCédric Le Goater     };
384cb228f5aSCédric Le Goater     char *name;
385cb228f5aSCédric Le Goater     int node;
386cb228f5aSCédric Le Goater 
387cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
388cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
389cb228f5aSCédric Le Goater     _FDT(node);
390cb228f5aSCédric Le Goater     g_free(name);
391cb228f5aSCédric Le Goater 
392cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
393cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
394cb228f5aSCédric Le Goater                       sizeof(compatible))));
395cb228f5aSCédric Le Goater 
396cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
397cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
398cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
399cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
400cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
401cb228f5aSCédric Le Goater 
402cb228f5aSCédric Le Goater     /* This is needed by Linux */
403cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
404cb228f5aSCédric Le Goater }
405cb228f5aSCédric Le Goater 
406b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
40704f6c8b2SCédric Le Goater {
40804f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
40904f6c8b2SCédric Le Goater     uint32_t io_base;
41004f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
41104f6c8b2SCédric Le Goater         cpu_to_be32(1),
41204f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
41304f6c8b2SCédric Le Goater         cpu_to_be32(3)
41404f6c8b2SCédric Le Goater     };
41504f6c8b2SCédric Le Goater     uint32_t irq;
41604f6c8b2SCédric Le Goater     char *name;
41704f6c8b2SCédric Le Goater     int node;
41804f6c8b2SCédric Le Goater 
41904f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
42004f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
42104f6c8b2SCédric Le Goater 
42204f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
42304f6c8b2SCédric Le Goater 
42404f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
42504f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
42604f6c8b2SCédric Le Goater     _FDT(node);
42704f6c8b2SCédric Le Goater     g_free(name);
42804f6c8b2SCédric Le Goater 
4297032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
4307032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
4317032d92aSCédric Le Goater                       sizeof(compatible))));
43204f6c8b2SCédric Le Goater 
43304f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
43404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
43504f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
43604f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
43704f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
43804f6c8b2SCédric Le Goater }
43904f6c8b2SCédric Le Goater 
440e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
441e7a3fee3SCédric Le Goater     void *fdt;
442e7a3fee3SCédric Le Goater     int offset;
443e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
444e7a3fee3SCédric Le Goater 
445b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
446e7a3fee3SCédric Le Goater {
447c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
448c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
449c5ffdcaeSCédric Le Goater 
450c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
451b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
452cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
453b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
45404f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
455b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
456c5ffdcaeSCédric Le Goater     } else {
457c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
458c5ffdcaeSCédric Le Goater                      d->ioport_id);
459c5ffdcaeSCédric Le Goater     }
460c5ffdcaeSCédric Le Goater 
461e7a3fee3SCédric Le Goater     return 0;
462e7a3fee3SCédric Le Goater }
463e7a3fee3SCédric Le Goater 
46459b7c1c2SBalamuruhan S /*
46559b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
466bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
467bb7ab95cSCédric Le Goater  */
468bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
469bb7ab95cSCédric Le Goater {
47064d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
471e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
472e7a3fee3SCédric Le Goater         .fdt = fdt,
473bb7ab95cSCédric Le Goater         .offset = isa_offset,
474e7a3fee3SCédric Le Goater     };
475f47a08d1SCédric Le Goater     uint32_t phandle;
476e7a3fee3SCédric Le Goater 
477bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
478bb7ab95cSCédric Le Goater 
479f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
480f47a08d1SCédric Le Goater     assert(phandle > 0);
481f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
482f47a08d1SCédric Le Goater 
48359b7c1c2SBalamuruhan S     /*
48459b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
48559b7c1c2SBalamuruhan S      * can not use object_child_foreach()
48659b7c1c2SBalamuruhan S      */
487bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
488bb7ab95cSCédric Le Goater                        &args);
489e7a3fee3SCédric Le Goater }
490e7a3fee3SCédric Le Goater 
4917a90c6a1SGreg Kurz static void pnv_dt_power_mgt(PnvMachineState *pnv, void *fdt)
492e5694793SCédric Le Goater {
493e5694793SCédric Le Goater     int off;
494e5694793SCédric Le Goater 
495e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
496e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
497e5694793SCédric Le Goater 
498e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
499e5694793SCédric Le Goater }
500e5694793SCédric Le Goater 
501b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
5029e933f4aSBenjamin Herrenschmidt {
503d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_GET_CLASS(machine);
504b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5059e933f4aSBenjamin Herrenschmidt     void *fdt;
5069e933f4aSBenjamin Herrenschmidt     char *buf;
5079e933f4aSBenjamin Herrenschmidt     int off;
508e997040eSCédric Le Goater     int i;
5099e933f4aSBenjamin Herrenschmidt 
5109e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
5119e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
5129e933f4aSBenjamin Herrenschmidt 
513ccb099b3SCédric Le Goater     /* /qemu node */
514ccb099b3SCédric Le Goater     _FDT((fdt_add_subnode(fdt, 0, "qemu")));
515ccb099b3SCédric Le Goater 
5169e933f4aSBenjamin Herrenschmidt     /* Root node */
5179e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
5189e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
5199e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
5209e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
521d76f2da7SGreg Kurz     _FDT((fdt_setprop(fdt, 0, "compatible", pmc->compat, pmc->compat_size)));
5229e933f4aSBenjamin Herrenschmidt 
5239e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
5249e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
5259e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
5269e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5279e933f4aSBenjamin Herrenschmidt     }
5289e933f4aSBenjamin Herrenschmidt     g_free(buf);
5299e933f4aSBenjamin Herrenschmidt 
5309e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5319e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5329e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5339e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5349e933f4aSBenjamin Herrenschmidt     }
5359e933f4aSBenjamin Herrenschmidt 
5369e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5379e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5389e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5399e933f4aSBenjamin Herrenschmidt 
5409e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5419e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5429e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5439e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5449e933f4aSBenjamin Herrenschmidt     }
5459e933f4aSBenjamin Herrenschmidt 
546e997040eSCédric Le Goater     /* Populate device tree for each chip */
547e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
548eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
549e997040eSCédric Le Goater     }
550e7a3fee3SCédric Le Goater 
551e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
552bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
553aeaef83dSCédric Le Goater 
554aeaef83dSCédric Le Goater     if (pnv->bmc) {
555b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
556aeaef83dSCédric Le Goater     }
557aeaef83dSCédric Le Goater 
5587a90c6a1SGreg Kurz     /* Create an extra node for power management on machines that support it */
5597a90c6a1SGreg Kurz     if (pmc->dt_power_mgt) {
5607a90c6a1SGreg Kurz         pmc->dt_power_mgt(pnv, fdt);
561e5694793SCédric Le Goater     }
562e5694793SCédric Le Goater 
5639e933f4aSBenjamin Herrenschmidt     return fdt;
5649e933f4aSBenjamin Herrenschmidt }
5659e933f4aSBenjamin Herrenschmidt 
566bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
567bce0b691SCédric Le Goater {
5688f06e370SCédric Le Goater     PnvMachineState *pnv = container_of(n, PnvMachineState, powerdown_notifier);
569bce0b691SCédric Le Goater 
570bce0b691SCédric Le Goater     if (pnv->bmc) {
571bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
572bce0b691SCédric Le Goater     }
573bce0b691SCédric Le Goater }
574bce0b691SCédric Le Goater 
575a0628599SLike Xu static void pnv_reset(MachineState *machine)
5769e933f4aSBenjamin Herrenschmidt {
57725f3170bSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
57825f3170bSCédric Le Goater     IPMIBmc *bmc;
5799e933f4aSBenjamin Herrenschmidt     void *fdt;
5809e933f4aSBenjamin Herrenschmidt 
5819e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5829e933f4aSBenjamin Herrenschmidt 
58325f3170bSCédric Le Goater     /*
58425f3170bSCédric Le Goater      * The machine should provide by default an internal BMC simulator.
58525f3170bSCédric Le Goater      * If not, try to use the BMC device that was provided on the command
58625f3170bSCédric Le Goater      * line.
58725f3170bSCédric Le Goater      */
58825f3170bSCédric Le Goater     bmc = pnv_bmc_find(&error_fatal);
58925f3170bSCédric Le Goater     if (!pnv->bmc) {
59025f3170bSCédric Le Goater         if (!bmc) {
59138d2448aSGreg Kurz             if (!qtest_enabled()) {
59225f3170bSCédric Le Goater                 warn_report("machine has no BMC device. Use '-device "
59325f3170bSCédric Le Goater                             "ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10' "
59425f3170bSCédric Le Goater                             "to define one");
59538d2448aSGreg Kurz             }
59625f3170bSCédric Le Goater         } else {
59725f3170bSCédric Le Goater             pnv_bmc_set_pnor(bmc, pnv->pnor);
59825f3170bSCédric Le Goater             pnv->bmc = bmc;
59925f3170bSCédric Le Goater         }
60025f3170bSCédric Le Goater     }
60125f3170bSCédric Le Goater 
602b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
6039e933f4aSBenjamin Herrenschmidt 
6049e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
6059e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
6069e933f4aSBenjamin Herrenschmidt 
6078d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
6089e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
609b2fb7a43SPan Nengyuan 
610b2fb7a43SPan Nengyuan     g_free(fdt);
6119e933f4aSBenjamin Herrenschmidt }
6129e933f4aSBenjamin Herrenschmidt 
61304026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
6143495b6b6SCédric Le Goater {
61577864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
61677864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
61704026890SCédric Le Goater }
6183495b6b6SCédric Le Goater 
61904026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
62004026890SCédric Le Goater {
62177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
62277864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
62304026890SCédric Le Goater }
6243495b6b6SCédric Le Goater 
62504026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
62604026890SCédric Le Goater {
62715376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
62815376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
62904026890SCédric Le Goater }
6303495b6b6SCédric Le Goater 
6312b548a42SCédric Le Goater static ISABus *pnv_chip_power10_isa_create(PnvChip *chip, Error **errp)
6322b548a42SCédric Le Goater {
6332661f6abSCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
6342661f6abSCédric Le Goater     return pnv_lpc_isa_create(&chip10->lpc, false, errp);
6352b548a42SCédric Le Goater }
6362b548a42SCédric Le Goater 
63704026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
63804026890SCédric Le Goater {
63904026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6403495b6b6SCédric Le Goater }
6413495b6b6SCédric Le Goater 
642d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
643d8e4aad5SCédric Le Goater {
644d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
6459ae1329eSCédric Le Goater     int i;
646d8e4aad5SCédric Le Goater 
647d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
6489ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
6499ae1329eSCédric Le Goater         pnv_phb3_msi_pic_print_info(&chip8->phbs[i].msis, mon);
6509ae1329eSCédric Le Goater         ics_pic_print_info(&chip8->phbs[i].lsis, mon);
6519ae1329eSCédric Le Goater     }
652d8e4aad5SCédric Le Goater }
653d8e4aad5SCédric Le Goater 
654d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
655d8e4aad5SCédric Le Goater {
656d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
6574f9924c4SBenjamin Herrenschmidt     int i, j;
658d8e4aad5SCédric Le Goater 
659d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
660c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
6614f9924c4SBenjamin Herrenschmidt 
6624f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
6634f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
6644f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks; j++) {
6654f9924c4SBenjamin Herrenschmidt             pnv_phb4_pic_print_info(&pec->stacks[j].phb, mon);
6664f9924c4SBenjamin Herrenschmidt         }
6674f9924c4SBenjamin Herrenschmidt     }
668d8e4aad5SCédric Le Goater }
669d8e4aad5SCédric Le Goater 
670c4b2c40cSGreg Kurz static uint64_t pnv_chip_power8_xscom_core_base(PnvChip *chip,
671c4b2c40cSGreg Kurz                                                 uint32_t core_id)
672c4b2c40cSGreg Kurz {
673c4b2c40cSGreg Kurz     return PNV_XSCOM_EX_BASE(core_id);
674c4b2c40cSGreg Kurz }
675c4b2c40cSGreg Kurz 
676c4b2c40cSGreg Kurz static uint64_t pnv_chip_power9_xscom_core_base(PnvChip *chip,
677c4b2c40cSGreg Kurz                                                 uint32_t core_id)
678c4b2c40cSGreg Kurz {
679c4b2c40cSGreg Kurz     return PNV9_XSCOM_EC_BASE(core_id);
680c4b2c40cSGreg Kurz }
681c4b2c40cSGreg Kurz 
682c4b2c40cSGreg Kurz static uint64_t pnv_chip_power10_xscom_core_base(PnvChip *chip,
683c4b2c40cSGreg Kurz                                                  uint32_t core_id)
684c4b2c40cSGreg Kurz {
685c4b2c40cSGreg Kurz     return PNV10_XSCOM_EC_BASE(core_id);
686c4b2c40cSGreg Kurz }
687c4b2c40cSGreg Kurz 
688f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
689f30c843cSCédric Le Goater {
690f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
691f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
692f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
693f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
694f30c843cSCédric Le Goater 
695f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
696f30c843cSCédric Le Goater }
697f30c843cSCédric Le Goater 
698e2392d43SCédric Le Goater static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq)
699e2392d43SCédric Le Goater {
700c23e0561SMarkus Armbruster     ISADevice *dev = isa_new("isa-ipmi-bt");
701e2392d43SCédric Le Goater 
7025325cc34SMarkus Armbruster     object_property_set_link(OBJECT(dev), "bmc", OBJECT(bmc), &error_fatal);
7035325cc34SMarkus Armbruster     object_property_set_int(OBJECT(dev), "irq", irq, &error_fatal);
704c23e0561SMarkus Armbruster     isa_realize_and_unref(dev, bus, &error_fatal);
705e2392d43SCédric Le Goater }
706e2392d43SCédric Le Goater 
7072b548a42SCédric Le Goater static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
7082b548a42SCédric Le Goater {
7098b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(chip);
7108b50ce85SCédric Le Goater 
7118b50ce85SCédric Le Goater     pnv_psi_pic_print_info(&chip10->psi, mon);
7122b548a42SCédric Le Goater }
7132b548a42SCédric Le Goater 
714b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
7159e933f4aSBenjamin Herrenschmidt {
716b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
717f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
7189e933f4aSBenjamin Herrenschmidt     char *fw_filename;
7199e933f4aSBenjamin Herrenschmidt     long fw_size;
720e997040eSCédric Le Goater     int i;
721e997040eSCédric Le Goater     char *chip_typename;
72235dde576SCédric Le Goater     DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
72335dde576SCédric Le Goater     DeviceState *dev;
7249e933f4aSBenjamin Herrenschmidt 
7259e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
726d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
7273dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
7289e933f4aSBenjamin Herrenschmidt     }
729173a36d8SIgor Mammedov     memory_region_add_subregion(get_system_memory(), 0, machine->ram);
7309e933f4aSBenjamin Herrenschmidt 
73135dde576SCédric Le Goater     /*
73235dde576SCédric Le Goater      * Create our simple PNOR device
73335dde576SCédric Le Goater      */
7343e80f690SMarkus Armbruster     dev = qdev_new(TYPE_PNV_PNOR);
73535dde576SCédric Le Goater     if (pnor) {
736934df912SMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(pnor));
73735dde576SCédric Le Goater     }
7383c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
73935dde576SCédric Le Goater     pnv->pnor = PNV_PNOR(dev);
74035dde576SCédric Le Goater 
7419e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
7429e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
7439e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
7449e933f4aSBenjamin Herrenschmidt     }
7459e933f4aSBenjamin Herrenschmidt 
7469e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
74715fcedb2SCédric Le Goater     if (!fw_filename) {
74815fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
74915fcedb2SCédric Le Goater         exit(1);
75015fcedb2SCédric Le Goater     }
7519e933f4aSBenjamin Herrenschmidt 
75208c3f3a7SCédric Le Goater     fw_size = load_image_targphys(fw_filename, pnv->fw_load_addr, FW_MAX_SIZE);
7539e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
75415fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
7559e933f4aSBenjamin Herrenschmidt         exit(1);
7569e933f4aSBenjamin Herrenschmidt     }
7579e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
7589e933f4aSBenjamin Herrenschmidt 
7599e933f4aSBenjamin Herrenschmidt     /* load kernel */
7609e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
7619e933f4aSBenjamin Herrenschmidt         long kernel_size;
7629e933f4aSBenjamin Herrenschmidt 
7639e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
764b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
7659e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
766802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
7679e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
7689e933f4aSBenjamin Herrenschmidt             exit(1);
7699e933f4aSBenjamin Herrenschmidt         }
7709e933f4aSBenjamin Herrenschmidt     }
7719e933f4aSBenjamin Herrenschmidt 
7729e933f4aSBenjamin Herrenschmidt     /* load initrd */
7739e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
7749e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
7759e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
776584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
7779e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
778802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
7799e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
7809e933f4aSBenjamin Herrenschmidt             exit(1);
7819e933f4aSBenjamin Herrenschmidt         }
7829e933f4aSBenjamin Herrenschmidt     }
783e997040eSCédric Le Goater 
7844f9924c4SBenjamin Herrenschmidt     /* MSIs are supported on this platform */
7854f9924c4SBenjamin Herrenschmidt     msi_nonbroken = true;
7864f9924c4SBenjamin Herrenschmidt 
787f30c843cSCédric Le Goater     /*
788f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
789f30c843cSCédric Le Goater      * default.
790f30c843cSCédric Le Goater      */
791f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
792f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
793f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
794f30c843cSCédric Le Goater         exit(1);
795f30c843cSCédric Le Goater     }
796f30c843cSCédric Le Goater 
797e997040eSCédric Le Goater     /* Create the processor chips */
7984a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7997fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
8004a12c699SIgor Mammedov                                     i, machine->cpu_type);
801e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
802f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
803f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
804e997040eSCédric Le Goater         exit(1);
805e997040eSCédric Le Goater     }
806e997040eSCédric Le Goater 
807e44acde2SGreg Kurz     pnv->num_chips =
808e44acde2SGreg Kurz         machine->smp.max_cpus / (machine->smp.cores * machine->smp.threads);
809e44acde2SGreg Kurz     /*
810e44acde2SGreg Kurz      * TODO: should we decide on how many chips we can create based
811e44acde2SGreg Kurz      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
812e44acde2SGreg Kurz      */
813e44acde2SGreg Kurz     if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 4) {
814e44acde2SGreg Kurz         error_report("invalid number of chips: '%d'", pnv->num_chips);
815e44acde2SGreg Kurz         error_printf("Try '-smp sockets=N'. Valid values are : 1, 2 or 4.\n");
816e44acde2SGreg Kurz         exit(1);
817e44acde2SGreg Kurz     }
818e44acde2SGreg Kurz 
819e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
820e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
821e997040eSCédric Le Goater         char chip_name[32];
822df707969SMarkus Armbruster         Object *chip = OBJECT(qdev_new(chip_typename));
823e997040eSCédric Le Goater 
824e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
825e997040eSCédric Le Goater 
82659b7c1c2SBalamuruhan S         /*
82759b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
828e997040eSCédric Le Goater          * way to specify different ranges for each chip
829e997040eSCédric Le Goater          */
830e997040eSCédric Le Goater         if (i == 0) {
8315325cc34SMarkus Armbruster             object_property_set_int(chip, "ram-size", machine->ram_size,
832e997040eSCédric Le Goater                                     &error_fatal);
833e997040eSCédric Le Goater         }
834e997040eSCédric Le Goater 
835e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
836d2623129SMarkus Armbruster         object_property_add_child(OBJECT(pnv), chip_name, chip);
8375325cc34SMarkus Armbruster         object_property_set_int(chip, "chip-id", PNV_CHIP_HWID(i),
838e997040eSCédric Le Goater                                 &error_fatal);
8395325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-cores", machine->smp.cores,
8405325cc34SMarkus Armbruster                                 &error_fatal);
8415325cc34SMarkus Armbruster         object_property_set_int(chip, "nr-threads", machine->smp.threads,
8425325cc34SMarkus Armbruster                                 &error_fatal);
843245cdb7fSCédric Le Goater         /*
844245cdb7fSCédric Le Goater          * The POWER8 machine use the XICS interrupt interface.
845245cdb7fSCédric Le Goater          * Propagate the XICS fabric to the chip and its controllers.
846245cdb7fSCédric Le Goater          */
847245cdb7fSCédric Le Goater         if (object_dynamic_cast(OBJECT(pnv), TYPE_XICS_FABRIC)) {
8485325cc34SMarkus Armbruster             object_property_set_link(chip, "xics", OBJECT(pnv), &error_abort);
849245cdb7fSCédric Le Goater         }
850d1214b81SGreg Kurz         if (object_dynamic_cast(OBJECT(pnv), TYPE_XIVE_FABRIC)) {
8515325cc34SMarkus Armbruster             object_property_set_link(chip, "xive-fabric", OBJECT(pnv),
852d1214b81SGreg Kurz                                      &error_abort);
853d1214b81SGreg Kurz         }
8543c6ef471SMarkus Armbruster         sysbus_realize_and_unref(SYS_BUS_DEVICE(chip), &error_fatal);
855e997040eSCédric Le Goater     }
856e997040eSCédric Le Goater     g_free(chip_typename);
8573495b6b6SCédric Le Goater 
8583495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
85904026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
8603495b6b6SCédric Le Goater 
8613495b6b6SCédric Le Goater     /* Create serial port */
862def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
8633495b6b6SCédric Le Goater 
8643495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
8656c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
866bce0b691SCédric Le Goater 
86725f3170bSCédric Le Goater     /*
86825f3170bSCédric Le Goater      * Create the machine BMC simulator and the IPMI BT device for
86925f3170bSCédric Le Goater      * communication with the BMC
87025f3170bSCédric Le Goater      */
87125f3170bSCédric Le Goater     if (defaults_enabled()) {
87225f3170bSCédric Le Goater         pnv->bmc = pnv_bmc_create(pnv->pnor);
873e2392d43SCédric Le Goater         pnv_ipmi_bt_init(pnv->isa_bus, pnv->bmc, 10);
87425f3170bSCédric Le Goater     }
875e2392d43SCédric Le Goater 
87659b7c1c2SBalamuruhan S     /*
87759b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
87859b7c1c2SBalamuruhan S      * host to powerdown
87959b7c1c2SBalamuruhan S      */
880bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
881bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
882e997040eSCédric Le Goater }
883e997040eSCédric Le Goater 
884631adaffSCédric Le Goater /*
885631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
886631adaffSCédric Le Goater  *   22:24  Chip ID
887631adaffSCédric Le Goater  *   25:28  Core number
888631adaffSCédric Le Goater  *   29:31  Thread ID
889631adaffSCédric Le Goater  */
890631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
891631adaffSCédric Le Goater {
892631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
893631adaffSCédric Le Goater }
894631adaffSCédric Le Goater 
8958fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
896d35aefa9SCédric Le Goater                                         Error **errp)
897d35aefa9SCédric Le Goater {
898245cdb7fSCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
8998fa1f4efSCédric Le Goater     Error *local_err = NULL;
9008fa1f4efSCédric Le Goater     Object *obj;
9018907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9028fa1f4efSCédric Le Goater 
903245cdb7fSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, chip8->xics, &local_err);
9048fa1f4efSCédric Le Goater     if (local_err) {
9058fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
9068fa1f4efSCédric Le Goater         return;
9078fa1f4efSCédric Le Goater     }
9088fa1f4efSCédric Le Goater 
909956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
910d35aefa9SCédric Le Goater }
911d35aefa9SCédric Le Goater 
9120990ce6aSGreg Kurz 
913d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
914d49e8a9bSCédric Le Goater {
915d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
916d49e8a9bSCédric Le Goater 
917d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
918d49e8a9bSCédric Le Goater }
919d49e8a9bSCédric Le Goater 
9200990ce6aSGreg Kurz static void pnv_chip_power8_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9210990ce6aSGreg Kurz {
9220990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9230990ce6aSGreg Kurz 
9240990ce6aSGreg Kurz     icp_destroy(ICP(pnv_cpu->intc));
9250990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9260990ce6aSGreg Kurz }
9270990ce6aSGreg Kurz 
92885913070SGreg Kurz static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
92985913070SGreg Kurz                                             Monitor *mon)
93085913070SGreg Kurz {
93185913070SGreg Kurz     icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
93285913070SGreg Kurz }
93385913070SGreg Kurz 
934631adaffSCédric Le Goater /*
935631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
936631adaffSCédric Le Goater  *   49:52  Node ID
937631adaffSCédric Le Goater  *   53:55  Chip ID
938631adaffSCédric Le Goater  *   56     Reserved - Read as zero
939631adaffSCédric Le Goater  *   57:61  Core number
940631adaffSCédric Le Goater  *   62:63  Thread ID
941631adaffSCédric Le Goater  *
942631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
943631adaffSCédric Le Goater  */
944631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
945631adaffSCédric Le Goater {
946631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
947631adaffSCédric Le Goater }
948631adaffSCédric Le Goater 
9492b548a42SCédric Le Goater static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
9502b548a42SCédric Le Goater {
9512b548a42SCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
9522b548a42SCédric Le Goater }
9532b548a42SCédric Le Goater 
9548fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
955d35aefa9SCédric Le Goater                                         Error **errp)
956d35aefa9SCédric Le Goater {
9572dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
9582dfa91a2SCédric Le Goater     Error *local_err = NULL;
9592dfa91a2SCédric Le Goater     Object *obj;
9602dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9612dfa91a2SCédric Le Goater 
9622dfa91a2SCédric Le Goater     /*
9632dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
9642dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
9652dfa91a2SCédric Le Goater      * only used at runtime.
9662dfa91a2SCédric Le Goater      */
96747950946SCédric Le Goater     obj = xive_tctx_create(OBJECT(cpu), XIVE_PRESENTER(&chip9->xive),
96847950946SCédric Le Goater                            &local_err);
9692dfa91a2SCédric Le Goater     if (local_err) {
9702dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
9718fa1f4efSCédric Le Goater         return;
972d35aefa9SCédric Le Goater     }
973d35aefa9SCédric Le Goater 
9742dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
9752dfa91a2SCédric Le Goater }
9762dfa91a2SCédric Le Goater 
977d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
978d49e8a9bSCédric Le Goater {
979d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
980d49e8a9bSCédric Le Goater 
981d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
982d49e8a9bSCédric Le Goater }
983d49e8a9bSCédric Le Goater 
9840990ce6aSGreg Kurz static void pnv_chip_power9_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
9850990ce6aSGreg Kurz {
9860990ce6aSGreg Kurz     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
9870990ce6aSGreg Kurz 
9880990ce6aSGreg Kurz     xive_tctx_destroy(XIVE_TCTX(pnv_cpu->intc));
9890990ce6aSGreg Kurz     pnv_cpu->intc = NULL;
9900990ce6aSGreg Kurz }
9910990ce6aSGreg Kurz 
99285913070SGreg Kurz static void pnv_chip_power9_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
99385913070SGreg Kurz                                             Monitor *mon)
99485913070SGreg Kurz {
99585913070SGreg Kurz     xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
99685913070SGreg Kurz }
99785913070SGreg Kurz 
9982b548a42SCédric Le Goater static void pnv_chip_power10_intc_create(PnvChip *chip, PowerPCCPU *cpu,
9992b548a42SCédric Le Goater                                         Error **errp)
10002b548a42SCédric Le Goater {
10012b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10022b548a42SCédric Le Goater 
10032b548a42SCédric Le Goater     /* Will be defined when the interrupt controller is */
10042b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10052b548a42SCédric Le Goater }
10062b548a42SCédric Le Goater 
10072b548a42SCédric Le Goater static void pnv_chip_power10_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
10082b548a42SCédric Le Goater {
10092b548a42SCédric Le Goater     ;
10102b548a42SCédric Le Goater }
10112b548a42SCédric Le Goater 
10122b548a42SCédric Le Goater static void pnv_chip_power10_intc_destroy(PnvChip *chip, PowerPCCPU *cpu)
10132b548a42SCédric Le Goater {
10142b548a42SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
10152b548a42SCédric Le Goater 
10162b548a42SCédric Le Goater     pnv_cpu->intc = NULL;
10172b548a42SCédric Le Goater }
10182b548a42SCédric Le Goater 
101985913070SGreg Kurz static void pnv_chip_power10_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
102085913070SGreg Kurz                                              Monitor *mon)
102185913070SGreg Kurz {
102285913070SGreg Kurz }
102385913070SGreg Kurz 
102459b7c1c2SBalamuruhan S /*
102559b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
1026397a79e7SCédric Le Goater  *
1027397a79e7SCédric Le Goater  * <EX0 reserved>
1028397a79e7SCédric Le Goater  *  EX1  - Venice only
1029397a79e7SCédric Le Goater  *  EX2  - Venice only
1030397a79e7SCédric Le Goater  *  EX3  - Venice only
1031397a79e7SCédric Le Goater  *  EX4
1032397a79e7SCédric Le Goater  *  EX5
1033397a79e7SCédric Le Goater  *  EX6
1034397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
1035397a79e7SCédric Le Goater  *  EX9  - Venice only
1036397a79e7SCédric Le Goater  *  EX10 - Venice only
1037397a79e7SCédric Le Goater  *  EX11 - Venice only
1038397a79e7SCédric Le Goater  *  EX12
1039397a79e7SCédric Le Goater  *  EX13
1040397a79e7SCédric Le Goater  *  EX14
1041397a79e7SCédric Le Goater  * <EX15 reserved>
1042397a79e7SCédric Le Goater  */
1043397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
1044397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
1045397a79e7SCédric Le Goater 
1046397a79e7SCédric Le Goater /*
104709279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
1048397a79e7SCédric Le Goater  */
104909279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
1050397a79e7SCédric Le Goater 
10512b548a42SCédric Le Goater 
10522b548a42SCédric Le Goater #define POWER10_CORE_MASK  (0xffffffffffffffull)
10532b548a42SCédric Le Goater 
105477864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
105577864267SCédric Le Goater {
10569ae1329eSCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
105777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
10589ae1329eSCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
10599ae1329eSCédric Le Goater     int i;
106077864267SCédric Le Goater 
1061245cdb7fSCédric Le Goater     object_property_add_link(obj, "xics", TYPE_XICS_FABRIC,
1062245cdb7fSCédric Le Goater                              (Object **)&chip8->xics,
1063245cdb7fSCédric Le Goater                              object_property_allow_set_link,
1064d2623129SMarkus Armbruster                              OBJ_PROP_LINK_STRONG);
1065245cdb7fSCédric Le Goater 
10669fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip8->psi, TYPE_PNV8_PSI);
106777864267SCédric Le Goater 
10689fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip8->lpc, TYPE_PNV8_LPC);
106977864267SCédric Le Goater 
10709fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip8->occ, TYPE_PNV8_OCC);
10713887d241SBalamuruhan S 
10729fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER);
10739ae1329eSCédric Le Goater 
10749ae1329eSCédric Le Goater     for (i = 0; i < pcc->num_phbs; i++) {
10759fc7fc4dSMarkus Armbruster         object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3);
10769ae1329eSCédric Le Goater     }
10779ae1329eSCédric Le Goater 
10789ae1329eSCédric Le Goater     /*
10799ae1329eSCédric Le Goater      * Number of PHBs is the chip default
10809ae1329eSCédric Le Goater      */
10819ae1329eSCédric Le Goater     chip->num_phbs = pcc->num_phbs;
108277864267SCédric Le Goater }
108377864267SCédric Le Goater 
108477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
108577864267SCédric Le Goater  {
108677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
108777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
108877864267SCédric Le Goater     int i, j;
108977864267SCédric Le Goater     char *name;
109077864267SCédric Le Goater 
109177864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
109277864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
109377864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
109477864267SCédric Le Goater     g_free(name);
109577864267SCédric Le Goater 
109677864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
109777864267SCédric Le Goater 
109877864267SCédric Le Goater     /* Map the ICP registers for each thread */
109977864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
11004fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i];
110177864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
110277864267SCédric Le Goater 
110377864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
110477864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
1105245cdb7fSCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
110677864267SCédric Le Goater 
110777864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
110877864267SCédric Le Goater                                         &icp->mmio);
110977864267SCédric Le Goater         }
111077864267SCédric Le Goater     }
111177864267SCédric Le Goater }
111277864267SCédric Le Goater 
111377864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
111477864267SCédric Le Goater {
111577864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
111677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
111777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
1118ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
111977864267SCédric Le Goater     Error *local_err = NULL;
11209ae1329eSCédric Le Goater     int i;
112177864267SCédric Le Goater 
1122245cdb7fSCédric Le Goater     assert(chip8->xics);
1123245cdb7fSCédric Le Goater 
1124709044fdSCédric Le Goater     /* XSCOM bridge is first */
1125709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
1126709044fdSCédric Le Goater     if (local_err) {
1127709044fdSCédric Le Goater         error_propagate(errp, local_err);
1128709044fdSCédric Le Goater         return;
1129709044fdSCédric Le Goater     }
1130709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
1131709044fdSCédric Le Goater 
113277864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
113377864267SCédric Le Goater     if (local_err) {
113477864267SCédric Le Goater         error_propagate(errp, local_err);
113577864267SCédric Le Goater         return;
113677864267SCédric Le Goater     }
113777864267SCédric Le Goater 
113877864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
11395325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip8->psi), "bar", PNV_PSIHB_BASE(chip),
11405325cc34SMarkus Armbruster                             &error_fatal);
11415325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->psi), ICS_PROP_XICS,
11425325cc34SMarkus Armbruster                              OBJECT(chip8->xics), &error_abort);
1143668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->psi), NULL, errp)) {
114477864267SCédric Le Goater         return;
114577864267SCédric Le Goater     }
1146ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
1147ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
114877864267SCédric Le Goater 
114977864267SCédric Le Goater     /* Create LPC controller */
11505325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->lpc), "psi", OBJECT(&chip8->psi),
1151b63f3893SGreg Kurz                              &error_abort);
1152ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(&chip8->lpc), NULL, &error_fatal);
115377864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
115477864267SCédric Le Goater 
115564d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
115664d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
115764d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
115864d011d5SCédric Le Goater 
115959b7c1c2SBalamuruhan S     /*
116059b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
116159b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
116259b7c1c2SBalamuruhan S      */
116377864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
116477864267SCédric Le Goater     if (local_err) {
116577864267SCédric Le Goater         error_propagate(errp, local_err);
116677864267SCédric Le Goater         return;
116777864267SCédric Le Goater     }
116877864267SCédric Le Goater 
116977864267SCédric Le Goater     /* Create the simplified OCC model */
11705325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->occ), "psi", OBJECT(&chip8->psi),
1171ee3d2713SGreg Kurz                              &error_abort);
1172668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->occ), NULL, errp)) {
117377864267SCédric Le Goater         return;
117477864267SCédric Le Goater     }
117577864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
1176f3db8266SBalamuruhan S 
1177f3db8266SBalamuruhan S     /* OCC SRAM model */
11783a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV_OCC_SENSOR_BASE(chip),
1179f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
11803887d241SBalamuruhan S 
11813887d241SBalamuruhan S     /* HOMER */
11825325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip8->homer), "chip", OBJECT(chip),
1183f2582acfSGreg Kurz                              &error_abort);
1184668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip8->homer), NULL, errp)) {
11853887d241SBalamuruhan S         return;
11863887d241SBalamuruhan S     }
11878f092316SCédric Le Goater     /* Homer Xscom region */
11888f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PBA_BASE, &chip8->homer.pba_regs);
11898f092316SCédric Le Goater 
11908f092316SCédric Le Goater     /* Homer mmio region */
11913887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
11923887d241SBalamuruhan S                                 &chip8->homer.regs);
11939ae1329eSCédric Le Goater 
11949ae1329eSCédric Le Goater     /* PHB3 controllers */
11959ae1329eSCédric Le Goater     for (i = 0; i < chip->num_phbs; i++) {
11969ae1329eSCédric Le Goater         PnvPHB3 *phb = &chip8->phbs[i];
11979ae1329eSCédric Le Goater         PnvPBCQState *pbcq = &phb->pbcq;
11989ae1329eSCédric Le Goater 
11995325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "index", i, &error_fatal);
12005325cc34SMarkus Armbruster         object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id,
12019ae1329eSCédric Le Goater                                 &error_fatal);
1202668f62ecSMarkus Armbruster         if (!sysbus_realize(SYS_BUS_DEVICE(phb), errp)) {
12039ae1329eSCédric Le Goater             return;
12049ae1329eSCédric Le Goater         }
12059ae1329eSCédric Le Goater 
12069ae1329eSCédric Le Goater         /* Populate the XSCOM address space. */
12079ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12089ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id,
12099ae1329eSCédric Le Goater                                 &pbcq->xscom_nest_regs);
12109ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12119ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id,
12129ae1329eSCédric Le Goater                                 &pbcq->xscom_pci_regs);
12139ae1329eSCédric Le Goater         pnv_xscom_add_subregion(chip,
12149ae1329eSCédric Le Goater                                 PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id,
12159ae1329eSCédric Le Goater                                 &pbcq->xscom_spci_regs);
12169ae1329eSCédric Le Goater     }
121777864267SCédric Le Goater }
121877864267SCédric Le Goater 
121970c059e9SGreg Kurz static uint32_t pnv_chip_power8_xscom_pcba(PnvChip *chip, uint64_t addr)
122070c059e9SGreg Kurz {
122170c059e9SGreg Kurz     addr &= (PNV_XSCOM_SIZE - 1);
122270c059e9SGreg Kurz     return ((addr >> 4) & ~0xfull) | ((addr >> 3) & 0xf);
122370c059e9SGreg Kurz }
122470c059e9SGreg Kurz 
1225e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
1226e997040eSCédric Le Goater {
1227e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1228e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1229e997040eSCédric Le Goater 
1230e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
1231397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
12329ae1329eSCédric Le Goater     k->num_phbs = 3;
1233631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1234d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1235d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12360990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
123785913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
123804026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1239eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1240d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1241c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
124270c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1243e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
124477864267SCédric Le Goater 
124577864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
124677864267SCédric Le Goater                                     &k->parent_realize);
1247e997040eSCédric Le Goater }
1248e997040eSCédric Le Goater 
1249e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1250e997040eSCédric Le Goater {
1251e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1252e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1253e997040eSCédric Le Goater 
1254e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1255397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12569ae1329eSCédric Le Goater     k->num_phbs = 3;
1257631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1258d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1259d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12600990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
126185913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
126204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1263eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1264d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1265c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
126670c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1267e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
126877864267SCédric Le Goater 
126977864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
127077864267SCédric Le Goater                                     &k->parent_realize);
1271e997040eSCédric Le Goater }
1272e997040eSCédric Le Goater 
1273e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1274e997040eSCédric Le Goater {
1275e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1276e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1277e997040eSCédric Le Goater 
1278e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1279397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
12809ae1329eSCédric Le Goater     k->num_phbs = 3;
1281631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1282d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1283d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
12840990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power8_intc_destroy;
128585913070SGreg Kurz     k->intc_print_info = pnv_chip_power8_intc_print_info;
128604026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1287eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1288d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1289c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power8_xscom_core_base;
129070c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power8_xscom_pcba;
1291e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
129277864267SCédric Le Goater 
129377864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
129477864267SCédric Le Goater                                     &k->parent_realize);
129577864267SCédric Le Goater }
129677864267SCédric Le Goater 
129777864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
129877864267SCédric Le Goater {
12994f9924c4SBenjamin Herrenschmidt     PnvChip *chip = PNV_CHIP(obj);
13002dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
13014f9924c4SBenjamin Herrenschmidt     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(obj);
13024f9924c4SBenjamin Herrenschmidt     int i;
13032dfa91a2SCédric Le Goater 
1304db873cc5SMarkus Armbruster     object_initialize_child(obj, "xive", &chip9->xive, TYPE_PNV_XIVE);
1305d1214b81SGreg Kurz     object_property_add_alias(obj, "xive-fabric", OBJECT(&chip9->xive),
1306d2623129SMarkus Armbruster                               "xive-fabric");
1307c38536bcSCédric Le Goater 
13089fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip9->psi, TYPE_PNV9_PSI);
130915376c66SCédric Le Goater 
13109fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip9->lpc, TYPE_PNV9_LPC);
13116598a70dSCédric Le Goater 
13129fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC);
13133887d241SBalamuruhan S 
13149fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER);
13154f9924c4SBenjamin Herrenschmidt 
13164f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13174f9924c4SBenjamin Herrenschmidt         object_initialize_child(obj, "pec[*]", &chip9->pecs[i],
13189fc7fc4dSMarkus Armbruster                                 TYPE_PNV_PHB4_PEC);
13194f9924c4SBenjamin Herrenschmidt     }
13204f9924c4SBenjamin Herrenschmidt 
13214f9924c4SBenjamin Herrenschmidt     /*
13224f9924c4SBenjamin Herrenschmidt      * Number of PHBs is the chip default
13234f9924c4SBenjamin Herrenschmidt      */
13244f9924c4SBenjamin Herrenschmidt     chip->num_phbs = pcc->num_phbs;
132577864267SCédric Le Goater }
132677864267SCédric Le Goater 
13275dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
13285dad902cSCédric Le Goater {
13295dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
13305dad902cSCédric Le Goater     int i;
13315dad902cSCédric Le Goater 
13325dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
13335dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
13345dad902cSCédric Le Goater 
13355dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
13365dad902cSCédric Le Goater         char eq_name[32];
13375dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
13384fa28f23SGreg Kurz         PnvCore *pnv_core = chip->cores[i * 4];
13395dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
13405dad902cSCédric Le Goater 
13415dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
13429fc7fc4dSMarkus Armbruster         object_initialize_child_with_props(OBJECT(chip), eq_name, eq,
13439fc7fc4dSMarkus Armbruster                                            sizeof(*eq), TYPE_PNV_QUAD,
13449fc7fc4dSMarkus Armbruster                                            &error_fatal, NULL);
13455dad902cSCédric Le Goater 
13465325cc34SMarkus Armbruster         object_property_set_int(OBJECT(eq), "id", core_id, &error_fatal);
1347ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(eq), NULL, &error_fatal);
13485dad902cSCédric Le Goater 
13495dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
13505dad902cSCédric Le Goater                                 &eq->xscom_regs);
13515dad902cSCédric Le Goater     }
13525dad902cSCédric Le Goater }
13535dad902cSCédric Le Goater 
13544f9924c4SBenjamin Herrenschmidt static void pnv_chip_power9_phb_realize(PnvChip *chip, Error **errp)
13554f9924c4SBenjamin Herrenschmidt {
13564f9924c4SBenjamin Herrenschmidt     Pnv9Chip *chip9 = PNV9_CHIP(chip);
13574f9924c4SBenjamin Herrenschmidt     int i, j;
13584f9924c4SBenjamin Herrenschmidt     int phb_id = 0;
13594f9924c4SBenjamin Herrenschmidt 
13604f9924c4SBenjamin Herrenschmidt     for (i = 0; i < PNV9_CHIP_MAX_PEC; i++) {
13614f9924c4SBenjamin Herrenschmidt         PnvPhb4PecState *pec = &chip9->pecs[i];
13624f9924c4SBenjamin Herrenschmidt         PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec);
13634f9924c4SBenjamin Herrenschmidt         uint32_t pec_nest_base;
13644f9924c4SBenjamin Herrenschmidt         uint32_t pec_pci_base;
13654f9924c4SBenjamin Herrenschmidt 
13665325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "index", i, &error_fatal);
13674f9924c4SBenjamin Herrenschmidt         /*
13684f9924c4SBenjamin Herrenschmidt          * PEC0 -> 1 stack
13694f9924c4SBenjamin Herrenschmidt          * PEC1 -> 2 stacks
13704f9924c4SBenjamin Herrenschmidt          * PEC2 -> 3 stacks
13714f9924c4SBenjamin Herrenschmidt          */
13725325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "num-stacks", i + 1,
13734f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
13745325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pec), "chip-id", chip->chip_id,
13754f9924c4SBenjamin Herrenschmidt                                 &error_fatal);
13765325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pec), "system-memory",
13775325cc34SMarkus Armbruster                                  OBJECT(get_system_memory()), &error_abort);
1378668f62ecSMarkus Armbruster         if (!qdev_realize(DEVICE(pec), NULL, errp)) {
13794f9924c4SBenjamin Herrenschmidt             return;
13804f9924c4SBenjamin Herrenschmidt         }
13814f9924c4SBenjamin Herrenschmidt 
13824f9924c4SBenjamin Herrenschmidt         pec_nest_base = pecc->xscom_nest_base(pec);
13834f9924c4SBenjamin Herrenschmidt         pec_pci_base = pecc->xscom_pci_base(pec);
13844f9924c4SBenjamin Herrenschmidt 
13854f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_nest_base, &pec->nest_regs_mr);
13864f9924c4SBenjamin Herrenschmidt         pnv_xscom_add_subregion(chip, pec_pci_base, &pec->pci_regs_mr);
13874f9924c4SBenjamin Herrenschmidt 
13884f9924c4SBenjamin Herrenschmidt         for (j = 0; j < pec->num_stacks && phb_id < chip->num_phbs;
13894f9924c4SBenjamin Herrenschmidt              j++, phb_id++) {
13904f9924c4SBenjamin Herrenschmidt             PnvPhb4PecStack *stack = &pec->stacks[j];
13914f9924c4SBenjamin Herrenschmidt             Object *obj = OBJECT(&stack->phb);
13924f9924c4SBenjamin Herrenschmidt 
13935325cc34SMarkus Armbruster             object_property_set_int(obj, "index", phb_id, &error_fatal);
13945325cc34SMarkus Armbruster             object_property_set_int(obj, "chip-id", chip->chip_id,
13954f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
13965325cc34SMarkus Armbruster             object_property_set_int(obj, "version", PNV_PHB4_VERSION,
13974f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
13985325cc34SMarkus Armbruster             object_property_set_int(obj, "device-id", PNV_PHB4_DEVICE_ID,
13994f9924c4SBenjamin Herrenschmidt                                     &error_fatal);
14005325cc34SMarkus Armbruster             object_property_set_link(obj, "stack", OBJECT(stack),
14015325cc34SMarkus Armbruster                                      &error_abort);
1402668f62ecSMarkus Armbruster             if (!sysbus_realize(SYS_BUS_DEVICE(obj), errp)) {
14034f9924c4SBenjamin Herrenschmidt                 return;
14044f9924c4SBenjamin Herrenschmidt             }
14054f9924c4SBenjamin Herrenschmidt 
14064f9924c4SBenjamin Herrenschmidt             /* Populate the XSCOM address space. */
14074f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14084f9924c4SBenjamin Herrenschmidt                                    pec_nest_base + 0x40 * (stack->stack_no + 1),
14094f9924c4SBenjamin Herrenschmidt                                    &stack->nest_regs_mr);
14104f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14114f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + 0x40 * (stack->stack_no + 1),
14124f9924c4SBenjamin Herrenschmidt                                     &stack->pci_regs_mr);
14134f9924c4SBenjamin Herrenschmidt             pnv_xscom_add_subregion(chip,
14144f9924c4SBenjamin Herrenschmidt                                     pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 +
14154f9924c4SBenjamin Herrenschmidt                                     0x40 * stack->stack_no,
14164f9924c4SBenjamin Herrenschmidt                                     &stack->phb_regs_mr);
14174f9924c4SBenjamin Herrenschmidt         }
14184f9924c4SBenjamin Herrenschmidt     }
14194f9924c4SBenjamin Herrenschmidt }
14204f9924c4SBenjamin Herrenschmidt 
142177864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
142277864267SCédric Le Goater {
142377864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
14242dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
14252dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1426c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
142777864267SCédric Le Goater     Error *local_err = NULL;
142877864267SCédric Le Goater 
1429709044fdSCédric Le Goater     /* XSCOM bridge is first */
1430709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1431709044fdSCédric Le Goater     if (local_err) {
1432709044fdSCédric Le Goater         error_propagate(errp, local_err);
1433709044fdSCédric Le Goater         return;
1434709044fdSCédric Le Goater     }
1435709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1436709044fdSCédric Le Goater 
143777864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
143877864267SCédric Le Goater     if (local_err) {
143977864267SCédric Le Goater         error_propagate(errp, local_err);
144077864267SCédric Le Goater         return;
144177864267SCédric Le Goater     }
14422dfa91a2SCédric Le Goater 
14435dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
14445dad902cSCédric Le Goater     if (local_err) {
14455dad902cSCédric Le Goater         error_propagate(errp, local_err);
14465dad902cSCédric Le Goater         return;
14475dad902cSCédric Le Goater     }
14485dad902cSCédric Le Goater 
14492dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
14505325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "ic-bar",
14515325cc34SMarkus Armbruster                             PNV9_XIVE_IC_BASE(chip), &error_fatal);
14525325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "vc-bar",
14535325cc34SMarkus Armbruster                             PNV9_XIVE_VC_BASE(chip), &error_fatal);
14545325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "pc-bar",
14555325cc34SMarkus Armbruster                             PNV9_XIVE_PC_BASE(chip), &error_fatal);
14565325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->xive), "tm-bar",
14575325cc34SMarkus Armbruster                             PNV9_XIVE_TM_BASE(chip), &error_fatal);
14585325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->xive), "chip", OBJECT(chip),
14597ae54cc3SGreg Kurz                              &error_abort);
1460668f62ecSMarkus Armbruster     if (!sysbus_realize(SYS_BUS_DEVICE(&chip9->xive), errp)) {
14612dfa91a2SCédric Le Goater         return;
14622dfa91a2SCédric Le Goater     }
14632dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
14642dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1465c38536bcSCédric Le Goater 
1466c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
14675325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip9->psi), "bar", PNV9_PSIHB_BASE(chip),
14685325cc34SMarkus Armbruster                             &error_fatal);
1469668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->psi), NULL, errp)) {
1470c38536bcSCédric Le Goater         return;
1471c38536bcSCédric Le Goater     }
1472c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1473c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
147415376c66SCédric Le Goater 
147515376c66SCédric Le Goater     /* LPC */
14765325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->lpc), "psi", OBJECT(&chip9->psi),
1477b63f3893SGreg Kurz                              &error_abort);
1478668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->lpc), NULL, errp)) {
147915376c66SCédric Le Goater         return;
148015376c66SCédric Le Goater     }
148115376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
148215376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
148315376c66SCédric Le Goater 
148415376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
148515376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
14866598a70dSCédric Le Goater 
14876598a70dSCédric Le Goater     /* Create the simplified OCC model */
14885325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->occ), "psi", OBJECT(&chip9->psi),
1489ee3d2713SGreg Kurz                              &error_abort);
1490668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->occ), NULL, errp)) {
14916598a70dSCédric Le Goater         return;
14926598a70dSCédric Le Goater     }
14936598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1494f3db8266SBalamuruhan S 
1495f3db8266SBalamuruhan S     /* OCC SRAM model */
14963a1b70b6SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip),
1497f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
14983887d241SBalamuruhan S 
14993887d241SBalamuruhan S     /* HOMER */
15005325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip),
1501f2582acfSGreg Kurz                              &error_abort);
1502668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip9->homer), NULL, errp)) {
15033887d241SBalamuruhan S         return;
15043887d241SBalamuruhan S     }
15058f092316SCédric Le Goater     /* Homer Xscom region */
15068f092316SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PBA_BASE, &chip9->homer.pba_regs);
15078f092316SCédric Le Goater 
15088f092316SCédric Le Goater     /* Homer mmio region */
15093887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
15103887d241SBalamuruhan S                                 &chip9->homer.regs);
15114f9924c4SBenjamin Herrenschmidt 
15124f9924c4SBenjamin Herrenschmidt     /* PHBs */
15134f9924c4SBenjamin Herrenschmidt     pnv_chip_power9_phb_realize(chip, &local_err);
15144f9924c4SBenjamin Herrenschmidt     if (local_err) {
15154f9924c4SBenjamin Herrenschmidt         error_propagate(errp, local_err);
15164f9924c4SBenjamin Herrenschmidt         return;
15174f9924c4SBenjamin Herrenschmidt     }
1518e997040eSCédric Le Goater }
1519e997040eSCédric Le Goater 
152070c059e9SGreg Kurz static uint32_t pnv_chip_power9_xscom_pcba(PnvChip *chip, uint64_t addr)
152170c059e9SGreg Kurz {
152270c059e9SGreg Kurz     addr &= (PNV9_XSCOM_SIZE - 1);
152370c059e9SGreg Kurz     return addr >> 3;
152470c059e9SGreg Kurz }
152570c059e9SGreg Kurz 
1526e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1527e997040eSCédric Le Goater {
1528e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1529e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1530e997040eSCédric Le Goater 
153183028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1532397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1533631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1534d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1535d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
15360990ce6aSGreg Kurz     k->intc_destroy = pnv_chip_power9_intc_destroy;
153785913070SGreg Kurz     k->intc_print_info = pnv_chip_power9_intc_print_info;
153804026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1539eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1540d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1541c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power9_xscom_core_base;
154270c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power9_xscom_pcba;
1543e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
15444f9924c4SBenjamin Herrenschmidt     k->num_phbs = 6;
154577864267SCédric Le Goater 
154677864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
154777864267SCédric Le Goater                                     &k->parent_realize);
1548e997040eSCédric Le Goater }
1549e997040eSCédric Le Goater 
15502b548a42SCédric Le Goater static void pnv_chip_power10_instance_init(Object *obj)
15512b548a42SCédric Le Goater {
15528b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(obj);
15538b50ce85SCédric Le Goater 
15549fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI);
15559fc7fc4dSMarkus Armbruster     object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC);
15562b548a42SCédric Le Goater }
15572b548a42SCédric Le Goater 
15582b548a42SCédric Le Goater static void pnv_chip_power10_realize(DeviceState *dev, Error **errp)
15592b548a42SCédric Le Goater {
15602b548a42SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
15612b548a42SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
15628b50ce85SCédric Le Goater     Pnv10Chip *chip10 = PNV10_CHIP(dev);
15632b548a42SCédric Le Goater     Error *local_err = NULL;
15642b548a42SCédric Le Goater 
15652b548a42SCédric Le Goater     /* XSCOM bridge is first */
15662b548a42SCédric Le Goater     pnv_xscom_realize(chip, PNV10_XSCOM_SIZE, &local_err);
15672b548a42SCédric Le Goater     if (local_err) {
15682b548a42SCédric Le Goater         error_propagate(errp, local_err);
15692b548a42SCédric Le Goater         return;
15702b548a42SCédric Le Goater     }
15712b548a42SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV10_XSCOM_BASE(chip));
15722b548a42SCédric Le Goater 
15732b548a42SCédric Le Goater     pcc->parent_realize(dev, &local_err);
15742b548a42SCédric Le Goater     if (local_err) {
15752b548a42SCédric Le Goater         error_propagate(errp, local_err);
15762b548a42SCédric Le Goater         return;
15772b548a42SCédric Le Goater     }
15788b50ce85SCédric Le Goater 
15798b50ce85SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
15805325cc34SMarkus Armbruster     object_property_set_int(OBJECT(&chip10->psi), "bar",
15815325cc34SMarkus Armbruster                             PNV10_PSIHB_BASE(chip), &error_fatal);
1582668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->psi), NULL, errp)) {
15838b50ce85SCédric Le Goater         return;
15848b50ce85SCédric Le Goater     }
15858b50ce85SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV10_XSCOM_PSIHB_BASE,
15868b50ce85SCédric Le Goater                             &PNV_PSI(&chip10->psi)->xscom_regs);
15872661f6abSCédric Le Goater 
15882661f6abSCédric Le Goater     /* LPC */
15895325cc34SMarkus Armbruster     object_property_set_link(OBJECT(&chip10->lpc), "psi",
15905325cc34SMarkus Armbruster                              OBJECT(&chip10->psi), &error_abort);
1591668f62ecSMarkus Armbruster     if (!qdev_realize(DEVICE(&chip10->lpc), NULL, errp)) {
15922661f6abSCédric Le Goater         return;
15932661f6abSCédric Le Goater     }
15942661f6abSCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV10_LPCM_BASE(chip),
15952661f6abSCédric Le Goater                                 &chip10->lpc.xscom_regs);
15962661f6abSCédric Le Goater 
15972661f6abSCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
15982661f6abSCédric Le Goater                                             (uint64_t) PNV10_LPCM_BASE(chip));
15992b548a42SCédric Le Goater }
16002b548a42SCédric Le Goater 
160170c059e9SGreg Kurz static uint32_t pnv_chip_power10_xscom_pcba(PnvChip *chip, uint64_t addr)
160270c059e9SGreg Kurz {
160370c059e9SGreg Kurz     addr &= (PNV10_XSCOM_SIZE - 1);
160470c059e9SGreg Kurz     return addr >> 3;
160570c059e9SGreg Kurz }
160670c059e9SGreg Kurz 
16072b548a42SCédric Le Goater static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
16082b548a42SCédric Le Goater {
16092b548a42SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
16102b548a42SCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
16112b548a42SCédric Le Goater 
16122b548a42SCédric Le Goater     k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
16132b548a42SCédric Le Goater     k->cores_mask = POWER10_CORE_MASK;
16142b548a42SCédric Le Goater     k->core_pir = pnv_chip_core_pir_p10;
16152b548a42SCédric Le Goater     k->intc_create = pnv_chip_power10_intc_create;
16162b548a42SCédric Le Goater     k->intc_reset = pnv_chip_power10_intc_reset;
16172b548a42SCédric Le Goater     k->intc_destroy = pnv_chip_power10_intc_destroy;
161885913070SGreg Kurz     k->intc_print_info = pnv_chip_power10_intc_print_info;
16192b548a42SCédric Le Goater     k->isa_create = pnv_chip_power10_isa_create;
16202b548a42SCédric Le Goater     k->dt_populate = pnv_chip_power10_dt_populate;
16212b548a42SCédric Le Goater     k->pic_print_info = pnv_chip_power10_pic_print_info;
1622c4b2c40cSGreg Kurz     k->xscom_core_base = pnv_chip_power10_xscom_core_base;
162370c059e9SGreg Kurz     k->xscom_pcba = pnv_chip_power10_xscom_pcba;
16242b548a42SCédric Le Goater     dc->desc = "PowerNV Chip POWER10";
16252b548a42SCédric Le Goater 
16262b548a42SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power10_realize,
16272b548a42SCédric Le Goater                                     &k->parent_realize);
16282b548a42SCédric Le Goater }
16292b548a42SCédric Le Goater 
1630397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1631397a79e7SCédric Le Goater {
1632397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1633397a79e7SCédric Le Goater     int cores_max;
1634397a79e7SCédric Le Goater 
1635397a79e7SCédric Le Goater     /*
1636397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1637397a79e7SCédric Le Goater      * the chip class
1638397a79e7SCédric Le Goater      */
1639397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1640397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1641397a79e7SCédric Le Goater     }
1642397a79e7SCédric Le Goater 
1643397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1644397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1645397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1646397a79e7SCédric Le Goater                    chip->cores_mask);
1647397a79e7SCédric Le Goater         return;
1648397a79e7SCédric Le Goater     }
1649397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1650397a79e7SCédric Le Goater 
1651397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
165227d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1653397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1654397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1655397a79e7SCédric Le Goater                    cores_max);
1656397a79e7SCédric Le Goater         return;
1657397a79e7SCédric Le Goater     }
1658397a79e7SCédric Le Goater }
1659397a79e7SCédric Le Goater 
166051c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1661e997040eSCédric Le Goater {
1662397a79e7SCédric Le Goater     Error *error = NULL;
1663d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
166440abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1665d2fd9612SCédric Le Goater     int i, core_hwid;
166608c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
1667397a79e7SCédric Le Goater 
1668d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1669d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1670d2fd9612SCédric Le Goater         return;
1671d2fd9612SCédric Le Goater     }
1672d2fd9612SCédric Le Goater 
1673d2fd9612SCédric Le Goater     /* Cores */
1674397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1675397a79e7SCédric Le Goater     if (error) {
1676397a79e7SCédric Le Goater         error_propagate(errp, error);
1677397a79e7SCédric Le Goater         return;
1678397a79e7SCédric Le Goater     }
1679d2fd9612SCédric Le Goater 
16804fa28f23SGreg Kurz     chip->cores = g_new0(PnvCore *, chip->nr_cores);
1681d2fd9612SCédric Le Goater 
1682d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1683d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1684d2fd9612SCédric Le Goater         char core_name[32];
16854fa28f23SGreg Kurz         PnvCore *pnv_core;
1686c035851aSCédric Le Goater         uint64_t xscom_core_base;
1687d2fd9612SCédric Le Goater 
1688d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1689d2fd9612SCédric Le Goater             continue;
1690d2fd9612SCédric Le Goater         }
1691d2fd9612SCédric Le Goater 
16924fa28f23SGreg Kurz         pnv_core = PNV_CORE(object_new(typename));
16934fa28f23SGreg Kurz 
1694d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1695d2623129SMarkus Armbruster         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core));
16964fa28f23SGreg Kurz         chip->cores[i] = pnv_core;
16975325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "nr-threads",
16985325cc34SMarkus Armbruster                                 chip->nr_threads, &error_fatal);
16995325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
17005325cc34SMarkus Armbruster                                 core_hwid, &error_fatal);
17015325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "pir",
17025325cc34SMarkus Armbruster                                 pcc->core_pir(chip, core_hwid), &error_fatal);
17035325cc34SMarkus Armbruster         object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
17045325cc34SMarkus Armbruster                                 &error_fatal);
17055325cc34SMarkus Armbruster         object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),
1706158e17a6SGreg Kurz                                  &error_abort);
1707ce189ab2SMarkus Armbruster         qdev_realize(DEVICE(pnv_core), NULL, &error_fatal);
170824ece072SCédric Le Goater 
170924ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1710c4b2c40cSGreg Kurz         xscom_core_base = pcc->xscom_core_base(chip, core_hwid);
1711c035851aSCédric Le Goater 
1712c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
17134fa28f23SGreg Kurz                                 &pnv_core->xscom_regs);
1714d2fd9612SCédric Le Goater         i++;
1715d2fd9612SCédric Le Goater     }
171651c04728SCédric Le Goater }
171751c04728SCédric Le Goater 
171851c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
171951c04728SCédric Le Goater {
172051c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
172151c04728SCédric Le Goater     Error *error = NULL;
172251c04728SCédric Le Goater 
172351c04728SCédric Le Goater     /* Cores */
172451c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
172551c04728SCédric Le Goater     if (error) {
172651c04728SCédric Le Goater         error_propagate(errp, error);
172751c04728SCédric Le Goater         return;
172851c04728SCédric Le Goater     }
1729e997040eSCédric Le Goater }
1730e997040eSCédric Le Goater 
1731e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1732e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1733e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1734e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1735397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1736397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1737764f9b25SGreg Kurz     DEFINE_PROP_UINT32("nr-threads", PnvChip, nr_threads, 1),
17384f9924c4SBenjamin Herrenschmidt     DEFINE_PROP_UINT32("num-phbs", PnvChip, num_phbs, 0),
1739e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1740e997040eSCédric Le Goater };
1741e997040eSCédric Le Goater 
1742e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1743e997040eSCédric Le Goater {
1744e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1745e997040eSCédric Le Goater 
17469d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1747e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
17484f67d30bSMarc-André Lureau     device_class_set_props(dc, pnv_chip_properties);
1749e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1750e997040eSCédric Le Goater }
1751e997040eSCédric Le Goater 
1752119eaa9dSCédric Le Goater PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir)
1753119eaa9dSCédric Le Goater {
1754119eaa9dSCédric Le Goater     int i, j;
1755119eaa9dSCédric Le Goater 
1756119eaa9dSCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
1757119eaa9dSCédric Le Goater         PnvCore *pc = chip->cores[i];
1758119eaa9dSCédric Le Goater         CPUCore *cc = CPU_CORE(pc);
1759119eaa9dSCédric Le Goater 
1760119eaa9dSCédric Le Goater         for (j = 0; j < cc->nr_threads; j++) {
1761119eaa9dSCédric Le Goater             if (ppc_cpu_pir(pc->threads[j]) == pir) {
1762119eaa9dSCédric Le Goater                 return pc->threads[j];
1763119eaa9dSCédric Le Goater             }
1764119eaa9dSCédric Le Goater         }
1765119eaa9dSCédric Le Goater     }
1766119eaa9dSCédric Le Goater     return NULL;
1767119eaa9dSCédric Le Goater }
1768119eaa9dSCédric Le Goater 
176954f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
177054f59d78SCédric Le Goater {
1771b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
17729ae1329eSCédric Le Goater     int i, j;
177354f59d78SCédric Le Goater 
177454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
17759ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
177677864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
177777864267SCédric Le Goater 
177877864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
177977864267SCédric Le Goater             return &chip8->psi.ics;
178054f59d78SCédric Le Goater         }
17819ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
17829ae1329eSCédric Le Goater             if (ics_valid_irq(&chip8->phbs[j].lsis, irq)) {
17839ae1329eSCédric Le Goater                 return &chip8->phbs[j].lsis;
17849ae1329eSCédric Le Goater             }
17859ae1329eSCédric Le Goater             if (ics_valid_irq(ICS(&chip8->phbs[j].msis), irq)) {
17869ae1329eSCédric Le Goater                 return ICS(&chip8->phbs[j].msis);
17879ae1329eSCédric Le Goater             }
17889ae1329eSCédric Le Goater         }
178954f59d78SCédric Le Goater     }
179054f59d78SCédric Le Goater     return NULL;
179154f59d78SCédric Le Goater }
179254f59d78SCédric Le Goater 
179354f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
179454f59d78SCédric Le Goater {
1795b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
17969ae1329eSCédric Le Goater     int i, j;
179754f59d78SCédric Le Goater 
179854f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
17999ae1329eSCédric Le Goater         PnvChip *chip = pnv->chips[i];
180077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
18019ae1329eSCédric Le Goater 
180277864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
18039ae1329eSCédric Le Goater         for (j = 0; j < chip->num_phbs; j++) {
18049ae1329eSCédric Le Goater             ics_resend(&chip8->phbs[j].lsis);
18059ae1329eSCédric Le Goater             ics_resend(ICS(&chip8->phbs[j].msis));
18069ae1329eSCédric Le Goater         }
180754f59d78SCédric Le Goater     }
180854f59d78SCédric Le Goater }
180954f59d78SCédric Le Goater 
181036fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
181136fc6f08SCédric Le Goater {
181236fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
181336fc6f08SCédric Le Goater 
1814956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
181536fc6f08SCédric Le Goater }
181636fc6f08SCédric Le Goater 
181747fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
181847fea43aSCédric Le Goater                                Monitor *mon)
181947fea43aSCédric Le Goater {
1820b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
182154f59d78SCédric Le Goater     int i;
182247fea43aSCédric Le Goater     CPUState *cs;
182347fea43aSCédric Le Goater 
182447fea43aSCédric Le Goater     CPU_FOREACH(cs) {
182547fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
182647fea43aSCédric Le Goater 
182785913070SGreg Kurz         /* XXX: loop on each chip/core/thread instead of CPU_FOREACH() */
182885913070SGreg Kurz         PNV_CHIP_GET_CLASS(pnv->chips[0])->intc_print_info(pnv->chips[0], cpu,
182985913070SGreg Kurz                                                            mon);
1830d8e4aad5SCédric Le Goater     }
183154f59d78SCédric Le Goater 
183254f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1833d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
183454f59d78SCédric Le Goater     }
183547fea43aSCédric Le Goater }
183647fea43aSCédric Le Goater 
1837c722579eSCédric Le Goater static int pnv_match_nvt(XiveFabric *xfb, uint8_t format,
1838c722579eSCédric Le Goater                          uint8_t nvt_blk, uint32_t nvt_idx,
1839c722579eSCédric Le Goater                          bool cam_ignore, uint8_t priority,
1840c722579eSCédric Le Goater                          uint32_t logic_serv,
1841c722579eSCédric Le Goater                          XiveTCTXMatch *match)
1842c722579eSCédric Le Goater {
1843c722579eSCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xfb);
1844c722579eSCédric Le Goater     int total_count = 0;
1845c722579eSCédric Le Goater     int i;
1846c722579eSCédric Le Goater 
1847c722579eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1848c722579eSCédric Le Goater         Pnv9Chip *chip9 = PNV9_CHIP(pnv->chips[i]);
1849c722579eSCédric Le Goater         XivePresenter *xptr = XIVE_PRESENTER(&chip9->xive);
1850c722579eSCédric Le Goater         XivePresenterClass *xpc = XIVE_PRESENTER_GET_CLASS(xptr);
1851c722579eSCédric Le Goater         int count;
1852c722579eSCédric Le Goater 
1853c722579eSCédric Le Goater         count = xpc->match_nvt(xptr, format, nvt_blk, nvt_idx, cam_ignore,
1854c722579eSCédric Le Goater                                priority, logic_serv, match);
1855c722579eSCédric Le Goater 
1856c722579eSCédric Le Goater         if (count < 0) {
1857c722579eSCédric Le Goater             return count;
1858c722579eSCédric Le Goater         }
1859c722579eSCédric Le Goater 
1860c722579eSCédric Le Goater         total_count += count;
1861c722579eSCédric Le Goater     }
1862c722579eSCédric Le Goater 
1863c722579eSCédric Le Goater     return total_count;
1864c722579eSCédric Le Goater }
1865c722579eSCédric Le Goater 
1866f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
18679e933f4aSBenjamin Herrenschmidt {
18689e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
186936fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1870d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1871d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
1872f30c843cSCédric Le Goater 
1873f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1874f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1875f30c843cSCédric Le Goater 
1876f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1877f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1878f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1879d76f2da7SGreg Kurz 
1880d76f2da7SGreg Kurz     pmc->compat = compat;
1881d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
1882f30c843cSCédric Le Goater }
1883f30c843cSCédric Le Goater 
1884f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1885f30c843cSCédric Le Goater {
1886f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1887c722579eSCédric Le Goater     XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc);
1888d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1889d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv9\0ibm,powernv";
1890f30c843cSCédric Le Goater 
1891f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1892f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1893c722579eSCédric Le Goater     xfc->match_nvt = pnv_match_nvt;
1894f30c843cSCédric Le Goater 
1895f30c843cSCédric Le Goater     mc->alias = "powernv";
1896d76f2da7SGreg Kurz 
1897d76f2da7SGreg Kurz     pmc->compat = compat;
1898d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
18997a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
1900f30c843cSCédric Le Goater }
1901f30c843cSCédric Le Goater 
19022b548a42SCédric Le Goater static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
19032b548a42SCédric Le Goater {
19042b548a42SCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1905d76f2da7SGreg Kurz     PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc);
1906d76f2da7SGreg Kurz     static const char compat[] = "qemu,powernv10\0ibm,powernv";
19072b548a42SCédric Le Goater 
19082b548a42SCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
19092b548a42SCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
1910d76f2da7SGreg Kurz 
1911d76f2da7SGreg Kurz     pmc->compat = compat;
1912d76f2da7SGreg Kurz     pmc->compat_size = sizeof(compat);
19137a90c6a1SGreg Kurz     pmc->dt_power_mgt = pnv_dt_power_mgt;
19142b548a42SCédric Le Goater }
19152b548a42SCédric Le Goater 
191608c3f3a7SCédric Le Goater static bool pnv_machine_get_hb(Object *obj, Error **errp)
191708c3f3a7SCédric Le Goater {
191808c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
191908c3f3a7SCédric Le Goater 
192008c3f3a7SCédric Le Goater     return !!pnv->fw_load_addr;
192108c3f3a7SCédric Le Goater }
192208c3f3a7SCédric Le Goater 
192308c3f3a7SCédric Le Goater static void pnv_machine_set_hb(Object *obj, bool value, Error **errp)
192408c3f3a7SCédric Le Goater {
192508c3f3a7SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
192608c3f3a7SCédric Le Goater 
192708c3f3a7SCédric Le Goater     if (value) {
192808c3f3a7SCédric Le Goater         pnv->fw_load_addr = 0x8000000;
192908c3f3a7SCédric Le Goater     }
193008c3f3a7SCédric Le Goater }
193108c3f3a7SCédric Le Goater 
193201b552b0SNicholas Piggin static void pnv_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
193301b552b0SNicholas Piggin {
193401b552b0SNicholas Piggin     PowerPCCPU *cpu = POWERPC_CPU(cs);
193501b552b0SNicholas Piggin     CPUPPCState *env = &cpu->env;
193601b552b0SNicholas Piggin 
193701b552b0SNicholas Piggin     cpu_synchronize_state(cs);
193801b552b0SNicholas Piggin     ppc_cpu_do_system_reset(cs);
19390911a60cSLeonardo Bras     if (env->spr[SPR_SRR1] & SRR1_WAKESTATE) {
194001b552b0SNicholas Piggin         /*
1941fe837714SNicholas Piggin          * Power-save wakeups, as indicated by non-zero SRR1[46:47] put the
1942fe837714SNicholas Piggin          * wakeup reason in SRR1[42:45], system reset is indicated with 0b0100
1943fe837714SNicholas Piggin          * (PPC_BIT(43)).
194401b552b0SNicholas Piggin          */
19450911a60cSLeonardo Bras         if (!(env->spr[SPR_SRR1] & SRR1_WAKERESET)) {
1946fe837714SNicholas Piggin             warn_report("ppc_cpu_do_system_reset does not set system reset wakeup reason");
19470911a60cSLeonardo Bras             env->spr[SPR_SRR1] |= SRR1_WAKERESET;
194801b552b0SNicholas Piggin         }
1949fe837714SNicholas Piggin     } else {
1950fe837714SNicholas Piggin         /*
1951fe837714SNicholas Piggin          * For non-powersave system resets, SRR1[42:45] are defined to be
1952fe837714SNicholas Piggin          * implementation-dependent. The POWER9 User Manual specifies that
1953fe837714SNicholas Piggin          * an external (SCOM driven, which may come from a BMC nmi command or
1954fe837714SNicholas Piggin          * another CPU requesting a NMI IPI) system reset exception should be
1955fe837714SNicholas Piggin          * 0b0010 (PPC_BIT(44)).
1956fe837714SNicholas Piggin          */
19570911a60cSLeonardo Bras         env->spr[SPR_SRR1] |= SRR1_WAKESCOM;
1958fe837714SNicholas Piggin     }
1959fe837714SNicholas Piggin }
196001b552b0SNicholas Piggin 
196101b552b0SNicholas Piggin static void pnv_nmi(NMIState *n, int cpu_index, Error **errp)
196201b552b0SNicholas Piggin {
196301b552b0SNicholas Piggin     CPUState *cs;
196401b552b0SNicholas Piggin 
196501b552b0SNicholas Piggin     CPU_FOREACH(cs) {
196601b552b0SNicholas Piggin         async_run_on_cpu(cs, pnv_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
196701b552b0SNicholas Piggin     }
196801b552b0SNicholas Piggin }
196901b552b0SNicholas Piggin 
1970f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1971f30c843cSCédric Le Goater {
1972f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
197347fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
197401b552b0SNicholas Piggin     NMIClass *nc = NMI_CLASS(oc);
19759e933f4aSBenjamin Herrenschmidt 
19769e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1977b168a138SCédric Le Goater     mc->init = pnv_init;
1978b168a138SCédric Le Goater     mc->reset = pnv_reset;
19799e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
198059b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
198159b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
19829e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
19839e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1984f1d18b0aSJoel Stanley     /*
1985f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1986f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1987f1d18b0aSJoel Stanley      */
1988f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
1989173a36d8SIgor Mammedov     mc->default_ram_id = "pnv.ram";
199047fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
199101b552b0SNicholas Piggin     nc->nmi_monitor_handler = pnv_nmi;
199208c3f3a7SCédric Le Goater 
199308c3f3a7SCédric Le Goater     object_class_property_add_bool(oc, "hb-mode",
1994d2623129SMarkus Armbruster                                    pnv_machine_get_hb, pnv_machine_set_hb);
199508c3f3a7SCédric Le Goater     object_class_property_set_description(oc, "hb-mode",
19967eecec7dSMarkus Armbruster                               "Use a hostboot like boot loader");
19979e933f4aSBenjamin Herrenschmidt }
19989e933f4aSBenjamin Herrenschmidt 
199977864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
2000beba5c0fSIgor Mammedov     {                                             \
2001beba5c0fSIgor Mammedov         .name          = type,                    \
2002beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
200377864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
200477864267SCédric Le Goater     }
200577864267SCédric Le Goater 
200677864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
200777864267SCédric Le Goater     {                                             \
200877864267SCédric Le Goater         .name          = type,                    \
200977864267SCédric Le Goater         .class_init    = class_initfn,            \
201077864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
2011beba5c0fSIgor Mammedov     }
2012beba5c0fSIgor Mammedov 
20132b548a42SCédric Le Goater #define DEFINE_PNV10_CHIP_TYPE(type, class_initfn) \
20142b548a42SCédric Le Goater     {                                              \
20152b548a42SCédric Le Goater         .name          = type,                     \
20162b548a42SCédric Le Goater         .class_init    = class_initfn,             \
20172b548a42SCédric Le Goater         .parent        = TYPE_PNV10_CHIP,          \
20182b548a42SCédric Le Goater     }
20192b548a42SCédric Le Goater 
2020beba5c0fSIgor Mammedov static const TypeInfo types[] = {
20211aba8716SCédric Le Goater     {
20222b548a42SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv10"),
20232b548a42SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20242b548a42SCédric Le Goater         .class_init    = pnv_machine_power10_class_init,
20252b548a42SCédric Le Goater     },
20262b548a42SCédric Le Goater     {
20271aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
20281aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20291aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
2030c722579eSCédric Le Goater         .interfaces = (InterfaceInfo[]) {
2031c722579eSCédric Le Goater             { TYPE_XIVE_FABRIC },
2032c722579eSCédric Le Goater             { },
2033c722579eSCédric Le Goater         },
20341aba8716SCédric Le Goater     },
20351aba8716SCédric Le Goater     {
20361aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
20371aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
20381aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
20391aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
20401aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
20411aba8716SCédric Le Goater             { },
20421aba8716SCédric Le Goater         },
20431aba8716SCédric Le Goater     },
2044beba5c0fSIgor Mammedov     {
2045b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
20469e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
2047f30c843cSCédric Le Goater         .abstract       = true,
20489e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
2049b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
2050d76f2da7SGreg Kurz         .class_size    = sizeof(PnvMachineClass),
205136fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
205247fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
205301b552b0SNicholas Piggin             { TYPE_NMI },
205436fc6f08SCédric Le Goater             { },
205536fc6f08SCédric Le Goater         },
2056beba5c0fSIgor Mammedov     },
2057beba5c0fSIgor Mammedov     {
2058beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
2059beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
2060beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
2061beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
2062beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
2063beba5c0fSIgor Mammedov         .abstract      = true,
2064beba5c0fSIgor Mammedov     },
206577864267SCédric Le Goater 
206677864267SCédric Le Goater     /*
20672b548a42SCédric Le Goater      * P10 chip and variants
20682b548a42SCédric Le Goater      */
20692b548a42SCédric Le Goater     {
20702b548a42SCédric Le Goater         .name          = TYPE_PNV10_CHIP,
20712b548a42SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
20722b548a42SCédric Le Goater         .instance_init = pnv_chip_power10_instance_init,
20732b548a42SCédric Le Goater         .instance_size = sizeof(Pnv10Chip),
20742b548a42SCédric Le Goater     },
20752b548a42SCédric Le Goater     DEFINE_PNV10_CHIP_TYPE(TYPE_PNV_CHIP_POWER10, pnv_chip_power10_class_init),
20762b548a42SCédric Le Goater 
20772b548a42SCédric Le Goater     /*
207877864267SCédric Le Goater      * P9 chip and variants
207977864267SCédric Le Goater      */
208077864267SCédric Le Goater     {
208177864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
208277864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
208377864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
208477864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
208577864267SCédric Le Goater     },
208677864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
208777864267SCédric Le Goater 
208877864267SCédric Le Goater     /*
208977864267SCédric Le Goater      * P8 chip and variants
209077864267SCédric Le Goater      */
209177864267SCédric Le Goater     {
209277864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
209377864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
209477864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
209577864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
209677864267SCédric Le Goater     },
209777864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
209877864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
209977864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
2100beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
21019e933f4aSBenjamin Herrenschmidt };
21029e933f4aSBenjamin Herrenschmidt 
2103beba5c0fSIgor Mammedov DEFINE_TYPES(types)
2104