xref: /qemu/hw/ppc/pnv.c (revision 36fc6f08)
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"
219e933f4aSBenjamin Herrenschmidt #include "qapi/error.h"
229e933f4aSBenjamin Herrenschmidt #include "sysemu/sysemu.h"
239e933f4aSBenjamin Herrenschmidt #include "sysemu/numa.h"
24d2528bdcSPaolo Bonzini #include "sysemu/cpus.h"
259e933f4aSBenjamin Herrenschmidt #include "hw/hw.h"
26fcf5ef2aSThomas Huth #include "target/ppc/cpu.h"
279e933f4aSBenjamin Herrenschmidt #include "qemu/log.h"
289e933f4aSBenjamin Herrenschmidt #include "hw/ppc/fdt.h"
299e933f4aSBenjamin Herrenschmidt #include "hw/ppc/ppc.h"
309e933f4aSBenjamin Herrenschmidt #include "hw/ppc/pnv.h"
31d2fd9612SCédric Le Goater #include "hw/ppc/pnv_core.h"
329e933f4aSBenjamin Herrenschmidt #include "hw/loader.h"
339e933f4aSBenjamin Herrenschmidt #include "exec/address-spaces.h"
349e933f4aSBenjamin Herrenschmidt #include "qemu/cutils.h"
35e997040eSCédric Le Goater #include "qapi/visitor.h"
369e933f4aSBenjamin Herrenschmidt 
37*36fc6f08SCédric Le Goater #include "hw/ppc/xics.h"
38967b7523SCédric Le Goater #include "hw/ppc/pnv_xscom.h"
39967b7523SCédric Le Goater 
403495b6b6SCédric Le Goater #include "hw/isa/isa.h"
413495b6b6SCédric Le Goater #include "hw/char/serial.h"
423495b6b6SCédric Le Goater #include "hw/timer/mc146818rtc.h"
433495b6b6SCédric Le Goater 
449e933f4aSBenjamin Herrenschmidt #include <libfdt.h>
459e933f4aSBenjamin Herrenschmidt 
469e933f4aSBenjamin Herrenschmidt #define FDT_MAX_SIZE            0x00100000
479e933f4aSBenjamin Herrenschmidt 
489e933f4aSBenjamin Herrenschmidt #define FW_FILE_NAME            "skiboot.lid"
499e933f4aSBenjamin Herrenschmidt #define FW_LOAD_ADDR            0x0
509e933f4aSBenjamin Herrenschmidt #define FW_MAX_SIZE             0x00400000
519e933f4aSBenjamin Herrenschmidt 
529e933f4aSBenjamin Herrenschmidt #define KERNEL_LOAD_ADDR        0x20000000
539e933f4aSBenjamin Herrenschmidt #define INITRD_LOAD_ADDR        0x40000000
549e933f4aSBenjamin Herrenschmidt 
559e933f4aSBenjamin Herrenschmidt /*
569e933f4aSBenjamin Herrenschmidt  * On Power Systems E880 (POWER8), the max cpus (threads) should be :
579e933f4aSBenjamin Herrenschmidt  *     4 * 4 sockets * 12 cores * 8 threads = 1536
589e933f4aSBenjamin Herrenschmidt  * Let's make it 2^11
599e933f4aSBenjamin Herrenschmidt  */
609e933f4aSBenjamin Herrenschmidt #define MAX_CPUS                2048
619e933f4aSBenjamin Herrenschmidt 
629e933f4aSBenjamin Herrenschmidt /*
639e933f4aSBenjamin Herrenschmidt  * Memory nodes are created by hostboot, one for each range of memory
649e933f4aSBenjamin Herrenschmidt  * that has a different "affinity". In practice, it means one range
659e933f4aSBenjamin Herrenschmidt  * per chip.
669e933f4aSBenjamin Herrenschmidt  */
679e933f4aSBenjamin Herrenschmidt static void powernv_populate_memory_node(void *fdt, int chip_id, hwaddr start,
689e933f4aSBenjamin Herrenschmidt                                          hwaddr size)
699e933f4aSBenjamin Herrenschmidt {
709e933f4aSBenjamin Herrenschmidt     char *mem_name;
719e933f4aSBenjamin Herrenschmidt     uint64_t mem_reg_property[2];
729e933f4aSBenjamin Herrenschmidt     int off;
739e933f4aSBenjamin Herrenschmidt 
749e933f4aSBenjamin Herrenschmidt     mem_reg_property[0] = cpu_to_be64(start);
759e933f4aSBenjamin Herrenschmidt     mem_reg_property[1] = cpu_to_be64(size);
769e933f4aSBenjamin Herrenschmidt 
779e933f4aSBenjamin Herrenschmidt     mem_name = g_strdup_printf("memory@%"HWADDR_PRIx, start);
789e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, mem_name);
799e933f4aSBenjamin Herrenschmidt     g_free(mem_name);
809e933f4aSBenjamin Herrenschmidt 
819e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
829e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
839e933f4aSBenjamin Herrenschmidt                        sizeof(mem_reg_property))));
849e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, off, "ibm,chip-id", chip_id)));
859e933f4aSBenjamin Herrenschmidt }
869e933f4aSBenjamin Herrenschmidt 
87d2fd9612SCédric Le Goater static int get_cpus_node(void *fdt)
88d2fd9612SCédric Le Goater {
89d2fd9612SCédric Le Goater     int cpus_offset = fdt_path_offset(fdt, "/cpus");
90d2fd9612SCédric Le Goater 
91d2fd9612SCédric Le Goater     if (cpus_offset < 0) {
92d2fd9612SCédric Le Goater         cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
93d2fd9612SCédric Le Goater                                       "cpus");
94d2fd9612SCédric Le Goater         if (cpus_offset) {
95d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
96d2fd9612SCédric Le Goater             _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
97d2fd9612SCédric Le Goater         }
98d2fd9612SCédric Le Goater     }
99d2fd9612SCédric Le Goater     _FDT(cpus_offset);
100d2fd9612SCédric Le Goater     return cpus_offset;
101d2fd9612SCédric Le Goater }
102d2fd9612SCédric Le Goater 
103d2fd9612SCédric Le Goater /*
104d2fd9612SCédric Le Goater  * The PowerNV cores (and threads) need to use real HW ids and not an
105d2fd9612SCédric Le Goater  * incremental index like it has been done on other platforms. This HW
106d2fd9612SCédric Le Goater  * id is stored in the CPU PIR, it is used to create cpu nodes in the
107d2fd9612SCédric Le Goater  * device tree, used in XSCOM to address cores and in interrupt
108d2fd9612SCédric Le Goater  * servers.
109d2fd9612SCédric Le Goater  */
110d2fd9612SCédric Le Goater static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt)
111d2fd9612SCédric Le Goater {
112d2fd9612SCédric Le Goater     CPUState *cs = CPU(DEVICE(pc->threads));
113d2fd9612SCédric Le Goater     DeviceClass *dc = DEVICE_GET_CLASS(cs);
114d2fd9612SCédric Le Goater     PowerPCCPU *cpu = POWERPC_CPU(cs);
1158bd9530eSDavid Gibson     int smt_threads = CPU_CORE(pc)->nr_threads;
116d2fd9612SCédric Le Goater     CPUPPCState *env = &cpu->env;
117d2fd9612SCédric Le Goater     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
118d2fd9612SCédric Le Goater     uint32_t servers_prop[smt_threads];
119d2fd9612SCédric Le Goater     int i;
120d2fd9612SCédric Le Goater     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
121d2fd9612SCédric Le Goater                        0xffffffff, 0xffffffff};
122d2fd9612SCédric Le Goater     uint32_t tbfreq = PNV_TIMEBASE_FREQ;
123d2fd9612SCédric Le Goater     uint32_t cpufreq = 1000000000;
124d2fd9612SCédric Le Goater     uint32_t page_sizes_prop[64];
125d2fd9612SCédric Le Goater     size_t page_sizes_prop_size;
126d2fd9612SCédric Le Goater     const uint8_t pa_features[] = { 24, 0,
127d2fd9612SCédric Le Goater                                     0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
128d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
129d2fd9612SCédric Le Goater                                     0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
130d2fd9612SCédric Le Goater                                     0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
131d2fd9612SCédric Le Goater     int offset;
132d2fd9612SCédric Le Goater     char *nodename;
133d2fd9612SCédric Le Goater     int cpus_offset = get_cpus_node(fdt);
134d2fd9612SCédric Le Goater 
135d2fd9612SCédric Le Goater     nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
136d2fd9612SCédric Le Goater     offset = fdt_add_subnode(fdt, cpus_offset, nodename);
137d2fd9612SCédric Le Goater     _FDT(offset);
138d2fd9612SCédric Le Goater     g_free(nodename);
139d2fd9612SCédric Le Goater 
140d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
141d2fd9612SCédric Le Goater 
142d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
143d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
144d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
145d2fd9612SCédric Le Goater 
146d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
147d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
148d2fd9612SCédric Le Goater                             env->dcache_line_size)));
149d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
150d2fd9612SCédric Le Goater                             env->dcache_line_size)));
151d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
152d2fd9612SCédric Le Goater                             env->icache_line_size)));
153d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
154d2fd9612SCédric Le Goater                             env->icache_line_size)));
155d2fd9612SCédric Le Goater 
156d2fd9612SCédric Le Goater     if (pcc->l1_dcache_size) {
157d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
158d2fd9612SCédric Le Goater                                pcc->l1_dcache_size)));
159d2fd9612SCédric Le Goater     } else {
160d2fd9612SCédric Le Goater         error_report("Warning: Unknown L1 dcache size for cpu");
161d2fd9612SCédric Le Goater     }
162d2fd9612SCédric Le Goater     if (pcc->l1_icache_size) {
163d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
164d2fd9612SCédric Le Goater                                pcc->l1_icache_size)));
165d2fd9612SCédric Le Goater     } else {
166d2fd9612SCédric Le Goater         error_report("Warning: Unknown L1 icache size for cpu");
167d2fd9612SCédric Le Goater     }
168d2fd9612SCédric Le Goater 
169d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
170d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
171d2fd9612SCédric Le Goater     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr)));
172d2fd9612SCédric Le Goater     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
173d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
174d2fd9612SCédric Le Goater 
175d2fd9612SCédric Le Goater     if (env->spr_cb[SPR_PURR].oea_read) {
176d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
177d2fd9612SCédric Le Goater     }
178d2fd9612SCédric Le Goater 
179d2fd9612SCédric Le Goater     if (env->mmu_model & POWERPC_MMU_1TSEG) {
180d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
181d2fd9612SCédric Le Goater                            segs, sizeof(segs))));
182d2fd9612SCédric Le Goater     }
183d2fd9612SCédric Le Goater 
184d2fd9612SCédric Le Goater     /* Advertise VMX/VSX (vector extensions) if available
185d2fd9612SCédric Le Goater      *   0 / no property == no vector extensions
186d2fd9612SCédric Le Goater      *   1               == VMX / Altivec available
187d2fd9612SCédric Le Goater      *   2               == VSX available */
188d2fd9612SCédric Le Goater     if (env->insns_flags & PPC_ALTIVEC) {
189d2fd9612SCédric Le Goater         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
190d2fd9612SCédric Le Goater 
191d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
192d2fd9612SCédric Le Goater     }
193d2fd9612SCédric Le Goater 
194d2fd9612SCédric Le Goater     /* Advertise DFP (Decimal Floating Point) if available
195d2fd9612SCédric Le Goater      *   0 / no property == no DFP
196d2fd9612SCédric Le Goater      *   1               == DFP available */
197d2fd9612SCédric Le Goater     if (env->insns_flags2 & PPC2_DFP) {
198d2fd9612SCédric Le Goater         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
199d2fd9612SCédric Le Goater     }
200d2fd9612SCédric Le Goater 
201d2fd9612SCédric Le Goater     page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop,
202d2fd9612SCédric Le Goater                                                   sizeof(page_sizes_prop));
203d2fd9612SCédric Le Goater     if (page_sizes_prop_size) {
204d2fd9612SCédric Le Goater         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
205d2fd9612SCédric Le Goater                            page_sizes_prop, page_sizes_prop_size)));
206d2fd9612SCédric Le Goater     }
207d2fd9612SCédric Le Goater 
208d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
209d2fd9612SCédric Le Goater                        pa_features, sizeof(pa_features))));
210d2fd9612SCédric Le Goater 
211d2fd9612SCédric Le Goater     /* Build interrupt servers properties */
212d2fd9612SCédric Le Goater     for (i = 0; i < smt_threads; i++) {
213d2fd9612SCédric Le Goater         servers_prop[i] = cpu_to_be32(pc->pir + i);
214d2fd9612SCédric Le Goater     }
215d2fd9612SCédric Le Goater     _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
216d2fd9612SCédric Le Goater                        servers_prop, sizeof(servers_prop))));
217d2fd9612SCédric Le Goater }
218d2fd9612SCédric Le Goater 
219e997040eSCédric Le Goater static void powernv_populate_chip(PnvChip *chip, void *fdt)
220e997040eSCédric Le Goater {
221d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
222d2fd9612SCédric Le Goater     char *typename = pnv_core_typename(pcc->cpu_model);
223d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
224d2fd9612SCédric Le Goater     int i;
225d2fd9612SCédric Le Goater 
226967b7523SCédric Le Goater     pnv_xscom_populate(chip, fdt, 0);
227967b7523SCédric Le Goater 
228d2fd9612SCédric Le Goater     for (i = 0; i < chip->nr_cores; i++) {
229d2fd9612SCédric Le Goater         PnvCore *pnv_core = PNV_CORE(chip->cores + i * typesize);
230d2fd9612SCédric Le Goater 
231d2fd9612SCédric Le Goater         powernv_create_core_node(chip, pnv_core, fdt);
232d2fd9612SCédric Le Goater     }
233d2fd9612SCédric Le Goater 
234e997040eSCédric Le Goater     if (chip->ram_size) {
235e997040eSCédric Le Goater         powernv_populate_memory_node(fdt, chip->chip_id, chip->ram_start,
236e997040eSCédric Le Goater                                      chip->ram_size);
237e997040eSCédric Le Goater     }
238d2fd9612SCédric Le Goater     g_free(typename);
239e997040eSCédric Le Goater }
240e997040eSCédric Le Goater 
2419e933f4aSBenjamin Herrenschmidt static void *powernv_create_fdt(MachineState *machine)
2429e933f4aSBenjamin Herrenschmidt {
2439e933f4aSBenjamin Herrenschmidt     const char plat_compat[] = "qemu,powernv\0ibm,powernv";
2449e933f4aSBenjamin Herrenschmidt     PnvMachineState *pnv = POWERNV_MACHINE(machine);
2459e933f4aSBenjamin Herrenschmidt     void *fdt;
2469e933f4aSBenjamin Herrenschmidt     char *buf;
2479e933f4aSBenjamin Herrenschmidt     int off;
248e997040eSCédric Le Goater     int i;
2499e933f4aSBenjamin Herrenschmidt 
2509e933f4aSBenjamin Herrenschmidt     fdt = g_malloc0(FDT_MAX_SIZE);
2519e933f4aSBenjamin Herrenschmidt     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
2529e933f4aSBenjamin Herrenschmidt 
2539e933f4aSBenjamin Herrenschmidt     /* Root node */
2549e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#address-cells", 0x2)));
2559e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_cell(fdt, 0, "#size-cells", 0x2)));
2569e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "model",
2579e933f4aSBenjamin Herrenschmidt                              "IBM PowerNV (emulated by qemu)")));
2589e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop(fdt, 0, "compatible", plat_compat,
2599e933f4aSBenjamin Herrenschmidt                       sizeof(plat_compat))));
2609e933f4aSBenjamin Herrenschmidt 
2619e933f4aSBenjamin Herrenschmidt     buf =  qemu_uuid_unparse_strdup(&qemu_uuid);
2629e933f4aSBenjamin Herrenschmidt     _FDT((fdt_setprop_string(fdt, 0, "vm,uuid", buf)));
2639e933f4aSBenjamin Herrenschmidt     if (qemu_uuid_set) {
2649e933f4aSBenjamin Herrenschmidt         _FDT((fdt_property_string(fdt, "system-id", buf)));
2659e933f4aSBenjamin Herrenschmidt     }
2669e933f4aSBenjamin Herrenschmidt     g_free(buf);
2679e933f4aSBenjamin Herrenschmidt 
2689e933f4aSBenjamin Herrenschmidt     off = fdt_add_subnode(fdt, 0, "chosen");
2699e933f4aSBenjamin Herrenschmidt     if (machine->kernel_cmdline) {
2709e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop_string(fdt, off, "bootargs",
2719e933f4aSBenjamin Herrenschmidt                                  machine->kernel_cmdline)));
2729e933f4aSBenjamin Herrenschmidt     }
2739e933f4aSBenjamin Herrenschmidt 
2749e933f4aSBenjamin Herrenschmidt     if (pnv->initrd_size) {
2759e933f4aSBenjamin Herrenschmidt         uint32_t start_prop = cpu_to_be32(pnv->initrd_base);
2769e933f4aSBenjamin Herrenschmidt         uint32_t end_prop = cpu_to_be32(pnv->initrd_base + pnv->initrd_size);
2779e933f4aSBenjamin Herrenschmidt 
2789e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-start",
2799e933f4aSBenjamin Herrenschmidt                                &start_prop, sizeof(start_prop))));
2809e933f4aSBenjamin Herrenschmidt         _FDT((fdt_setprop(fdt, off, "linux,initrd-end",
2819e933f4aSBenjamin Herrenschmidt                                &end_prop, sizeof(end_prop))));
2829e933f4aSBenjamin Herrenschmidt     }
2839e933f4aSBenjamin Herrenschmidt 
284e997040eSCédric Le Goater     /* Populate device tree for each chip */
285e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
286e997040eSCédric Le Goater         powernv_populate_chip(pnv->chips[i], fdt);
287e997040eSCédric Le Goater     }
2889e933f4aSBenjamin Herrenschmidt     return fdt;
2899e933f4aSBenjamin Herrenschmidt }
2909e933f4aSBenjamin Herrenschmidt 
2919e933f4aSBenjamin Herrenschmidt static void ppc_powernv_reset(void)
2929e933f4aSBenjamin Herrenschmidt {
2939e933f4aSBenjamin Herrenschmidt     MachineState *machine = MACHINE(qdev_get_machine());
2949e933f4aSBenjamin Herrenschmidt     void *fdt;
2959e933f4aSBenjamin Herrenschmidt 
2969e933f4aSBenjamin Herrenschmidt     qemu_devices_reset();
2979e933f4aSBenjamin Herrenschmidt 
2989e933f4aSBenjamin Herrenschmidt     fdt = powernv_create_fdt(machine);
2999e933f4aSBenjamin Herrenschmidt 
3009e933f4aSBenjamin Herrenschmidt     /* Pack resulting tree */
3019e933f4aSBenjamin Herrenschmidt     _FDT((fdt_pack(fdt)));
3029e933f4aSBenjamin Herrenschmidt 
3039e933f4aSBenjamin Herrenschmidt     cpu_physical_memory_write(PNV_FDT_ADDR, fdt, fdt_totalsize(fdt));
3049e933f4aSBenjamin Herrenschmidt }
3059e933f4aSBenjamin Herrenschmidt 
3063495b6b6SCédric Le Goater /* If we don't use the built-in LPC interrupt deserializer, we need
3073495b6b6SCédric Le Goater  * to provide a set of qirqs for the ISA bus or things will go bad.
3083495b6b6SCédric Le Goater  *
3093495b6b6SCédric Le Goater  * Most machines using pre-Naples chips (without said deserializer)
3103495b6b6SCédric Le Goater  * have a CPLD that will collect the SerIRQ and shoot them as a
3113495b6b6SCédric Le Goater  * single level interrupt to the P8 chip. So let's setup a hook
3123495b6b6SCédric Le Goater  * for doing just that.
3133495b6b6SCédric Le Goater  *
3143495b6b6SCédric Le Goater  * Note: The actual interrupt input isn't emulated yet, this will
3153495b6b6SCédric Le Goater  * come with the PSI bridge model.
3163495b6b6SCédric Le Goater  */
3173495b6b6SCédric Le Goater static void pnv_lpc_isa_irq_handler_cpld(void *opaque, int n, int level)
3183495b6b6SCédric Le Goater {
3193495b6b6SCédric Le Goater     /* We don't yet emulate the PSI bridge which provides the external
3203495b6b6SCédric Le Goater      * interrupt, so just drop interrupts on the floor
3213495b6b6SCédric Le Goater      */
3223495b6b6SCédric Le Goater }
3233495b6b6SCédric Le Goater 
3243495b6b6SCédric Le Goater static void pnv_lpc_isa_irq_handler(void *opaque, int n, int level)
3253495b6b6SCédric Le Goater {
3263495b6b6SCédric Le Goater      /* XXX TODO */
3273495b6b6SCédric Le Goater }
3283495b6b6SCédric Le Goater 
3293495b6b6SCédric Le Goater static ISABus *pnv_isa_create(PnvChip *chip)
3303495b6b6SCédric Le Goater {
3313495b6b6SCédric Le Goater     PnvLpcController *lpc = &chip->lpc;
3323495b6b6SCédric Le Goater     ISABus *isa_bus;
3333495b6b6SCédric Le Goater     qemu_irq *irqs;
3343495b6b6SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
3353495b6b6SCédric Le Goater 
3363495b6b6SCédric Le Goater     /* let isa_bus_new() create its own bridge on SysBus otherwise
3373495b6b6SCédric Le Goater      * devices speficied on the command line won't find the bus and
3383495b6b6SCédric Le Goater      * will fail to create.
3393495b6b6SCédric Le Goater      */
3403495b6b6SCédric Le Goater     isa_bus = isa_bus_new(NULL, &lpc->isa_mem, &lpc->isa_io,
3413495b6b6SCédric Le Goater                           &error_fatal);
3423495b6b6SCédric Le Goater 
3433495b6b6SCédric Le Goater     /* Not all variants have a working serial irq decoder. If not,
3443495b6b6SCédric Le Goater      * handling of LPC interrupts becomes a platform issue (some
3453495b6b6SCédric Le Goater      * platforms have a CPLD to do it).
3463495b6b6SCédric Le Goater      */
3473495b6b6SCédric Le Goater     if (pcc->chip_type == PNV_CHIP_POWER8NVL) {
3483495b6b6SCédric Le Goater         irqs = qemu_allocate_irqs(pnv_lpc_isa_irq_handler, chip, ISA_NUM_IRQS);
3493495b6b6SCédric Le Goater     } else {
3503495b6b6SCédric Le Goater         irqs = qemu_allocate_irqs(pnv_lpc_isa_irq_handler_cpld, chip,
3513495b6b6SCédric Le Goater                                   ISA_NUM_IRQS);
3523495b6b6SCédric Le Goater     }
3533495b6b6SCédric Le Goater 
3543495b6b6SCédric Le Goater     isa_bus_irqs(isa_bus, irqs);
3553495b6b6SCédric Le Goater     return isa_bus;
3563495b6b6SCédric Le Goater }
3573495b6b6SCédric Le Goater 
3589e933f4aSBenjamin Herrenschmidt static void ppc_powernv_init(MachineState *machine)
3599e933f4aSBenjamin Herrenschmidt {
3609e933f4aSBenjamin Herrenschmidt     PnvMachineState *pnv = POWERNV_MACHINE(machine);
3619e933f4aSBenjamin Herrenschmidt     MemoryRegion *ram;
3629e933f4aSBenjamin Herrenschmidt     char *fw_filename;
3639e933f4aSBenjamin Herrenschmidt     long fw_size;
364e997040eSCédric Le Goater     int i;
365e997040eSCédric Le Goater     char *chip_typename;
3669e933f4aSBenjamin Herrenschmidt 
3679e933f4aSBenjamin Herrenschmidt     /* allocate RAM */
3689e933f4aSBenjamin Herrenschmidt     if (machine->ram_size < (1 * G_BYTE)) {
3699e933f4aSBenjamin Herrenschmidt         error_report("Warning: skiboot may not work with < 1GB of RAM");
3709e933f4aSBenjamin Herrenschmidt     }
3719e933f4aSBenjamin Herrenschmidt 
3729e933f4aSBenjamin Herrenschmidt     ram = g_new(MemoryRegion, 1);
3739e933f4aSBenjamin Herrenschmidt     memory_region_allocate_system_memory(ram, NULL, "ppc_powernv.ram",
3749e933f4aSBenjamin Herrenschmidt                                          machine->ram_size);
3759e933f4aSBenjamin Herrenschmidt     memory_region_add_subregion(get_system_memory(), 0, ram);
3769e933f4aSBenjamin Herrenschmidt 
3779e933f4aSBenjamin Herrenschmidt     /* load skiboot firmware  */
3789e933f4aSBenjamin Herrenschmidt     if (bios_name == NULL) {
3799e933f4aSBenjamin Herrenschmidt         bios_name = FW_FILE_NAME;
3809e933f4aSBenjamin Herrenschmidt     }
3819e933f4aSBenjamin Herrenschmidt 
3829e933f4aSBenjamin Herrenschmidt     fw_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
3839e933f4aSBenjamin Herrenschmidt 
3849e933f4aSBenjamin Herrenschmidt     fw_size = load_image_targphys(fw_filename, FW_LOAD_ADDR, FW_MAX_SIZE);
3859e933f4aSBenjamin Herrenschmidt     if (fw_size < 0) {
386802fc7abSThomas Huth         error_report("Could not load OPAL '%s'", fw_filename);
3879e933f4aSBenjamin Herrenschmidt         exit(1);
3889e933f4aSBenjamin Herrenschmidt     }
3899e933f4aSBenjamin Herrenschmidt     g_free(fw_filename);
3909e933f4aSBenjamin Herrenschmidt 
3919e933f4aSBenjamin Herrenschmidt     /* load kernel */
3929e933f4aSBenjamin Herrenschmidt     if (machine->kernel_filename) {
3939e933f4aSBenjamin Herrenschmidt         long kernel_size;
3949e933f4aSBenjamin Herrenschmidt 
3959e933f4aSBenjamin Herrenschmidt         kernel_size = load_image_targphys(machine->kernel_filename,
3969e933f4aSBenjamin Herrenschmidt                                           KERNEL_LOAD_ADDR, 0x2000000);
3979e933f4aSBenjamin Herrenschmidt         if (kernel_size < 0) {
398802fc7abSThomas Huth             error_report("Could not load kernel '%s'",
3999e933f4aSBenjamin Herrenschmidt                          machine->kernel_filename);
4009e933f4aSBenjamin Herrenschmidt             exit(1);
4019e933f4aSBenjamin Herrenschmidt         }
4029e933f4aSBenjamin Herrenschmidt     }
4039e933f4aSBenjamin Herrenschmidt 
4049e933f4aSBenjamin Herrenschmidt     /* load initrd */
4059e933f4aSBenjamin Herrenschmidt     if (machine->initrd_filename) {
4069e933f4aSBenjamin Herrenschmidt         pnv->initrd_base = INITRD_LOAD_ADDR;
4079e933f4aSBenjamin Herrenschmidt         pnv->initrd_size = load_image_targphys(machine->initrd_filename,
4089e933f4aSBenjamin Herrenschmidt                                   pnv->initrd_base, 0x10000000); /* 128MB max */
4099e933f4aSBenjamin Herrenschmidt         if (pnv->initrd_size < 0) {
410802fc7abSThomas Huth             error_report("Could not load initial ram disk '%s'",
4119e933f4aSBenjamin Herrenschmidt                          machine->initrd_filename);
4129e933f4aSBenjamin Herrenschmidt             exit(1);
4139e933f4aSBenjamin Herrenschmidt         }
4149e933f4aSBenjamin Herrenschmidt     }
415e997040eSCédric Le Goater 
416e997040eSCédric Le Goater     /* We need some cpu model to instantiate the PnvChip class */
417e997040eSCédric Le Goater     if (machine->cpu_model == NULL) {
418e997040eSCédric Le Goater         machine->cpu_model = "POWER8";
419e997040eSCédric Le Goater     }
420e997040eSCédric Le Goater 
421e997040eSCédric Le Goater     /* Create the processor chips */
422e997040eSCédric Le Goater     chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", machine->cpu_model);
423e997040eSCédric Le Goater     if (!object_class_by_name(chip_typename)) {
424e997040eSCédric Le Goater         error_report("qemu: invalid CPU model '%s' for %s machine",
425e997040eSCédric Le Goater                      machine->cpu_model, MACHINE_GET_CLASS(machine)->name);
426e997040eSCédric Le Goater         exit(1);
427e997040eSCédric Le Goater     }
428e997040eSCédric Le Goater 
429e997040eSCédric Le Goater     pnv->chips = g_new0(PnvChip *, pnv->num_chips);
430e997040eSCédric Le Goater     for (i = 0; i < pnv->num_chips; i++) {
431e997040eSCédric Le Goater         char chip_name[32];
432e997040eSCédric Le Goater         Object *chip = object_new(chip_typename);
433e997040eSCédric Le Goater 
434e997040eSCédric Le Goater         pnv->chips[i] = PNV_CHIP(chip);
435e997040eSCédric Le Goater 
436e997040eSCédric Le Goater         /* TODO: put all the memory in one node on chip 0 until we find a
437e997040eSCédric Le Goater          * way to specify different ranges for each chip
438e997040eSCédric Le Goater          */
439e997040eSCédric Le Goater         if (i == 0) {
440e997040eSCédric Le Goater             object_property_set_int(chip, machine->ram_size, "ram-size",
441e997040eSCédric Le Goater                                     &error_fatal);
442e997040eSCédric Le Goater         }
443e997040eSCédric Le Goater 
444e997040eSCédric Le Goater         snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
445e997040eSCédric Le Goater         object_property_add_child(OBJECT(pnv), chip_name, chip, &error_fatal);
446e997040eSCédric Le Goater         object_property_set_int(chip, PNV_CHIP_HWID(i), "chip-id",
447e997040eSCédric Le Goater                                 &error_fatal);
448397a79e7SCédric Le Goater         object_property_set_int(chip, smp_cores, "nr-cores", &error_fatal);
449e997040eSCédric Le Goater         object_property_set_bool(chip, true, "realized", &error_fatal);
450e997040eSCédric Le Goater     }
451e997040eSCédric Le Goater     g_free(chip_typename);
4523495b6b6SCédric Le Goater 
4533495b6b6SCédric Le Goater     /* Instantiate ISA bus on chip 0 */
4543495b6b6SCédric Le Goater     pnv->isa_bus = pnv_isa_create(pnv->chips[0]);
4553495b6b6SCédric Le Goater 
4563495b6b6SCédric Le Goater     /* Create serial port */
4573495b6b6SCédric Le Goater     serial_hds_isa_init(pnv->isa_bus, 0, MAX_SERIAL_PORTS);
4583495b6b6SCédric Le Goater 
4593495b6b6SCédric Le Goater     /* Create an RTC ISA device too */
4603495b6b6SCédric Le Goater     rtc_init(pnv->isa_bus, 2000, NULL);
461e997040eSCédric Le Goater }
462e997040eSCédric Le Goater 
463631adaffSCédric Le Goater /*
464631adaffSCédric Le Goater  *    0:21  Reserved - Read as zeros
465631adaffSCédric Le Goater  *   22:24  Chip ID
466631adaffSCédric Le Goater  *   25:28  Core number
467631adaffSCédric Le Goater  *   29:31  Thread ID
468631adaffSCédric Le Goater  */
469631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
470631adaffSCédric Le Goater {
471631adaffSCédric Le Goater     return (chip->chip_id << 7) | (core_id << 3);
472631adaffSCédric Le Goater }
473631adaffSCédric Le Goater 
474631adaffSCédric Le Goater /*
475631adaffSCédric Le Goater  *    0:48  Reserved - Read as zeroes
476631adaffSCédric Le Goater  *   49:52  Node ID
477631adaffSCédric Le Goater  *   53:55  Chip ID
478631adaffSCédric Le Goater  *   56     Reserved - Read as zero
479631adaffSCédric Le Goater  *   57:61  Core number
480631adaffSCédric Le Goater  *   62:63  Thread ID
481631adaffSCédric Le Goater  *
482631adaffSCédric Le Goater  * We only care about the lower bits. uint32_t is fine for the moment.
483631adaffSCédric Le Goater  */
484631adaffSCédric Le Goater static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
485631adaffSCédric Le Goater {
486631adaffSCédric Le Goater     return (chip->chip_id << 8) | (core_id << 2);
487631adaffSCédric Le Goater }
488631adaffSCédric Le Goater 
489397a79e7SCédric Le Goater /* Allowed core identifiers on a POWER8 Processor Chip :
490397a79e7SCédric Le Goater  *
491397a79e7SCédric Le Goater  * <EX0 reserved>
492397a79e7SCédric Le Goater  *  EX1  - Venice only
493397a79e7SCédric Le Goater  *  EX2  - Venice only
494397a79e7SCédric Le Goater  *  EX3  - Venice only
495397a79e7SCédric Le Goater  *  EX4
496397a79e7SCédric Le Goater  *  EX5
497397a79e7SCédric Le Goater  *  EX6
498397a79e7SCédric Le Goater  * <EX7,8 reserved> <reserved>
499397a79e7SCédric Le Goater  *  EX9  - Venice only
500397a79e7SCédric Le Goater  *  EX10 - Venice only
501397a79e7SCédric Le Goater  *  EX11 - Venice only
502397a79e7SCédric Le Goater  *  EX12
503397a79e7SCédric Le Goater  *  EX13
504397a79e7SCédric Le Goater  *  EX14
505397a79e7SCédric Le Goater  * <EX15 reserved>
506397a79e7SCédric Le Goater  */
507397a79e7SCédric Le Goater #define POWER8E_CORE_MASK  (0x7070ull)
508397a79e7SCédric Le Goater #define POWER8_CORE_MASK   (0x7e7eull)
509397a79e7SCédric Le Goater 
510397a79e7SCédric Le Goater /*
511397a79e7SCédric Le Goater  * POWER9 has 24 cores, ids starting at 0x20
512397a79e7SCédric Le Goater  */
513397a79e7SCédric Le Goater #define POWER9_CORE_MASK   (0xffffff00000000ull)
514397a79e7SCédric Le Goater 
515e997040eSCédric Le Goater static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
516e997040eSCédric Le Goater {
517e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
518e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
519e997040eSCédric Le Goater 
520e997040eSCédric Le Goater     k->cpu_model = "POWER8E";
521e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8E;
522e997040eSCédric Le Goater     k->chip_cfam_id = 0x221ef04980000000ull;  /* P8 Murano DD2.1 */
523397a79e7SCédric Le Goater     k->cores_mask = POWER8E_CORE_MASK;
524631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
525967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
526ad521238SCédric Le Goater     k->xscom_core_base = 0x10000000ull;
527e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8E";
528e997040eSCédric Le Goater }
529e997040eSCédric Le Goater 
530e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8e_info = {
531e997040eSCédric Le Goater     .name          = TYPE_PNV_CHIP_POWER8E,
532e997040eSCédric Le Goater     .parent        = TYPE_PNV_CHIP,
533e997040eSCédric Le Goater     .instance_size = sizeof(PnvChip),
534e997040eSCédric Le Goater     .class_init    = pnv_chip_power8e_class_init,
535e997040eSCédric Le Goater };
536e997040eSCédric Le Goater 
537e997040eSCédric Le Goater static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
538e997040eSCédric Le Goater {
539e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
540e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
541e997040eSCédric Le Goater 
542e997040eSCédric Le Goater     k->cpu_model = "POWER8";
543e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8;
544e997040eSCédric Le Goater     k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
545397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
546631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
547967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
548ad521238SCédric Le Goater     k->xscom_core_base = 0x10000000ull;
549e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8";
550e997040eSCédric Le Goater }
551e997040eSCédric Le Goater 
552e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8_info = {
553e997040eSCédric Le Goater     .name          = TYPE_PNV_CHIP_POWER8,
554e997040eSCédric Le Goater     .parent        = TYPE_PNV_CHIP,
555e997040eSCédric Le Goater     .instance_size = sizeof(PnvChip),
556e997040eSCédric Le Goater     .class_init    = pnv_chip_power8_class_init,
557e997040eSCédric Le Goater };
558e997040eSCédric Le Goater 
559e997040eSCédric Le Goater static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
560e997040eSCédric Le Goater {
561e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
562e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
563e997040eSCédric Le Goater 
564e997040eSCédric Le Goater     k->cpu_model = "POWER8NVL";
565e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER8NVL;
566e997040eSCédric Le Goater     k->chip_cfam_id = 0x120d304980000000ull;  /* P8 Naples DD1.0 */
567397a79e7SCédric Le Goater     k->cores_mask = POWER8_CORE_MASK;
568631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p8;
569967b7523SCédric Le Goater     k->xscom_base = 0x003fc0000000000ull;
570ad521238SCédric Le Goater     k->xscom_core_base = 0x10000000ull;
571e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER8NVL";
572e997040eSCédric Le Goater }
573e997040eSCédric Le Goater 
574e997040eSCédric Le Goater static const TypeInfo pnv_chip_power8nvl_info = {
575e997040eSCédric Le Goater     .name          = TYPE_PNV_CHIP_POWER8NVL,
576e997040eSCédric Le Goater     .parent        = TYPE_PNV_CHIP,
577e997040eSCédric Le Goater     .instance_size = sizeof(PnvChip),
578e997040eSCédric Le Goater     .class_init    = pnv_chip_power8nvl_class_init,
579e997040eSCédric Le Goater };
580e997040eSCédric Le Goater 
581e997040eSCédric Le Goater static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
582e997040eSCédric Le Goater {
583e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
584e997040eSCédric Le Goater     PnvChipClass *k = PNV_CHIP_CLASS(klass);
585e997040eSCédric Le Goater 
586e997040eSCédric Le Goater     k->cpu_model = "POWER9";
587e997040eSCédric Le Goater     k->chip_type = PNV_CHIP_POWER9;
588e997040eSCédric Le Goater     k->chip_cfam_id = 0x100d104980000000ull; /* P9 Nimbus DD1.0 */
589397a79e7SCédric Le Goater     k->cores_mask = POWER9_CORE_MASK;
590631adaffSCédric Le Goater     k->core_pir = pnv_chip_core_pir_p9;
591967b7523SCédric Le Goater     k->xscom_base = 0x00603fc00000000ull;
592ad521238SCédric Le Goater     k->xscom_core_base = 0x0ull;
593e997040eSCédric Le Goater     dc->desc = "PowerNV Chip POWER9";
594e997040eSCédric Le Goater }
595e997040eSCédric Le Goater 
596e997040eSCédric Le Goater static const TypeInfo pnv_chip_power9_info = {
597e997040eSCédric Le Goater     .name          = TYPE_PNV_CHIP_POWER9,
598e997040eSCédric Le Goater     .parent        = TYPE_PNV_CHIP,
599e997040eSCédric Le Goater     .instance_size = sizeof(PnvChip),
600e997040eSCédric Le Goater     .class_init    = pnv_chip_power9_class_init,
601e997040eSCédric Le Goater };
602e997040eSCédric Le Goater 
603397a79e7SCédric Le Goater static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp)
604397a79e7SCédric Le Goater {
605397a79e7SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
606397a79e7SCédric Le Goater     int cores_max;
607397a79e7SCédric Le Goater 
608397a79e7SCédric Le Goater     /*
609397a79e7SCédric Le Goater      * No custom mask for this chip, let's use the default one from *
610397a79e7SCédric Le Goater      * the chip class
611397a79e7SCédric Le Goater      */
612397a79e7SCédric Le Goater     if (!chip->cores_mask) {
613397a79e7SCédric Le Goater         chip->cores_mask = pcc->cores_mask;
614397a79e7SCédric Le Goater     }
615397a79e7SCédric Le Goater 
616397a79e7SCédric Le Goater     /* filter alien core ids ! some are reserved */
617397a79e7SCédric Le Goater     if ((chip->cores_mask & pcc->cores_mask) != chip->cores_mask) {
618397a79e7SCédric Le Goater         error_setg(errp, "warning: invalid core mask for chip Ox%"PRIx64" !",
619397a79e7SCédric Le Goater                    chip->cores_mask);
620397a79e7SCédric Le Goater         return;
621397a79e7SCédric Le Goater     }
622397a79e7SCédric Le Goater     chip->cores_mask &= pcc->cores_mask;
623397a79e7SCédric Le Goater 
624397a79e7SCédric Le Goater     /* now that we have a sane layout, let check the number of cores */
62527d9ffd4SDavid Gibson     cores_max = ctpop64(chip->cores_mask);
626397a79e7SCédric Le Goater     if (chip->nr_cores > cores_max) {
627397a79e7SCédric Le Goater         error_setg(errp, "warning: too many cores for chip ! Limit is %d",
628397a79e7SCédric Le Goater                    cores_max);
629397a79e7SCédric Le Goater         return;
630397a79e7SCédric Le Goater     }
631397a79e7SCédric Le Goater }
632397a79e7SCédric Le Goater 
633967b7523SCédric Le Goater static void pnv_chip_init(Object *obj)
634967b7523SCédric Le Goater {
635967b7523SCédric Le Goater     PnvChip *chip = PNV_CHIP(obj);
636967b7523SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
637967b7523SCédric Le Goater 
638967b7523SCédric Le Goater     chip->xscom_base = pcc->xscom_base;
639a3980bf5SBenjamin Herrenschmidt 
640a3980bf5SBenjamin Herrenschmidt     object_initialize(&chip->lpc, sizeof(chip->lpc), TYPE_PNV_LPC);
641a3980bf5SBenjamin Herrenschmidt     object_property_add_child(obj, "lpc", OBJECT(&chip->lpc), NULL);
642967b7523SCédric Le Goater }
643967b7523SCédric Le Goater 
644e997040eSCédric Le Goater static void pnv_chip_realize(DeviceState *dev, Error **errp)
645e997040eSCédric Le Goater {
646397a79e7SCédric Le Goater     PnvChip *chip = PNV_CHIP(dev);
647397a79e7SCédric Le Goater     Error *error = NULL;
648d2fd9612SCédric Le Goater     PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
649d2fd9612SCédric Le Goater     char *typename = pnv_core_typename(pcc->cpu_model);
650d2fd9612SCédric Le Goater     size_t typesize = object_type_get_instance_size(typename);
651d2fd9612SCédric Le Goater     int i, core_hwid;
652397a79e7SCédric Le Goater 
653d2fd9612SCédric Le Goater     if (!object_class_by_name(typename)) {
654d2fd9612SCédric Le Goater         error_setg(errp, "Unable to find PowerNV CPU Core '%s'", typename);
655d2fd9612SCédric Le Goater         return;
656d2fd9612SCédric Le Goater     }
657d2fd9612SCédric Le Goater 
658967b7523SCédric Le Goater     /* XSCOM bridge */
659967b7523SCédric Le Goater     pnv_xscom_realize(chip, &error);
660967b7523SCédric Le Goater     if (error) {
661967b7523SCédric Le Goater         error_propagate(errp, error);
662967b7523SCédric Le Goater         return;
663967b7523SCédric Le Goater     }
664967b7523SCédric Le Goater     sysbus_mmio_map(SYS_BUS_DEVICE(chip), 0, PNV_XSCOM_BASE(chip));
665967b7523SCédric Le Goater 
666d2fd9612SCédric Le Goater     /* Cores */
667397a79e7SCédric Le Goater     pnv_chip_core_sanitize(chip, &error);
668397a79e7SCédric Le Goater     if (error) {
669397a79e7SCédric Le Goater         error_propagate(errp, error);
670397a79e7SCédric Le Goater         return;
671397a79e7SCédric Le Goater     }
672d2fd9612SCédric Le Goater 
673d2fd9612SCédric Le Goater     chip->cores = g_malloc0(typesize * chip->nr_cores);
674d2fd9612SCédric Le Goater 
675d2fd9612SCédric Le Goater     for (i = 0, core_hwid = 0; (core_hwid < sizeof(chip->cores_mask) * 8)
676d2fd9612SCédric Le Goater              && (i < chip->nr_cores); core_hwid++) {
677d2fd9612SCédric Le Goater         char core_name[32];
678d2fd9612SCédric Le Goater         void *pnv_core = chip->cores + i * typesize;
679d2fd9612SCédric Le Goater 
680d2fd9612SCédric Le Goater         if (!(chip->cores_mask & (1ull << core_hwid))) {
681d2fd9612SCédric Le Goater             continue;
682d2fd9612SCédric Le Goater         }
683d2fd9612SCédric Le Goater 
684d2fd9612SCédric Le Goater         object_initialize(pnv_core, typesize, typename);
685d2fd9612SCédric Le Goater         snprintf(core_name, sizeof(core_name), "core[%d]", core_hwid);
686d2fd9612SCédric Le Goater         object_property_add_child(OBJECT(chip), core_name, OBJECT(pnv_core),
687d2fd9612SCédric Le Goater                                   &error_fatal);
688d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), smp_threads, "nr-threads",
689d2fd9612SCédric Le Goater                                 &error_fatal);
690d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core), core_hwid,
691d2fd9612SCédric Le Goater                                 CPU_CORE_PROP_CORE_ID, &error_fatal);
692d2fd9612SCédric Le Goater         object_property_set_int(OBJECT(pnv_core),
693d2fd9612SCédric Le Goater                                 pcc->core_pir(chip, core_hwid),
694d2fd9612SCédric Le Goater                                 "pir", &error_fatal);
695d2fd9612SCédric Le Goater         object_property_set_bool(OBJECT(pnv_core), true, "realized",
696d2fd9612SCédric Le Goater                                  &error_fatal);
697d2fd9612SCédric Le Goater         object_unref(OBJECT(pnv_core));
69824ece072SCédric Le Goater 
69924ece072SCédric Le Goater         /* Each core has an XSCOM MMIO region */
700ad521238SCédric Le Goater         pnv_xscom_add_subregion(chip,
701ad521238SCédric Le Goater                                 PNV_XSCOM_EX_CORE_BASE(pcc->xscom_core_base,
702ad521238SCédric Le Goater                                                        core_hwid),
70324ece072SCédric Le Goater                                 &PNV_CORE(pnv_core)->xscom_regs);
704d2fd9612SCédric Le Goater         i++;
705d2fd9612SCédric Le Goater     }
706d2fd9612SCédric Le Goater     g_free(typename);
707a3980bf5SBenjamin Herrenschmidt 
708a3980bf5SBenjamin Herrenschmidt     /* Create LPC controller */
709a3980bf5SBenjamin Herrenschmidt     object_property_set_bool(OBJECT(&chip->lpc), true, "realized",
710a3980bf5SBenjamin Herrenschmidt                              &error_fatal);
711a3980bf5SBenjamin Herrenschmidt     pnv_xscom_add_subregion(chip, PNV_XSCOM_LPC_BASE, &chip->lpc.xscom_regs);
712e997040eSCédric Le Goater }
713e997040eSCédric Le Goater 
714e997040eSCédric Le Goater static Property pnv_chip_properties[] = {
715e997040eSCédric Le Goater     DEFINE_PROP_UINT32("chip-id", PnvChip, chip_id, 0),
716e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-start", PnvChip, ram_start, 0),
717e997040eSCédric Le Goater     DEFINE_PROP_UINT64("ram-size", PnvChip, ram_size, 0),
718397a79e7SCédric Le Goater     DEFINE_PROP_UINT32("nr-cores", PnvChip, nr_cores, 1),
719397a79e7SCédric Le Goater     DEFINE_PROP_UINT64("cores-mask", PnvChip, cores_mask, 0x0),
720e997040eSCédric Le Goater     DEFINE_PROP_END_OF_LIST(),
721e997040eSCédric Le Goater };
722e997040eSCédric Le Goater 
723e997040eSCédric Le Goater static void pnv_chip_class_init(ObjectClass *klass, void *data)
724e997040eSCédric Le Goater {
725e997040eSCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
726e997040eSCédric Le Goater 
7279d169fb3SThomas Huth     set_bit(DEVICE_CATEGORY_CPU, dc->categories);
728e997040eSCédric Le Goater     dc->realize = pnv_chip_realize;
729e997040eSCédric Le Goater     dc->props = pnv_chip_properties;
730e997040eSCédric Le Goater     dc->desc = "PowerNV Chip";
731e997040eSCédric Le Goater }
732e997040eSCédric Le Goater 
733e997040eSCédric Le Goater static const TypeInfo pnv_chip_info = {
734e997040eSCédric Le Goater     .name          = TYPE_PNV_CHIP,
735e997040eSCédric Le Goater     .parent        = TYPE_SYS_BUS_DEVICE,
736e997040eSCédric Le Goater     .class_init    = pnv_chip_class_init,
737967b7523SCédric Le Goater     .instance_init = pnv_chip_init,
738e997040eSCédric Le Goater     .class_size    = sizeof(PnvChipClass),
739e997040eSCédric Le Goater     .abstract      = true,
740e997040eSCédric Le Goater };
741e997040eSCédric Le Goater 
742*36fc6f08SCédric Le Goater static PowerPCCPU *ppc_get_vcpu_by_pir(int pir)
743*36fc6f08SCédric Le Goater {
744*36fc6f08SCédric Le Goater     CPUState *cs;
745*36fc6f08SCédric Le Goater 
746*36fc6f08SCédric Le Goater     CPU_FOREACH(cs) {
747*36fc6f08SCédric Le Goater         PowerPCCPU *cpu = POWERPC_CPU(cs);
748*36fc6f08SCédric Le Goater         CPUPPCState *env = &cpu->env;
749*36fc6f08SCédric Le Goater 
750*36fc6f08SCédric Le Goater         if (env->spr_cb[SPR_PIR].default_value == pir) {
751*36fc6f08SCédric Le Goater             return cpu;
752*36fc6f08SCédric Le Goater         }
753*36fc6f08SCédric Le Goater     }
754*36fc6f08SCédric Le Goater 
755*36fc6f08SCédric Le Goater     return NULL;
756*36fc6f08SCédric Le Goater }
757*36fc6f08SCédric Le Goater 
758*36fc6f08SCédric Le Goater static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
759*36fc6f08SCédric Le Goater {
760*36fc6f08SCédric Le Goater     PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
761*36fc6f08SCédric Le Goater 
762*36fc6f08SCédric Le Goater     return cpu ? ICP(cpu->intc) : NULL;
763*36fc6f08SCédric Le Goater }
764*36fc6f08SCédric Le Goater 
765e997040eSCédric Le Goater static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
766e997040eSCédric Le Goater                               void *opaque, Error **errp)
767e997040eSCédric Le Goater {
768e997040eSCédric Le Goater     visit_type_uint32(v, name, &POWERNV_MACHINE(obj)->num_chips, errp);
769e997040eSCédric Le Goater }
770e997040eSCédric Le Goater 
771e997040eSCédric Le Goater static void pnv_set_num_chips(Object *obj, Visitor *v, const char *name,
772e997040eSCédric Le Goater                               void *opaque, Error **errp)
773e997040eSCédric Le Goater {
774e997040eSCédric Le Goater     PnvMachineState *pnv = POWERNV_MACHINE(obj);
775e997040eSCédric Le Goater     uint32_t num_chips;
776e997040eSCédric Le Goater     Error *local_err = NULL;
777e997040eSCédric Le Goater 
778e997040eSCédric Le Goater     visit_type_uint32(v, name, &num_chips, &local_err);
779e997040eSCédric Le Goater     if (local_err) {
780e997040eSCédric Le Goater         error_propagate(errp, local_err);
781e997040eSCédric Le Goater         return;
782e997040eSCédric Le Goater     }
783e997040eSCédric Le Goater 
784e997040eSCédric Le Goater     /*
785e997040eSCédric Le Goater      * TODO: should we decide on how many chips we can create based
786e997040eSCédric Le Goater      * on #cores and Venice vs. Murano vs. Naples chip type etc...,
787e997040eSCédric Le Goater      */
788e997040eSCédric Le Goater     if (!is_power_of_2(num_chips) || num_chips > 4) {
789e997040eSCédric Le Goater         error_setg(errp, "invalid number of chips: '%d'", num_chips);
790e997040eSCédric Le Goater         return;
791e997040eSCédric Le Goater     }
792e997040eSCédric Le Goater 
793e997040eSCédric Le Goater     pnv->num_chips = num_chips;
794e997040eSCédric Le Goater }
795e997040eSCédric Le Goater 
796e997040eSCédric Le Goater static void powernv_machine_initfn(Object *obj)
797e997040eSCédric Le Goater {
798e997040eSCédric Le Goater     PnvMachineState *pnv = POWERNV_MACHINE(obj);
799e997040eSCédric Le Goater     pnv->num_chips = 1;
800e997040eSCédric Le Goater }
801e997040eSCédric Le Goater 
802e997040eSCédric Le Goater static void powernv_machine_class_props_init(ObjectClass *oc)
803e997040eSCédric Le Goater {
804e997040eSCédric Le Goater     object_class_property_add(oc, "num-chips", "uint32_t",
805e997040eSCédric Le Goater                               pnv_get_num_chips, pnv_set_num_chips,
806e997040eSCédric Le Goater                               NULL, NULL, NULL);
807e997040eSCédric Le Goater     object_class_property_set_description(oc, "num-chips",
808e997040eSCédric Le Goater                               "Specifies the number of processor chips",
809e997040eSCédric Le Goater                               NULL);
8109e933f4aSBenjamin Herrenschmidt }
8119e933f4aSBenjamin Herrenschmidt 
8129e933f4aSBenjamin Herrenschmidt static void powernv_machine_class_init(ObjectClass *oc, void *data)
8139e933f4aSBenjamin Herrenschmidt {
8149e933f4aSBenjamin Herrenschmidt     MachineClass *mc = MACHINE_CLASS(oc);
815*36fc6f08SCédric Le Goater     XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
8169e933f4aSBenjamin Herrenschmidt 
8179e933f4aSBenjamin Herrenschmidt     mc->desc = "IBM PowerNV (Non-Virtualized)";
8189e933f4aSBenjamin Herrenschmidt     mc->init = ppc_powernv_init;
8199e933f4aSBenjamin Herrenschmidt     mc->reset = ppc_powernv_reset;
8209e933f4aSBenjamin Herrenschmidt     mc->max_cpus = MAX_CPUS;
8219e933f4aSBenjamin Herrenschmidt     mc->block_default_type = IF_IDE; /* Pnv provides a AHCI device for
8229e933f4aSBenjamin Herrenschmidt                                       * storage */
8239e933f4aSBenjamin Herrenschmidt     mc->no_parallel = 1;
8249e933f4aSBenjamin Herrenschmidt     mc->default_boot_order = NULL;
8259e933f4aSBenjamin Herrenschmidt     mc->default_ram_size = 1 * G_BYTE;
826*36fc6f08SCédric Le Goater     xic->icp_get = pnv_icp_get;
827e997040eSCédric Le Goater 
828e997040eSCédric Le Goater     powernv_machine_class_props_init(oc);
8299e933f4aSBenjamin Herrenschmidt }
8309e933f4aSBenjamin Herrenschmidt 
8319e933f4aSBenjamin Herrenschmidt static const TypeInfo powernv_machine_info = {
8329e933f4aSBenjamin Herrenschmidt     .name          = TYPE_POWERNV_MACHINE,
8339e933f4aSBenjamin Herrenschmidt     .parent        = TYPE_MACHINE,
8349e933f4aSBenjamin Herrenschmidt     .instance_size = sizeof(PnvMachineState),
835e997040eSCédric Le Goater     .instance_init = powernv_machine_initfn,
8369e933f4aSBenjamin Herrenschmidt     .class_init    = powernv_machine_class_init,
837*36fc6f08SCédric Le Goater     .interfaces = (InterfaceInfo[]) {
838*36fc6f08SCédric Le Goater         { TYPE_XICS_FABRIC },
839*36fc6f08SCédric Le Goater         { },
840*36fc6f08SCédric Le Goater     },
8419e933f4aSBenjamin Herrenschmidt };
8429e933f4aSBenjamin Herrenschmidt 
8439e933f4aSBenjamin Herrenschmidt static void powernv_machine_register_types(void)
8449e933f4aSBenjamin Herrenschmidt {
8459e933f4aSBenjamin Herrenschmidt     type_register_static(&powernv_machine_info);
846e997040eSCédric Le Goater     type_register_static(&pnv_chip_info);
847e997040eSCédric Le Goater     type_register_static(&pnv_chip_power8e_info);
848e997040eSCédric Le Goater     type_register_static(&pnv_chip_power8_info);
849e997040eSCédric Le Goater     type_register_static(&pnv_chip_power8nvl_info);
850e997040eSCédric Le Goater     type_register_static(&pnv_chip_power9_info);
8519e933f4aSBenjamin Herrenschmidt }
8529e933f4aSBenjamin Herrenschmidt 
8539e933f4aSBenjamin Herrenschmidt type_init(powernv_machine_register_types)
854