xref: /qemu/hw/ppc/pnv.c (revision bcdb9064)
19e933f4aSBenjamin Herrenschmidt /*
29e933f4aSBenjamin Herrenschmidt  * QEMU PowerPC PowerNV machine model
39e933f4aSBenjamin Herrenschmidt  *
49e933f4aSBenjamin Herrenschmidt  * Copyright (c) 2016, IBM Corporation.
59e933f4aSBenjamin Herrenschmidt  *
69e933f4aSBenjamin Herrenschmidt  * This library is free software; you can redistribute it and/or
79e933f4aSBenjamin Herrenschmidt  * modify it under the terms of the GNU Lesser General Public
89e933f4aSBenjamin Herrenschmidt  * License as published by the Free Software Foundation; either
99e933f4aSBenjamin Herrenschmidt  * version 2 of the License, or (at your option) any later version.
109e933f4aSBenjamin Herrenschmidt  *
119e933f4aSBenjamin Herrenschmidt  * This library is distributed in the hope that it will be useful,
129e933f4aSBenjamin Herrenschmidt  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139e933f4aSBenjamin Herrenschmidt  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
149e933f4aSBenjamin Herrenschmidt  * Lesser General Public License for more details.
159e933f4aSBenjamin Herrenschmidt  *
169e933f4aSBenjamin Herrenschmidt  * You should have received a copy of the GNU Lesser General Public
179e933f4aSBenjamin Herrenschmidt  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
189e933f4aSBenjamin Herrenschmidt  */
199e933f4aSBenjamin Herrenschmidt 
209e933f4aSBenjamin Herrenschmidt #include "qemu/osdep.h"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22fc6b3cf9SPhilippe Mathieu-Daudé #include "qemu/units.h"
239e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
249e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
259e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
2671e8a915SMarkus Armbruster #include "sysemu/reset.h"
2754d31236SMarkus Armbruster #include "sysemu/runstate.h"
28d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
298d409261SCédric Le Goater #include "sysemu/device_tree.h"
30fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
319e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
329e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
339e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
349e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
35d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
369e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
379e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
38e997040eSCédric Le Goater #include "qapi/visitor.h"
3947fea43aSCédric Le Goater #include "monitor/monitor.h"
4047fea43aSCédric Le Goater #include "hw/intc/intc.h"
41aeaef83dSCédric Le Goater #include "hw/ipmi/ipmi.h"
4258969eeeSDavid Gibson #include "target/ppc/mmu-hash64.h"
439e933f4aSBenjamin Herrenschmidt 
4436fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
45a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
46967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
47967b7523SCédric Le Goater 
483495b6b6SCédric Le Goater #include "hw/isa/isa.h"
4912e9493dSMarkus Armbruster #include "hw/boards.h"
503495b6b6SCédric Le Goater #include "hw/char/serial.h"
51*bcdb9064SPhilippe Mathieu-Daudé #include "hw/rtc/mc146818rtc.h"
523495b6b6SCédric Le Goater 
539e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
549e933f4aSBenjamin Herrenschmidt 
55b268a616SMurilo Opsfelder Araujo #define FDT_MAX_SIZE            (1 * MiB)
569e933f4aSBenjamin Herrenschmidt 
579e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
589e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
59b268a616SMurilo Opsfelder Araujo #define FW_MAX_SIZE             (4 * MiB)
609e933f4aSBenjamin Herrenschmidt 
619e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
62b45b56baSMurilo Opsfelder Araujo #define KERNEL_MAX_SIZE         (256 * MiB)
63fef592f9SCédric Le Goater #define INITRD_LOAD_ADDR        0x60000000
64584ea7e7SMurilo Opsfelder Araujo #define INITRD_MAX_SIZE         (256 * MiB)
659e933f4aSBenjamin Herrenschmidt 
6640abf43fSIgor Mammedov static const char *pnv_chip_core_typename(const PnvChip *o)
6740abf43fSIgor Mammedov {
6840abf43fSIgor Mammedov     const char *chip_type = object_class_get_name(object_get_class(OBJECT(o)));
6940abf43fSIgor Mammedov     int len = strlen(chip_type) - strlen(PNV_CHIP_TYPE_SUFFIX);
7040abf43fSIgor Mammedov     char *s = g_strdup_printf(PNV_CORE_TYPE_NAME("%.*s"), len, chip_type);
7140abf43fSIgor Mammedov     const char *core_type = object_class_get_name(object_class_by_name(s));
7240abf43fSIgor Mammedov     g_free(s);
7340abf43fSIgor Mammedov     return core_type;
7440abf43fSIgor Mammedov }
7540abf43fSIgor Mammedov 
769e933f4aSBenjamin Herrenschmidt /*
779e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
789e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
799e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
809e933f4aSBenjamin Herrenschmidt  */
819e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
829e933f4aSBenjamin Herrenschmidt 
839e933f4aSBenjamin Herrenschmidt /*
849e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
859e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
869e933f4aSBenjamin Herrenschmidt  * per chip.
879e933f4aSBenjamin Herrenschmidt  */
88b168a138SCédric Le Goater static void pnv_dt_memory(void *fdt, int chip_id, hwaddr start, hwaddr size)
899e933f4aSBenjamin Herrenschmidt {
909e933f4aSBenjamin Herrenschmidt     char *mem_name;
919e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
929e933f4aSBenjamin Herrenschmidt     int off;
939e933f4aSBenjamin Herrenschmidt 
949e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
959e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
969e933f4aSBenjamin Herrenschmidt 
979e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
989e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
999e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
1009e933f4aSBenjamin Herrenschmidt 
1019e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
1029e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
1039e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
1049e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
1059e933f4aSBenjamin Herrenschmidt }
1069e933f4aSBenjamin Herrenschmidt 
107d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
108d2fd9612SCédric Le Goater {
109d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
110d2fd9612SCédric Le Goater 
111d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
112a4f3885cSGreg Kurz         cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
113d2fd9612SCédric Le Goater         if (cpus_offset) {
114d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
115d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
116d2fd9612SCédric Le Goater         }
117d2fd9612SCédric Le Goater     }
118d2fd9612SCédric Le Goater     _FDT(cpus_offset);
119d2fd9612SCédric Le Goater     return cpus_offset;
120d2fd9612SCédric Le Goater }
121d2fd9612SCédric Le Goater 
122d2fd9612SCédric Le Goater /*
123d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
124d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
125d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
126d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
127d2fd9612SCédric Le Goater  * servers.
128d2fd9612SCédric Le Goater  */
129b168a138SCédric Le Goater static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
130d2fd9612SCédric Le Goater {
13108304a86SDavid Gibson     PowerPCCPU *cpu = pc->threads[0];
13208304a86SDavid Gibson     CPUState *cs = CPU(cpu);
133d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
1348bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
135d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
136d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
137d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
138d2fd9612SCédric Le Goater     int i;
139d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
140d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
141d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
142d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
143d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
144d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
145d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
146d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
147d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
148d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
149d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
150d2fd9612SCédric Le Goater     int offset;
151d2fd9612SCédric Le Goater     char *nodename;
152d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
153d2fd9612SCédric Le Goater 
154d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
155d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
156d2fd9612SCédric Le Goater     _FDT(offset);
157d2fd9612SCédric Le Goater     g_free(nodename);
158d2fd9612SCédric Le Goater 
159d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
160d2fd9612SCédric Le Goater 
161d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
162d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
163d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
164d2fd9612SCédric Le Goater 
165d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
166d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
167d2fd9612SCédric Le Goater                             env->dcache_line_size)));
168d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
169d2fd9612SCédric Le Goater                             env->dcache_line_size)));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
171d2fd9612SCédric Le Goater                             env->icache_line_size)));
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
173d2fd9612SCédric Le Goater                             env->icache_line_size)));
174d2fd9612SCédric Le Goater 
175d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
176d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
177d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
178d2fd9612SCédric Le Goater     } else {
1793dc6f869SAlistair Francis         warn_report("Unknown L1 dcache size for cpu");
180d2fd9612SCédric Le Goater     }
181d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
182d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
183d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
184d2fd9612SCédric Le Goater     } else {
1853dc6f869SAlistair Francis         warn_report("Unknown L1 icache size for cpu");
186d2fd9612SCédric Le Goater     }
187d2fd9612SCédric Le Goater 
188d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
189d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
19059b7c1c2SBalamuruhan S     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size",
19159b7c1c2SBalamuruhan S                            cpu->hash64_opts->slb_size)));
192d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
193d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
194d2fd9612SCédric Le Goater 
195d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
196d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
197d2fd9612SCédric Le Goater     }
198d2fd9612SCédric Le Goater 
19958969eeeSDavid Gibson     if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
200d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
201d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
202d2fd9612SCédric Le Goater     }
203d2fd9612SCédric Le Goater 
20459b7c1c2SBalamuruhan S     /*
20559b7c1c2SBalamuruhan S      * Advertise VMX/VSX (vector extensions) if available
206d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
207d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
20859b7c1c2SBalamuruhan S      *   2               == VSX available
20959b7c1c2SBalamuruhan S      */
210d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
211d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
212d2fd9612SCédric Le Goater 
213d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
214d2fd9612SCédric Le Goater     }
215d2fd9612SCédric Le Goater 
21659b7c1c2SBalamuruhan S     /*
21759b7c1c2SBalamuruhan S      * Advertise DFP (Decimal Floating Point) if available
218d2fd9612SCédric Le Goater      *   0 / no property == no DFP
21959b7c1c2SBalamuruhan S      *   1               == DFP available
22059b7c1c2SBalamuruhan S      */
221d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
222d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
223d2fd9612SCédric Le Goater     }
224d2fd9612SCédric Le Goater 
225644a2c99SDavid Gibson     page_sizes_prop_size = ppc_create_page_sizes_prop(cpu, page_sizes_prop,
226d2fd9612SCédric Le Goater                                                       sizeof(page_sizes_prop));
227d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
228d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
229d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
230d2fd9612SCédric Le Goater     }
231d2fd9612SCédric Le Goater 
232d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
233d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
234d2fd9612SCédric Le Goater 
235d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
236d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
237d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
238d2fd9612SCédric Le Goater     }
239d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
240d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
241d2fd9612SCédric Le Goater }
242d2fd9612SCédric Le Goater 
243b168a138SCédric Le Goater static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
244bf5615e7SCédric Le Goater                        uint32_t nr_threads)
245bf5615e7SCédric Le Goater {
246bf5615e7SCédric Le Goater     uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
247bf5615e7SCédric Le Goater     char *name;
248bf5615e7SCédric Le Goater     const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
249bf5615e7SCédric Le Goater     uint32_t irange[2], i, rsize;
250bf5615e7SCédric Le Goater     uint64_t *reg;
251bf5615e7SCédric Le Goater     int offset;
252bf5615e7SCédric Le Goater 
253bf5615e7SCédric Le Goater     irange[0] = cpu_to_be32(pir);
254bf5615e7SCédric Le Goater     irange[1] = cpu_to_be32(nr_threads);
255bf5615e7SCédric Le Goater 
256bf5615e7SCédric Le Goater     rsize = sizeof(uint64_t) * 2 * nr_threads;
257bf5615e7SCédric Le Goater     reg = g_malloc(rsize);
258bf5615e7SCédric Le Goater     for (i = 0; i < nr_threads; i++) {
259bf5615e7SCédric Le Goater         reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
260bf5615e7SCédric Le Goater         reg[i * 2 + 1] = cpu_to_be64(0x1000);
261bf5615e7SCédric Le Goater     }
262bf5615e7SCédric Le Goater 
263bf5615e7SCédric Le Goater     name = g_strdup_printf("interrupt-controller@%"PRIX64, addr);
264bf5615e7SCédric Le Goater     offset = fdt_add_subnode(fdt, 0, name);
265bf5615e7SCédric Le Goater     _FDT(offset);
266bf5615e7SCédric Le Goater     g_free(name);
267bf5615e7SCédric Le Goater 
268bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "compatible", compat, sizeof(compat))));
269bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "reg", reg, rsize)));
270bf5615e7SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type",
271bf5615e7SCédric Le Goater                               "PowerPC-External-Interrupt-Presentation")));
272bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "interrupt-controller", NULL, 0)));
273bf5615e7SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,interrupt-server-ranges",
274bf5615e7SCédric Le Goater                        irange, sizeof(irange))));
275bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#interrupt-cells", 1)));
276bf5615e7SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0)));
277bf5615e7SCédric Le Goater     g_free(reg);
278bf5615e7SCédric Le Goater }
279bf5615e7SCédric Le Goater 
280eb859a27SCédric Le Goater static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
281e997040eSCédric Le Goater {
28240abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
283d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
284d2fd9612SCédric Le Goater     int i;
285d2fd9612SCédric Le Goater 
286b168a138SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
287967b7523SCédric Le Goater 
288d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
289d2fd9612SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
290d2fd9612SCédric Le Goater 
291b168a138SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
292bf5615e7SCédric Le Goater 
293bf5615e7SCédric Le Goater         /* Interrupt Control Presenters (ICP). One per core. */
294b168a138SCédric Le Goater         pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
295d2fd9612SCédric Le Goater     }
296d2fd9612SCédric Le Goater 
297e997040eSCédric Le Goater     if (chip->ram_size) {
298b168a138SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
299e997040eSCédric Le Goater     }
300e997040eSCédric Le Goater }
301e997040eSCédric Le Goater 
302eb859a27SCédric Le Goater static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
303eb859a27SCédric Le Goater {
304eb859a27SCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
305eb859a27SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
306eb859a27SCédric Le Goater     int i;
307eb859a27SCédric Le Goater 
308eb859a27SCédric Le Goater     pnv_dt_xscom(chip, fdt, 0);
309eb859a27SCédric Le Goater 
310eb859a27SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
311eb859a27SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
312eb859a27SCédric Le Goater 
313eb859a27SCédric Le Goater         pnv_dt_core(chip, pnv_core, fdt);
314eb859a27SCédric Le Goater     }
315eb859a27SCédric Le Goater 
316eb859a27SCédric Le Goater     if (chip->ram_size) {
317eb859a27SCédric Le Goater         pnv_dt_memory(fdt, chip->chip_id, chip->ram_start, chip->ram_size);
318eb859a27SCédric Le Goater     }
31915376c66SCédric Le Goater 
32015376c66SCédric Le Goater     pnv_dt_lpc(chip, fdt, 0);
321eb859a27SCédric Le Goater }
322eb859a27SCédric Le Goater 
323b168a138SCédric Le Goater static void pnv_dt_rtc(ISADevice *d, void *fdt, int lpc_off)
324c5ffdcaeSCédric Le Goater {
325c5ffdcaeSCédric Le Goater     uint32_t io_base = d->ioport_id;
326c5ffdcaeSCédric Le Goater     uint32_t io_regs[] = {
327c5ffdcaeSCédric Le Goater         cpu_to_be32(1),
328c5ffdcaeSCédric Le Goater         cpu_to_be32(io_base),
329c5ffdcaeSCédric Le Goater         cpu_to_be32(2)
330c5ffdcaeSCédric Le Goater     };
331c5ffdcaeSCédric Le Goater     char *name;
332c5ffdcaeSCédric Le Goater     int node;
333c5ffdcaeSCédric Le Goater 
334c5ffdcaeSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
335c5ffdcaeSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
336c5ffdcaeSCédric Le Goater     _FDT(node);
337c5ffdcaeSCédric Le Goater     g_free(name);
338c5ffdcaeSCédric Le Goater 
339c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
340c5ffdcaeSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "compatible", "pnpPNP,b00")));
341c5ffdcaeSCédric Le Goater }
342c5ffdcaeSCédric Le Goater 
343b168a138SCédric Le Goater static void pnv_dt_serial(ISADevice *d, void *fdt, int lpc_off)
344cb228f5aSCédric Le Goater {
345cb228f5aSCédric Le Goater     const char compatible[] = "ns16550\0pnpPNP,501";
346cb228f5aSCédric Le Goater     uint32_t io_base = d->ioport_id;
347cb228f5aSCédric Le Goater     uint32_t io_regs[] = {
348cb228f5aSCédric Le Goater         cpu_to_be32(1),
349cb228f5aSCédric Le Goater         cpu_to_be32(io_base),
350cb228f5aSCédric Le Goater         cpu_to_be32(8)
351cb228f5aSCédric Le Goater     };
352cb228f5aSCédric Le Goater     char *name;
353cb228f5aSCédric Le Goater     int node;
354cb228f5aSCédric Le Goater 
355cb228f5aSCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
356cb228f5aSCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
357cb228f5aSCédric Le Goater     _FDT(node);
358cb228f5aSCédric Le Goater     g_free(name);
359cb228f5aSCédric Le Goater 
360cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
361cb228f5aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
362cb228f5aSCédric Le Goater                       sizeof(compatible))));
363cb228f5aSCédric Le Goater 
364cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "clock-frequency", 1843200)));
365cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "current-speed", 115200)));
366cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", d->isairq[0])));
367cb228f5aSCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
368cb228f5aSCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
369cb228f5aSCédric Le Goater 
370cb228f5aSCédric Le Goater     /* This is needed by Linux */
371cb228f5aSCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "device_type", "serial")));
372cb228f5aSCédric Le Goater }
373cb228f5aSCédric Le Goater 
374b168a138SCédric Le Goater static void pnv_dt_ipmi_bt(ISADevice *d, void *fdt, int lpc_off)
37504f6c8b2SCédric Le Goater {
37604f6c8b2SCédric Le Goater     const char compatible[] = "bt\0ipmi-bt";
37704f6c8b2SCédric Le Goater     uint32_t io_base;
37804f6c8b2SCédric Le Goater     uint32_t io_regs[] = {
37904f6c8b2SCédric Le Goater         cpu_to_be32(1),
38004f6c8b2SCédric Le Goater         0, /* 'io_base' retrieved from the 'ioport' property of 'isa-ipmi-bt' */
38104f6c8b2SCédric Le Goater         cpu_to_be32(3)
38204f6c8b2SCédric Le Goater     };
38304f6c8b2SCédric Le Goater     uint32_t irq;
38404f6c8b2SCédric Le Goater     char *name;
38504f6c8b2SCédric Le Goater     int node;
38604f6c8b2SCédric Le Goater 
38704f6c8b2SCédric Le Goater     io_base = object_property_get_int(OBJECT(d), "ioport", &error_fatal);
38804f6c8b2SCédric Le Goater     io_regs[1] = cpu_to_be32(io_base);
38904f6c8b2SCédric Le Goater 
39004f6c8b2SCédric Le Goater     irq = object_property_get_int(OBJECT(d), "irq", &error_fatal);
39104f6c8b2SCédric Le Goater 
39204f6c8b2SCédric Le Goater     name = g_strdup_printf("%s@i%x", qdev_fw_name(DEVICE(d)), io_base);
39304f6c8b2SCédric Le Goater     node = fdt_add_subnode(fdt, lpc_off, name);
39404f6c8b2SCédric Le Goater     _FDT(node);
39504f6c8b2SCédric Le Goater     g_free(name);
39604f6c8b2SCédric Le Goater 
3977032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs))));
3987032d92aSCédric Le Goater     _FDT((fdt_setprop(fdt, node, "compatible", compatible,
3997032d92aSCédric Le Goater                       sizeof(compatible))));
40004f6c8b2SCédric Le Goater 
40104f6c8b2SCédric Le Goater     /* Mark it as reserved to avoid Linux trying to claim it */
40204f6c8b2SCédric Le Goater     _FDT((fdt_setprop_string(fdt, node, "status", "reserved")));
40304f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupts", irq)));
40404f6c8b2SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, node, "interrupt-parent",
40504f6c8b2SCédric Le Goater                            fdt_get_phandle(fdt, lpc_off))));
40604f6c8b2SCédric Le Goater }
40704f6c8b2SCédric Le Goater 
408e7a3fee3SCédric Le Goater typedef struct ForeachPopulateArgs {
409e7a3fee3SCédric Le Goater     void *fdt;
410e7a3fee3SCédric Le Goater     int offset;
411e7a3fee3SCédric Le Goater } ForeachPopulateArgs;
412e7a3fee3SCédric Le Goater 
413b168a138SCédric Le Goater static int pnv_dt_isa_device(DeviceState *dev, void *opaque)
414e7a3fee3SCédric Le Goater {
415c5ffdcaeSCédric Le Goater     ForeachPopulateArgs *args = opaque;
416c5ffdcaeSCédric Le Goater     ISADevice *d = ISA_DEVICE(dev);
417c5ffdcaeSCédric Le Goater 
418c5ffdcaeSCédric Le Goater     if (object_dynamic_cast(OBJECT(dev), TYPE_MC146818_RTC)) {
419b168a138SCédric Le Goater         pnv_dt_rtc(d, args->fdt, args->offset);
420cb228f5aSCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), TYPE_ISA_SERIAL)) {
421b168a138SCédric Le Goater         pnv_dt_serial(d, args->fdt, args->offset);
42204f6c8b2SCédric Le Goater     } else if (object_dynamic_cast(OBJECT(dev), "isa-ipmi-bt")) {
423b168a138SCédric Le Goater         pnv_dt_ipmi_bt(d, args->fdt, args->offset);
424c5ffdcaeSCédric Le Goater     } else {
425c5ffdcaeSCédric Le Goater         error_report("unknown isa device %s@i%x", qdev_fw_name(dev),
426c5ffdcaeSCédric Le Goater                      d->ioport_id);
427c5ffdcaeSCédric Le Goater     }
428c5ffdcaeSCédric Le Goater 
429e7a3fee3SCédric Le Goater     return 0;
430e7a3fee3SCédric Le Goater }
431e7a3fee3SCédric Le Goater 
43259b7c1c2SBalamuruhan S /*
43359b7c1c2SBalamuruhan S  * The default LPC bus of a multichip system is on chip 0. It's
434bb7ab95cSCédric Le Goater  * recognized by the firmware (skiboot) using a "primary" property.
435bb7ab95cSCédric Le Goater  */
436bb7ab95cSCédric Le Goater static void pnv_dt_isa(PnvMachineState *pnv, void *fdt)
437bb7ab95cSCédric Le Goater {
43864d011d5SCédric Le Goater     int isa_offset = fdt_path_offset(fdt, pnv->chips[0]->dt_isa_nodename);
439e7a3fee3SCédric Le Goater     ForeachPopulateArgs args = {
440e7a3fee3SCédric Le Goater         .fdt = fdt,
441bb7ab95cSCédric Le Goater         .offset = isa_offset,
442e7a3fee3SCédric Le Goater     };
443f47a08d1SCédric Le Goater     uint32_t phandle;
444e7a3fee3SCédric Le Goater 
445bb7ab95cSCédric Le Goater     _FDT((fdt_setprop(fdt, isa_offset, "primary", NULL, 0)));
446bb7ab95cSCédric Le Goater 
447f47a08d1SCédric Le Goater     phandle = qemu_fdt_alloc_phandle(fdt);
448f47a08d1SCédric Le Goater     assert(phandle > 0);
449f47a08d1SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, isa_offset, "phandle", phandle)));
450f47a08d1SCédric Le Goater 
45159b7c1c2SBalamuruhan S     /*
45259b7c1c2SBalamuruhan S      * ISA devices are not necessarily parented to the ISA bus so we
45359b7c1c2SBalamuruhan S      * can not use object_child_foreach()
45459b7c1c2SBalamuruhan S      */
455bb7ab95cSCédric Le Goater     qbus_walk_children(BUS(pnv->isa_bus), pnv_dt_isa_device, NULL, NULL, NULL,
456bb7ab95cSCédric Le Goater                        &args);
457e7a3fee3SCédric Le Goater }
458e7a3fee3SCédric Le Goater 
459e5694793SCédric Le Goater static void pnv_dt_power_mgt(void *fdt)
460e5694793SCédric Le Goater {
461e5694793SCédric Le Goater     int off;
462e5694793SCédric Le Goater 
463e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, 0, "ibm,opal");
464e5694793SCédric Le Goater     off = fdt_add_subnode(fdt, off, "power-mgt");
465e5694793SCédric Le Goater 
466e5694793SCédric Le Goater     _FDT(fdt_setprop_cell(fdt, off, "ibm,enabled-stop-levels", 0xc0000000));
467e5694793SCédric Le Goater }
468e5694793SCédric Le Goater 
469b168a138SCédric Le Goater static void *pnv_dt_create(MachineState *machine)
4709e933f4aSBenjamin Herrenschmidt {
47183b90bf0SCédric Le Goater     const char plat_compat8[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv";
47283b90bf0SCédric Le Goater     const char plat_compat9[] = "qemu,powernv9\0ibm,powernv";
473b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
4749e933f4aSBenjamin Herrenschmidt     void *fdt;
4759e933f4aSBenjamin Herrenschmidt     char *buf;
4769e933f4aSBenjamin Herrenschmidt     int off;
477e997040eSCédric Le Goater     int i;
4789e933f4aSBenjamin Herrenschmidt 
4799e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
4809e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
4819e933f4aSBenjamin Herrenschmidt 
4829e933f4aSBenjamin Herrenschmidt     /* Root node */
4839e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
4849e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
4859e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
4869e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
48783b90bf0SCédric Le Goater     if (pnv_is_power9(pnv)) {
48883b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat9,
48983b90bf0SCédric Le Goater                           sizeof(plat_compat9))));
49083b90bf0SCédric Le Goater     } else {
49183b90bf0SCédric Le Goater         _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat8,
49283b90bf0SCédric Le Goater                           sizeof(plat_compat8))));
49383b90bf0SCédric Le Goater     }
49483b90bf0SCédric Le Goater 
4959e933f4aSBenjamin Herrenschmidt 
4969e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
4979e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
4989e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
4999e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
5009e933f4aSBenjamin Herrenschmidt     }
5019e933f4aSBenjamin Herrenschmidt     g_free(buf);
5029e933f4aSBenjamin Herrenschmidt 
5039e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
5049e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
5059e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
5069e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
5079e933f4aSBenjamin Herrenschmidt     }
5089e933f4aSBenjamin Herrenschmidt 
5099e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
5109e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
5119e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
5129e933f4aSBenjamin Herrenschmidt 
5139e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
5149e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
5159e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
5169e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
5179e933f4aSBenjamin Herrenschmidt     }
5189e933f4aSBenjamin Herrenschmidt 
519e997040eSCédric Le Goater     /* Populate device tree for each chip */
520e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
521eb859a27SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->dt_populate(pnv->chips[i], fdt);
522e997040eSCédric Le Goater     }
523e7a3fee3SCédric Le Goater 
524e7a3fee3SCédric Le Goater     /* Populate ISA devices on chip 0 */
525bb7ab95cSCédric Le Goater     pnv_dt_isa(pnv, fdt);
526aeaef83dSCédric Le Goater 
527aeaef83dSCédric Le Goater     if (pnv->bmc) {
528b168a138SCédric Le Goater         pnv_dt_bmc_sensors(pnv->bmc, fdt);
529aeaef83dSCédric Le Goater     }
530aeaef83dSCédric Le Goater 
531e5694793SCédric Le Goater     /* Create an extra node for power management on Power9 */
532e5694793SCédric Le Goater     if (pnv_is_power9(pnv)) {
533e5694793SCédric Le Goater         pnv_dt_power_mgt(fdt);
534e5694793SCédric Le Goater     }
535e5694793SCédric Le Goater 
5369e933f4aSBenjamin Herrenschmidt     return fdt;
5379e933f4aSBenjamin Herrenschmidt }
5389e933f4aSBenjamin Herrenschmidt 
539bce0b691SCédric Le Goater static void pnv_powerdown_notify(Notifier *n, void *opaque)
540bce0b691SCédric Le Goater {
541b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
542bce0b691SCédric Le Goater 
543bce0b691SCédric Le Goater     if (pnv->bmc) {
544bce0b691SCédric Le Goater         pnv_bmc_powerdown(pnv->bmc);
545bce0b691SCédric Le Goater     }
546bce0b691SCédric Le Goater }
547bce0b691SCédric Le Goater 
548a0628599SLike Xu static void pnv_reset(MachineState *machine)
5499e933f4aSBenjamin Herrenschmidt {
550b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
5519e933f4aSBenjamin Herrenschmidt     void *fdt;
552aeaef83dSCédric Le Goater     Object *obj;
5539e933f4aSBenjamin Herrenschmidt 
5549e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
5559e933f4aSBenjamin Herrenschmidt 
55659b7c1c2SBalamuruhan S     /*
55759b7c1c2SBalamuruhan S      * OpenPOWER systems have a BMC, which can be defined on the
558aeaef83dSCédric Le Goater      * command line with:
559aeaef83dSCédric Le Goater      *
560aeaef83dSCédric Le Goater      *   -device ipmi-bmc-sim,id=bmc0
561aeaef83dSCédric Le Goater      *
562aeaef83dSCédric Le Goater      * This is the internal simulator but it could also be an external
563aeaef83dSCédric Le Goater      * BMC.
564aeaef83dSCédric Le Goater      */
565a1a636b8SCédric Le Goater     obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL);
566aeaef83dSCédric Le Goater     if (obj) {
567aeaef83dSCédric Le Goater         pnv->bmc = IPMI_BMC(obj);
568aeaef83dSCédric Le Goater     }
569aeaef83dSCédric Le Goater 
570b168a138SCédric Le Goater     fdt = pnv_dt_create(machine);
5719e933f4aSBenjamin Herrenschmidt 
5729e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
5739e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
5749e933f4aSBenjamin Herrenschmidt 
5758d409261SCédric Le Goater     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
5769e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
5779e933f4aSBenjamin Herrenschmidt }
5789e933f4aSBenjamin Herrenschmidt 
57904026890SCédric Le Goater static ISABus *pnv_chip_power8_isa_create(PnvChip *chip, Error **errp)
5803495b6b6SCédric Le Goater {
58177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58277864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, true, errp);
58304026890SCédric Le Goater }
5843495b6b6SCédric Le Goater 
58504026890SCédric Le Goater static ISABus *pnv_chip_power8nvl_isa_create(PnvChip *chip, Error **errp)
58604026890SCédric Le Goater {
58777864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
58877864267SCédric Le Goater     return pnv_lpc_isa_create(&chip8->lpc, false, errp);
58904026890SCédric Le Goater }
5903495b6b6SCédric Le Goater 
59104026890SCédric Le Goater static ISABus *pnv_chip_power9_isa_create(PnvChip *chip, Error **errp)
59204026890SCédric Le Goater {
59315376c66SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
59415376c66SCédric Le Goater     return pnv_lpc_isa_create(&chip9->lpc, false, errp);
59504026890SCédric Le Goater }
5963495b6b6SCédric Le Goater 
59704026890SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip, Error **errp)
59804026890SCédric Le Goater {
59904026890SCédric Le Goater     return PNV_CHIP_GET_CLASS(chip)->isa_create(chip, errp);
6003495b6b6SCédric Le Goater }
6013495b6b6SCédric Le Goater 
602d8e4aad5SCédric Le Goater static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon)
603d8e4aad5SCédric Le Goater {
604d8e4aad5SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(chip);
605d8e4aad5SCédric Le Goater 
606d8e4aad5SCédric Le Goater     ics_pic_print_info(&chip8->psi.ics, mon);
607d8e4aad5SCédric Le Goater }
608d8e4aad5SCédric Le Goater 
609d8e4aad5SCédric Le Goater static void pnv_chip_power9_pic_print_info(PnvChip *chip, Monitor *mon)
610d8e4aad5SCédric Le Goater {
611d8e4aad5SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
612d8e4aad5SCédric Le Goater 
613d8e4aad5SCédric Le Goater     pnv_xive_pic_print_info(&chip9->xive, mon);
614c38536bcSCédric Le Goater     pnv_psi_pic_print_info(&chip9->psi, mon);
615d8e4aad5SCédric Le Goater }
616d8e4aad5SCédric Le Goater 
617f30c843cSCédric Le Goater static bool pnv_match_cpu(const char *default_type, const char *cpu_type)
618f30c843cSCédric Le Goater {
619f30c843cSCédric Le Goater     PowerPCCPUClass *ppc_default =
620f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(default_type));
621f30c843cSCédric Le Goater     PowerPCCPUClass *ppc =
622f30c843cSCédric Le Goater         POWERPC_CPU_CLASS(object_class_by_name(cpu_type));
623f30c843cSCédric Le Goater 
624f30c843cSCédric Le Goater     return ppc_default->pvr_match(ppc_default, ppc->pvr);
625f30c843cSCédric Le Goater }
626f30c843cSCédric Le Goater 
627b168a138SCédric Le Goater static void pnv_init(MachineState *machine)
6289e933f4aSBenjamin Herrenschmidt {
629b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(machine);
630f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_GET_CLASS(machine);
6319e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
6329e933f4aSBenjamin Herrenschmidt     char *fw_filename;
6339e933f4aSBenjamin Herrenschmidt     long fw_size;
634e997040eSCédric Le Goater     int i;
635e997040eSCédric Le Goater     char *chip_typename;
6369e933f4aSBenjamin Herrenschmidt 
6379e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
638d23b6caaSPhilippe Mathieu-Daudé     if (machine->ram_size < (1 * GiB)) {
6393dc6f869SAlistair Francis         warn_report("skiboot may not work with < 1GB of RAM");
6409e933f4aSBenjamin Herrenschmidt     }
6419e933f4aSBenjamin Herrenschmidt 
6429e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
643b168a138SCédric Le Goater     memory_region_allocate_system_memory(ram, NULL, "pnv.ram",
6449e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
6459e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
6469e933f4aSBenjamin Herrenschmidt 
6479e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
6489e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
6499e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
6509e933f4aSBenjamin Herrenschmidt     }
6519e933f4aSBenjamin Herrenschmidt 
6529e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
65315fcedb2SCédric Le Goater     if (!fw_filename) {
65415fcedb2SCédric Le Goater         error_report("Could not find OPAL firmware '%s'", bios_name);
65515fcedb2SCédric Le Goater         exit(1);
65615fcedb2SCédric Le Goater     }
6579e933f4aSBenjamin Herrenschmidt 
6589e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
6599e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
66015fcedb2SCédric Le Goater         error_report("Could not load OPAL firmware '%s'", fw_filename);
6619e933f4aSBenjamin Herrenschmidt         exit(1);
6629e933f4aSBenjamin Herrenschmidt     }
6639e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
6649e933f4aSBenjamin Herrenschmidt 
6659e933f4aSBenjamin Herrenschmidt     /* load kernel */
6669e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
6679e933f4aSBenjamin Herrenschmidt         long kernel_size;
6689e933f4aSBenjamin Herrenschmidt 
6699e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
670b45b56baSMurilo Opsfelder Araujo                                           KERNEL_LOAD_ADDR, KERNEL_MAX_SIZE);
6719e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
672802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
6739e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
6749e933f4aSBenjamin Herrenschmidt             exit(1);
6759e933f4aSBenjamin Herrenschmidt         }
6769e933f4aSBenjamin Herrenschmidt     }
6779e933f4aSBenjamin Herrenschmidt 
6789e933f4aSBenjamin Herrenschmidt     /* load initrd */
6799e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
6809e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
6819e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
682584ea7e7SMurilo Opsfelder Araujo                                   pnv->initrd_base, INITRD_MAX_SIZE);
6839e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
684802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
6859e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
6869e933f4aSBenjamin Herrenschmidt             exit(1);
6879e933f4aSBenjamin Herrenschmidt         }
6889e933f4aSBenjamin Herrenschmidt     }
689e997040eSCédric Le Goater 
690f30c843cSCédric Le Goater     /*
691f30c843cSCédric Le Goater      * Check compatibility of the specified CPU with the machine
692f30c843cSCédric Le Goater      * default.
693f30c843cSCédric Le Goater      */
694f30c843cSCédric Le Goater     if (!pnv_match_cpu(mc->default_cpu_type, machine->cpu_type)) {
695f30c843cSCédric Le Goater         error_report("invalid CPU model '%s' for %s machine",
696f30c843cSCédric Le Goater                      machine->cpu_type, mc->name);
697f30c843cSCédric Le Goater         exit(1);
698f30c843cSCédric Le Goater     }
699f30c843cSCédric Le Goater 
700e997040eSCédric Le Goater     /* Create the processor chips */
7014a12c699SIgor Mammedov     i = strlen(machine->cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
7027fd544d8SIgor Mammedov     chip_typename = g_strdup_printf(PNV_CHIP_TYPE_NAME("%.*s"),
7034a12c699SIgor Mammedov                                     i, machine->cpu_type);
704e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
705f30c843cSCédric Le Goater         error_report("invalid chip model '%.*s' for %s machine",
706f30c843cSCédric Le Goater                      i, machine->cpu_type, mc->name);
707e997040eSCédric Le Goater         exit(1);
708e997040eSCédric Le Goater     }
709e997040eSCédric Le Goater 
710e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
711e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
712e997040eSCédric Le Goater         char chip_name[32];
713e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
714e997040eSCédric Le Goater 
715e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
716e997040eSCédric Le Goater 
71759b7c1c2SBalamuruhan S         /*
71859b7c1c2SBalamuruhan S          * TODO: put all the memory in one node on chip 0 until we find a
719e997040eSCédric Le Goater          * way to specify different ranges for each chip
720e997040eSCédric Le Goater          */
721e997040eSCédric Le Goater         if (i == 0) {
722e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
723e997040eSCédric Le Goater                                     &error_fatal);
724e997040eSCédric Le Goater         }
725e997040eSCédric Le Goater 
726e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
727e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
728e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
729e997040eSCédric Le Goater                                 &error_fatal);
730fe6b6346SLike Xu         object_property_set_int(chip, machine->smp.cores,
731fe6b6346SLike Xu                                 "nr-cores", &error_fatal);
732e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
733e997040eSCédric Le Goater     }
734e997040eSCédric Le Goater     g_free(chip_typename);
7353495b6b6SCédric Le Goater 
7363495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
73704026890SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0], &error_fatal);
7383495b6b6SCédric Le Goater 
7393495b6b6SCédric Le Goater     /* Create serial port */
740def337ffSPeter Maydell     serial_hds_isa_init(pnv->isa_bus, 0, MAX_ISA_SERIAL_PORTS);
7413495b6b6SCédric Le Goater 
7423495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
7436c646a11SPhilippe Mathieu-Daudé     mc146818_rtc_init(pnv->isa_bus, 2000, NULL);
744bce0b691SCédric Le Goater 
74559b7c1c2SBalamuruhan S     /*
74659b7c1c2SBalamuruhan S      * OpenPOWER systems use a IPMI SEL Event message to notify the
74759b7c1c2SBalamuruhan S      * host to powerdown
74859b7c1c2SBalamuruhan S      */
749bce0b691SCédric Le Goater     pnv->powerdown_notifier.notify = pnv_powerdown_notify;
750bce0b691SCédric Le Goater     qemu_register_powerdown_notifier(&pnv->powerdown_notifier);
751e997040eSCédric Le Goater }
752e997040eSCédric Le Goater 
753631adaffSCédric Le Goater /*
754631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
755631adaffSCédric Le Goater  *   22:24  Chip ID
756631adaffSCédric Le Goater  *   25:28  Core number
757631adaffSCédric Le Goater  *   29:31  Thread ID
758631adaffSCédric Le Goater  */
759631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
760631adaffSCédric Le Goater {
761631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
762631adaffSCédric Le Goater }
763631adaffSCédric Le Goater 
7648fa1f4efSCédric Le Goater static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
765d35aefa9SCédric Le Goater                                         Error **errp)
766d35aefa9SCédric Le Goater {
7678fa1f4efSCédric Le Goater     Error *local_err = NULL;
7688fa1f4efSCédric Le Goater     Object *obj;
7698907fc25SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
7708fa1f4efSCédric Le Goater 
7718fa1f4efSCédric Le Goater     obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
7728fa1f4efSCédric Le Goater                      &local_err);
7738fa1f4efSCédric Le Goater     if (local_err) {
7748fa1f4efSCédric Le Goater         error_propagate(errp, local_err);
7758fa1f4efSCédric Le Goater         return;
7768fa1f4efSCédric Le Goater     }
7778fa1f4efSCédric Le Goater 
778956b8f46SCédric Le Goater     pnv_cpu->intc = obj;
779d35aefa9SCédric Le Goater }
780d35aefa9SCédric Le Goater 
781d49e8a9bSCédric Le Goater static void pnv_chip_power8_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
782d49e8a9bSCédric Le Goater {
783d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
784d49e8a9bSCédric Le Goater 
785d49e8a9bSCédric Le Goater     icp_reset(ICP(pnv_cpu->intc));
786d49e8a9bSCédric Le Goater }
787d49e8a9bSCédric Le Goater 
788631adaffSCédric Le Goater /*
789631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
790631adaffSCédric Le Goater  *   49:52  Node ID
791631adaffSCédric Le Goater  *   53:55  Chip ID
792631adaffSCédric Le Goater  *   56     Reserved - Read as zero
793631adaffSCédric Le Goater  *   57:61  Core number
794631adaffSCédric Le Goater  *   62:63  Thread ID
795631adaffSCédric Le Goater  *
796631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
797631adaffSCédric Le Goater  */
798631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
799631adaffSCédric Le Goater {
800631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
801631adaffSCédric Le Goater }
802631adaffSCédric Le Goater 
8038fa1f4efSCédric Le Goater static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
804d35aefa9SCédric Le Goater                                         Error **errp)
805d35aefa9SCédric Le Goater {
8062dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(chip);
8072dfa91a2SCédric Le Goater     Error *local_err = NULL;
8082dfa91a2SCédric Le Goater     Object *obj;
8092dfa91a2SCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
8102dfa91a2SCédric Le Goater 
8112dfa91a2SCédric Le Goater     /*
8122dfa91a2SCédric Le Goater      * The core creates its interrupt presenter but the XIVE interrupt
8132dfa91a2SCédric Le Goater      * controller object is initialized afterwards. Hopefully, it's
8142dfa91a2SCédric Le Goater      * only used at runtime.
8152dfa91a2SCédric Le Goater      */
81626aa5b1eSGreg Kurz     obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(&chip9->xive), &local_err);
8172dfa91a2SCédric Le Goater     if (local_err) {
8182dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
8198fa1f4efSCédric Le Goater         return;
820d35aefa9SCédric Le Goater     }
821d35aefa9SCédric Le Goater 
8222dfa91a2SCédric Le Goater     pnv_cpu->intc = obj;
8232dfa91a2SCédric Le Goater }
8242dfa91a2SCédric Le Goater 
825d49e8a9bSCédric Le Goater static void pnv_chip_power9_intc_reset(PnvChip *chip, PowerPCCPU *cpu)
826d49e8a9bSCédric Le Goater {
827d49e8a9bSCédric Le Goater     PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
828d49e8a9bSCédric Le Goater 
829d49e8a9bSCédric Le Goater     xive_tctx_reset(XIVE_TCTX(pnv_cpu->intc));
830d49e8a9bSCédric Le Goater }
831d49e8a9bSCédric Le Goater 
83259b7c1c2SBalamuruhan S /*
83359b7c1c2SBalamuruhan S  * Allowed core identifiers on a POWER8 Processor Chip :
834397a79e7SCédric Le Goater  *
835397a79e7SCédric Le Goater  * <EX0 reserved>
836397a79e7SCédric Le Goater  *  EX1  - Venice only
837397a79e7SCédric Le Goater  *  EX2  - Venice only
838397a79e7SCédric Le Goater  *  EX3  - Venice only
839397a79e7SCédric Le Goater  *  EX4
840397a79e7SCédric Le Goater  *  EX5
841397a79e7SCédric Le Goater  *  EX6
842397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
843397a79e7SCédric Le Goater  *  EX9  - Venice only
844397a79e7SCédric Le Goater  *  EX10 - Venice only
845397a79e7SCédric Le Goater  *  EX11 - Venice only
846397a79e7SCédric Le Goater  *  EX12
847397a79e7SCédric Le Goater  *  EX13
848397a79e7SCédric Le Goater  *  EX14
849397a79e7SCédric Le Goater  * <EX15 reserved>
850397a79e7SCédric Le Goater  */
851397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
852397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
853397a79e7SCédric Le Goater 
854397a79e7SCédric Le Goater /*
85509279d7eSCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x0
856397a79e7SCédric Le Goater  */
85709279d7eSCédric Le Goater #define POWER9_CORE_MASK   (0xffffffffffffffull)
858397a79e7SCédric Le Goater 
85977864267SCédric Le Goater static void pnv_chip_power8_instance_init(Object *obj)
86077864267SCédric Le Goater {
86177864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(obj);
86277864267SCédric Le Goater 
863f6d4dca8SThomas Huth     object_initialize_child(obj, "psi",  &chip8->psi, sizeof(chip8->psi),
864ae856055SCédric Le Goater                             TYPE_PNV8_PSI, &error_abort, NULL);
86577864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->psi), "xics",
86677864267SCédric Le Goater                                    OBJECT(qdev_get_machine()), &error_abort);
86777864267SCédric Le Goater 
868f6d4dca8SThomas Huth     object_initialize_child(obj, "lpc",  &chip8->lpc, sizeof(chip8->lpc),
86982514be2SCédric Le Goater                             TYPE_PNV8_LPC, &error_abort, NULL);
87077864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->lpc), "psi",
87177864267SCédric Le Goater                                    OBJECT(&chip8->psi), &error_abort);
87277864267SCédric Le Goater 
873f6d4dca8SThomas Huth     object_initialize_child(obj, "occ",  &chip8->occ, sizeof(chip8->occ),
8743233838cSCédric Le Goater                             TYPE_PNV8_OCC, &error_abort, NULL);
87577864267SCédric Le Goater     object_property_add_const_link(OBJECT(&chip8->occ), "psi",
87677864267SCédric Le Goater                                    OBJECT(&chip8->psi), &error_abort);
8773887d241SBalamuruhan S 
8783887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip8->homer, sizeof(chip8->homer),
8793887d241SBalamuruhan S                             TYPE_PNV8_HOMER, &error_abort, NULL);
8803887d241SBalamuruhan S     object_property_add_const_link(OBJECT(&chip8->homer), "chip", obj,
8813887d241SBalamuruhan S                                    &error_abort);
88277864267SCédric Le Goater }
88377864267SCédric Le Goater 
88477864267SCédric Le Goater static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
88577864267SCédric Le Goater  {
88677864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(chip8);
88777864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
88877864267SCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
88977864267SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
89077864267SCédric Le Goater     int i, j;
89177864267SCédric Le Goater     char *name;
89277864267SCédric Le Goater     XICSFabric *xi = XICS_FABRIC(qdev_get_machine());
89377864267SCédric Le Goater 
89477864267SCédric Le Goater     name = g_strdup_printf("icp-%x", chip->chip_id);
89577864267SCédric Le Goater     memory_region_init(&chip8->icp_mmio, OBJECT(chip), name, PNV_ICP_SIZE);
89677864267SCédric Le Goater     sysbus_init_mmio(SYS_BUS_DEVICE(chip), &chip8->icp_mmio);
89777864267SCédric Le Goater     g_free(name);
89877864267SCédric Le Goater 
89977864267SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 1, PNV_ICP_BASE(chip));
90077864267SCédric Le Goater 
90177864267SCédric Le Goater     /* Map the ICP registers for each thread */
90277864267SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
90377864267SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
90477864267SCédric Le Goater         int core_hwid = CPU_CORE(pnv_core)->core_id;
90577864267SCédric Le Goater 
90677864267SCédric Le Goater         for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
90777864267SCédric Le Goater             uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
90877864267SCédric Le Goater             PnvICPState *icp = PNV_ICP(xics_icp_get(xi, pir));
90977864267SCédric Le Goater 
91077864267SCédric Le Goater             memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
91177864267SCédric Le Goater                                         &icp->mmio);
91277864267SCédric Le Goater         }
91377864267SCédric Le Goater     }
91477864267SCédric Le Goater }
91577864267SCédric Le Goater 
91677864267SCédric Le Goater static void pnv_chip_power8_realize(DeviceState *dev, Error **errp)
91777864267SCédric Le Goater {
91877864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
91977864267SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
92077864267SCédric Le Goater     Pnv8Chip *chip8 = PNV8_CHIP(dev);
921ae856055SCédric Le Goater     Pnv8Psi *psi8 = &chip8->psi;
92277864267SCédric Le Goater     Error *local_err = NULL;
92377864267SCédric Le Goater 
924709044fdSCédric Le Goater     /* XSCOM bridge is first */
925709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV_XSCOM_SIZE, &local_err);
926709044fdSCédric Le Goater     if (local_err) {
927709044fdSCédric Le Goater         error_propagate(errp, local_err);
928709044fdSCédric Le Goater         return;
929709044fdSCédric Le Goater     }
930709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
931709044fdSCédric Le Goater 
93277864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
93377864267SCédric Le Goater     if (local_err) {
93477864267SCédric Le Goater         error_propagate(errp, local_err);
93577864267SCédric Le Goater         return;
93677864267SCédric Le Goater     }
93777864267SCédric Le Goater 
93877864267SCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
93977864267SCédric Le Goater     object_property_set_int(OBJECT(&chip8->psi), PNV_PSIHB_BASE(chip),
94077864267SCédric Le Goater                             "bar", &error_fatal);
94177864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->psi), true, "realized", &local_err);
94277864267SCédric Le Goater     if (local_err) {
94377864267SCédric Le Goater         error_propagate(errp, local_err);
94477864267SCédric Le Goater         return;
94577864267SCédric Le Goater     }
946ae856055SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_PSIHB_BASE,
947ae856055SCédric Le Goater                             &PNV_PSI(psi8)->xscom_regs);
94877864267SCédric Le Goater 
94977864267SCédric Le Goater     /* Create LPC controller */
95077864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->lpc), true, "realized",
95177864267SCédric Le Goater                              &error_fatal);
95277864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip8->lpc.xscom_regs);
95377864267SCédric Le Goater 
95464d011d5SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/xscom@%" PRIx64 "/isa@%x",
95564d011d5SCédric Le Goater                                             (uint64_t) PNV_XSCOM_BASE(chip),
95664d011d5SCédric Le Goater                                             PNV_XSCOM_LPC_BASE);
95764d011d5SCédric Le Goater 
95859b7c1c2SBalamuruhan S     /*
95959b7c1c2SBalamuruhan S      * Interrupt Management Area. This is the memory region holding
96059b7c1c2SBalamuruhan S      * all the Interrupt Control Presenter (ICP) registers
96159b7c1c2SBalamuruhan S      */
96277864267SCédric Le Goater     pnv_chip_icp_realize(chip8, &local_err);
96377864267SCédric Le Goater     if (local_err) {
96477864267SCédric Le Goater         error_propagate(errp, local_err);
96577864267SCédric Le Goater         return;
96677864267SCédric Le Goater     }
96777864267SCédric Le Goater 
96877864267SCédric Le Goater     /* Create the simplified OCC model */
96977864267SCédric Le Goater     object_property_set_bool(OBJECT(&chip8->occ), true, "realized", &local_err);
97077864267SCédric Le Goater     if (local_err) {
97177864267SCédric Le Goater         error_propagate(errp, local_err);
97277864267SCédric Le Goater         return;
97377864267SCédric Le Goater     }
97477864267SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV_XSCOM_OCC_BASE, &chip8->occ.xscom_regs);
975f3db8266SBalamuruhan S 
976f3db8266SBalamuruhan S     /* OCC SRAM model */
977f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_OCC_COMMON_AREA(chip),
978f3db8266SBalamuruhan S                                 &chip8->occ.sram_regs);
9793887d241SBalamuruhan S 
9803887d241SBalamuruhan S     /* HOMER */
9813887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip8->homer), true, "realized",
9823887d241SBalamuruhan S                              &local_err);
9833887d241SBalamuruhan S     if (local_err) {
9843887d241SBalamuruhan S         error_propagate(errp, local_err);
9853887d241SBalamuruhan S         return;
9863887d241SBalamuruhan S     }
9873887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip),
9883887d241SBalamuruhan S                                 &chip8->homer.regs);
98977864267SCédric Le Goater }
99077864267SCédric Le Goater 
991e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
992e997040eSCédric Le Goater {
993e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
994e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
995e997040eSCédric Le Goater 
996e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
997e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
998397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
999631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1000d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1001d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
100204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1003eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1004d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1005e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
100677864267SCédric Le Goater 
100777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
100877864267SCédric Le Goater                                     &k->parent_realize);
1009e997040eSCédric Le Goater }
1010e997040eSCédric Le Goater 
1011e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
1012e997040eSCédric Le Goater {
1013e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1014e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1015e997040eSCédric Le Goater 
1016e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
1017e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
1018397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1019631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1020d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1021d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
102204026890SCédric Le Goater     k->isa_create = pnv_chip_power8_isa_create;
1023eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1024d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1025e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
102677864267SCédric Le Goater 
102777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
102877864267SCédric Le Goater                                     &k->parent_realize);
1029e997040eSCédric Le Goater }
1030e997040eSCédric Le Goater 
1031e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
1032e997040eSCédric Le Goater {
1033e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1034e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1035e997040eSCédric Le Goater 
1036e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
1037e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
1038397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
1039631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
1040d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power8_intc_create;
1041d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power8_intc_reset;
104204026890SCédric Le Goater     k->isa_create = pnv_chip_power8nvl_isa_create;
1043eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power8_dt_populate;
1044d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power8_pic_print_info;
1045e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
104677864267SCédric Le Goater 
104777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power8_realize,
104877864267SCédric Le Goater                                     &k->parent_realize);
104977864267SCédric Le Goater }
105077864267SCédric Le Goater 
105177864267SCédric Le Goater static void pnv_chip_power9_instance_init(Object *obj)
105277864267SCédric Le Goater {
10532dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(obj);
10542dfa91a2SCédric Le Goater 
10552dfa91a2SCédric Le Goater     object_initialize_child(obj, "xive", &chip9->xive, sizeof(chip9->xive),
10562dfa91a2SCédric Le Goater                             TYPE_PNV_XIVE, &error_abort, NULL);
10572dfa91a2SCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->xive), "chip", obj,
10582dfa91a2SCédric Le Goater                                    &error_abort);
1059c38536bcSCédric Le Goater 
1060c38536bcSCédric Le Goater     object_initialize_child(obj, "psi",  &chip9->psi, sizeof(chip9->psi),
1061c38536bcSCédric Le Goater                             TYPE_PNV9_PSI, &error_abort, NULL);
1062c38536bcSCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->psi), "chip", obj,
1063c38536bcSCédric Le Goater                                    &error_abort);
106415376c66SCédric Le Goater 
106515376c66SCédric Le Goater     object_initialize_child(obj, "lpc",  &chip9->lpc, sizeof(chip9->lpc),
106615376c66SCédric Le Goater                             TYPE_PNV9_LPC, &error_abort, NULL);
106715376c66SCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->lpc), "psi",
106815376c66SCédric Le Goater                                    OBJECT(&chip9->psi), &error_abort);
10696598a70dSCédric Le Goater 
10706598a70dSCédric Le Goater     object_initialize_child(obj, "occ",  &chip9->occ, sizeof(chip9->occ),
10716598a70dSCédric Le Goater                             TYPE_PNV9_OCC, &error_abort, NULL);
10726598a70dSCédric Le Goater     object_property_add_const_link(OBJECT(&chip9->occ), "psi",
10736598a70dSCédric Le Goater                                    OBJECT(&chip9->psi), &error_abort);
10743887d241SBalamuruhan S 
10753887d241SBalamuruhan S     object_initialize_child(obj, "homer",  &chip9->homer, sizeof(chip9->homer),
10763887d241SBalamuruhan S                             TYPE_PNV9_HOMER, &error_abort, NULL);
10773887d241SBalamuruhan S     object_property_add_const_link(OBJECT(&chip9->homer), "chip", obj,
10783887d241SBalamuruhan S                                    &error_abort);
107977864267SCédric Le Goater }
108077864267SCédric Le Goater 
10815dad902cSCédric Le Goater static void pnv_chip_quad_realize(Pnv9Chip *chip9, Error **errp)
10825dad902cSCédric Le Goater {
10835dad902cSCédric Le Goater     PnvChip *chip = PNV_CHIP(chip9);
10845dad902cSCédric Le Goater     const char *typename = pnv_chip_core_typename(chip);
10855dad902cSCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
10865dad902cSCédric Le Goater     int i;
10875dad902cSCédric Le Goater 
10885dad902cSCédric Le Goater     chip9->nr_quads = DIV_ROUND_UP(chip->nr_cores, 4);
10895dad902cSCédric Le Goater     chip9->quads = g_new0(PnvQuad, chip9->nr_quads);
10905dad902cSCédric Le Goater 
10915dad902cSCédric Le Goater     for (i = 0; i < chip9->nr_quads; i++) {
10925dad902cSCédric Le Goater         char eq_name[32];
10935dad902cSCédric Le Goater         PnvQuad *eq = &chip9->quads[i];
10945dad902cSCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + (i * 4) * typesize);
10955dad902cSCédric Le Goater         int core_id = CPU_CORE(pnv_core)->core_id;
10965dad902cSCédric Le Goater 
10975dad902cSCédric Le Goater         snprintf(eq_name, sizeof(eq_name), "eq[%d]", core_id);
1098bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), eq_name, eq, sizeof(*eq),
1099bc4c406cSPhilippe Mathieu-Daudé                                 TYPE_PNV_QUAD, &error_fatal, NULL);
11005dad902cSCédric Le Goater 
11015dad902cSCédric Le Goater         object_property_set_int(OBJECT(eq), core_id, "id", &error_fatal);
11025dad902cSCédric Le Goater         object_property_set_bool(OBJECT(eq), true, "realized", &error_fatal);
11035dad902cSCédric Le Goater 
11045dad902cSCédric Le Goater         pnv_xscom_add_subregion(chip, PNV9_XSCOM_EQ_BASE(eq->id),
11055dad902cSCédric Le Goater                                 &eq->xscom_regs);
11065dad902cSCédric Le Goater     }
11075dad902cSCédric Le Goater }
11085dad902cSCédric Le Goater 
110977864267SCédric Le Goater static void pnv_chip_power9_realize(DeviceState *dev, Error **errp)
111077864267SCédric Le Goater {
111177864267SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev);
11122dfa91a2SCédric Le Goater     Pnv9Chip *chip9 = PNV9_CHIP(dev);
11132dfa91a2SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
1114c38536bcSCédric Le Goater     Pnv9Psi *psi9 = &chip9->psi;
111577864267SCédric Le Goater     Error *local_err = NULL;
111677864267SCédric Le Goater 
1117709044fdSCédric Le Goater     /* XSCOM bridge is first */
1118709044fdSCédric Le Goater     pnv_xscom_realize(chip, PNV9_XSCOM_SIZE, &local_err);
1119709044fdSCédric Le Goater     if (local_err) {
1120709044fdSCédric Le Goater         error_propagate(errp, local_err);
1121709044fdSCédric Le Goater         return;
1122709044fdSCédric Le Goater     }
1123709044fdSCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV9_XSCOM_BASE(chip));
1124709044fdSCédric Le Goater 
112577864267SCédric Le Goater     pcc->parent_realize(dev, &local_err);
112677864267SCédric Le Goater     if (local_err) {
112777864267SCédric Le Goater         error_propagate(errp, local_err);
112877864267SCédric Le Goater         return;
112977864267SCédric Le Goater     }
11302dfa91a2SCédric Le Goater 
11315dad902cSCédric Le Goater     pnv_chip_quad_realize(chip9, &local_err);
11325dad902cSCédric Le Goater     if (local_err) {
11335dad902cSCédric Le Goater         error_propagate(errp, local_err);
11345dad902cSCédric Le Goater         return;
11355dad902cSCédric Le Goater     }
11365dad902cSCédric Le Goater 
11372dfa91a2SCédric Le Goater     /* XIVE interrupt controller (POWER9) */
11382dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_IC_BASE(chip),
11392dfa91a2SCédric Le Goater                             "ic-bar", &error_fatal);
11402dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_VC_BASE(chip),
11412dfa91a2SCédric Le Goater                             "vc-bar", &error_fatal);
11422dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_PC_BASE(chip),
11432dfa91a2SCédric Le Goater                             "pc-bar", &error_fatal);
11442dfa91a2SCédric Le Goater     object_property_set_int(OBJECT(&chip9->xive), PNV9_XIVE_TM_BASE(chip),
11452dfa91a2SCédric Le Goater                             "tm-bar", &error_fatal);
11462dfa91a2SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->xive), true, "realized",
11472dfa91a2SCédric Le Goater                              &local_err);
11482dfa91a2SCédric Le Goater     if (local_err) {
11492dfa91a2SCédric Le Goater         error_propagate(errp, local_err);
11502dfa91a2SCédric Le Goater         return;
11512dfa91a2SCédric Le Goater     }
11522dfa91a2SCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_XIVE_BASE,
11532dfa91a2SCédric Le Goater                             &chip9->xive.xscom_regs);
1154c38536bcSCédric Le Goater 
1155c38536bcSCédric Le Goater     /* Processor Service Interface (PSI) Host Bridge */
1156c38536bcSCédric Le Goater     object_property_set_int(OBJECT(&chip9->psi), PNV9_PSIHB_BASE(chip),
1157c38536bcSCédric Le Goater                             "bar", &error_fatal);
1158c38536bcSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->psi), true, "realized", &local_err);
1159c38536bcSCédric Le Goater     if (local_err) {
1160c38536bcSCédric Le Goater         error_propagate(errp, local_err);
1161c38536bcSCédric Le Goater         return;
1162c38536bcSCédric Le Goater     }
1163c38536bcSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_PSIHB_BASE,
1164c38536bcSCédric Le Goater                             &PNV_PSI(psi9)->xscom_regs);
116515376c66SCédric Le Goater 
116615376c66SCédric Le Goater     /* LPC */
116715376c66SCédric Le Goater     object_property_set_bool(OBJECT(&chip9->lpc), true, "realized", &local_err);
116815376c66SCédric Le Goater     if (local_err) {
116915376c66SCédric Le Goater         error_propagate(errp, local_err);
117015376c66SCédric Le Goater         return;
117115376c66SCédric Le Goater     }
117215376c66SCédric Le Goater     memory_region_add_subregion(get_system_memory(), PNV9_LPCM_BASE(chip),
117315376c66SCédric Le Goater                                 &chip9->lpc.xscom_regs);
117415376c66SCédric Le Goater 
117515376c66SCédric Le Goater     chip->dt_isa_nodename = g_strdup_printf("/lpcm-opb@%" PRIx64 "/lpc@0",
117615376c66SCédric Le Goater                                             (uint64_t) PNV9_LPCM_BASE(chip));
11776598a70dSCédric Le Goater 
11786598a70dSCédric Le Goater     /* Create the simplified OCC model */
11796598a70dSCédric Le Goater     object_property_set_bool(OBJECT(&chip9->occ), true, "realized", &local_err);
11806598a70dSCédric Le Goater     if (local_err) {
11816598a70dSCédric Le Goater         error_propagate(errp, local_err);
11826598a70dSCédric Le Goater         return;
11836598a70dSCédric Le Goater     }
11846598a70dSCédric Le Goater     pnv_xscom_add_subregion(chip, PNV9_XSCOM_OCC_BASE, &chip9->occ.xscom_regs);
1185f3db8266SBalamuruhan S 
1186f3db8266SBalamuruhan S     /* OCC SRAM model */
1187f3db8266SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_OCC_COMMON_AREA(chip),
1188f3db8266SBalamuruhan S                                 &chip9->occ.sram_regs);
11893887d241SBalamuruhan S 
11903887d241SBalamuruhan S     /* HOMER */
11913887d241SBalamuruhan S     object_property_set_bool(OBJECT(&chip9->homer), true, "realized",
11923887d241SBalamuruhan S                              &local_err);
11933887d241SBalamuruhan S     if (local_err) {
11943887d241SBalamuruhan S         error_propagate(errp, local_err);
11953887d241SBalamuruhan S         return;
11963887d241SBalamuruhan S     }
11973887d241SBalamuruhan S     memory_region_add_subregion(get_system_memory(), PNV9_HOMER_BASE(chip),
11983887d241SBalamuruhan S                                 &chip9->homer.regs);
1199e997040eSCédric Le Goater }
1200e997040eSCédric Le Goater 
1201e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
1202e997040eSCédric Le Goater {
1203e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1204e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
1205e997040eSCédric Le Goater 
1206e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
120783028a2bSCédric Le Goater     k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
1208397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
1209631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
1210d35aefa9SCédric Le Goater     k->intc_create = pnv_chip_power9_intc_create;
1211d49e8a9bSCédric Le Goater     k->intc_reset = pnv_chip_power9_intc_reset;
121204026890SCédric Le Goater     k->isa_create = pnv_chip_power9_isa_create;
1213eb859a27SCédric Le Goater     k->dt_populate = pnv_chip_power9_dt_populate;
1214d8e4aad5SCédric Le Goater     k->pic_print_info = pnv_chip_power9_pic_print_info;
1215e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
121677864267SCédric Le Goater 
121777864267SCédric Le Goater     device_class_set_parent_realize(dc, pnv_chip_power9_realize,
121877864267SCédric Le Goater                                     &k->parent_realize);
1219e997040eSCédric Le Goater }
1220e997040eSCédric Le Goater 
1221397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
1222397a79e7SCédric Le Goater {
1223397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
1224397a79e7SCédric Le Goater     int cores_max;
1225397a79e7SCédric Le Goater 
1226397a79e7SCédric Le Goater     /*
1227397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
1228397a79e7SCédric Le Goater      * the chip class
1229397a79e7SCédric Le Goater      */
1230397a79e7SCédric Le Goater     if (!chip->cores_mask) {
1231397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
1232397a79e7SCédric Le Goater     }
1233397a79e7SCédric Le Goater 
1234397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
1235397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
1236397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
1237397a79e7SCédric Le Goater                    chip->cores_mask);
1238397a79e7SCédric Le Goater         return;
1239397a79e7SCédric Le Goater     }
1240397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
1241397a79e7SCédric Le Goater 
1242397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
124327d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
1244397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
1245397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
1246397a79e7SCédric Le Goater                    cores_max);
1247397a79e7SCédric Le Goater         return;
1248397a79e7SCédric Le Goater     }
1249397a79e7SCédric Le Goater }
1250397a79e7SCédric Le Goater 
125151c04728SCédric Le Goater static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
1252e997040eSCédric Le Goater {
1253fe6b6346SLike Xu     MachineState *ms = MACHINE(qdev_get_machine());
1254397a79e7SCédric Le Goater     Error *error = NULL;
1255d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
125640abf43fSIgor Mammedov     const char *typename = pnv_chip_core_typename(chip);
1257d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
1258d2fd9612SCédric Le Goater     int i, core_hwid;
1259397a79e7SCédric Le Goater 
1260d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
1261d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
1262d2fd9612SCédric Le Goater         return;
1263d2fd9612SCédric Le Goater     }
1264d2fd9612SCédric Le Goater 
1265d2fd9612SCédric Le Goater     /* Cores */
1266397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
1267397a79e7SCédric Le Goater     if (error) {
1268397a79e7SCédric Le Goater         error_propagate(errp, error);
1269397a79e7SCédric Le Goater         return;
1270397a79e7SCédric Le Goater     }
1271d2fd9612SCédric Le Goater 
1272d2fd9612SCédric Le Goater     chip->cores = g_malloc0(typesize * chip->nr_cores);
1273d2fd9612SCédric Le Goater 
1274d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
1275d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
1276d2fd9612SCédric Le Goater         char core_name[32];
1277d2fd9612SCédric Le Goater         void *pnv_core = chip->cores + i * typesize;
1278c035851aSCédric Le Goater         uint64_t xscom_core_base;
1279d2fd9612SCédric Le Goater 
1280d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
1281d2fd9612SCédric Le Goater             continue;
1282d2fd9612SCédric Le Goater         }
1283d2fd9612SCédric Le Goater 
1284d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
1285bc4c406cSPhilippe Mathieu-Daudé         object_initialize_child(OBJECT(chip), core_name, pnv_core, typesize,
1286bc4c406cSPhilippe Mathieu-Daudé                                 typename, &error_fatal, NULL);
1287fe6b6346SLike Xu         object_property_set_int(OBJECT(pnv_core), ms->smp.threads, "nr-threads",
1288d2fd9612SCédric Le Goater                                 &error_fatal);
1289d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
1290d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
1291d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
1292d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
1293d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
1294d35aefa9SCédric Le Goater         object_property_add_const_link(OBJECT(pnv_core), "chip",
1295d35aefa9SCédric Le Goater                                        OBJECT(chip), &error_fatal);
1296d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
1297d2fd9612SCédric Le Goater                                  &error_fatal);
129824ece072SCédric Le Goater 
129924ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
1300c035851aSCédric Le Goater         if (!pnv_chip_is_power9(chip)) {
1301c035851aSCédric Le Goater             xscom_core_base = PNV_XSCOM_EX_BASE(core_hwid);
1302c035851aSCédric Le Goater         } else {
13035dad902cSCédric Le Goater             xscom_core_base = PNV9_XSCOM_EC_BASE(core_hwid);
1304c035851aSCédric Le Goater         }
1305c035851aSCédric Le Goater 
1306c035851aSCédric Le Goater         pnv_xscom_add_subregion(chip, xscom_core_base,
130724ece072SCédric Le Goater                                 &PNV_CORE(pnv_core)->xscom_regs);
1308d2fd9612SCédric Le Goater         i++;
1309d2fd9612SCédric Le Goater     }
131051c04728SCédric Le Goater }
131151c04728SCédric Le Goater 
131251c04728SCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
131351c04728SCédric Le Goater {
131451c04728SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
131551c04728SCédric Le Goater     Error *error = NULL;
131651c04728SCédric Le Goater 
131751c04728SCédric Le Goater     /* Cores */
131851c04728SCédric Le Goater     pnv_chip_core_realize(chip, &error);
131951c04728SCédric Le Goater     if (error) {
132051c04728SCédric Le Goater         error_propagate(errp, error);
132151c04728SCédric Le Goater         return;
132251c04728SCédric Le Goater     }
1323e997040eSCédric Le Goater }
1324e997040eSCédric Le Goater 
1325e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
1326e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
1327e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
1328e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
1329397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
1330397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
1331e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
1332e997040eSCédric Le Goater };
1333e997040eSCédric Le Goater 
1334e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
1335e997040eSCédric Le Goater {
1336e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
1337e997040eSCédric Le Goater 
13389d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
1339e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
1340e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
1341e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
1342e997040eSCédric Le Goater }
1343e997040eSCédric Le Goater 
134454f59d78SCédric Le Goater static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
134554f59d78SCédric Le Goater {
1346b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
134754f59d78SCédric Le Goater     int i;
134854f59d78SCédric Le Goater 
134954f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
135077864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
135177864267SCédric Le Goater 
135277864267SCédric Le Goater         if (ics_valid_irq(&chip8->psi.ics, irq)) {
135377864267SCédric Le Goater             return &chip8->psi.ics;
135454f59d78SCédric Le Goater         }
135554f59d78SCédric Le Goater     }
135654f59d78SCédric Le Goater     return NULL;
135754f59d78SCédric Le Goater }
135854f59d78SCédric Le Goater 
135954f59d78SCédric Le Goater static void pnv_ics_resend(XICSFabric *xi)
136054f59d78SCédric Le Goater {
1361b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(xi);
136254f59d78SCédric Le Goater     int i;
136354f59d78SCédric Le Goater 
136454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
136577864267SCédric Le Goater         Pnv8Chip *chip8 = PNV8_CHIP(pnv->chips[i]);
136677864267SCédric Le Goater         ics_resend(&chip8->psi.ics);
136754f59d78SCédric Le Goater     }
136854f59d78SCédric Le Goater }
136954f59d78SCédric Le Goater 
137036fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
137136fc6f08SCédric Le Goater {
137236fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
137336fc6f08SCédric Le Goater 
1374956b8f46SCédric Le Goater     return cpu ? ICP(pnv_cpu_state(cpu)->intc) : NULL;
137536fc6f08SCédric Le Goater }
137636fc6f08SCédric Le Goater 
137747fea43aSCédric Le Goater static void pnv_pic_print_info(InterruptStatsProvider *obj,
137847fea43aSCédric Le Goater                                Monitor *mon)
137947fea43aSCédric Le Goater {
1380b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
138154f59d78SCédric Le Goater     int i;
138247fea43aSCédric Le Goater     CPUState *cs;
138347fea43aSCédric Le Goater 
138447fea43aSCédric Le Goater     CPU_FOREACH(cs) {
138547fea43aSCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
138647fea43aSCédric Le Goater 
1387d8e4aad5SCédric Le Goater         if (pnv_chip_is_power9(pnv->chips[0])) {
1388d8e4aad5SCédric Le Goater             xive_tctx_pic_print_info(XIVE_TCTX(pnv_cpu_state(cpu)->intc), mon);
1389d8e4aad5SCédric Le Goater         } else {
1390956b8f46SCédric Le Goater             icp_pic_print_info(ICP(pnv_cpu_state(cpu)->intc), mon);
139147fea43aSCédric Le Goater         }
1392d8e4aad5SCédric Le Goater     }
139354f59d78SCédric Le Goater 
139454f59d78SCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
1395d8e4aad5SCédric Le Goater         PNV_CHIP_GET_CLASS(pnv->chips[i])->pic_print_info(pnv->chips[i], mon);
139654f59d78SCédric Le Goater     }
139747fea43aSCédric Le Goater }
139847fea43aSCédric Le Goater 
1399e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
1400e997040eSCédric Le Goater                               void *opaque, Error **errp)
1401e997040eSCédric Le Goater {
1402b168a138SCédric Le Goater     visit_type_uint32(v, name, &PNV_MACHINE(obj)->num_chips, errp);
1403e997040eSCédric Le Goater }
1404e997040eSCédric Le Goater 
1405e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
1406e997040eSCédric Le Goater                               void *opaque, Error **errp)
1407e997040eSCédric Le Goater {
1408b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1409e997040eSCédric Le Goater     uint32_t num_chips;
1410e997040eSCédric Le Goater     Error *local_err = NULL;
1411e997040eSCédric Le Goater 
1412e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
1413e997040eSCédric Le Goater     if (local_err) {
1414e997040eSCédric Le Goater         error_propagate(errp, local_err);
1415e997040eSCédric Le Goater         return;
1416e997040eSCédric Le Goater     }
1417e997040eSCédric Le Goater 
1418e997040eSCédric Le Goater     /*
1419e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
1420e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
1421e997040eSCédric Le Goater      */
1422e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
1423e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
1424e997040eSCédric Le Goater         return;
1425e997040eSCédric Le Goater     }
1426e997040eSCédric Le Goater 
1427e997040eSCédric Le Goater     pnv->num_chips = num_chips;
1428e997040eSCédric Le Goater }
1429e997040eSCédric Le Goater 
143077864267SCédric Le Goater static void pnv_machine_instance_init(Object *obj)
1431e997040eSCédric Le Goater {
1432b168a138SCédric Le Goater     PnvMachineState *pnv = PNV_MACHINE(obj);
1433e997040eSCédric Le Goater     pnv->num_chips = 1;
1434e997040eSCédric Le Goater }
1435e997040eSCédric Le Goater 
1436b168a138SCédric Le Goater static void pnv_machine_class_props_init(ObjectClass *oc)
1437e997040eSCédric Le Goater {
14381e507bb0SMarc-André Lureau     object_class_property_add(oc, "num-chips", "uint32",
1439e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
1440e997040eSCédric Le Goater                               NULL, NULL, NULL);
1441e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
1442e997040eSCédric Le Goater                               "Specifies the number of processor chips",
1443e997040eSCédric Le Goater                               NULL);
14449e933f4aSBenjamin Herrenschmidt }
14459e933f4aSBenjamin Herrenschmidt 
1446f30c843cSCédric Le Goater static void pnv_machine_power8_class_init(ObjectClass *oc, void *data)
14479e933f4aSBenjamin Herrenschmidt {
14489e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
144936fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
1450f30c843cSCédric Le Goater 
1451f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER8";
1452f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
1453f30c843cSCédric Le Goater 
1454f30c843cSCédric Le Goater     xic->icp_get = pnv_icp_get;
1455f30c843cSCédric Le Goater     xic->ics_get = pnv_ics_get;
1456f30c843cSCédric Le Goater     xic->ics_resend = pnv_ics_resend;
1457f30c843cSCédric Le Goater }
1458f30c843cSCédric Le Goater 
1459f30c843cSCédric Le Goater static void pnv_machine_power9_class_init(ObjectClass *oc, void *data)
1460f30c843cSCédric Le Goater {
1461f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
1462f30c843cSCédric Le Goater 
1463f30c843cSCédric Le Goater     mc->desc = "IBM PowerNV (Non-Virtualized) POWER9";
1464f30c843cSCédric Le Goater     mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0");
1465f30c843cSCédric Le Goater 
1466f30c843cSCédric Le Goater     mc->alias = "powernv";
1467f30c843cSCédric Le Goater }
1468f30c843cSCédric Le Goater 
1469f30c843cSCédric Le Goater static void pnv_machine_class_init(ObjectClass *oc, void *data)
1470f30c843cSCédric Le Goater {
1471f30c843cSCédric Le Goater     MachineClass *mc = MACHINE_CLASS(oc);
147247fea43aSCédric Le Goater     InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc);
14739e933f4aSBenjamin Herrenschmidt 
14749e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
1475b168a138SCédric Le Goater     mc->init = pnv_init;
1476b168a138SCédric Le Goater     mc->reset = pnv_reset;
14779e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
147859b7c1c2SBalamuruhan S     /* Pnv provides a AHCI device for storage */
147959b7c1c2SBalamuruhan S     mc->block_default_type = IF_IDE;
14809e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
14819e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
1482f1d18b0aSJoel Stanley     /*
1483f1d18b0aSJoel Stanley      * RAM defaults to less than 2048 for 32-bit hosts, and large
1484f1d18b0aSJoel Stanley      * enough to fit the maximum initrd size at it's load address
1485f1d18b0aSJoel Stanley      */
1486f1d18b0aSJoel Stanley     mc->default_ram_size = INITRD_LOAD_ADDR + INITRD_MAX_SIZE;
148747fea43aSCédric Le Goater     ispc->print_info = pnv_pic_print_info;
1488e997040eSCédric Le Goater 
1489b168a138SCédric Le Goater     pnv_machine_class_props_init(oc);
14909e933f4aSBenjamin Herrenschmidt }
14919e933f4aSBenjamin Herrenschmidt 
149277864267SCédric Le Goater #define DEFINE_PNV8_CHIP_TYPE(type, class_initfn) \
1493beba5c0fSIgor Mammedov     {                                             \
1494beba5c0fSIgor Mammedov         .name          = type,                    \
1495beba5c0fSIgor Mammedov         .class_init    = class_initfn,            \
149677864267SCédric Le Goater         .parent        = TYPE_PNV8_CHIP,          \
149777864267SCédric Le Goater     }
149877864267SCédric Le Goater 
149977864267SCédric Le Goater #define DEFINE_PNV9_CHIP_TYPE(type, class_initfn) \
150077864267SCédric Le Goater     {                                             \
150177864267SCédric Le Goater         .name          = type,                    \
150277864267SCédric Le Goater         .class_init    = class_initfn,            \
150377864267SCédric Le Goater         .parent        = TYPE_PNV9_CHIP,          \
1504beba5c0fSIgor Mammedov     }
1505beba5c0fSIgor Mammedov 
1506beba5c0fSIgor Mammedov static const TypeInfo types[] = {
15071aba8716SCédric Le Goater     {
15081aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv9"),
15091aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
15101aba8716SCédric Le Goater         .class_init    = pnv_machine_power9_class_init,
15111aba8716SCédric Le Goater     },
15121aba8716SCédric Le Goater     {
15131aba8716SCédric Le Goater         .name          = MACHINE_TYPE_NAME("powernv8"),
15141aba8716SCédric Le Goater         .parent        = TYPE_PNV_MACHINE,
15151aba8716SCédric Le Goater         .class_init    = pnv_machine_power8_class_init,
15161aba8716SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
15171aba8716SCédric Le Goater             { TYPE_XICS_FABRIC },
15181aba8716SCédric Le Goater             { },
15191aba8716SCédric Le Goater         },
15201aba8716SCédric Le Goater     },
1521beba5c0fSIgor Mammedov     {
1522b168a138SCédric Le Goater         .name          = TYPE_PNV_MACHINE,
15239e933f4aSBenjamin Herrenschmidt         .parent        = TYPE_MACHINE,
1524f30c843cSCédric Le Goater         .abstract       = true,
15259e933f4aSBenjamin Herrenschmidt         .instance_size = sizeof(PnvMachineState),
152677864267SCédric Le Goater         .instance_init = pnv_machine_instance_init,
1527b168a138SCédric Le Goater         .class_init    = pnv_machine_class_init,
152836fc6f08SCédric Le Goater         .interfaces = (InterfaceInfo[]) {
152947fea43aSCédric Le Goater             { TYPE_INTERRUPT_STATS_PROVIDER },
153036fc6f08SCédric Le Goater             { },
153136fc6f08SCédric Le Goater         },
1532beba5c0fSIgor Mammedov     },
1533beba5c0fSIgor Mammedov     {
1534beba5c0fSIgor Mammedov         .name          = TYPE_PNV_CHIP,
1535beba5c0fSIgor Mammedov         .parent        = TYPE_SYS_BUS_DEVICE,
1536beba5c0fSIgor Mammedov         .class_init    = pnv_chip_class_init,
1537beba5c0fSIgor Mammedov         .instance_size = sizeof(PnvChip),
1538beba5c0fSIgor Mammedov         .class_size    = sizeof(PnvChipClass),
1539beba5c0fSIgor Mammedov         .abstract      = true,
1540beba5c0fSIgor Mammedov     },
154177864267SCédric Le Goater 
154277864267SCédric Le Goater     /*
154377864267SCédric Le Goater      * P9 chip and variants
154477864267SCédric Le Goater      */
154577864267SCédric Le Goater     {
154677864267SCédric Le Goater         .name          = TYPE_PNV9_CHIP,
154777864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
154877864267SCédric Le Goater         .instance_init = pnv_chip_power9_instance_init,
154977864267SCédric Le Goater         .instance_size = sizeof(Pnv9Chip),
155077864267SCédric Le Goater     },
155177864267SCédric Le Goater     DEFINE_PNV9_CHIP_TYPE(TYPE_PNV_CHIP_POWER9, pnv_chip_power9_class_init),
155277864267SCédric Le Goater 
155377864267SCédric Le Goater     /*
155477864267SCédric Le Goater      * P8 chip and variants
155577864267SCédric Le Goater      */
155677864267SCédric Le Goater     {
155777864267SCédric Le Goater         .name          = TYPE_PNV8_CHIP,
155877864267SCédric Le Goater         .parent        = TYPE_PNV_CHIP,
155977864267SCédric Le Goater         .instance_init = pnv_chip_power8_instance_init,
156077864267SCédric Le Goater         .instance_size = sizeof(Pnv8Chip),
156177864267SCédric Le Goater     },
156277864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8, pnv_chip_power8_class_init),
156377864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8E, pnv_chip_power8e_class_init),
156477864267SCédric Le Goater     DEFINE_PNV8_CHIP_TYPE(TYPE_PNV_CHIP_POWER8NVL,
1565beba5c0fSIgor Mammedov                           pnv_chip_power8nvl_class_init),
15669e933f4aSBenjamin Herrenschmidt };
15679e933f4aSBenjamin Herrenschmidt 
1568beba5c0fSIgor Mammedov DEFINE_TYPES(types)
1569