xref: /openbmc/qemu/hw/ppc/spapr.c (revision 5c0139a8)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Copyright (c) 2004-2007 Fabrice Bellard
553018216SPaolo Bonzini  * Copyright (c) 2007 Jocelyn Mayer
653018216SPaolo Bonzini  * Copyright (c) 2010 David Gibson, IBM Corporation.
753018216SPaolo Bonzini  *
853018216SPaolo Bonzini  * Permission is hereby granted, free of charge, to any person obtaining a copy
953018216SPaolo Bonzini  * of this software and associated documentation files (the "Software"), to deal
1053018216SPaolo Bonzini  * in the Software without restriction, including without limitation the rights
1153018216SPaolo Bonzini  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1253018216SPaolo Bonzini  * copies of the Software, and to permit persons to whom the Software is
1353018216SPaolo Bonzini  * furnished to do so, subject to the following conditions:
1453018216SPaolo Bonzini  *
1553018216SPaolo Bonzini  * The above copyright notice and this permission notice shall be included in
1653018216SPaolo Bonzini  * all copies or substantial portions of the Software.
1753018216SPaolo Bonzini  *
1853018216SPaolo Bonzini  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1953018216SPaolo Bonzini  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2053018216SPaolo Bonzini  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
2153018216SPaolo Bonzini  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2253018216SPaolo Bonzini  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2353018216SPaolo Bonzini  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2453018216SPaolo Bonzini  * THE SOFTWARE.
2553018216SPaolo Bonzini  *
2653018216SPaolo Bonzini  */
270d75590dSPeter Maydell #include "qemu/osdep.h"
28da34e65cSMarkus Armbruster #include "qapi/error.h"
2953018216SPaolo Bonzini #include "sysemu/sysemu.h"
30e35704baSEduardo Habkost #include "sysemu/numa.h"
3153018216SPaolo Bonzini #include "hw/hw.h"
3203dd024fSPaolo Bonzini #include "qemu/log.h"
3371461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h"
3453018216SPaolo Bonzini #include "elf.h"
3553018216SPaolo Bonzini #include "net/net.h"
36ad440b4aSAndrew Jones #include "sysemu/device_tree.h"
37fa1d36dfSMarkus Armbruster #include "sysemu/block-backend.h"
3853018216SPaolo Bonzini #include "sysemu/cpus.h"
3953018216SPaolo Bonzini #include "sysemu/kvm.h"
4053018216SPaolo Bonzini #include "kvm_ppc.h"
41ff14e817SDr. David Alan Gilbert #include "migration/migration.h"
424be21d56SDavid Gibson #include "mmu-hash64.h"
433794d548SAlexey Kardashevskiy #include "qom/cpu.h"
4453018216SPaolo Bonzini 
4553018216SPaolo Bonzini #include "hw/boards.h"
460d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h"
4753018216SPaolo Bonzini #include "hw/loader.h"
4853018216SPaolo Bonzini 
497804c353SCédric Le Goater #include "hw/ppc/fdt.h"
500d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h"
510d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h"
520d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h"
530d09e41aSPaolo Bonzini #include "hw/ppc/xics.h"
5453018216SPaolo Bonzini #include "hw/pci/msi.h"
5553018216SPaolo Bonzini 
5653018216SPaolo Bonzini #include "hw/pci/pci.h"
5771461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h"
5871461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h"
5953018216SPaolo Bonzini 
6053018216SPaolo Bonzini #include "exec/address-spaces.h"
6153018216SPaolo Bonzini #include "hw/usb.h"
6253018216SPaolo Bonzini #include "qemu/config-file.h"
63135a129aSAneesh Kumar K.V #include "qemu/error-report.h"
642a6593cbSAlexey Kardashevskiy #include "trace.h"
6534316482SAlexey Kardashevskiy #include "hw/nmi.h"
6653018216SPaolo Bonzini 
6768a27b20SMichael S. Tsirkin #include "hw/compat.h"
68f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
6994a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h"
702474bfd4SIgor Mammedov #include "qmp-commands.h"
7168a27b20SMichael S. Tsirkin 
7253018216SPaolo Bonzini #include <libfdt.h>
7353018216SPaolo Bonzini 
7453018216SPaolo Bonzini /* SLOF memory layout:
7553018216SPaolo Bonzini  *
7653018216SPaolo Bonzini  * SLOF raw image loaded at 0, copies its romfs right below the flat
7753018216SPaolo Bonzini  * device-tree, then position SLOF itself 31M below that
7853018216SPaolo Bonzini  *
7953018216SPaolo Bonzini  * So we set FW_OVERHEAD to 40MB which should account for all of that
8053018216SPaolo Bonzini  * and more
8153018216SPaolo Bonzini  *
8253018216SPaolo Bonzini  * We load our kernel at 4M, leaving space for SLOF initial image
8353018216SPaolo Bonzini  */
8438b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE            0x100000
8553018216SPaolo Bonzini #define RTAS_MAX_SIZE           0x10000
86b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR           0x80000000 /* RTAS must stay below that */
8753018216SPaolo Bonzini #define FW_MAX_SIZE             0x400000
8853018216SPaolo Bonzini #define FW_FILE_NAME            "slof.bin"
8953018216SPaolo Bonzini #define FW_OVERHEAD             0x2800000
9053018216SPaolo Bonzini #define KERNEL_LOAD_ADDR        FW_MAX_SIZE
9153018216SPaolo Bonzini 
9253018216SPaolo Bonzini #define MIN_RMA_SLOF            128UL
9353018216SPaolo Bonzini 
9453018216SPaolo Bonzini #define PHANDLE_XICP            0x00001111
9553018216SPaolo Bonzini 
9653018216SPaolo Bonzini #define HTAB_SIZE(spapr)        (1ULL << ((spapr)->htab_shift))
9753018216SPaolo Bonzini 
98c04d6cfaSAnthony Liguori static XICSState *try_create_xics(const char *type, int nr_servers,
9934f2af3dSMarkus Armbruster                                   int nr_irqs, Error **errp)
100c04d6cfaSAnthony Liguori {
10134f2af3dSMarkus Armbruster     Error *err = NULL;
102c04d6cfaSAnthony Liguori     DeviceState *dev;
103c04d6cfaSAnthony Liguori 
104c04d6cfaSAnthony Liguori     dev = qdev_create(NULL, type);
105c04d6cfaSAnthony Liguori     qdev_prop_set_uint32(dev, "nr_servers", nr_servers);
106c04d6cfaSAnthony Liguori     qdev_prop_set_uint32(dev, "nr_irqs", nr_irqs);
10734f2af3dSMarkus Armbruster     object_property_set_bool(OBJECT(dev), true, "realized", &err);
10834f2af3dSMarkus Armbruster     if (err) {
10934f2af3dSMarkus Armbruster         error_propagate(errp, err);
11034f2af3dSMarkus Armbruster         object_unparent(OBJECT(dev));
111c04d6cfaSAnthony Liguori         return NULL;
112c04d6cfaSAnthony Liguori     }
1135a3d7b23SAlexey Kardashevskiy     return XICS_COMMON(dev);
114c04d6cfaSAnthony Liguori }
115c04d6cfaSAnthony Liguori 
116446f16a6SMarcel Apfelbaum static XICSState *xics_system_init(MachineState *machine,
1171e49182dSDavid Gibson                                    int nr_servers, int nr_irqs, Error **errp)
118c04d6cfaSAnthony Liguori {
11927f24582SBenjamin Herrenschmidt     XICSState *xics = NULL;
120c04d6cfaSAnthony Liguori 
12111ad93f6SDavid Gibson     if (kvm_enabled()) {
12234f2af3dSMarkus Armbruster         Error *err = NULL;
12334f2af3dSMarkus Armbruster 
124446f16a6SMarcel Apfelbaum         if (machine_kernel_irqchip_allowed(machine)) {
12527f24582SBenjamin Herrenschmidt             xics = try_create_xics(TYPE_XICS_SPAPR_KVM, nr_servers, nr_irqs,
126161deaf2SBenjamin Herrenschmidt                                    &err);
12711ad93f6SDavid Gibson         }
12827f24582SBenjamin Herrenschmidt         if (machine_kernel_irqchip_required(machine) && !xics) {
129b83baa60SMarkus Armbruster             error_reportf_err(err,
130b83baa60SMarkus Armbruster                               "kernel_irqchip requested but unavailable: ");
131b83baa60SMarkus Armbruster         } else {
132903a41d3SStefano Dong (董兴水)             error_free(err);
13311ad93f6SDavid Gibson         }
134b83baa60SMarkus Armbruster     }
13511ad93f6SDavid Gibson 
13627f24582SBenjamin Herrenschmidt     if (!xics) {
13727f24582SBenjamin Herrenschmidt         xics = try_create_xics(TYPE_XICS_SPAPR, nr_servers, nr_irqs, errp);
138c04d6cfaSAnthony Liguori     }
139c04d6cfaSAnthony Liguori 
14027f24582SBenjamin Herrenschmidt     return xics;
141c04d6cfaSAnthony Liguori }
142c04d6cfaSAnthony Liguori 
143833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu,
144833d4668SAlexey Kardashevskiy                                   int smt_threads)
145833d4668SAlexey Kardashevskiy {
146833d4668SAlexey Kardashevskiy     int i, ret = 0;
147833d4668SAlexey Kardashevskiy     uint32_t servers_prop[smt_threads];
148833d4668SAlexey Kardashevskiy     uint32_t gservers_prop[smt_threads * 2];
149833d4668SAlexey Kardashevskiy     int index = ppc_get_vcpu_dt_id(cpu);
150833d4668SAlexey Kardashevskiy 
1516d9412eaSAlexey Kardashevskiy     if (cpu->cpu_version) {
1524bce526eSLaurent Dufour         ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->cpu_version);
1536d9412eaSAlexey Kardashevskiy         if (ret < 0) {
1546d9412eaSAlexey Kardashevskiy             return ret;
1556d9412eaSAlexey Kardashevskiy         }
1566d9412eaSAlexey Kardashevskiy     }
1576d9412eaSAlexey Kardashevskiy 
158833d4668SAlexey Kardashevskiy     /* Build interrupt servers and gservers properties */
159833d4668SAlexey Kardashevskiy     for (i = 0; i < smt_threads; i++) {
160833d4668SAlexey Kardashevskiy         servers_prop[i] = cpu_to_be32(index + i);
161833d4668SAlexey Kardashevskiy         /* Hack, direct the group queues back to cpu 0 */
162833d4668SAlexey Kardashevskiy         gservers_prop[i*2] = cpu_to_be32(index + i);
163833d4668SAlexey Kardashevskiy         gservers_prop[i*2 + 1] = 0;
164833d4668SAlexey Kardashevskiy     }
165833d4668SAlexey Kardashevskiy     ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
166833d4668SAlexey Kardashevskiy                       servers_prop, sizeof(servers_prop));
167833d4668SAlexey Kardashevskiy     if (ret < 0) {
168833d4668SAlexey Kardashevskiy         return ret;
169833d4668SAlexey Kardashevskiy     }
170833d4668SAlexey Kardashevskiy     ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s",
171833d4668SAlexey Kardashevskiy                       gservers_prop, sizeof(gservers_prop));
172833d4668SAlexey Kardashevskiy 
173833d4668SAlexey Kardashevskiy     return ret;
174833d4668SAlexey Kardashevskiy }
175833d4668SAlexey Kardashevskiy 
1760da6f3feSBharata B Rao static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, CPUState *cs)
1770da6f3feSBharata B Rao {
1780da6f3feSBharata B Rao     int ret = 0;
1790da6f3feSBharata B Rao     PowerPCCPU *cpu = POWERPC_CPU(cs);
1800da6f3feSBharata B Rao     int index = ppc_get_vcpu_dt_id(cpu);
1810da6f3feSBharata B Rao     uint32_t associativity[] = {cpu_to_be32(0x5),
1820da6f3feSBharata B Rao                                 cpu_to_be32(0x0),
1830da6f3feSBharata B Rao                                 cpu_to_be32(0x0),
1840da6f3feSBharata B Rao                                 cpu_to_be32(0x0),
1850da6f3feSBharata B Rao                                 cpu_to_be32(cs->numa_node),
1860da6f3feSBharata B Rao                                 cpu_to_be32(index)};
1870da6f3feSBharata B Rao 
1880da6f3feSBharata B Rao     /* Advertise NUMA via ibm,associativity */
1890da6f3feSBharata B Rao     if (nb_numa_nodes > 1) {
1900da6f3feSBharata B Rao         ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity,
1910da6f3feSBharata B Rao                           sizeof(associativity));
1920da6f3feSBharata B Rao     }
1930da6f3feSBharata B Rao 
1940da6f3feSBharata B Rao     return ret;
1950da6f3feSBharata B Rao }
1960da6f3feSBharata B Rao 
19728e02042SDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr)
19853018216SPaolo Bonzini {
19982677ed2SAlexey Kardashevskiy     int ret = 0, offset, cpus_offset;
20082677ed2SAlexey Kardashevskiy     CPUState *cs;
20153018216SPaolo Bonzini     char cpu_model[32];
20253018216SPaolo Bonzini     int smt = kvmppc_smt_threads();
20353018216SPaolo Bonzini     uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
20453018216SPaolo Bonzini 
20582677ed2SAlexey Kardashevskiy     CPU_FOREACH(cs) {
20682677ed2SAlexey Kardashevskiy         PowerPCCPU *cpu = POWERPC_CPU(cs);
20782677ed2SAlexey Kardashevskiy         DeviceClass *dc = DEVICE_GET_CLASS(cs);
20882677ed2SAlexey Kardashevskiy         int index = ppc_get_vcpu_dt_id(cpu);
20953018216SPaolo Bonzini 
2100f20ba62SAlexey Kardashevskiy         if ((index % smt) != 0) {
21153018216SPaolo Bonzini             continue;
21253018216SPaolo Bonzini         }
21353018216SPaolo Bonzini 
21482677ed2SAlexey Kardashevskiy         snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index);
21553018216SPaolo Bonzini 
21682677ed2SAlexey Kardashevskiy         cpus_offset = fdt_path_offset(fdt, "/cpus");
21782677ed2SAlexey Kardashevskiy         if (cpus_offset < 0) {
21882677ed2SAlexey Kardashevskiy             cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
21982677ed2SAlexey Kardashevskiy                                           "cpus");
22082677ed2SAlexey Kardashevskiy             if (cpus_offset < 0) {
22182677ed2SAlexey Kardashevskiy                 return cpus_offset;
22282677ed2SAlexey Kardashevskiy             }
22382677ed2SAlexey Kardashevskiy         }
22482677ed2SAlexey Kardashevskiy         offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model);
22582677ed2SAlexey Kardashevskiy         if (offset < 0) {
22682677ed2SAlexey Kardashevskiy             offset = fdt_add_subnode(fdt, cpus_offset, cpu_model);
22753018216SPaolo Bonzini             if (offset < 0) {
22853018216SPaolo Bonzini                 return offset;
22953018216SPaolo Bonzini             }
23082677ed2SAlexey Kardashevskiy         }
23153018216SPaolo Bonzini 
2320da6f3feSBharata B Rao         ret = fdt_setprop(fdt, offset, "ibm,pft-size",
2330da6f3feSBharata B Rao                           pft_size_prop, sizeof(pft_size_prop));
23453018216SPaolo Bonzini         if (ret < 0) {
23553018216SPaolo Bonzini             return ret;
23653018216SPaolo Bonzini         }
23753018216SPaolo Bonzini 
2380da6f3feSBharata B Rao         ret = spapr_fixup_cpu_numa_dt(fdt, offset, cs);
23953018216SPaolo Bonzini         if (ret < 0) {
24053018216SPaolo Bonzini             return ret;
24153018216SPaolo Bonzini         }
242833d4668SAlexey Kardashevskiy 
24382677ed2SAlexey Kardashevskiy         ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu,
2442a48d993SAlexey Kardashevskiy                                      ppc_get_compat_smt_threads(cpu));
245833d4668SAlexey Kardashevskiy         if (ret < 0) {
246833d4668SAlexey Kardashevskiy             return ret;
247833d4668SAlexey Kardashevskiy         }
24853018216SPaolo Bonzini     }
24953018216SPaolo Bonzini     return ret;
25053018216SPaolo Bonzini }
25153018216SPaolo Bonzini 
252b082d65aSAlexey Kardashevskiy static hwaddr spapr_node0_size(void)
253b082d65aSAlexey Kardashevskiy {
254fb164994SDavid Gibson     MachineState *machine = MACHINE(qdev_get_machine());
255fb164994SDavid Gibson 
256b082d65aSAlexey Kardashevskiy     if (nb_numa_nodes) {
257b082d65aSAlexey Kardashevskiy         int i;
258b082d65aSAlexey Kardashevskiy         for (i = 0; i < nb_numa_nodes; ++i) {
259b082d65aSAlexey Kardashevskiy             if (numa_info[i].node_mem) {
260fb164994SDavid Gibson                 return MIN(pow2floor(numa_info[i].node_mem),
261fb164994SDavid Gibson                            machine->ram_size);
262b082d65aSAlexey Kardashevskiy             }
263b082d65aSAlexey Kardashevskiy         }
264b082d65aSAlexey Kardashevskiy     }
265fb164994SDavid Gibson     return machine->ram_size;
266b082d65aSAlexey Kardashevskiy }
267b082d65aSAlexey Kardashevskiy 
268a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1)
269a1d59c0fSAlexey Kardashevskiy {
270a1d59c0fSAlexey Kardashevskiy     g_string_append_len(s, s1, strlen(s1) + 1);
271a1d59c0fSAlexey Kardashevskiy }
27253018216SPaolo Bonzini 
27303d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
27426a8c353SAlexey Kardashevskiy                                        hwaddr size)
27526a8c353SAlexey Kardashevskiy {
27626a8c353SAlexey Kardashevskiy     uint32_t associativity[] = {
27726a8c353SAlexey Kardashevskiy         cpu_to_be32(0x4), /* length */
27826a8c353SAlexey Kardashevskiy         cpu_to_be32(0x0), cpu_to_be32(0x0),
279c3b4f589SAlexey Kardashevskiy         cpu_to_be32(0x0), cpu_to_be32(nodeid)
28026a8c353SAlexey Kardashevskiy     };
28126a8c353SAlexey Kardashevskiy     char mem_name[32];
28226a8c353SAlexey Kardashevskiy     uint64_t mem_reg_property[2];
28326a8c353SAlexey Kardashevskiy     int off;
28426a8c353SAlexey Kardashevskiy 
28526a8c353SAlexey Kardashevskiy     mem_reg_property[0] = cpu_to_be64(start);
28626a8c353SAlexey Kardashevskiy     mem_reg_property[1] = cpu_to_be64(size);
28726a8c353SAlexey Kardashevskiy 
28826a8c353SAlexey Kardashevskiy     sprintf(mem_name, "memory@" TARGET_FMT_lx, start);
28926a8c353SAlexey Kardashevskiy     off = fdt_add_subnode(fdt, 0, mem_name);
29026a8c353SAlexey Kardashevskiy     _FDT(off);
29126a8c353SAlexey Kardashevskiy     _FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
29226a8c353SAlexey Kardashevskiy     _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
29326a8c353SAlexey Kardashevskiy                       sizeof(mem_reg_property))));
29426a8c353SAlexey Kardashevskiy     _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
29526a8c353SAlexey Kardashevskiy                       sizeof(associativity))));
29603d196b7SBharata B Rao     return off;
29726a8c353SAlexey Kardashevskiy }
29826a8c353SAlexey Kardashevskiy 
29928e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
30053018216SPaolo Bonzini {
301fb164994SDavid Gibson     MachineState *machine = MACHINE(spapr);
3027db8a127SAlexey Kardashevskiy     hwaddr mem_start, node_size;
3037db8a127SAlexey Kardashevskiy     int i, nb_nodes = nb_numa_nodes;
3047db8a127SAlexey Kardashevskiy     NodeInfo *nodes = numa_info;
3057db8a127SAlexey Kardashevskiy     NodeInfo ramnode;
30653018216SPaolo Bonzini 
3077db8a127SAlexey Kardashevskiy     /* No NUMA nodes, assume there is just one node with whole RAM */
3087db8a127SAlexey Kardashevskiy     if (!nb_numa_nodes) {
3097db8a127SAlexey Kardashevskiy         nb_nodes = 1;
310fb164994SDavid Gibson         ramnode.node_mem = machine->ram_size;
3117db8a127SAlexey Kardashevskiy         nodes = &ramnode;
3125fe269b1SPaul Mackerras     }
31353018216SPaolo Bonzini 
3147db8a127SAlexey Kardashevskiy     for (i = 0, mem_start = 0; i < nb_nodes; ++i) {
3157db8a127SAlexey Kardashevskiy         if (!nodes[i].node_mem) {
3167db8a127SAlexey Kardashevskiy             continue;
31753018216SPaolo Bonzini         }
318fb164994SDavid Gibson         if (mem_start >= machine->ram_size) {
3195fe269b1SPaul Mackerras             node_size = 0;
3205fe269b1SPaul Mackerras         } else {
3217db8a127SAlexey Kardashevskiy             node_size = nodes[i].node_mem;
322fb164994SDavid Gibson             if (node_size > machine->ram_size - mem_start) {
323fb164994SDavid Gibson                 node_size = machine->ram_size - mem_start;
3245fe269b1SPaul Mackerras             }
3255fe269b1SPaul Mackerras         }
3267db8a127SAlexey Kardashevskiy         if (!mem_start) {
3277db8a127SAlexey Kardashevskiy             /* ppc_spapr_init() checks for rma_size <= node0_size already */
328e8f986fcSBharata B Rao             spapr_populate_memory_node(fdt, i, 0, spapr->rma_size);
3297db8a127SAlexey Kardashevskiy             mem_start += spapr->rma_size;
3307db8a127SAlexey Kardashevskiy             node_size -= spapr->rma_size;
3317db8a127SAlexey Kardashevskiy         }
3326010818cSAlexey Kardashevskiy         for ( ; node_size; ) {
3336010818cSAlexey Kardashevskiy             hwaddr sizetmp = pow2floor(node_size);
3346010818cSAlexey Kardashevskiy 
3356010818cSAlexey Kardashevskiy             /* mem_start != 0 here */
3366010818cSAlexey Kardashevskiy             if (ctzl(mem_start) < ctzl(sizetmp)) {
3376010818cSAlexey Kardashevskiy                 sizetmp = 1ULL << ctzl(mem_start);
3386010818cSAlexey Kardashevskiy             }
3396010818cSAlexey Kardashevskiy 
3406010818cSAlexey Kardashevskiy             spapr_populate_memory_node(fdt, i, mem_start, sizetmp);
3416010818cSAlexey Kardashevskiy             node_size -= sizetmp;
3426010818cSAlexey Kardashevskiy             mem_start += sizetmp;
3436010818cSAlexey Kardashevskiy         }
34453018216SPaolo Bonzini     }
34553018216SPaolo Bonzini 
34653018216SPaolo Bonzini     return 0;
34753018216SPaolo Bonzini }
34853018216SPaolo Bonzini 
349230bf719SThomas Huth /* Populate the "ibm,pa-features" property */
350230bf719SThomas Huth static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset)
351230bf719SThomas Huth {
352230bf719SThomas Huth     uint8_t pa_features_206[] = { 6, 0,
353230bf719SThomas Huth         0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
354230bf719SThomas Huth     uint8_t pa_features_207[] = { 24, 0,
355230bf719SThomas Huth         0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
356230bf719SThomas Huth         0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
357230bf719SThomas Huth         0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
358bac3bf28SThomas Huth         0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
359230bf719SThomas Huth     uint8_t *pa_features;
360230bf719SThomas Huth     size_t pa_size;
361230bf719SThomas Huth 
3624cbec30dSThomas Huth     switch (env->mmu_model) {
3634cbec30dSThomas Huth     case POWERPC_MMU_2_06:
3644cbec30dSThomas Huth     case POWERPC_MMU_2_06a:
365230bf719SThomas Huth         pa_features = pa_features_206;
366230bf719SThomas Huth         pa_size = sizeof(pa_features_206);
3674cbec30dSThomas Huth         break;
3684cbec30dSThomas Huth     case POWERPC_MMU_2_07:
3694cbec30dSThomas Huth     case POWERPC_MMU_2_07a:
370230bf719SThomas Huth         pa_features = pa_features_207;
371230bf719SThomas Huth         pa_size = sizeof(pa_features_207);
3724cbec30dSThomas Huth         break;
3734cbec30dSThomas Huth     default:
3744cbec30dSThomas Huth         return;
375230bf719SThomas Huth     }
376230bf719SThomas Huth 
377230bf719SThomas Huth     if (env->ci_large_pages) {
378230bf719SThomas Huth         /*
379230bf719SThomas Huth          * Note: we keep CI large pages off by default because a 64K capable
380230bf719SThomas Huth          * guest provisioned with large pages might otherwise try to map a qemu
381230bf719SThomas Huth          * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages
382230bf719SThomas Huth          * even if that qemu runs on a 4k host.
383230bf719SThomas Huth          * We dd this bit back here if we are confident this is not an issue
384230bf719SThomas Huth          */
385230bf719SThomas Huth         pa_features[3] |= 0x20;
386230bf719SThomas Huth     }
387bac3bf28SThomas Huth     if (kvmppc_has_cap_htm() && pa_size > 24) {
388bac3bf28SThomas Huth         pa_features[24] |= 0x80;    /* Transactional memory support */
389bac3bf28SThomas Huth     }
390230bf719SThomas Huth 
391230bf719SThomas Huth     _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size)));
392230bf719SThomas Huth }
393230bf719SThomas Huth 
3940da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
3950da6f3feSBharata B Rao                                   sPAPRMachineState *spapr)
3960da6f3feSBharata B Rao {
3970da6f3feSBharata B Rao     PowerPCCPU *cpu = POWERPC_CPU(cs);
3980da6f3feSBharata B Rao     CPUPPCState *env = &cpu->env;
3990da6f3feSBharata B Rao     PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
4000da6f3feSBharata B Rao     int index = ppc_get_vcpu_dt_id(cpu);
4010da6f3feSBharata B Rao     uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
4020da6f3feSBharata B Rao                        0xffffffff, 0xffffffff};
403afd10a0fSBharata B Rao     uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq()
404afd10a0fSBharata B Rao         : SPAPR_TIMEBASE_FREQ;
4050da6f3feSBharata B Rao     uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000;
4060da6f3feSBharata B Rao     uint32_t page_sizes_prop[64];
4070da6f3feSBharata B Rao     size_t page_sizes_prop_size;
40822419c2aSDavid Gibson     uint32_t vcpus_per_socket = smp_threads * smp_cores;
4090da6f3feSBharata B Rao     uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
410af81cf32SBharata B Rao     sPAPRDRConnector *drc;
411af81cf32SBharata B Rao     sPAPRDRConnectorClass *drck;
412af81cf32SBharata B Rao     int drc_index;
413af81cf32SBharata B Rao 
414af81cf32SBharata B Rao     drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index);
415af81cf32SBharata B Rao     if (drc) {
416af81cf32SBharata B Rao         drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
417af81cf32SBharata B Rao         drc_index = drck->get_index(drc);
418af81cf32SBharata B Rao         _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
419af81cf32SBharata B Rao     }
4200da6f3feSBharata B Rao 
4210da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "reg", index)));
4220da6f3feSBharata B Rao     _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
4230da6f3feSBharata B Rao 
4240da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
4250da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size",
4260da6f3feSBharata B Rao                            env->dcache_line_size)));
4270da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size",
4280da6f3feSBharata B Rao                            env->dcache_line_size)));
4290da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size",
4300da6f3feSBharata B Rao                            env->icache_line_size)));
4310da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size",
4320da6f3feSBharata B Rao                            env->icache_line_size)));
4330da6f3feSBharata B Rao 
4340da6f3feSBharata B Rao     if (pcc->l1_dcache_size) {
4350da6f3feSBharata B Rao         _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size",
4360da6f3feSBharata B Rao                                pcc->l1_dcache_size)));
4370da6f3feSBharata B Rao     } else {
438ce9863b7SCédric Le Goater         error_report("Warning: Unknown L1 dcache size for cpu");
4390da6f3feSBharata B Rao     }
4400da6f3feSBharata B Rao     if (pcc->l1_icache_size) {
4410da6f3feSBharata B Rao         _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size",
4420da6f3feSBharata B Rao                                pcc->l1_icache_size)));
4430da6f3feSBharata B Rao     } else {
444ce9863b7SCédric Le Goater         error_report("Warning: Unknown L1 icache size for cpu");
4450da6f3feSBharata B Rao     }
4460da6f3feSBharata B Rao 
4470da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq)));
4480da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq)));
449fd5da5c4SThomas Huth     _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr)));
4500da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr)));
4510da6f3feSBharata B Rao     _FDT((fdt_setprop_string(fdt, offset, "status", "okay")));
4520da6f3feSBharata B Rao     _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0)));
4530da6f3feSBharata B Rao 
4540da6f3feSBharata B Rao     if (env->spr_cb[SPR_PURR].oea_read) {
4550da6f3feSBharata B Rao         _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0)));
4560da6f3feSBharata B Rao     }
4570da6f3feSBharata B Rao 
4580da6f3feSBharata B Rao     if (env->mmu_model & POWERPC_MMU_1TSEG) {
4590da6f3feSBharata B Rao         _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes",
4600da6f3feSBharata B Rao                           segs, sizeof(segs))));
4610da6f3feSBharata B Rao     }
4620da6f3feSBharata B Rao 
4630da6f3feSBharata B Rao     /* Advertise VMX/VSX (vector extensions) if available
4640da6f3feSBharata B Rao      *   0 / no property == no vector extensions
4650da6f3feSBharata B Rao      *   1               == VMX / Altivec available
4660da6f3feSBharata B Rao      *   2               == VSX available */
4670da6f3feSBharata B Rao     if (env->insns_flags & PPC_ALTIVEC) {
4680da6f3feSBharata B Rao         uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1;
4690da6f3feSBharata B Rao 
4700da6f3feSBharata B Rao         _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx)));
4710da6f3feSBharata B Rao     }
4720da6f3feSBharata B Rao 
4730da6f3feSBharata B Rao     /* Advertise DFP (Decimal Floating Point) if available
4740da6f3feSBharata B Rao      *   0 / no property == no DFP
4750da6f3feSBharata B Rao      *   1               == DFP available */
4760da6f3feSBharata B Rao     if (env->insns_flags2 & PPC2_DFP) {
4770da6f3feSBharata B Rao         _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1)));
4780da6f3feSBharata B Rao     }
4790da6f3feSBharata B Rao 
4803654fa95SCédric Le Goater     page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop,
4810da6f3feSBharata B Rao                                                   sizeof(page_sizes_prop));
4820da6f3feSBharata B Rao     if (page_sizes_prop_size) {
4830da6f3feSBharata B Rao         _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes",
4840da6f3feSBharata B Rao                           page_sizes_prop, page_sizes_prop_size)));
4850da6f3feSBharata B Rao     }
4860da6f3feSBharata B Rao 
487230bf719SThomas Huth     spapr_populate_pa_features(env, fdt, offset);
48890da0d5aSBenjamin Herrenschmidt 
4890da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id",
49022419c2aSDavid Gibson                            cs->cpu_index / vcpus_per_socket)));
4910da6f3feSBharata B Rao 
4920da6f3feSBharata B Rao     _FDT((fdt_setprop(fdt, offset, "ibm,pft-size",
4930da6f3feSBharata B Rao                       pft_size_prop, sizeof(pft_size_prop))));
4940da6f3feSBharata B Rao 
4950da6f3feSBharata B Rao     _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs));
4960da6f3feSBharata B Rao 
4970da6f3feSBharata B Rao     _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu,
4980da6f3feSBharata B Rao                                 ppc_get_compat_smt_threads(cpu)));
4990da6f3feSBharata B Rao }
5000da6f3feSBharata B Rao 
5010da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr)
5020da6f3feSBharata B Rao {
5030da6f3feSBharata B Rao     CPUState *cs;
5040da6f3feSBharata B Rao     int cpus_offset;
5050da6f3feSBharata B Rao     char *nodename;
5060da6f3feSBharata B Rao     int smt = kvmppc_smt_threads();
5070da6f3feSBharata B Rao 
5080da6f3feSBharata B Rao     cpus_offset = fdt_add_subnode(fdt, 0, "cpus");
5090da6f3feSBharata B Rao     _FDT(cpus_offset);
5100da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1)));
5110da6f3feSBharata B Rao     _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0)));
5120da6f3feSBharata B Rao 
5130da6f3feSBharata B Rao     /*
5140da6f3feSBharata B Rao      * We walk the CPUs in reverse order to ensure that CPU DT nodes
5150da6f3feSBharata B Rao      * created by fdt_add_subnode() end up in the right order in FDT
5160da6f3feSBharata B Rao      * for the guest kernel the enumerate the CPUs correctly.
5170da6f3feSBharata B Rao      */
5180da6f3feSBharata B Rao     CPU_FOREACH_REVERSE(cs) {
5190da6f3feSBharata B Rao         PowerPCCPU *cpu = POWERPC_CPU(cs);
5200da6f3feSBharata B Rao         int index = ppc_get_vcpu_dt_id(cpu);
5210da6f3feSBharata B Rao         DeviceClass *dc = DEVICE_GET_CLASS(cs);
5220da6f3feSBharata B Rao         int offset;
5230da6f3feSBharata B Rao 
5240da6f3feSBharata B Rao         if ((index % smt) != 0) {
5250da6f3feSBharata B Rao             continue;
5260da6f3feSBharata B Rao         }
5270da6f3feSBharata B Rao 
5280da6f3feSBharata B Rao         nodename = g_strdup_printf("%s@%x", dc->fw_name, index);
5290da6f3feSBharata B Rao         offset = fdt_add_subnode(fdt, cpus_offset, nodename);
5300da6f3feSBharata B Rao         g_free(nodename);
5310da6f3feSBharata B Rao         _FDT(offset);
5320da6f3feSBharata B Rao         spapr_populate_cpu_dt(cs, fdt, offset, spapr);
5330da6f3feSBharata B Rao     }
5340da6f3feSBharata B Rao 
5350da6f3feSBharata B Rao }
5360da6f3feSBharata B Rao 
53703d196b7SBharata B Rao /*
53803d196b7SBharata B Rao  * Adds ibm,dynamic-reconfiguration-memory node.
53903d196b7SBharata B Rao  * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation
54003d196b7SBharata B Rao  * of this device tree node.
54103d196b7SBharata B Rao  */
54203d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
54303d196b7SBharata B Rao {
54403d196b7SBharata B Rao     MachineState *machine = MACHINE(spapr);
54503d196b7SBharata B Rao     int ret, i, offset;
54603d196b7SBharata B Rao     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
54703d196b7SBharata B Rao     uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
548d0e5a8f2SBharata B Rao     uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size;
549d0e5a8f2SBharata B Rao     uint32_t nr_lmbs = (spapr->hotplug_memory.base +
550d0e5a8f2SBharata B Rao                        memory_region_size(&spapr->hotplug_memory.mr)) /
551d0e5a8f2SBharata B Rao                        lmb_size;
55203d196b7SBharata B Rao     uint32_t *int_buf, *cur_index, buf_len;
5536663864eSBharata B Rao     int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
55403d196b7SBharata B Rao 
555ef001f06SThomas Huth     /*
556d0e5a8f2SBharata B Rao      * Don't create the node if there is no hotpluggable memory
55716c25aefSBharata B Rao      */
558d0e5a8f2SBharata B Rao     if (machine->ram_size == machine->maxram_size) {
55916c25aefSBharata B Rao         return 0;
56016c25aefSBharata B Rao     }
56116c25aefSBharata B Rao 
56216c25aefSBharata B Rao     /*
563ef001f06SThomas Huth      * Allocate enough buffer size to fit in ibm,dynamic-memory
564ef001f06SThomas Huth      * or ibm,associativity-lookup-arrays
565ef001f06SThomas Huth      */
566ef001f06SThomas Huth     buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2)
567ef001f06SThomas Huth               * sizeof(uint32_t);
56803d196b7SBharata B Rao     cur_index = int_buf = g_malloc0(buf_len);
56903d196b7SBharata B Rao 
57003d196b7SBharata B Rao     offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory");
57103d196b7SBharata B Rao 
57203d196b7SBharata B Rao     ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size,
57303d196b7SBharata B Rao                     sizeof(prop_lmb_size));
57403d196b7SBharata B Rao     if (ret < 0) {
57503d196b7SBharata B Rao         goto out;
57603d196b7SBharata B Rao     }
57703d196b7SBharata B Rao 
57803d196b7SBharata B Rao     ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff);
57903d196b7SBharata B Rao     if (ret < 0) {
58003d196b7SBharata B Rao         goto out;
58103d196b7SBharata B Rao     }
58203d196b7SBharata B Rao 
58303d196b7SBharata B Rao     ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0);
58403d196b7SBharata B Rao     if (ret < 0) {
58503d196b7SBharata B Rao         goto out;
58603d196b7SBharata B Rao     }
58703d196b7SBharata B Rao 
58803d196b7SBharata B Rao     /* ibm,dynamic-memory */
58903d196b7SBharata B Rao     int_buf[0] = cpu_to_be32(nr_lmbs);
59003d196b7SBharata B Rao     cur_index++;
59103d196b7SBharata B Rao     for (i = 0; i < nr_lmbs; i++) {
592d0e5a8f2SBharata B Rao         uint64_t addr = i * lmb_size;
59303d196b7SBharata B Rao         uint32_t *dynamic_memory = cur_index;
59403d196b7SBharata B Rao 
595d0e5a8f2SBharata B Rao         if (i >= hotplug_lmb_start) {
596d0e5a8f2SBharata B Rao             sPAPRDRConnector *drc;
597d0e5a8f2SBharata B Rao             sPAPRDRConnectorClass *drck;
598d0e5a8f2SBharata B Rao 
599d0e5a8f2SBharata B Rao             drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i);
60003d196b7SBharata B Rao             g_assert(drc);
60103d196b7SBharata B Rao             drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
60203d196b7SBharata B Rao 
60303d196b7SBharata B Rao             dynamic_memory[0] = cpu_to_be32(addr >> 32);
60403d196b7SBharata B Rao             dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
60503d196b7SBharata B Rao             dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
60603d196b7SBharata B Rao             dynamic_memory[3] = cpu_to_be32(0); /* reserved */
60703d196b7SBharata B Rao             dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
608d0e5a8f2SBharata B Rao             if (memory_region_present(get_system_memory(), addr)) {
60903d196b7SBharata B Rao                 dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
61003d196b7SBharata B Rao             } else {
61103d196b7SBharata B Rao                 dynamic_memory[5] = cpu_to_be32(0);
61203d196b7SBharata B Rao             }
613d0e5a8f2SBharata B Rao         } else {
614d0e5a8f2SBharata B Rao             /*
615d0e5a8f2SBharata B Rao              * LMB information for RMA, boot time RAM and gap b/n RAM and
616d0e5a8f2SBharata B Rao              * hotplug memory region -- all these are marked as reserved
617d0e5a8f2SBharata B Rao              * and as having no valid DRC.
618d0e5a8f2SBharata B Rao              */
619d0e5a8f2SBharata B Rao             dynamic_memory[0] = cpu_to_be32(addr >> 32);
620d0e5a8f2SBharata B Rao             dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
621d0e5a8f2SBharata B Rao             dynamic_memory[2] = cpu_to_be32(0);
622d0e5a8f2SBharata B Rao             dynamic_memory[3] = cpu_to_be32(0); /* reserved */
623d0e5a8f2SBharata B Rao             dynamic_memory[4] = cpu_to_be32(-1);
624d0e5a8f2SBharata B Rao             dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED |
625d0e5a8f2SBharata B Rao                                             SPAPR_LMB_FLAGS_DRC_INVALID);
626d0e5a8f2SBharata B Rao         }
62703d196b7SBharata B Rao 
62803d196b7SBharata B Rao         cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
62903d196b7SBharata B Rao     }
63003d196b7SBharata B Rao     ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len);
63103d196b7SBharata B Rao     if (ret < 0) {
63203d196b7SBharata B Rao         goto out;
63303d196b7SBharata B Rao     }
63403d196b7SBharata B Rao 
63503d196b7SBharata B Rao     /* ibm,associativity-lookup-arrays */
63603d196b7SBharata B Rao     cur_index = int_buf;
6376663864eSBharata B Rao     int_buf[0] = cpu_to_be32(nr_nodes);
63803d196b7SBharata B Rao     int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */
63903d196b7SBharata B Rao     cur_index += 2;
6406663864eSBharata B Rao     for (i = 0; i < nr_nodes; i++) {
64103d196b7SBharata B Rao         uint32_t associativity[] = {
64203d196b7SBharata B Rao             cpu_to_be32(0x0),
64303d196b7SBharata B Rao             cpu_to_be32(0x0),
64403d196b7SBharata B Rao             cpu_to_be32(0x0),
64503d196b7SBharata B Rao             cpu_to_be32(i)
64603d196b7SBharata B Rao         };
64703d196b7SBharata B Rao         memcpy(cur_index, associativity, sizeof(associativity));
64803d196b7SBharata B Rao         cur_index += 4;
64903d196b7SBharata B Rao     }
65003d196b7SBharata B Rao     ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf,
65103d196b7SBharata B Rao             (cur_index - int_buf) * sizeof(uint32_t));
65203d196b7SBharata B Rao out:
65303d196b7SBharata B Rao     g_free(int_buf);
65403d196b7SBharata B Rao     return ret;
65503d196b7SBharata B Rao }
65603d196b7SBharata B Rao 
6576787d27bSMichael Roth static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt,
6586787d27bSMichael Roth                                 sPAPROptionVector *ov5_updates)
6596787d27bSMichael Roth {
6606787d27bSMichael Roth     sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
661417ece33SMichael Roth     int ret = 0, offset;
6626787d27bSMichael Roth 
6636787d27bSMichael Roth     /* Generate ibm,dynamic-reconfiguration-memory node if required */
6646787d27bSMichael Roth     if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) {
6656787d27bSMichael Roth         g_assert(smc->dr_lmb_enabled);
6666787d27bSMichael Roth         ret = spapr_populate_drconf_memory(spapr, fdt);
667417ece33SMichael Roth         if (ret) {
668417ece33SMichael Roth             goto out;
669417ece33SMichael Roth         }
6706787d27bSMichael Roth     }
6716787d27bSMichael Roth 
672417ece33SMichael Roth     offset = fdt_path_offset(fdt, "/chosen");
673417ece33SMichael Roth     if (offset < 0) {
674417ece33SMichael Roth         offset = fdt_add_subnode(fdt, 0, "chosen");
675417ece33SMichael Roth         if (offset < 0) {
676417ece33SMichael Roth             return offset;
677417ece33SMichael Roth         }
678417ece33SMichael Roth     }
679417ece33SMichael Roth     ret = spapr_ovec_populate_dt(fdt, offset, spapr->ov5_cas,
680417ece33SMichael Roth                                  "ibm,architecture-vec-5");
681417ece33SMichael Roth 
682417ece33SMichael Roth out:
6836787d27bSMichael Roth     return ret;
6846787d27bSMichael Roth }
6856787d27bSMichael Roth 
68603d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
68703d196b7SBharata B Rao                                  target_ulong addr, target_ulong size,
6886787d27bSMichael Roth                                  bool cpu_update,
6896787d27bSMichael Roth                                  sPAPROptionVector *ov5_updates)
69003d196b7SBharata B Rao {
69103d196b7SBharata B Rao     void *fdt, *fdt_skel;
69203d196b7SBharata B Rao     sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
69303d196b7SBharata B Rao 
69403d196b7SBharata B Rao     size -= sizeof(hdr);
69503d196b7SBharata B Rao 
69603d196b7SBharata B Rao     /* Create sceleton */
69703d196b7SBharata B Rao     fdt_skel = g_malloc0(size);
69803d196b7SBharata B Rao     _FDT((fdt_create(fdt_skel, size)));
69903d196b7SBharata B Rao     _FDT((fdt_begin_node(fdt_skel, "")));
70003d196b7SBharata B Rao     _FDT((fdt_end_node(fdt_skel)));
70103d196b7SBharata B Rao     _FDT((fdt_finish(fdt_skel)));
70203d196b7SBharata B Rao     fdt = g_malloc0(size);
70303d196b7SBharata B Rao     _FDT((fdt_open_into(fdt_skel, fdt, size)));
70403d196b7SBharata B Rao     g_free(fdt_skel);
70503d196b7SBharata B Rao 
70603d196b7SBharata B Rao     /* Fixup cpu nodes */
70703d196b7SBharata B Rao     if (cpu_update) {
70803d196b7SBharata B Rao         _FDT((spapr_fixup_cpu_dt(fdt, spapr)));
70903d196b7SBharata B Rao     }
71003d196b7SBharata B Rao 
7116787d27bSMichael Roth     if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) {
7126787d27bSMichael Roth         return -1;
71303d196b7SBharata B Rao     }
71403d196b7SBharata B Rao 
71503d196b7SBharata B Rao     /* Pack resulting tree */
71603d196b7SBharata B Rao     _FDT((fdt_pack(fdt)));
71703d196b7SBharata B Rao 
71803d196b7SBharata B Rao     if (fdt_totalsize(fdt) + sizeof(hdr) > size) {
71903d196b7SBharata B Rao         trace_spapr_cas_failed(size);
72003d196b7SBharata B Rao         return -1;
72103d196b7SBharata B Rao     }
72203d196b7SBharata B Rao 
72303d196b7SBharata B Rao     cpu_physical_memory_write(addr, &hdr, sizeof(hdr));
72403d196b7SBharata B Rao     cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt));
72503d196b7SBharata B Rao     trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr));
72603d196b7SBharata B Rao     g_free(fdt);
72703d196b7SBharata B Rao 
72803d196b7SBharata B Rao     return 0;
72903d196b7SBharata B Rao }
73003d196b7SBharata B Rao 
7313f5dabceSDavid Gibson static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
7323f5dabceSDavid Gibson {
7333f5dabceSDavid Gibson     int rtas;
7343f5dabceSDavid Gibson     GString *hypertas = g_string_sized_new(256);
7353f5dabceSDavid Gibson     GString *qemu_hypertas = g_string_sized_new(256);
7363f5dabceSDavid Gibson     uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) };
7373f5dabceSDavid Gibson     uint64_t max_hotplug_addr = spapr->hotplug_memory.base +
7383f5dabceSDavid Gibson         memory_region_size(&spapr->hotplug_memory.mr);
7393f5dabceSDavid Gibson     uint32_t lrdr_capacity[] = {
7403f5dabceSDavid Gibson         cpu_to_be32(max_hotplug_addr >> 32),
7413f5dabceSDavid Gibson         cpu_to_be32(max_hotplug_addr & 0xffffffff),
7423f5dabceSDavid Gibson         0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE),
7433f5dabceSDavid Gibson         cpu_to_be32(max_cpus / smp_threads),
7443f5dabceSDavid Gibson     };
7453f5dabceSDavid Gibson 
7463f5dabceSDavid Gibson     _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas"));
7473f5dabceSDavid Gibson 
7483f5dabceSDavid Gibson     /* hypertas */
7493f5dabceSDavid Gibson     add_str(hypertas, "hcall-pft");
7503f5dabceSDavid Gibson     add_str(hypertas, "hcall-term");
7513f5dabceSDavid Gibson     add_str(hypertas, "hcall-dabr");
7523f5dabceSDavid Gibson     add_str(hypertas, "hcall-interrupt");
7533f5dabceSDavid Gibson     add_str(hypertas, "hcall-tce");
7543f5dabceSDavid Gibson     add_str(hypertas, "hcall-vio");
7553f5dabceSDavid Gibson     add_str(hypertas, "hcall-splpar");
7563f5dabceSDavid Gibson     add_str(hypertas, "hcall-bulk");
7573f5dabceSDavid Gibson     add_str(hypertas, "hcall-set-mode");
7583f5dabceSDavid Gibson     add_str(hypertas, "hcall-sprg0");
7593f5dabceSDavid Gibson     add_str(hypertas, "hcall-copy");
7603f5dabceSDavid Gibson     add_str(hypertas, "hcall-debug");
7613f5dabceSDavid Gibson     add_str(qemu_hypertas, "hcall-memop1");
7623f5dabceSDavid Gibson 
7633f5dabceSDavid Gibson     if (!kvm_enabled() || kvmppc_spapr_use_multitce()) {
7643f5dabceSDavid Gibson         add_str(hypertas, "hcall-multi-tce");
7653f5dabceSDavid Gibson     }
7663f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions",
7673f5dabceSDavid Gibson                      hypertas->str, hypertas->len));
7683f5dabceSDavid Gibson     g_string_free(hypertas, TRUE);
7693f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions",
7703f5dabceSDavid Gibson                      qemu_hypertas->str, qemu_hypertas->len));
7713f5dabceSDavid Gibson     g_string_free(qemu_hypertas, TRUE);
7723f5dabceSDavid Gibson 
7733f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points",
7743f5dabceSDavid Gibson                      refpoints, sizeof(refpoints)));
7753f5dabceSDavid Gibson 
7763f5dabceSDavid Gibson     _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max",
7773f5dabceSDavid Gibson                           RTAS_ERROR_LOG_MAX));
7783f5dabceSDavid Gibson     _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate",
7793f5dabceSDavid Gibson                           RTAS_EVENT_SCAN_RATE));
7803f5dabceSDavid Gibson 
7813f5dabceSDavid Gibson     if (msi_nonbroken) {
7823f5dabceSDavid Gibson         _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0));
7833f5dabceSDavid Gibson     }
7843f5dabceSDavid Gibson 
7853f5dabceSDavid Gibson     /*
7863f5dabceSDavid Gibson      * According to PAPR, rtas ibm,os-term does not guarantee a return
7873f5dabceSDavid Gibson      * back to the guest cpu.
7883f5dabceSDavid Gibson      *
7893f5dabceSDavid Gibson      * While an additional ibm,extended-os-term property indicates
7903f5dabceSDavid Gibson      * that rtas call return will always occur. Set this property.
7913f5dabceSDavid Gibson      */
7923f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0));
7933f5dabceSDavid Gibson 
7943f5dabceSDavid Gibson     _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity",
7953f5dabceSDavid Gibson                      lrdr_capacity, sizeof(lrdr_capacity)));
7963f5dabceSDavid Gibson 
7973f5dabceSDavid Gibson     spapr_dt_rtas_tokens(fdt, rtas);
7983f5dabceSDavid Gibson }
7993f5dabceSDavid Gibson 
8007c866c6aSDavid Gibson static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
8017c866c6aSDavid Gibson {
8027c866c6aSDavid Gibson     MachineState *machine = MACHINE(spapr);
8037c866c6aSDavid Gibson     int chosen;
8047c866c6aSDavid Gibson     const char *boot_device = machine->boot_order;
8057c866c6aSDavid Gibson     char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
8067c866c6aSDavid Gibson     size_t cb = 0;
8077c866c6aSDavid Gibson     char *bootlist = get_boot_devices_list(&cb, true);
8087c866c6aSDavid Gibson 
8097c866c6aSDavid Gibson     _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
8107c866c6aSDavid Gibson 
8117c866c6aSDavid Gibson     _FDT(fdt_setprop_string(fdt, chosen, "bootargs", machine->kernel_cmdline));
8127c866c6aSDavid Gibson     _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start",
8137c866c6aSDavid Gibson                           spapr->initrd_base));
8147c866c6aSDavid Gibson     _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end",
8157c866c6aSDavid Gibson                           spapr->initrd_base + spapr->initrd_size));
8167c866c6aSDavid Gibson 
8177c866c6aSDavid Gibson     if (spapr->kernel_size) {
8187c866c6aSDavid Gibson         uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR),
8197c866c6aSDavid Gibson                               cpu_to_be64(spapr->kernel_size) };
8207c866c6aSDavid Gibson 
8217c866c6aSDavid Gibson         _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel",
8227c866c6aSDavid Gibson                          &kprop, sizeof(kprop)));
8237c866c6aSDavid Gibson         if (spapr->kernel_le) {
8247c866c6aSDavid Gibson             _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0));
8257c866c6aSDavid Gibson         }
8267c866c6aSDavid Gibson     }
8277c866c6aSDavid Gibson     if (boot_menu) {
8287c866c6aSDavid Gibson         _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu)));
8297c866c6aSDavid Gibson     }
8307c866c6aSDavid Gibson     _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width));
8317c866c6aSDavid Gibson     _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height));
8327c866c6aSDavid Gibson     _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth));
8337c866c6aSDavid Gibson 
8347c866c6aSDavid Gibson     if (cb && bootlist) {
8357c866c6aSDavid Gibson         int i;
8367c866c6aSDavid Gibson 
8377c866c6aSDavid Gibson         for (i = 0; i < cb; i++) {
8387c866c6aSDavid Gibson             if (bootlist[i] == '\n') {
8397c866c6aSDavid Gibson                 bootlist[i] = ' ';
8407c866c6aSDavid Gibson             }
8417c866c6aSDavid Gibson         }
8427c866c6aSDavid Gibson         _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist));
8437c866c6aSDavid Gibson     }
8447c866c6aSDavid Gibson 
8457c866c6aSDavid Gibson     if (boot_device && strlen(boot_device)) {
8467c866c6aSDavid Gibson         _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device));
8477c866c6aSDavid Gibson     }
8487c866c6aSDavid Gibson 
8497c866c6aSDavid Gibson     if (!spapr->has_graphics && stdout_path) {
8507c866c6aSDavid Gibson         _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path));
8517c866c6aSDavid Gibson     }
8527c866c6aSDavid Gibson 
8537c866c6aSDavid Gibson     g_free(stdout_path);
8547c866c6aSDavid Gibson     g_free(bootlist);
8557c866c6aSDavid Gibson }
8567c866c6aSDavid Gibson 
857fca5f2dcSDavid Gibson static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt)
858fca5f2dcSDavid Gibson {
859fca5f2dcSDavid Gibson     /* The /hypervisor node isn't in PAPR - this is a hack to allow PR
860fca5f2dcSDavid Gibson      * KVM to work under pHyp with some guest co-operation */
861fca5f2dcSDavid Gibson     int hypervisor;
862fca5f2dcSDavid Gibson     uint8_t hypercall[16];
863fca5f2dcSDavid Gibson 
864fca5f2dcSDavid Gibson     _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor"));
865fca5f2dcSDavid Gibson     /* indicate KVM hypercall interface */
866fca5f2dcSDavid Gibson     _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm"));
867fca5f2dcSDavid Gibson     if (kvmppc_has_cap_fixup_hcalls()) {
868fca5f2dcSDavid Gibson         /*
869fca5f2dcSDavid Gibson          * Older KVM versions with older guest kernels were broken
870fca5f2dcSDavid Gibson          * with the magic page, don't allow the guest to map it.
871fca5f2dcSDavid Gibson          */
872fca5f2dcSDavid Gibson         if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall,
873fca5f2dcSDavid Gibson                                   sizeof(hypercall))) {
874fca5f2dcSDavid Gibson             _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions",
875fca5f2dcSDavid Gibson                              hypercall, sizeof(hypercall)));
876fca5f2dcSDavid Gibson         }
877fca5f2dcSDavid Gibson     }
878fca5f2dcSDavid Gibson }
879fca5f2dcSDavid Gibson 
880997b6cfcSDavid Gibson static void *spapr_build_fdt(sPAPRMachineState *spapr,
88153018216SPaolo Bonzini                              hwaddr rtas_addr,
88253018216SPaolo Bonzini                              hwaddr rtas_size)
88353018216SPaolo Bonzini {
8845b2128d2SAlexander Graf     MachineState *machine = MACHINE(qdev_get_machine());
8853c0c47e3SDavid Gibson     MachineClass *mc = MACHINE_GET_CLASS(machine);
886c20d332aSBharata B Rao     sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
8877c866c6aSDavid Gibson     int ret;
88853018216SPaolo Bonzini     void *fdt;
88953018216SPaolo Bonzini     sPAPRPHBState *phb;
890398a0bd5SDavid Gibson     char *buf;
89153018216SPaolo Bonzini 
892398a0bd5SDavid Gibson     fdt = g_malloc0(FDT_MAX_SIZE);
893398a0bd5SDavid Gibson     _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE)));
89453018216SPaolo Bonzini 
895398a0bd5SDavid Gibson     /* Root node */
896398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp"));
897398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)"));
898398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries"));
899398a0bd5SDavid Gibson 
900398a0bd5SDavid Gibson     /*
901398a0bd5SDavid Gibson      * Add info to guest to indentify which host is it being run on
902398a0bd5SDavid Gibson      * and what is the uuid of the guest
903398a0bd5SDavid Gibson      */
904398a0bd5SDavid Gibson     if (kvmppc_get_host_model(&buf)) {
905398a0bd5SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "host-model", buf));
906398a0bd5SDavid Gibson         g_free(buf);
907398a0bd5SDavid Gibson     }
908398a0bd5SDavid Gibson     if (kvmppc_get_host_serial(&buf)) {
909398a0bd5SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf));
910398a0bd5SDavid Gibson         g_free(buf);
911398a0bd5SDavid Gibson     }
912398a0bd5SDavid Gibson 
913398a0bd5SDavid Gibson     buf = qemu_uuid_unparse_strdup(&qemu_uuid);
914398a0bd5SDavid Gibson 
915398a0bd5SDavid Gibson     _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf));
916398a0bd5SDavid Gibson     if (qemu_uuid_set) {
917398a0bd5SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "system-id", buf));
918398a0bd5SDavid Gibson     }
919398a0bd5SDavid Gibson     g_free(buf);
920398a0bd5SDavid Gibson 
921398a0bd5SDavid Gibson     if (qemu_get_vm_name()) {
922398a0bd5SDavid Gibson         _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name",
923398a0bd5SDavid Gibson                                 qemu_get_vm_name()));
924398a0bd5SDavid Gibson     }
925398a0bd5SDavid Gibson 
926398a0bd5SDavid Gibson     _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2));
927398a0bd5SDavid Gibson     _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
92853018216SPaolo Bonzini 
9299b9a1908SDavid Gibson     /* /interrupt controller */
9309b9a1908SDavid Gibson     spapr_dt_xics(spapr->xics, fdt, PHANDLE_XICP);
9319b9a1908SDavid Gibson 
932e8f986fcSBharata B Rao     ret = spapr_populate_memory(spapr, fdt);
933e8f986fcSBharata B Rao     if (ret < 0) {
934ce9863b7SCédric Le Goater         error_report("couldn't setup memory nodes in fdt");
935e8f986fcSBharata B Rao         exit(1);
93653018216SPaolo Bonzini     }
93753018216SPaolo Bonzini 
938bf5a6696SDavid Gibson     /* /vdevice */
939bf5a6696SDavid Gibson     spapr_dt_vdevice(spapr->vio_bus, fdt);
94053018216SPaolo Bonzini 
9414d9392beSThomas Huth     if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) {
9424d9392beSThomas Huth         ret = spapr_rng_populate_dt(fdt);
9434d9392beSThomas Huth         if (ret < 0) {
944ce9863b7SCédric Le Goater             error_report("could not set up rng device in the fdt");
9454d9392beSThomas Huth             exit(1);
9464d9392beSThomas Huth         }
9474d9392beSThomas Huth     }
9484d9392beSThomas Huth 
94953018216SPaolo Bonzini     QLIST_FOREACH(phb, &spapr->phbs, list) {
95053018216SPaolo Bonzini         ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt);
95153018216SPaolo Bonzini         if (ret < 0) {
952da34fed7SThomas Huth             error_report("couldn't setup PCI devices in fdt");
95353018216SPaolo Bonzini             exit(1);
95453018216SPaolo Bonzini         }
955da34fed7SThomas Huth     }
95653018216SPaolo Bonzini 
9570da6f3feSBharata B Rao     /* cpus */
9580da6f3feSBharata B Rao     spapr_populate_cpus_dt_node(fdt, spapr);
95953018216SPaolo Bonzini 
960c20d332aSBharata B Rao     if (smc->dr_lmb_enabled) {
961c20d332aSBharata B Rao         _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
962c20d332aSBharata B Rao     }
963c20d332aSBharata B Rao 
9643c0c47e3SDavid Gibson     if (mc->query_hotpluggable_cpus) {
965af81cf32SBharata B Rao         int offset = fdt_path_offset(fdt, "/cpus");
966af81cf32SBharata B Rao         ret = spapr_drc_populate_dt(fdt, offset, NULL,
967af81cf32SBharata B Rao                                     SPAPR_DR_CONNECTOR_TYPE_CPU);
968af81cf32SBharata B Rao         if (ret < 0) {
969af81cf32SBharata B Rao             error_report("Couldn't set up CPU DR device tree properties");
970af81cf32SBharata B Rao             exit(1);
971af81cf32SBharata B Rao         }
972af81cf32SBharata B Rao     }
973af81cf32SBharata B Rao 
974ffb1e275SDavid Gibson     /* /event-sources */
975ffbb1705SMichael Roth     spapr_dt_events(spapr, fdt);
976ffb1e275SDavid Gibson 
9773f5dabceSDavid Gibson     /* /rtas */
9783f5dabceSDavid Gibson     spapr_dt_rtas(spapr, fdt);
9793f5dabceSDavid Gibson 
9807c866c6aSDavid Gibson     /* /chosen */
9817c866c6aSDavid Gibson     spapr_dt_chosen(spapr, fdt);
982cf6e5223SDavid Gibson 
983fca5f2dcSDavid Gibson     /* /hypervisor */
984fca5f2dcSDavid Gibson     if (kvm_enabled()) {
985fca5f2dcSDavid Gibson         spapr_dt_hypervisor(spapr, fdt);
986fca5f2dcSDavid Gibson     }
987fca5f2dcSDavid Gibson 
988cf6e5223SDavid Gibson     /* Build memory reserve map */
989cf6e5223SDavid Gibson     if (spapr->kernel_size) {
990cf6e5223SDavid Gibson         _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size)));
991cf6e5223SDavid Gibson     }
992cf6e5223SDavid Gibson     if (spapr->initrd_size) {
993cf6e5223SDavid Gibson         _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size)));
994cf6e5223SDavid Gibson     }
995cf6e5223SDavid Gibson 
9966787d27bSMichael Roth     /* ibm,client-architecture-support updates */
9976787d27bSMichael Roth     ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas);
9986787d27bSMichael Roth     if (ret < 0) {
9996787d27bSMichael Roth         error_report("couldn't setup CAS properties fdt");
10006787d27bSMichael Roth         exit(1);
10016787d27bSMichael Roth     }
10026787d27bSMichael Roth 
1003997b6cfcSDavid Gibson     return fdt;
100453018216SPaolo Bonzini }
100553018216SPaolo Bonzini 
100653018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
100753018216SPaolo Bonzini {
100853018216SPaolo Bonzini     return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
100953018216SPaolo Bonzini }
101053018216SPaolo Bonzini 
101153018216SPaolo Bonzini static void emulate_spapr_hypercall(PowerPCCPU *cpu)
101253018216SPaolo Bonzini {
101353018216SPaolo Bonzini     CPUPPCState *env = &cpu->env;
101453018216SPaolo Bonzini 
101553018216SPaolo Bonzini     if (msr_pr) {
101653018216SPaolo Bonzini         hcall_dprintf("Hypercall made with MSR[PR]=1\n");
101753018216SPaolo Bonzini         env->gpr[3] = H_PRIVILEGE;
101853018216SPaolo Bonzini     } else {
101953018216SPaolo Bonzini         env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]);
102053018216SPaolo Bonzini     }
102153018216SPaolo Bonzini }
102253018216SPaolo Bonzini 
1023e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i)   (void *)(((uint64_t *)(_table)) + ((_i) * 2))
1024e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte)  (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID)
1025e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte)  (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY)
1026e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte)  ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY))
1027e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte)  ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY))
1028e6b8fd24SSamuel Mendoza-Jonas 
1029715c5407SDavid Gibson /*
1030715c5407SDavid Gibson  * Get the fd to access the kernel htab, re-opening it if necessary
1031715c5407SDavid Gibson  */
1032715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr)
1033715c5407SDavid Gibson {
1034715c5407SDavid Gibson     if (spapr->htab_fd >= 0) {
1035715c5407SDavid Gibson         return spapr->htab_fd;
1036715c5407SDavid Gibson     }
1037715c5407SDavid Gibson 
1038715c5407SDavid Gibson     spapr->htab_fd = kvmppc_get_htab_fd(false);
1039715c5407SDavid Gibson     if (spapr->htab_fd < 0) {
1040715c5407SDavid Gibson         error_report("Unable to open fd for reading hash table from KVM: %s",
1041715c5407SDavid Gibson                      strerror(errno));
1042715c5407SDavid Gibson     }
1043715c5407SDavid Gibson 
1044715c5407SDavid Gibson     return spapr->htab_fd;
1045715c5407SDavid Gibson }
1046715c5407SDavid Gibson 
1047715c5407SDavid Gibson static void close_htab_fd(sPAPRMachineState *spapr)
1048715c5407SDavid Gibson {
1049715c5407SDavid Gibson     if (spapr->htab_fd >= 0) {
1050715c5407SDavid Gibson         close(spapr->htab_fd);
1051715c5407SDavid Gibson     }
1052715c5407SDavid Gibson     spapr->htab_fd = -1;
1053715c5407SDavid Gibson }
1054715c5407SDavid Gibson 
10558dfe8e7fSDavid Gibson static int spapr_hpt_shift_for_ramsize(uint64_t ramsize)
10568dfe8e7fSDavid Gibson {
10578dfe8e7fSDavid Gibson     int shift;
10588dfe8e7fSDavid Gibson 
10598dfe8e7fSDavid Gibson     /* We aim for a hash table of size 1/128 the size of RAM (rounded
10608dfe8e7fSDavid Gibson      * up).  The PAPR recommendation is actually 1/64 of RAM size, but
10618dfe8e7fSDavid Gibson      * that's much more than is needed for Linux guests */
10628dfe8e7fSDavid Gibson     shift = ctz64(pow2ceil(ramsize)) - 7;
10638dfe8e7fSDavid Gibson     shift = MAX(shift, 18); /* Minimum architected size */
10648dfe8e7fSDavid Gibson     shift = MIN(shift, 46); /* Maximum architected size */
10658dfe8e7fSDavid Gibson     return shift;
10668dfe8e7fSDavid Gibson }
10678dfe8e7fSDavid Gibson 
1068c5f54f3eSDavid Gibson static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
1069c5f54f3eSDavid Gibson                                  Error **errp)
107053018216SPaolo Bonzini {
1071c5f54f3eSDavid Gibson     long rc;
107253018216SPaolo Bonzini 
1073c5f54f3eSDavid Gibson     /* Clean up any HPT info from a previous boot */
1074c5f54f3eSDavid Gibson     g_free(spapr->htab);
1075c5f54f3eSDavid Gibson     spapr->htab = NULL;
1076c5f54f3eSDavid Gibson     spapr->htab_shift = 0;
1077c5f54f3eSDavid Gibson     close_htab_fd(spapr);
107853018216SPaolo Bonzini 
1079c5f54f3eSDavid Gibson     rc = kvmppc_reset_htab(shift);
1080c5f54f3eSDavid Gibson     if (rc < 0) {
1081c5f54f3eSDavid Gibson         /* kernel-side HPT needed, but couldn't allocate one */
1082c5f54f3eSDavid Gibson         error_setg_errno(errp, errno,
1083c5f54f3eSDavid Gibson                          "Failed to allocate KVM HPT of order %d (try smaller maxmem?)",
1084c5f54f3eSDavid Gibson                          shift);
1085c5f54f3eSDavid Gibson         /* This is almost certainly fatal, but if the caller really
1086c5f54f3eSDavid Gibson          * wants to carry on with shift == 0, it's welcome to try */
1087c5f54f3eSDavid Gibson     } else if (rc > 0) {
1088c5f54f3eSDavid Gibson         /* kernel-side HPT allocated */
1089c5f54f3eSDavid Gibson         if (rc != shift) {
1090c5f54f3eSDavid Gibson             error_setg(errp,
1091c5f54f3eSDavid Gibson                        "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)",
1092c5f54f3eSDavid Gibson                        shift, rc);
10937735fedaSBharata B Rao         }
10947735fedaSBharata B Rao 
109553018216SPaolo Bonzini         spapr->htab_shift = shift;
1096c18ad9a5SDavid Gibson         spapr->htab = NULL;
1097b817772aSBharata B Rao     } else {
1098c5f54f3eSDavid Gibson         /* kernel-side HPT not needed, allocate in userspace instead */
1099c5f54f3eSDavid Gibson         size_t size = 1ULL << shift;
1100c5f54f3eSDavid Gibson         int i;
110101a57972SSamuel Mendoza-Jonas 
1102c5f54f3eSDavid Gibson         spapr->htab = qemu_memalign(size, size);
1103c5f54f3eSDavid Gibson         if (!spapr->htab) {
1104c5f54f3eSDavid Gibson             error_setg_errno(errp, errno,
1105c5f54f3eSDavid Gibson                              "Could not allocate HPT of order %d", shift);
1106c5f54f3eSDavid Gibson             return;
1107b817772aSBharata B Rao         }
1108b817772aSBharata B Rao 
1109c5f54f3eSDavid Gibson         memset(spapr->htab, 0, size);
1110c5f54f3eSDavid Gibson         spapr->htab_shift = shift;
1111b817772aSBharata B Rao 
1112c5f54f3eSDavid Gibson         for (i = 0; i < size / HASH_PTE_SIZE_64; i++) {
1113c5f54f3eSDavid Gibson             DIRTY_HPTE(HPTE(spapr->htab, i));
11147735fedaSBharata B Rao         }
111553018216SPaolo Bonzini     }
111653018216SPaolo Bonzini }
111753018216SPaolo Bonzini 
11184f01a637SDavid Gibson static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque)
11199e3f9733SAlexander Graf {
11209e3f9733SAlexander Graf     bool matched = false;
11219e3f9733SAlexander Graf 
11229e3f9733SAlexander Graf     if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) {
11239e3f9733SAlexander Graf         matched = true;
11249e3f9733SAlexander Graf     }
11259e3f9733SAlexander Graf 
11269e3f9733SAlexander Graf     if (!matched) {
11279e3f9733SAlexander Graf         error_report("Device %s is not supported by this machine yet.",
11289e3f9733SAlexander Graf                      qdev_fw_name(DEVICE(sbdev)));
11299e3f9733SAlexander Graf         exit(1);
11309e3f9733SAlexander Graf     }
11319e3f9733SAlexander Graf }
11329e3f9733SAlexander Graf 
113353018216SPaolo Bonzini static void ppc_spapr_reset(void)
113453018216SPaolo Bonzini {
1135c5f54f3eSDavid Gibson     MachineState *machine = MACHINE(qdev_get_machine());
1136c5f54f3eSDavid Gibson     sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
1137182735efSAndreas Färber     PowerPCCPU *first_ppc_cpu;
1138b7d1f77aSBenjamin Herrenschmidt     uint32_t rtas_limit;
1139cae172abSDavid Gibson     hwaddr rtas_addr, fdt_addr;
1140997b6cfcSDavid Gibson     void *fdt;
1141997b6cfcSDavid Gibson     int rc;
1142259186a7SAndreas Färber 
11439e3f9733SAlexander Graf     /* Check for unknown sysbus devices */
11449e3f9733SAlexander Graf     foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL);
11459e3f9733SAlexander Graf 
1146c5f54f3eSDavid Gibson     /* Allocate and/or reset the hash page table */
1147c5f54f3eSDavid Gibson     spapr_reallocate_hpt(spapr,
1148c5f54f3eSDavid Gibson                          spapr_hpt_shift_for_ramsize(machine->maxram_size),
1149c5f54f3eSDavid Gibson                          &error_fatal);
1150c5f54f3eSDavid Gibson 
1151c5f54f3eSDavid Gibson     /* Update the RMA size if necessary */
1152c5f54f3eSDavid Gibson     if (spapr->vrma_adjust) {
1153c5f54f3eSDavid Gibson         spapr->rma_size = kvmppc_rma_size(spapr_node0_size(),
1154c5f54f3eSDavid Gibson                                           spapr->htab_shift);
1155c5f54f3eSDavid Gibson     }
115653018216SPaolo Bonzini 
115753018216SPaolo Bonzini     qemu_devices_reset();
115853018216SPaolo Bonzini 
1159b7d1f77aSBenjamin Herrenschmidt     /*
1160b7d1f77aSBenjamin Herrenschmidt      * We place the device tree and RTAS just below either the top of the RMA,
1161b7d1f77aSBenjamin Herrenschmidt      * or just below 2GB, whichever is lowere, so that it can be
1162b7d1f77aSBenjamin Herrenschmidt      * processed with 32-bit real mode code if necessary
1163b7d1f77aSBenjamin Herrenschmidt      */
1164b7d1f77aSBenjamin Herrenschmidt     rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
1165cae172abSDavid Gibson     rtas_addr = rtas_limit - RTAS_MAX_SIZE;
1166cae172abSDavid Gibson     fdt_addr = rtas_addr - FDT_MAX_SIZE;
1167b7d1f77aSBenjamin Herrenschmidt 
11686787d27bSMichael Roth     /* if this reset wasn't generated by CAS, we should reset our
11696787d27bSMichael Roth      * negotiated options and start from scratch */
11706787d27bSMichael Roth     if (!spapr->cas_reboot) {
11716787d27bSMichael Roth         spapr_ovec_cleanup(spapr->ov5_cas);
11726787d27bSMichael Roth         spapr->ov5_cas = spapr_ovec_new();
11736787d27bSMichael Roth     }
11746787d27bSMichael Roth 
1175cae172abSDavid Gibson     fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size);
117653018216SPaolo Bonzini 
11772cac78c1SDavid Gibson     spapr_load_rtas(spapr, fdt, rtas_addr);
1178b7d1f77aSBenjamin Herrenschmidt 
1179997b6cfcSDavid Gibson     rc = fdt_pack(fdt);
1180997b6cfcSDavid Gibson 
1181997b6cfcSDavid Gibson     /* Should only fail if we've built a corrupted tree */
1182997b6cfcSDavid Gibson     assert(rc == 0);
1183997b6cfcSDavid Gibson 
1184997b6cfcSDavid Gibson     if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
1185997b6cfcSDavid Gibson         error_report("FDT too big ! 0x%x bytes (max is 0x%x)",
1186997b6cfcSDavid Gibson                      fdt_totalsize(fdt), FDT_MAX_SIZE);
1187997b6cfcSDavid Gibson         exit(1);
1188997b6cfcSDavid Gibson     }
1189997b6cfcSDavid Gibson 
1190997b6cfcSDavid Gibson     /* Load the fdt */
1191997b6cfcSDavid Gibson     qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt));
1192cae172abSDavid Gibson     cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
1193997b6cfcSDavid Gibson     g_free(fdt);
1194997b6cfcSDavid Gibson 
119553018216SPaolo Bonzini     /* Set up the entry state */
1196182735efSAndreas Färber     first_ppc_cpu = POWERPC_CPU(first_cpu);
1197cae172abSDavid Gibson     first_ppc_cpu->env.gpr[3] = fdt_addr;
1198182735efSAndreas Färber     first_ppc_cpu->env.gpr[5] = 0;
1199182735efSAndreas Färber     first_cpu->halted = 0;
12001b718907SDavid Gibson     first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT;
120153018216SPaolo Bonzini 
12026787d27bSMichael Roth     spapr->cas_reboot = false;
120353018216SPaolo Bonzini }
120453018216SPaolo Bonzini 
120528e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr)
120653018216SPaolo Bonzini {
12072ff3de68SMarkus Armbruster     DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
12083978b863SPaolo Bonzini     DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0);
120953018216SPaolo Bonzini 
12103978b863SPaolo Bonzini     if (dinfo) {
12116231a6daSMarkus Armbruster         qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo),
12126231a6daSMarkus Armbruster                             &error_fatal);
121353018216SPaolo Bonzini     }
121453018216SPaolo Bonzini 
121553018216SPaolo Bonzini     qdev_init_nofail(dev);
121653018216SPaolo Bonzini 
121753018216SPaolo Bonzini     spapr->nvram = (struct sPAPRNVRAM *)dev;
121853018216SPaolo Bonzini }
121953018216SPaolo Bonzini 
122028e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr)
122128df36a1SDavid Gibson {
122228df36a1SDavid Gibson     DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC);
122328df36a1SDavid Gibson 
122428df36a1SDavid Gibson     qdev_init_nofail(dev);
122528df36a1SDavid Gibson     spapr->rtc = dev;
122674e5ae28SDavid Gibson 
122774e5ae28SDavid Gibson     object_property_add_alias(qdev_get_machine(), "rtc-time",
122874e5ae28SDavid Gibson                               OBJECT(spapr->rtc), "date", NULL);
122928df36a1SDavid Gibson }
123028df36a1SDavid Gibson 
123153018216SPaolo Bonzini /* Returns whether we want to use VGA or not */
123214c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
123353018216SPaolo Bonzini {
123453018216SPaolo Bonzini     switch (vga_interface_type) {
123553018216SPaolo Bonzini     case VGA_NONE:
12367effdaa3SMark Wu         return false;
12377effdaa3SMark Wu     case VGA_DEVICE:
12387effdaa3SMark Wu         return true;
123953018216SPaolo Bonzini     case VGA_STD:
1240b798c190SBenjamin Herrenschmidt     case VGA_VIRTIO:
124153018216SPaolo Bonzini         return pci_vga_init(pci_bus) != NULL;
124253018216SPaolo Bonzini     default:
124314c6a894SDavid Gibson         error_setg(errp,
124414c6a894SDavid Gibson                    "Unsupported VGA mode, only -vga std or -vga virtio is supported");
124514c6a894SDavid Gibson         return false;
124653018216SPaolo Bonzini     }
124753018216SPaolo Bonzini }
124853018216SPaolo Bonzini 
1249880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id)
1250880ae7deSDavid Gibson {
125128e02042SDavid Gibson     sPAPRMachineState *spapr = (sPAPRMachineState *)opaque;
1252880ae7deSDavid Gibson     int err = 0;
1253880ae7deSDavid Gibson 
1254631b22eaSStefan Weil     /* In earlier versions, there was no separate qdev for the PAPR
1255880ae7deSDavid Gibson      * RTC, so the RTC offset was stored directly in sPAPREnvironment.
1256880ae7deSDavid Gibson      * So when migrating from those versions, poke the incoming offset
1257880ae7deSDavid Gibson      * value into the RTC device */
1258880ae7deSDavid Gibson     if (version_id < 3) {
1259880ae7deSDavid Gibson         err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset);
1260880ae7deSDavid Gibson     }
1261880ae7deSDavid Gibson 
1262880ae7deSDavid Gibson     return err;
1263880ae7deSDavid Gibson }
1264880ae7deSDavid Gibson 
1265880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id)
1266880ae7deSDavid Gibson {
1267880ae7deSDavid Gibson     return version_id < 3;
1268880ae7deSDavid Gibson }
1269880ae7deSDavid Gibson 
127062ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque)
127162ef3760SMichael Roth {
127262ef3760SMichael Roth     sPAPRMachineState *spapr = opaque;
127362ef3760SMichael Roth     sPAPROptionVector *ov5_mask = spapr_ovec_new();
127462ef3760SMichael Roth     sPAPROptionVector *ov5_legacy = spapr_ovec_new();
127562ef3760SMichael Roth     sPAPROptionVector *ov5_removed = spapr_ovec_new();
127662ef3760SMichael Roth     bool cas_needed;
127762ef3760SMichael Roth 
127862ef3760SMichael Roth     /* Prior to the introduction of sPAPROptionVector, we had two option
127962ef3760SMichael Roth      * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY.
128062ef3760SMichael Roth      * Both of these options encode machine topology into the device-tree
128162ef3760SMichael Roth      * in such a way that the now-booted OS should still be able to interact
128262ef3760SMichael Roth      * appropriately with QEMU regardless of what options were actually
128362ef3760SMichael Roth      * negotiatied on the source side.
128462ef3760SMichael Roth      *
128562ef3760SMichael Roth      * As such, we can avoid migrating the CAS-negotiated options if these
128662ef3760SMichael Roth      * are the only options available on the current machine/platform.
128762ef3760SMichael Roth      * Since these are the only options available for pseries-2.7 and
128862ef3760SMichael Roth      * earlier, this allows us to maintain old->new/new->old migration
128962ef3760SMichael Roth      * compatibility.
129062ef3760SMichael Roth      *
129162ef3760SMichael Roth      * For QEMU 2.8+, there are additional CAS-negotiatable options available
129262ef3760SMichael Roth      * via default pseries-2.8 machines and explicit command-line parameters.
129362ef3760SMichael Roth      * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware
129462ef3760SMichael Roth      * of the actual CAS-negotiated values to continue working properly. For
129562ef3760SMichael Roth      * example, availability of memory unplug depends on knowing whether
129662ef3760SMichael Roth      * OV5_HP_EVT was negotiated via CAS.
129762ef3760SMichael Roth      *
129862ef3760SMichael Roth      * Thus, for any cases where the set of available CAS-negotiatable
129962ef3760SMichael Roth      * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we
130062ef3760SMichael Roth      * include the CAS-negotiated options in the migration stream.
130162ef3760SMichael Roth      */
130262ef3760SMichael Roth     spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY);
130362ef3760SMichael Roth     spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY);
130462ef3760SMichael Roth 
130562ef3760SMichael Roth     /* spapr_ovec_diff returns true if bits were removed. we avoid using
130662ef3760SMichael Roth      * the mask itself since in the future it's possible "legacy" bits may be
130762ef3760SMichael Roth      * removed via machine options, which could generate a false positive
130862ef3760SMichael Roth      * that breaks migration.
130962ef3760SMichael Roth      */
131062ef3760SMichael Roth     spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask);
131162ef3760SMichael Roth     cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy);
131262ef3760SMichael Roth 
131362ef3760SMichael Roth     spapr_ovec_cleanup(ov5_mask);
131462ef3760SMichael Roth     spapr_ovec_cleanup(ov5_legacy);
131562ef3760SMichael Roth     spapr_ovec_cleanup(ov5_removed);
131662ef3760SMichael Roth 
131762ef3760SMichael Roth     return cas_needed;
131862ef3760SMichael Roth }
131962ef3760SMichael Roth 
132062ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = {
132162ef3760SMichael Roth     .name = "spapr_option_vector_ov5_cas",
132262ef3760SMichael Roth     .version_id = 1,
132362ef3760SMichael Roth     .minimum_version_id = 1,
132462ef3760SMichael Roth     .needed = spapr_ov5_cas_needed,
132562ef3760SMichael Roth     .fields = (VMStateField[]) {
132662ef3760SMichael Roth         VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1,
132762ef3760SMichael Roth                                  vmstate_spapr_ovec, sPAPROptionVector),
132862ef3760SMichael Roth         VMSTATE_END_OF_LIST()
132962ef3760SMichael Roth     },
133062ef3760SMichael Roth };
133162ef3760SMichael Roth 
13324be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = {
13334be21d56SDavid Gibson     .name = "spapr",
1334880ae7deSDavid Gibson     .version_id = 3,
13354be21d56SDavid Gibson     .minimum_version_id = 1,
1336880ae7deSDavid Gibson     .post_load = spapr_post_load,
13374be21d56SDavid Gibson     .fields = (VMStateField[]) {
1338880ae7deSDavid Gibson         /* used to be @next_irq */
1339880ae7deSDavid Gibson         VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4),
13404be21d56SDavid Gibson 
13414be21d56SDavid Gibson         /* RTC offset */
134228e02042SDavid Gibson         VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3),
1343880ae7deSDavid Gibson 
134428e02042SDavid Gibson         VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2),
13454be21d56SDavid Gibson         VMSTATE_END_OF_LIST()
13464be21d56SDavid Gibson     },
134762ef3760SMichael Roth     .subsections = (const VMStateDescription*[]) {
134862ef3760SMichael Roth         &vmstate_spapr_ov5_cas,
134962ef3760SMichael Roth         NULL
135062ef3760SMichael Roth     }
13514be21d56SDavid Gibson };
13524be21d56SDavid Gibson 
13534be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque)
13544be21d56SDavid Gibson {
135528e02042SDavid Gibson     sPAPRMachineState *spapr = opaque;
13564be21d56SDavid Gibson 
13574be21d56SDavid Gibson     /* "Iteration" header */
13584be21d56SDavid Gibson     qemu_put_be32(f, spapr->htab_shift);
13594be21d56SDavid Gibson 
1360e68cb8b4SAlexey Kardashevskiy     if (spapr->htab) {
1361e68cb8b4SAlexey Kardashevskiy         spapr->htab_save_index = 0;
1362e68cb8b4SAlexey Kardashevskiy         spapr->htab_first_pass = true;
1363e68cb8b4SAlexey Kardashevskiy     } else {
1364e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
13654be21d56SDavid Gibson     }
13664be21d56SDavid Gibson 
1367e68cb8b4SAlexey Kardashevskiy 
1368e68cb8b4SAlexey Kardashevskiy     return 0;
1369e68cb8b4SAlexey Kardashevskiy }
13704be21d56SDavid Gibson 
137128e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr,
13724be21d56SDavid Gibson                                  int64_t max_ns)
13734be21d56SDavid Gibson {
1374378bc217SDavid Gibson     bool has_timeout = max_ns != -1;
13754be21d56SDavid Gibson     int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
13764be21d56SDavid Gibson     int index = spapr->htab_save_index;
1377bc72ad67SAlex Bligh     int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
13784be21d56SDavid Gibson 
13794be21d56SDavid Gibson     assert(spapr->htab_first_pass);
13804be21d56SDavid Gibson 
13814be21d56SDavid Gibson     do {
13824be21d56SDavid Gibson         int chunkstart;
13834be21d56SDavid Gibson 
13844be21d56SDavid Gibson         /* Consume invalid HPTEs */
13854be21d56SDavid Gibson         while ((index < htabslots)
13864be21d56SDavid Gibson                && !HPTE_VALID(HPTE(spapr->htab, index))) {
13874be21d56SDavid Gibson             index++;
13884be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
13894be21d56SDavid Gibson         }
13904be21d56SDavid Gibson 
13914be21d56SDavid Gibson         /* Consume valid HPTEs */
13924be21d56SDavid Gibson         chunkstart = index;
1393338c25b6SSamuel Mendoza-Jonas         while ((index < htabslots) && (index - chunkstart < USHRT_MAX)
13944be21d56SDavid Gibson                && HPTE_VALID(HPTE(spapr->htab, index))) {
13954be21d56SDavid Gibson             index++;
13964be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
13974be21d56SDavid Gibson         }
13984be21d56SDavid Gibson 
13994be21d56SDavid Gibson         if (index > chunkstart) {
14004be21d56SDavid Gibson             int n_valid = index - chunkstart;
14014be21d56SDavid Gibson 
14024be21d56SDavid Gibson             qemu_put_be32(f, chunkstart);
14034be21d56SDavid Gibson             qemu_put_be16(f, n_valid);
14044be21d56SDavid Gibson             qemu_put_be16(f, 0);
14054be21d56SDavid Gibson             qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
14064be21d56SDavid Gibson                             HASH_PTE_SIZE_64 * n_valid);
14074be21d56SDavid Gibson 
1408378bc217SDavid Gibson             if (has_timeout &&
1409378bc217SDavid Gibson                 (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
14104be21d56SDavid Gibson                 break;
14114be21d56SDavid Gibson             }
14124be21d56SDavid Gibson         }
14134be21d56SDavid Gibson     } while ((index < htabslots) && !qemu_file_rate_limit(f));
14144be21d56SDavid Gibson 
14154be21d56SDavid Gibson     if (index >= htabslots) {
14164be21d56SDavid Gibson         assert(index == htabslots);
14174be21d56SDavid Gibson         index = 0;
14184be21d56SDavid Gibson         spapr->htab_first_pass = false;
14194be21d56SDavid Gibson     }
14204be21d56SDavid Gibson     spapr->htab_save_index = index;
14214be21d56SDavid Gibson }
14224be21d56SDavid Gibson 
142328e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr,
14244be21d56SDavid Gibson                                 int64_t max_ns)
14254be21d56SDavid Gibson {
14264be21d56SDavid Gibson     bool final = max_ns < 0;
14274be21d56SDavid Gibson     int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64;
14284be21d56SDavid Gibson     int examined = 0, sent = 0;
14294be21d56SDavid Gibson     int index = spapr->htab_save_index;
1430bc72ad67SAlex Bligh     int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
14314be21d56SDavid Gibson 
14324be21d56SDavid Gibson     assert(!spapr->htab_first_pass);
14334be21d56SDavid Gibson 
14344be21d56SDavid Gibson     do {
14354be21d56SDavid Gibson         int chunkstart, invalidstart;
14364be21d56SDavid Gibson 
14374be21d56SDavid Gibson         /* Consume non-dirty HPTEs */
14384be21d56SDavid Gibson         while ((index < htabslots)
14394be21d56SDavid Gibson                && !HPTE_DIRTY(HPTE(spapr->htab, index))) {
14404be21d56SDavid Gibson             index++;
14414be21d56SDavid Gibson             examined++;
14424be21d56SDavid Gibson         }
14434be21d56SDavid Gibson 
14444be21d56SDavid Gibson         chunkstart = index;
14454be21d56SDavid Gibson         /* Consume valid dirty HPTEs */
1446338c25b6SSamuel Mendoza-Jonas         while ((index < htabslots) && (index - chunkstart < USHRT_MAX)
14474be21d56SDavid Gibson                && HPTE_DIRTY(HPTE(spapr->htab, index))
14484be21d56SDavid Gibson                && HPTE_VALID(HPTE(spapr->htab, index))) {
14494be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
14504be21d56SDavid Gibson             index++;
14514be21d56SDavid Gibson             examined++;
14524be21d56SDavid Gibson         }
14534be21d56SDavid Gibson 
14544be21d56SDavid Gibson         invalidstart = index;
14554be21d56SDavid Gibson         /* Consume invalid dirty HPTEs */
1456338c25b6SSamuel Mendoza-Jonas         while ((index < htabslots) && (index - invalidstart < USHRT_MAX)
14574be21d56SDavid Gibson                && HPTE_DIRTY(HPTE(spapr->htab, index))
14584be21d56SDavid Gibson                && !HPTE_VALID(HPTE(spapr->htab, index))) {
14594be21d56SDavid Gibson             CLEAN_HPTE(HPTE(spapr->htab, index));
14604be21d56SDavid Gibson             index++;
14614be21d56SDavid Gibson             examined++;
14624be21d56SDavid Gibson         }
14634be21d56SDavid Gibson 
14644be21d56SDavid Gibson         if (index > chunkstart) {
14654be21d56SDavid Gibson             int n_valid = invalidstart - chunkstart;
14664be21d56SDavid Gibson             int n_invalid = index - invalidstart;
14674be21d56SDavid Gibson 
14684be21d56SDavid Gibson             qemu_put_be32(f, chunkstart);
14694be21d56SDavid Gibson             qemu_put_be16(f, n_valid);
14704be21d56SDavid Gibson             qemu_put_be16(f, n_invalid);
14714be21d56SDavid Gibson             qemu_put_buffer(f, HPTE(spapr->htab, chunkstart),
14724be21d56SDavid Gibson                             HASH_PTE_SIZE_64 * n_valid);
14734be21d56SDavid Gibson             sent += index - chunkstart;
14744be21d56SDavid Gibson 
1475bc72ad67SAlex Bligh             if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) {
14764be21d56SDavid Gibson                 break;
14774be21d56SDavid Gibson             }
14784be21d56SDavid Gibson         }
14794be21d56SDavid Gibson 
14804be21d56SDavid Gibson         if (examined >= htabslots) {
14814be21d56SDavid Gibson             break;
14824be21d56SDavid Gibson         }
14834be21d56SDavid Gibson 
14844be21d56SDavid Gibson         if (index >= htabslots) {
14854be21d56SDavid Gibson             assert(index == htabslots);
14864be21d56SDavid Gibson             index = 0;
14874be21d56SDavid Gibson         }
14884be21d56SDavid Gibson     } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final));
14894be21d56SDavid Gibson 
14904be21d56SDavid Gibson     if (index >= htabslots) {
14914be21d56SDavid Gibson         assert(index == htabslots);
14924be21d56SDavid Gibson         index = 0;
14934be21d56SDavid Gibson     }
14944be21d56SDavid Gibson 
14954be21d56SDavid Gibson     spapr->htab_save_index = index;
14964be21d56SDavid Gibson 
1497e68cb8b4SAlexey Kardashevskiy     return (examined >= htabslots) && (sent == 0) ? 1 : 0;
14984be21d56SDavid Gibson }
14994be21d56SDavid Gibson 
1500e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS    5000000 /* 5 ms */
1501e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE    2048
1502e68cb8b4SAlexey Kardashevskiy 
15034be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque)
15044be21d56SDavid Gibson {
150528e02042SDavid Gibson     sPAPRMachineState *spapr = opaque;
1506715c5407SDavid Gibson     int fd;
1507e68cb8b4SAlexey Kardashevskiy     int rc = 0;
15084be21d56SDavid Gibson 
15094be21d56SDavid Gibson     /* Iteration header */
15104be21d56SDavid Gibson     qemu_put_be32(f, 0);
15114be21d56SDavid Gibson 
1512e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
1513e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
1514e68cb8b4SAlexey Kardashevskiy 
1515715c5407SDavid Gibson         fd = get_htab_fd(spapr);
1516715c5407SDavid Gibson         if (fd < 0) {
1517715c5407SDavid Gibson             return fd;
151801a57972SSamuel Mendoza-Jonas         }
151901a57972SSamuel Mendoza-Jonas 
1520715c5407SDavid Gibson         rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS);
1521e68cb8b4SAlexey Kardashevskiy         if (rc < 0) {
1522e68cb8b4SAlexey Kardashevskiy             return rc;
1523e68cb8b4SAlexey Kardashevskiy         }
1524e68cb8b4SAlexey Kardashevskiy     } else  if (spapr->htab_first_pass) {
15254be21d56SDavid Gibson         htab_save_first_pass(f, spapr, MAX_ITERATION_NS);
15264be21d56SDavid Gibson     } else {
1527e68cb8b4SAlexey Kardashevskiy         rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS);
15284be21d56SDavid Gibson     }
15294be21d56SDavid Gibson 
15304be21d56SDavid Gibson     /* End marker */
15314be21d56SDavid Gibson     qemu_put_be32(f, 0);
15324be21d56SDavid Gibson     qemu_put_be16(f, 0);
15334be21d56SDavid Gibson     qemu_put_be16(f, 0);
15344be21d56SDavid Gibson 
1535e68cb8b4SAlexey Kardashevskiy     return rc;
15364be21d56SDavid Gibson }
15374be21d56SDavid Gibson 
15384be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque)
15394be21d56SDavid Gibson {
154028e02042SDavid Gibson     sPAPRMachineState *spapr = opaque;
1541715c5407SDavid Gibson     int fd;
15424be21d56SDavid Gibson 
15434be21d56SDavid Gibson     /* Iteration header */
15444be21d56SDavid Gibson     qemu_put_be32(f, 0);
15454be21d56SDavid Gibson 
1546e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
1547e68cb8b4SAlexey Kardashevskiy         int rc;
1548e68cb8b4SAlexey Kardashevskiy 
1549e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
1550e68cb8b4SAlexey Kardashevskiy 
1551715c5407SDavid Gibson         fd = get_htab_fd(spapr);
1552715c5407SDavid Gibson         if (fd < 0) {
1553715c5407SDavid Gibson             return fd;
155401a57972SSamuel Mendoza-Jonas         }
155501a57972SSamuel Mendoza-Jonas 
1556715c5407SDavid Gibson         rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1);
1557e68cb8b4SAlexey Kardashevskiy         if (rc < 0) {
1558e68cb8b4SAlexey Kardashevskiy             return rc;
1559e68cb8b4SAlexey Kardashevskiy         }
1560e68cb8b4SAlexey Kardashevskiy     } else {
1561378bc217SDavid Gibson         if (spapr->htab_first_pass) {
1562378bc217SDavid Gibson             htab_save_first_pass(f, spapr, -1);
1563378bc217SDavid Gibson         }
15644be21d56SDavid Gibson         htab_save_later_pass(f, spapr, -1);
1565e68cb8b4SAlexey Kardashevskiy     }
15664be21d56SDavid Gibson 
15674be21d56SDavid Gibson     /* End marker */
15684be21d56SDavid Gibson     qemu_put_be32(f, 0);
15694be21d56SDavid Gibson     qemu_put_be16(f, 0);
15704be21d56SDavid Gibson     qemu_put_be16(f, 0);
15714be21d56SDavid Gibson 
15724be21d56SDavid Gibson     return 0;
15734be21d56SDavid Gibson }
15744be21d56SDavid Gibson 
15754be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id)
15764be21d56SDavid Gibson {
157728e02042SDavid Gibson     sPAPRMachineState *spapr = opaque;
15784be21d56SDavid Gibson     uint32_t section_hdr;
1579e68cb8b4SAlexey Kardashevskiy     int fd = -1;
15804be21d56SDavid Gibson 
15814be21d56SDavid Gibson     if (version_id < 1 || version_id > 1) {
158298a5d100SDavid Gibson         error_report("htab_load() bad version");
15834be21d56SDavid Gibson         return -EINVAL;
15844be21d56SDavid Gibson     }
15854be21d56SDavid Gibson 
15864be21d56SDavid Gibson     section_hdr = qemu_get_be32(f);
15874be21d56SDavid Gibson 
15884be21d56SDavid Gibson     if (section_hdr) {
15899897e462SGreg Kurz         Error *local_err = NULL;
1590c5f54f3eSDavid Gibson 
1591c5f54f3eSDavid Gibson         /* First section gives the htab size */
1592c5f54f3eSDavid Gibson         spapr_reallocate_hpt(spapr, section_hdr, &local_err);
1593c5f54f3eSDavid Gibson         if (local_err) {
1594c5f54f3eSDavid Gibson             error_report_err(local_err);
15954be21d56SDavid Gibson             return -EINVAL;
15964be21d56SDavid Gibson         }
15974be21d56SDavid Gibson         return 0;
15984be21d56SDavid Gibson     }
15994be21d56SDavid Gibson 
1600e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
1601e68cb8b4SAlexey Kardashevskiy         assert(kvm_enabled());
1602e68cb8b4SAlexey Kardashevskiy 
1603e68cb8b4SAlexey Kardashevskiy         fd = kvmppc_get_htab_fd(true);
1604e68cb8b4SAlexey Kardashevskiy         if (fd < 0) {
160598a5d100SDavid Gibson             error_report("Unable to open fd to restore KVM hash table: %s",
1606e68cb8b4SAlexey Kardashevskiy                          strerror(errno));
1607e68cb8b4SAlexey Kardashevskiy         }
1608e68cb8b4SAlexey Kardashevskiy     }
1609e68cb8b4SAlexey Kardashevskiy 
16104be21d56SDavid Gibson     while (true) {
16114be21d56SDavid Gibson         uint32_t index;
16124be21d56SDavid Gibson         uint16_t n_valid, n_invalid;
16134be21d56SDavid Gibson 
16144be21d56SDavid Gibson         index = qemu_get_be32(f);
16154be21d56SDavid Gibson         n_valid = qemu_get_be16(f);
16164be21d56SDavid Gibson         n_invalid = qemu_get_be16(f);
16174be21d56SDavid Gibson 
16184be21d56SDavid Gibson         if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) {
16194be21d56SDavid Gibson             /* End of Stream */
16204be21d56SDavid Gibson             break;
16214be21d56SDavid Gibson         }
16224be21d56SDavid Gibson 
1623e68cb8b4SAlexey Kardashevskiy         if ((index + n_valid + n_invalid) >
16244be21d56SDavid Gibson             (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) {
16254be21d56SDavid Gibson             /* Bad index in stream */
162698a5d100SDavid Gibson             error_report(
162798a5d100SDavid Gibson                 "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)",
162898a5d100SDavid Gibson                 index, n_valid, n_invalid, spapr->htab_shift);
16294be21d56SDavid Gibson             return -EINVAL;
16304be21d56SDavid Gibson         }
16314be21d56SDavid Gibson 
1632e68cb8b4SAlexey Kardashevskiy         if (spapr->htab) {
16334be21d56SDavid Gibson             if (n_valid) {
16344be21d56SDavid Gibson                 qemu_get_buffer(f, HPTE(spapr->htab, index),
16354be21d56SDavid Gibson                                 HASH_PTE_SIZE_64 * n_valid);
16364be21d56SDavid Gibson             }
16374be21d56SDavid Gibson             if (n_invalid) {
16384be21d56SDavid Gibson                 memset(HPTE(spapr->htab, index + n_valid), 0,
16394be21d56SDavid Gibson                        HASH_PTE_SIZE_64 * n_invalid);
16404be21d56SDavid Gibson             }
1641e68cb8b4SAlexey Kardashevskiy         } else {
1642e68cb8b4SAlexey Kardashevskiy             int rc;
1643e68cb8b4SAlexey Kardashevskiy 
1644e68cb8b4SAlexey Kardashevskiy             assert(fd >= 0);
1645e68cb8b4SAlexey Kardashevskiy 
1646e68cb8b4SAlexey Kardashevskiy             rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid);
1647e68cb8b4SAlexey Kardashevskiy             if (rc < 0) {
1648e68cb8b4SAlexey Kardashevskiy                 return rc;
1649e68cb8b4SAlexey Kardashevskiy             }
1650e68cb8b4SAlexey Kardashevskiy         }
1651e68cb8b4SAlexey Kardashevskiy     }
1652e68cb8b4SAlexey Kardashevskiy 
1653e68cb8b4SAlexey Kardashevskiy     if (!spapr->htab) {
1654e68cb8b4SAlexey Kardashevskiy         assert(fd >= 0);
1655e68cb8b4SAlexey Kardashevskiy         close(fd);
16564be21d56SDavid Gibson     }
16574be21d56SDavid Gibson 
16584be21d56SDavid Gibson     return 0;
16594be21d56SDavid Gibson }
16604be21d56SDavid Gibson 
1661c573fc03SThomas Huth static void htab_cleanup(void *opaque)
1662c573fc03SThomas Huth {
1663c573fc03SThomas Huth     sPAPRMachineState *spapr = opaque;
1664c573fc03SThomas Huth 
1665c573fc03SThomas Huth     close_htab_fd(spapr);
1666c573fc03SThomas Huth }
1667c573fc03SThomas Huth 
16684be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = {
16694be21d56SDavid Gibson     .save_live_setup = htab_save_setup,
16704be21d56SDavid Gibson     .save_live_iterate = htab_save_iterate,
1671a3e06c3dSDr. David Alan Gilbert     .save_live_complete_precopy = htab_save_complete,
1672c573fc03SThomas Huth     .cleanup = htab_cleanup,
16734be21d56SDavid Gibson     .load_state = htab_load,
16744be21d56SDavid Gibson };
16754be21d56SDavid Gibson 
16765b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device,
16775b2128d2SAlexander Graf                            Error **errp)
16785b2128d2SAlexander Graf {
16795b2128d2SAlexander Graf     MachineState *machine = MACHINE(qdev_get_machine());
16805b2128d2SAlexander Graf     machine->boot_order = g_strdup(boot_device);
16815b2128d2SAlexander Graf }
16825b2128d2SAlexander Graf 
1683224245bfSDavid Gibson /*
1684224245bfSDavid Gibson  * Reset routine for LMB DR devices.
1685224245bfSDavid Gibson  *
1686224245bfSDavid Gibson  * Unlike PCI DR devices, LMB DR devices explicitly register this reset
1687224245bfSDavid Gibson  * routine. Reset for PCI DR devices will be handled by PHB reset routine
1688224245bfSDavid Gibson  * when it walks all its children devices. LMB devices reset occurs
1689224245bfSDavid Gibson  * as part of spapr_ppc_reset().
1690224245bfSDavid Gibson  */
1691224245bfSDavid Gibson static void spapr_drc_reset(void *opaque)
1692224245bfSDavid Gibson {
1693224245bfSDavid Gibson     sPAPRDRConnector *drc = opaque;
1694224245bfSDavid Gibson     DeviceState *d = DEVICE(drc);
1695224245bfSDavid Gibson 
1696224245bfSDavid Gibson     if (d) {
1697224245bfSDavid Gibson         device_reset(d);
1698224245bfSDavid Gibson     }
1699224245bfSDavid Gibson }
1700224245bfSDavid Gibson 
1701224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr)
1702224245bfSDavid Gibson {
1703224245bfSDavid Gibson     MachineState *machine = MACHINE(spapr);
1704224245bfSDavid Gibson     uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
1705e8f986fcSBharata B Rao     uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size;
1706224245bfSDavid Gibson     int i;
1707224245bfSDavid Gibson 
1708224245bfSDavid Gibson     for (i = 0; i < nr_lmbs; i++) {
1709224245bfSDavid Gibson         sPAPRDRConnector *drc;
1710224245bfSDavid Gibson         uint64_t addr;
1711224245bfSDavid Gibson 
1712e8f986fcSBharata B Rao         addr = i * lmb_size + spapr->hotplug_memory.base;
1713224245bfSDavid Gibson         drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB,
1714224245bfSDavid Gibson                                      addr/lmb_size);
1715224245bfSDavid Gibson         qemu_register_reset(spapr_drc_reset, drc);
1716224245bfSDavid Gibson     }
1717224245bfSDavid Gibson }
1718224245bfSDavid Gibson 
1719224245bfSDavid Gibson /*
1720224245bfSDavid Gibson  * If RAM size, maxmem size and individual node mem sizes aren't aligned
1721224245bfSDavid Gibson  * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest
1722224245bfSDavid Gibson  * since we can't support such unaligned sizes with DRCONF_MEMORY.
1723224245bfSDavid Gibson  */
17247c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp)
1725224245bfSDavid Gibson {
1726224245bfSDavid Gibson     int i;
1727224245bfSDavid Gibson 
17287c150d6fSDavid Gibson     if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) {
17297c150d6fSDavid Gibson         error_setg(errp, "Memory size 0x" RAM_ADDR_FMT
17307c150d6fSDavid Gibson                    " is not aligned to %llu MiB",
17317c150d6fSDavid Gibson                    machine->ram_size,
1732224245bfSDavid Gibson                    SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
17337c150d6fSDavid Gibson         return;
17347c150d6fSDavid Gibson     }
17357c150d6fSDavid Gibson 
17367c150d6fSDavid Gibson     if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) {
17377c150d6fSDavid Gibson         error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT
17387c150d6fSDavid Gibson                    " is not aligned to %llu MiB",
17397c150d6fSDavid Gibson                    machine->ram_size,
17407c150d6fSDavid Gibson                    SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
17417c150d6fSDavid Gibson         return;
1742224245bfSDavid Gibson     }
1743224245bfSDavid Gibson 
1744224245bfSDavid Gibson     for (i = 0; i < nb_numa_nodes; i++) {
1745224245bfSDavid Gibson         if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) {
17467c150d6fSDavid Gibson             error_setg(errp,
17477c150d6fSDavid Gibson                        "Node %d memory size 0x%" PRIx64
17487c150d6fSDavid Gibson                        " is not aligned to %llu MiB",
17497c150d6fSDavid Gibson                        i, numa_info[i].node_mem,
1750224245bfSDavid Gibson                        SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
17517c150d6fSDavid Gibson             return;
1752224245bfSDavid Gibson         }
1753224245bfSDavid Gibson     }
1754224245bfSDavid Gibson }
1755224245bfSDavid Gibson 
175653018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */
17573ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine)
175853018216SPaolo Bonzini {
175928e02042SDavid Gibson     sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
17603c0c47e3SDavid Gibson     MachineClass *mc = MACHINE_GET_CLASS(machine);
1761224245bfSDavid Gibson     sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine);
17623ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
17633ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
176453018216SPaolo Bonzini     PCIHostState *phb;
176553018216SPaolo Bonzini     int i;
176653018216SPaolo Bonzini     MemoryRegion *sysmem = get_system_memory();
176753018216SPaolo Bonzini     MemoryRegion *ram = g_new(MemoryRegion, 1);
1768658fa66bSAlexey Kardashevskiy     MemoryRegion *rma_region;
1769658fa66bSAlexey Kardashevskiy     void *rma = NULL;
177053018216SPaolo Bonzini     hwaddr rma_alloc_size;
1771b082d65aSAlexey Kardashevskiy     hwaddr node0_size = spapr_node0_size();
1772b7d1f77aSBenjamin Herrenschmidt     long load_limit, fw_size;
177353018216SPaolo Bonzini     char *filename;
177494a94e4cSBharata B Rao     int smt = kvmppc_smt_threads();
177594a94e4cSBharata B Rao     int spapr_cores = smp_cpus / smp_threads;
177694a94e4cSBharata B Rao     int spapr_max_cores = max_cpus / smp_threads;
177794a94e4cSBharata B Rao 
17783c0c47e3SDavid Gibson     if (mc->query_hotpluggable_cpus) {
177994a94e4cSBharata B Rao         if (smp_cpus % smp_threads) {
178094a94e4cSBharata B Rao             error_report("smp_cpus (%u) must be multiple of threads (%u)",
178194a94e4cSBharata B Rao                          smp_cpus, smp_threads);
178294a94e4cSBharata B Rao             exit(1);
178394a94e4cSBharata B Rao         }
178494a94e4cSBharata B Rao         if (max_cpus % smp_threads) {
178594a94e4cSBharata B Rao             error_report("max_cpus (%u) must be multiple of threads (%u)",
178694a94e4cSBharata B Rao                          max_cpus, smp_threads);
178794a94e4cSBharata B Rao             exit(1);
178894a94e4cSBharata B Rao         }
178994a94e4cSBharata B Rao     }
179053018216SPaolo Bonzini 
1791226419d6SMichael S. Tsirkin     msi_nonbroken = true;
179253018216SPaolo Bonzini 
179353018216SPaolo Bonzini     QLIST_INIT(&spapr->phbs);
179453018216SPaolo Bonzini 
179553018216SPaolo Bonzini     cpu_ppc_hypercall = emulate_spapr_hypercall;
179653018216SPaolo Bonzini 
179753018216SPaolo Bonzini     /* Allocate RMA if necessary */
1798658fa66bSAlexey Kardashevskiy     rma_alloc_size = kvmppc_alloc_rma(&rma);
179953018216SPaolo Bonzini 
180053018216SPaolo Bonzini     if (rma_alloc_size == -1) {
1801730fce59SThomas Huth         error_report("Unable to create RMA");
180253018216SPaolo Bonzini         exit(1);
180353018216SPaolo Bonzini     }
180453018216SPaolo Bonzini 
1805c4177479SAlexey Kardashevskiy     if (rma_alloc_size && (rma_alloc_size < node0_size)) {
180653018216SPaolo Bonzini         spapr->rma_size = rma_alloc_size;
180753018216SPaolo Bonzini     } else {
1808c4177479SAlexey Kardashevskiy         spapr->rma_size = node0_size;
180953018216SPaolo Bonzini 
181053018216SPaolo Bonzini         /* With KVM, we don't actually know whether KVM supports an
181153018216SPaolo Bonzini          * unbounded RMA (PR KVM) or is limited by the hash table size
181253018216SPaolo Bonzini          * (HV KVM using VRMA), so we always assume the latter
181353018216SPaolo Bonzini          *
181453018216SPaolo Bonzini          * In that case, we also limit the initial allocations for RTAS
181553018216SPaolo Bonzini          * etc... to 256M since we have no way to know what the VRMA size
181653018216SPaolo Bonzini          * is going to be as it depends on the size of the hash table
181753018216SPaolo Bonzini          * isn't determined yet.
181853018216SPaolo Bonzini          */
181953018216SPaolo Bonzini         if (kvm_enabled()) {
182053018216SPaolo Bonzini             spapr->vrma_adjust = 1;
182153018216SPaolo Bonzini             spapr->rma_size = MIN(spapr->rma_size, 0x10000000);
182253018216SPaolo Bonzini         }
1823912acdf4SBenjamin Herrenschmidt 
1824912acdf4SBenjamin Herrenschmidt         /* Actually we don't support unbounded RMA anymore since we
1825912acdf4SBenjamin Herrenschmidt          * added proper emulation of HV mode. The max we can get is
1826912acdf4SBenjamin Herrenschmidt          * 16G which also happens to be what we configure for PAPR
1827912acdf4SBenjamin Herrenschmidt          * mode so make sure we don't do anything bigger than that
1828912acdf4SBenjamin Herrenschmidt          */
1829912acdf4SBenjamin Herrenschmidt         spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull);
183053018216SPaolo Bonzini     }
183153018216SPaolo Bonzini 
1832c4177479SAlexey Kardashevskiy     if (spapr->rma_size > node0_size) {
1833d54e4d76SDavid Gibson         error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")",
1834c4177479SAlexey Kardashevskiy                      spapr->rma_size);
1835c4177479SAlexey Kardashevskiy         exit(1);
1836c4177479SAlexey Kardashevskiy     }
1837c4177479SAlexey Kardashevskiy 
1838b7d1f77aSBenjamin Herrenschmidt     /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
1839b7d1f77aSBenjamin Herrenschmidt     load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
184053018216SPaolo Bonzini 
18417b565160SDavid Gibson     /* Set up Interrupt Controller before we create the VCPUs */
184227f24582SBenjamin Herrenschmidt     spapr->xics = xics_system_init(machine,
184394a94e4cSBharata B Rao                                    DIV_ROUND_UP(max_cpus * smt, smp_threads),
1844161deaf2SBenjamin Herrenschmidt                                    XICS_IRQS_SPAPR, &error_fatal);
18457b565160SDavid Gibson 
1846facdb8b6SMichael Roth     /* Set up containers for ibm,client-set-architecture negotiated options */
1847facdb8b6SMichael Roth     spapr->ov5 = spapr_ovec_new();
1848facdb8b6SMichael Roth     spapr->ov5_cas = spapr_ovec_new();
1849facdb8b6SMichael Roth 
1850224245bfSDavid Gibson     if (smc->dr_lmb_enabled) {
1851facdb8b6SMichael Roth         spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY);
18527c150d6fSDavid Gibson         spapr_validate_node_memory(machine, &error_fatal);
1853224245bfSDavid Gibson     }
1854224245bfSDavid Gibson 
1855417ece33SMichael Roth     spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY);
1856417ece33SMichael Roth 
1857ffbb1705SMichael Roth     /* advertise support for dedicated HP event source to guests */
1858ffbb1705SMichael Roth     if (spapr->use_hotplug_event_source) {
1859ffbb1705SMichael Roth         spapr_ovec_set(spapr->ov5, OV5_HP_EVT);
1860ffbb1705SMichael Roth     }
1861ffbb1705SMichael Roth 
186253018216SPaolo Bonzini     /* init CPUs */
186319fb2c36SBharata B Rao     if (machine->cpu_model == NULL) {
18643daa4a9fSThomas Huth         machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu;
186553018216SPaolo Bonzini     }
186694a94e4cSBharata B Rao 
1867e703d2f7SGreg Kurz     ppc_cpu_parse_features(machine->cpu_model);
1868e703d2f7SGreg Kurz 
18693c0c47e3SDavid Gibson     if (mc->query_hotpluggable_cpus) {
187094a94e4cSBharata B Rao         char *type = spapr_get_cpu_core_type(machine->cpu_model);
187194a94e4cSBharata B Rao 
18724babfaf0SThomas Huth         if (type == NULL) {
1873caebf378SCédric Le Goater             error_report("Unable to find sPAPR CPU Core definition");
1874caebf378SCédric Le Goater             exit(1);
1875caebf378SCédric Le Goater         }
1876caebf378SCédric Le Goater 
187794a94e4cSBharata B Rao         spapr->cores = g_new0(Object *, spapr_max_cores);
1878af81cf32SBharata B Rao         for (i = 0; i < spapr_max_cores; i++) {
187912bf2d33SGreg Kurz             int core_id = i * smp_threads;
1880af81cf32SBharata B Rao             sPAPRDRConnector *drc =
1881af81cf32SBharata B Rao                 spapr_dr_connector_new(OBJECT(spapr),
188212bf2d33SGreg Kurz                                        SPAPR_DR_CONNECTOR_TYPE_CPU,
188312bf2d33SGreg Kurz                                        (core_id / smp_threads) * smt);
1884af81cf32SBharata B Rao 
1885af81cf32SBharata B Rao             qemu_register_reset(spapr_drc_reset, drc);
1886af81cf32SBharata B Rao 
1887af81cf32SBharata B Rao             if (i < spapr_cores) {
1888caebf378SCédric Le Goater                 Object *core  = object_new(type);
188994a94e4cSBharata B Rao                 object_property_set_int(core, smp_threads, "nr-threads",
189094a94e4cSBharata B Rao                                         &error_fatal);
189112bf2d33SGreg Kurz                 object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID,
189294a94e4cSBharata B Rao                                         &error_fatal);
189394a94e4cSBharata B Rao                 object_property_set_bool(core, true, "realized", &error_fatal);
189494a94e4cSBharata B Rao             }
1895af81cf32SBharata B Rao         }
189694a94e4cSBharata B Rao         g_free(type);
189794a94e4cSBharata B Rao     } else {
189853018216SPaolo Bonzini         for (i = 0; i < smp_cpus; i++) {
189994a94e4cSBharata B Rao             PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model);
190053018216SPaolo Bonzini             if (cpu == NULL) {
1901569f4967SDavid Gibson                 error_report("Unable to find PowerPC CPU definition");
190253018216SPaolo Bonzini                 exit(1);
190353018216SPaolo Bonzini             }
1904569f4967SDavid Gibson             spapr_cpu_init(spapr, cpu, &error_fatal);
190553018216SPaolo Bonzini        }
190694a94e4cSBharata B Rao     }
190753018216SPaolo Bonzini 
1908026bfd89SDavid Gibson     if (kvm_enabled()) {
1909026bfd89SDavid Gibson         /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */
1910026bfd89SDavid Gibson         kvmppc_enable_logical_ci_hcalls();
1911ef9971ddSAlexey Kardashevskiy         kvmppc_enable_set_mode_hcall();
19125145ad4fSNathan Whitehorn 
19135145ad4fSNathan Whitehorn         /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */
19145145ad4fSNathan Whitehorn         kvmppc_enable_clear_ref_mod_hcalls();
1915026bfd89SDavid Gibson     }
1916026bfd89SDavid Gibson 
191753018216SPaolo Bonzini     /* allocate RAM */
1918f92f5da1SAlexey Kardashevskiy     memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram",
1919fb164994SDavid Gibson                                          machine->ram_size);
1920f92f5da1SAlexey Kardashevskiy     memory_region_add_subregion(sysmem, 0, ram);
192153018216SPaolo Bonzini 
1922658fa66bSAlexey Kardashevskiy     if (rma_alloc_size && rma) {
1923658fa66bSAlexey Kardashevskiy         rma_region = g_new(MemoryRegion, 1);
1924658fa66bSAlexey Kardashevskiy         memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma",
1925658fa66bSAlexey Kardashevskiy                                    rma_alloc_size, rma);
1926658fa66bSAlexey Kardashevskiy         vmstate_register_ram_global(rma_region);
1927658fa66bSAlexey Kardashevskiy         memory_region_add_subregion(sysmem, 0, rma_region);
1928658fa66bSAlexey Kardashevskiy     }
1929658fa66bSAlexey Kardashevskiy 
19304a1c9cf0SBharata B Rao     /* initialize hotplug memory address space */
19314a1c9cf0SBharata B Rao     if (machine->ram_size < machine->maxram_size) {
19324a1c9cf0SBharata B Rao         ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
193371c9a3ddSBharata B Rao         /*
193471c9a3ddSBharata B Rao          * Limit the number of hotpluggable memory slots to half the number
193571c9a3ddSBharata B Rao          * slots that KVM supports, leaving the other half for PCI and other
193671c9a3ddSBharata B Rao          * devices. However ensure that number of slots doesn't drop below 32.
193771c9a3ddSBharata B Rao          */
193871c9a3ddSBharata B Rao         int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 :
193971c9a3ddSBharata B Rao                            SPAPR_MAX_RAM_SLOTS;
19404a1c9cf0SBharata B Rao 
194171c9a3ddSBharata B Rao         if (max_memslots < SPAPR_MAX_RAM_SLOTS) {
194271c9a3ddSBharata B Rao             max_memslots = SPAPR_MAX_RAM_SLOTS;
194371c9a3ddSBharata B Rao         }
194471c9a3ddSBharata B Rao         if (machine->ram_slots > max_memslots) {
1945d54e4d76SDavid Gibson             error_report("Specified number of memory slots %"
1946d54e4d76SDavid Gibson                          PRIu64" exceeds max supported %d",
194771c9a3ddSBharata B Rao                          machine->ram_slots, max_memslots);
1948d54e4d76SDavid Gibson             exit(1);
19494a1c9cf0SBharata B Rao         }
19504a1c9cf0SBharata B Rao 
19514a1c9cf0SBharata B Rao         spapr->hotplug_memory.base = ROUND_UP(machine->ram_size,
19524a1c9cf0SBharata B Rao                                               SPAPR_HOTPLUG_MEM_ALIGN);
19534a1c9cf0SBharata B Rao         memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr),
19544a1c9cf0SBharata B Rao                            "hotplug-memory", hotplug_mem_size);
19554a1c9cf0SBharata B Rao         memory_region_add_subregion(sysmem, spapr->hotplug_memory.base,
19564a1c9cf0SBharata B Rao                                     &spapr->hotplug_memory.mr);
19574a1c9cf0SBharata B Rao     }
19584a1c9cf0SBharata B Rao 
1959224245bfSDavid Gibson     if (smc->dr_lmb_enabled) {
1960224245bfSDavid Gibson         spapr_create_lmb_dr_connectors(spapr);
1961224245bfSDavid Gibson     }
1962224245bfSDavid Gibson 
196353018216SPaolo Bonzini     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
19644c56440dSStefan Weil     if (!filename) {
1965730fce59SThomas Huth         error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin");
19664c56440dSStefan Weil         exit(1);
19674c56440dSStefan Weil     }
1968b7d1f77aSBenjamin Herrenschmidt     spapr->rtas_size = get_image_size(filename);
19698afc22a2SZhou Jie     if (spapr->rtas_size < 0) {
19708afc22a2SZhou Jie         error_report("Could not get size of LPAR rtas '%s'", filename);
19718afc22a2SZhou Jie         exit(1);
19728afc22a2SZhou Jie     }
1973b7d1f77aSBenjamin Herrenschmidt     spapr->rtas_blob = g_malloc(spapr->rtas_size);
1974b7d1f77aSBenjamin Herrenschmidt     if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
1975730fce59SThomas Huth         error_report("Could not load LPAR rtas '%s'", filename);
197653018216SPaolo Bonzini         exit(1);
197753018216SPaolo Bonzini     }
197853018216SPaolo Bonzini     if (spapr->rtas_size > RTAS_MAX_SIZE) {
1979730fce59SThomas Huth         error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)",
19802f285bddSPeter Maydell                      (size_t)spapr->rtas_size, RTAS_MAX_SIZE);
198153018216SPaolo Bonzini         exit(1);
198253018216SPaolo Bonzini     }
198353018216SPaolo Bonzini     g_free(filename);
198453018216SPaolo Bonzini 
1985ffbb1705SMichael Roth     /* Set up RTAS event infrastructure */
198653018216SPaolo Bonzini     spapr_events_init(spapr);
198753018216SPaolo Bonzini 
198812f42174SDavid Gibson     /* Set up the RTC RTAS interfaces */
198928df36a1SDavid Gibson     spapr_rtc_create(spapr);
199012f42174SDavid Gibson 
199153018216SPaolo Bonzini     /* Set up VIO bus */
199253018216SPaolo Bonzini     spapr->vio_bus = spapr_vio_bus_init();
199353018216SPaolo Bonzini 
199453018216SPaolo Bonzini     for (i = 0; i < MAX_SERIAL_PORTS; i++) {
199553018216SPaolo Bonzini         if (serial_hds[i]) {
199653018216SPaolo Bonzini             spapr_vty_create(spapr->vio_bus, serial_hds[i]);
199753018216SPaolo Bonzini         }
199853018216SPaolo Bonzini     }
199953018216SPaolo Bonzini 
200053018216SPaolo Bonzini     /* We always have at least the nvram device on VIO */
200153018216SPaolo Bonzini     spapr_create_nvram(spapr);
200253018216SPaolo Bonzini 
200353018216SPaolo Bonzini     /* Set up PCI */
200453018216SPaolo Bonzini     spapr_pci_rtas_init();
200553018216SPaolo Bonzini 
200689dfd6e1SDavid Gibson     phb = spapr_create_phb(spapr, 0);
200753018216SPaolo Bonzini 
200853018216SPaolo Bonzini     for (i = 0; i < nb_nics; i++) {
200953018216SPaolo Bonzini         NICInfo *nd = &nd_table[i];
201053018216SPaolo Bonzini 
201153018216SPaolo Bonzini         if (!nd->model) {
201253018216SPaolo Bonzini             nd->model = g_strdup("ibmveth");
201353018216SPaolo Bonzini         }
201453018216SPaolo Bonzini 
201553018216SPaolo Bonzini         if (strcmp(nd->model, "ibmveth") == 0) {
201653018216SPaolo Bonzini             spapr_vlan_create(spapr->vio_bus, nd);
201753018216SPaolo Bonzini         } else {
201829b358f9SDavid Gibson             pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL);
201953018216SPaolo Bonzini         }
202053018216SPaolo Bonzini     }
202153018216SPaolo Bonzini 
202253018216SPaolo Bonzini     for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) {
202353018216SPaolo Bonzini         spapr_vscsi_create(spapr->vio_bus);
202453018216SPaolo Bonzini     }
202553018216SPaolo Bonzini 
202653018216SPaolo Bonzini     /* Graphics */
202714c6a894SDavid Gibson     if (spapr_vga_init(phb->bus, &error_fatal)) {
202853018216SPaolo Bonzini         spapr->has_graphics = true;
2029c6e76503SPaolo Bonzini         machine->usb |= defaults_enabled() && !machine->usb_disabled;
203053018216SPaolo Bonzini     }
203153018216SPaolo Bonzini 
20324ee9ced9SMarcel Apfelbaum     if (machine->usb) {
203357040d45SThomas Huth         if (smc->use_ohci_by_default) {
203453018216SPaolo Bonzini             pci_create_simple(phb->bus, -1, "pci-ohci");
203557040d45SThomas Huth         } else {
203657040d45SThomas Huth             pci_create_simple(phb->bus, -1, "nec-usb-xhci");
203757040d45SThomas Huth         }
2038c86580b8SMarkus Armbruster 
203953018216SPaolo Bonzini         if (spapr->has_graphics) {
2040c86580b8SMarkus Armbruster             USBBus *usb_bus = usb_bus_find(-1);
2041c86580b8SMarkus Armbruster 
2042c86580b8SMarkus Armbruster             usb_create_simple(usb_bus, "usb-kbd");
2043c86580b8SMarkus Armbruster             usb_create_simple(usb_bus, "usb-mouse");
204453018216SPaolo Bonzini         }
204553018216SPaolo Bonzini     }
204653018216SPaolo Bonzini 
204753018216SPaolo Bonzini     if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
2048d54e4d76SDavid Gibson         error_report(
2049d54e4d76SDavid Gibson             "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)",
2050d54e4d76SDavid Gibson             MIN_RMA_SLOF);
205153018216SPaolo Bonzini         exit(1);
205253018216SPaolo Bonzini     }
205353018216SPaolo Bonzini 
205453018216SPaolo Bonzini     if (kernel_filename) {
205553018216SPaolo Bonzini         uint64_t lowaddr = 0;
205653018216SPaolo Bonzini 
2057a19f7fb0SDavid Gibson         spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address,
2058a19f7fb0SDavid Gibson                                       NULL, NULL, &lowaddr, NULL, 1,
2059a19f7fb0SDavid Gibson                                       PPC_ELF_MACHINE, 0, 0);
2060a19f7fb0SDavid Gibson         if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) {
2061a19f7fb0SDavid Gibson             spapr->kernel_size = load_elf(kernel_filename,
2062a19f7fb0SDavid Gibson                                           translate_kernel_address, NULL, NULL,
2063a19f7fb0SDavid Gibson                                           &lowaddr, NULL, 0, PPC_ELF_MACHINE,
20647ef295eaSPeter Crosthwaite                                           0, 0);
2065a19f7fb0SDavid Gibson             spapr->kernel_le = spapr->kernel_size > 0;
206616457e7fSBenjamin Herrenschmidt         }
2067a19f7fb0SDavid Gibson         if (spapr->kernel_size < 0) {
2068a19f7fb0SDavid Gibson             error_report("error loading %s: %s", kernel_filename,
2069a19f7fb0SDavid Gibson                          load_elf_strerror(spapr->kernel_size));
207053018216SPaolo Bonzini             exit(1);
207153018216SPaolo Bonzini         }
207253018216SPaolo Bonzini 
207353018216SPaolo Bonzini         /* load initrd */
207453018216SPaolo Bonzini         if (initrd_filename) {
207553018216SPaolo Bonzini             /* Try to locate the initrd in the gap between the kernel
207653018216SPaolo Bonzini              * and the firmware. Add a bit of space just in case
207753018216SPaolo Bonzini              */
2078a19f7fb0SDavid Gibson             spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size
2079a19f7fb0SDavid Gibson                                   + 0x1ffff) & ~0xffff;
2080a19f7fb0SDavid Gibson             spapr->initrd_size = load_image_targphys(initrd_filename,
2081a19f7fb0SDavid Gibson                                                      spapr->initrd_base,
2082a19f7fb0SDavid Gibson                                                      load_limit
2083a19f7fb0SDavid Gibson                                                      - spapr->initrd_base);
2084a19f7fb0SDavid Gibson             if (spapr->initrd_size < 0) {
2085d54e4d76SDavid Gibson                 error_report("could not load initial ram disk '%s'",
208653018216SPaolo Bonzini                              initrd_filename);
208753018216SPaolo Bonzini                 exit(1);
208853018216SPaolo Bonzini             }
208953018216SPaolo Bonzini         }
209053018216SPaolo Bonzini     }
209153018216SPaolo Bonzini 
20928e7ea787SAndreas Färber     if (bios_name == NULL) {
20938e7ea787SAndreas Färber         bios_name = FW_FILE_NAME;
20948e7ea787SAndreas Färber     }
20958e7ea787SAndreas Färber     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
20964c56440dSStefan Weil     if (!filename) {
209768fea5a0SThomas Huth         error_report("Could not find LPAR firmware '%s'", bios_name);
20984c56440dSStefan Weil         exit(1);
20994c56440dSStefan Weil     }
210053018216SPaolo Bonzini     fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE);
210168fea5a0SThomas Huth     if (fw_size <= 0) {
210268fea5a0SThomas Huth         error_report("Could not load LPAR firmware '%s'", filename);
210353018216SPaolo Bonzini         exit(1);
210453018216SPaolo Bonzini     }
210553018216SPaolo Bonzini     g_free(filename);
210653018216SPaolo Bonzini 
210728e02042SDavid Gibson     /* FIXME: Should register things through the MachineState's qdev
210828e02042SDavid Gibson      * interface, this is a legacy from the sPAPREnvironment structure
210928e02042SDavid Gibson      * which predated MachineState but had a similar function */
21104be21d56SDavid Gibson     vmstate_register(NULL, 0, &vmstate_spapr, spapr);
21114be21d56SDavid Gibson     register_savevm_live(NULL, "spapr/htab", -1, 1,
21124be21d56SDavid Gibson                          &savevm_htab_handlers, spapr);
21134be21d56SDavid Gibson 
211446503c2bSMichael Roth     /* used by RTAS */
211546503c2bSMichael Roth     QTAILQ_INIT(&spapr->ccs_list);
211646503c2bSMichael Roth     qemu_register_reset(spapr_ccs_reset_hook, spapr);
211746503c2bSMichael Roth 
21185b2128d2SAlexander Graf     qemu_register_boot_set(spapr_boot_set, spapr);
211953018216SPaolo Bonzini }
212053018216SPaolo Bonzini 
2121135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type)
2122135a129aSAneesh Kumar K.V {
2123135a129aSAneesh Kumar K.V     if (!vm_type) {
2124135a129aSAneesh Kumar K.V         return 0;
2125135a129aSAneesh Kumar K.V     }
2126135a129aSAneesh Kumar K.V 
2127135a129aSAneesh Kumar K.V     if (!strcmp(vm_type, "HV")) {
2128135a129aSAneesh Kumar K.V         return 1;
2129135a129aSAneesh Kumar K.V     }
2130135a129aSAneesh Kumar K.V 
2131135a129aSAneesh Kumar K.V     if (!strcmp(vm_type, "PR")) {
2132135a129aSAneesh Kumar K.V         return 2;
2133135a129aSAneesh Kumar K.V     }
2134135a129aSAneesh Kumar K.V 
2135135a129aSAneesh Kumar K.V     error_report("Unknown kvm-type specified '%s'", vm_type);
2136135a129aSAneesh Kumar K.V     exit(1);
2137135a129aSAneesh Kumar K.V }
2138135a129aSAneesh Kumar K.V 
213971461b0fSAlexey Kardashevskiy /*
2140627b84f4SGonglei  * Implementation of an interface to adjust firmware path
214171461b0fSAlexey Kardashevskiy  * for the bootindex property handling.
214271461b0fSAlexey Kardashevskiy  */
214371461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
214471461b0fSAlexey Kardashevskiy                                    DeviceState *dev)
214571461b0fSAlexey Kardashevskiy {
214671461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \
214771461b0fSAlexey Kardashevskiy     ((type *)object_dynamic_cast(OBJECT(obj), (name)))
214871461b0fSAlexey Kardashevskiy     SCSIDevice *d = CAST(SCSIDevice,  dev, TYPE_SCSI_DEVICE);
214971461b0fSAlexey Kardashevskiy     sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE);
215071461b0fSAlexey Kardashevskiy 
215171461b0fSAlexey Kardashevskiy     if (d) {
215271461b0fSAlexey Kardashevskiy         void *spapr = CAST(void, bus->parent, "spapr-vscsi");
215371461b0fSAlexey Kardashevskiy         VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI);
215471461b0fSAlexey Kardashevskiy         USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE);
215571461b0fSAlexey Kardashevskiy 
215671461b0fSAlexey Kardashevskiy         if (spapr) {
215771461b0fSAlexey Kardashevskiy             /*
215871461b0fSAlexey Kardashevskiy              * Replace "channel@0/disk@0,0" with "disk@8000000000000000":
215971461b0fSAlexey Kardashevskiy              * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun
216071461b0fSAlexey Kardashevskiy              * in the top 16 bits of the 64-bit LUN
216171461b0fSAlexey Kardashevskiy              */
216271461b0fSAlexey Kardashevskiy             unsigned id = 0x8000 | (d->id << 8) | d->lun;
216371461b0fSAlexey Kardashevskiy             return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
216471461b0fSAlexey Kardashevskiy                                    (uint64_t)id << 48);
216571461b0fSAlexey Kardashevskiy         } else if (virtio) {
216671461b0fSAlexey Kardashevskiy             /*
216771461b0fSAlexey Kardashevskiy              * We use SRP luns of the form 01000000 | (target << 8) | lun
216871461b0fSAlexey Kardashevskiy              * in the top 32 bits of the 64-bit LUN
216971461b0fSAlexey Kardashevskiy              * Note: the quote above is from SLOF and it is wrong,
217071461b0fSAlexey Kardashevskiy              * the actual binding is:
217171461b0fSAlexey Kardashevskiy              * swap 0100 or 10 << or 20 << ( target lun-id -- srplun )
217271461b0fSAlexey Kardashevskiy              */
217371461b0fSAlexey Kardashevskiy             unsigned id = 0x1000000 | (d->id << 16) | d->lun;
217471461b0fSAlexey Kardashevskiy             return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
217571461b0fSAlexey Kardashevskiy                                    (uint64_t)id << 32);
217671461b0fSAlexey Kardashevskiy         } else if (usb) {
217771461b0fSAlexey Kardashevskiy             /*
217871461b0fSAlexey Kardashevskiy              * We use SRP luns of the form 01000000 | (usb-port << 16) | lun
217971461b0fSAlexey Kardashevskiy              * in the top 32 bits of the 64-bit LUN
218071461b0fSAlexey Kardashevskiy              */
218171461b0fSAlexey Kardashevskiy             unsigned usb_port = atoi(usb->port->path);
218271461b0fSAlexey Kardashevskiy             unsigned id = 0x1000000 | (usb_port << 16) | d->lun;
218371461b0fSAlexey Kardashevskiy             return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
218471461b0fSAlexey Kardashevskiy                                    (uint64_t)id << 32);
218571461b0fSAlexey Kardashevskiy         }
218671461b0fSAlexey Kardashevskiy     }
218771461b0fSAlexey Kardashevskiy 
218871461b0fSAlexey Kardashevskiy     if (phb) {
218971461b0fSAlexey Kardashevskiy         /* Replace "pci" with "pci@800000020000000" */
219071461b0fSAlexey Kardashevskiy         return g_strdup_printf("pci@%"PRIX64, phb->buid);
219171461b0fSAlexey Kardashevskiy     }
219271461b0fSAlexey Kardashevskiy 
219371461b0fSAlexey Kardashevskiy     return NULL;
219471461b0fSAlexey Kardashevskiy }
219571461b0fSAlexey Kardashevskiy 
219623825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp)
219723825581SEduardo Habkost {
219828e02042SDavid Gibson     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
219923825581SEduardo Habkost 
220028e02042SDavid Gibson     return g_strdup(spapr->kvm_type);
220123825581SEduardo Habkost }
220223825581SEduardo Habkost 
220323825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp)
220423825581SEduardo Habkost {
220528e02042SDavid Gibson     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
220623825581SEduardo Habkost 
220728e02042SDavid Gibson     g_free(spapr->kvm_type);
220828e02042SDavid Gibson     spapr->kvm_type = g_strdup(value);
220923825581SEduardo Habkost }
221023825581SEduardo Habkost 
2211f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp)
2212f6229214SMichael Roth {
2213f6229214SMichael Roth     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
2214f6229214SMichael Roth 
2215f6229214SMichael Roth     return spapr->use_hotplug_event_source;
2216f6229214SMichael Roth }
2217f6229214SMichael Roth 
2218f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value,
2219f6229214SMichael Roth                                             Error **errp)
2220f6229214SMichael Roth {
2221f6229214SMichael Roth     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
2222f6229214SMichael Roth 
2223f6229214SMichael Roth     spapr->use_hotplug_event_source = value;
2224f6229214SMichael Roth }
2225f6229214SMichael Roth 
222623825581SEduardo Habkost static void spapr_machine_initfn(Object *obj)
222723825581SEduardo Habkost {
2228715c5407SDavid Gibson     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
2229715c5407SDavid Gibson 
2230715c5407SDavid Gibson     spapr->htab_fd = -1;
2231f6229214SMichael Roth     spapr->use_hotplug_event_source = true;
223223825581SEduardo Habkost     object_property_add_str(obj, "kvm-type",
223323825581SEduardo Habkost                             spapr_get_kvm_type, spapr_set_kvm_type, NULL);
223449d2e648SMarcel Apfelbaum     object_property_set_description(obj, "kvm-type",
223549d2e648SMarcel Apfelbaum                                     "Specifies the KVM virtualization mode (HV, PR)",
223649d2e648SMarcel Apfelbaum                                     NULL);
2237f6229214SMichael Roth     object_property_add_bool(obj, "modern-hotplug-events",
2238f6229214SMichael Roth                             spapr_get_modern_hotplug_events,
2239f6229214SMichael Roth                             spapr_set_modern_hotplug_events,
2240f6229214SMichael Roth                             NULL);
2241f6229214SMichael Roth     object_property_set_description(obj, "modern-hotplug-events",
2242f6229214SMichael Roth                                     "Use dedicated hotplug event mechanism in"
2243f6229214SMichael Roth                                     " place of standard EPOW events when possible"
2244f6229214SMichael Roth                                     " (required for memory hot-unplug support)",
2245f6229214SMichael Roth                                     NULL);
224623825581SEduardo Habkost }
224723825581SEduardo Habkost 
224887bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj)
224987bbdd9cSDavid Gibson {
225087bbdd9cSDavid Gibson     sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
225187bbdd9cSDavid Gibson 
225287bbdd9cSDavid Gibson     g_free(spapr->kvm_type);
225387bbdd9cSDavid Gibson }
225487bbdd9cSDavid Gibson 
225514e6fe12SPaolo Bonzini static void ppc_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg)
225634316482SAlexey Kardashevskiy {
225734316482SAlexey Kardashevskiy     cpu_synchronize_state(cs);
225834316482SAlexey Kardashevskiy     ppc_cpu_do_system_reset(cs);
225934316482SAlexey Kardashevskiy }
226034316482SAlexey Kardashevskiy 
226134316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
226234316482SAlexey Kardashevskiy {
226334316482SAlexey Kardashevskiy     CPUState *cs;
226434316482SAlexey Kardashevskiy 
226534316482SAlexey Kardashevskiy     CPU_FOREACH(cs) {
226614e6fe12SPaolo Bonzini         async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL);
226734316482SAlexey Kardashevskiy     }
226834316482SAlexey Kardashevskiy }
226934316482SAlexey Kardashevskiy 
227079b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
227179b78a6bSMichael Roth                            uint32_t node, bool dedicated_hp_event_source,
227279b78a6bSMichael Roth                            Error **errp)
2273c20d332aSBharata B Rao {
2274c20d332aSBharata B Rao     sPAPRDRConnector *drc;
2275c20d332aSBharata B Rao     sPAPRDRConnectorClass *drck;
2276c20d332aSBharata B Rao     uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
2277c20d332aSBharata B Rao     int i, fdt_offset, fdt_size;
2278c20d332aSBharata B Rao     void *fdt;
227979b78a6bSMichael Roth     uint64_t addr = addr_start;
2280c20d332aSBharata B Rao 
2281c20d332aSBharata B Rao     for (i = 0; i < nr_lmbs; i++) {
2282c20d332aSBharata B Rao         drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
2283c20d332aSBharata B Rao                 addr/SPAPR_MEMORY_BLOCK_SIZE);
2284c20d332aSBharata B Rao         g_assert(drc);
2285c20d332aSBharata B Rao 
2286c20d332aSBharata B Rao         fdt = create_device_tree(&fdt_size);
2287c20d332aSBharata B Rao         fdt_offset = spapr_populate_memory_node(fdt, node, addr,
2288c20d332aSBharata B Rao                                                 SPAPR_MEMORY_BLOCK_SIZE);
2289c20d332aSBharata B Rao 
2290c20d332aSBharata B Rao         drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
2291c20d332aSBharata B Rao         drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);
2292c20d332aSBharata B Rao         addr += SPAPR_MEMORY_BLOCK_SIZE;
2293*5c0139a8SMichael Roth         if (!dev->hotplugged) {
2294*5c0139a8SMichael Roth             /* guests expect coldplugged LMBs to be pre-allocated */
2295*5c0139a8SMichael Roth             drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE);
2296*5c0139a8SMichael Roth             drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED);
2297*5c0139a8SMichael Roth         }
2298c20d332aSBharata B Rao     }
22995dd5238cSJianjun Duan     /* send hotplug notification to the
23005dd5238cSJianjun Duan      * guest only in case of hotplugged memory
23015dd5238cSJianjun Duan      */
23025dd5238cSJianjun Duan     if (dev->hotplugged) {
230379b78a6bSMichael Roth         if (dedicated_hp_event_source) {
230479b78a6bSMichael Roth             drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
230579b78a6bSMichael Roth                     addr_start / SPAPR_MEMORY_BLOCK_SIZE);
230679b78a6bSMichael Roth             drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
230779b78a6bSMichael Roth             spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
230879b78a6bSMichael Roth                                                    nr_lmbs,
230979b78a6bSMichael Roth                                                    drck->get_index(drc));
231079b78a6bSMichael Roth         } else {
231179b78a6bSMichael Roth             spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB,
231279b78a6bSMichael Roth                                            nr_lmbs);
231379b78a6bSMichael Roth         }
2314c20d332aSBharata B Rao     }
23155dd5238cSJianjun Duan }
2316c20d332aSBharata B Rao 
2317c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
2318c20d332aSBharata B Rao                               uint32_t node, Error **errp)
2319c20d332aSBharata B Rao {
2320c20d332aSBharata B Rao     Error *local_err = NULL;
2321c20d332aSBharata B Rao     sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
2322c20d332aSBharata B Rao     PCDIMMDevice *dimm = PC_DIMM(dev);
2323c20d332aSBharata B Rao     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
2324c20d332aSBharata B Rao     MemoryRegion *mr = ddc->get_memory_region(dimm);
2325c20d332aSBharata B Rao     uint64_t align = memory_region_get_alignment(mr);
2326c20d332aSBharata B Rao     uint64_t size = memory_region_size(mr);
2327c20d332aSBharata B Rao     uint64_t addr;
2328c20d332aSBharata B Rao 
2329c20d332aSBharata B Rao     if (size % SPAPR_MEMORY_BLOCK_SIZE) {
2330c20d332aSBharata B Rao         error_setg(&local_err, "Hotplugged memory size must be a multiple of "
2331c20d332aSBharata B Rao                       "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE);
2332c20d332aSBharata B Rao         goto out;
2333c20d332aSBharata B Rao     }
2334c20d332aSBharata B Rao 
2335d6a9b0b8SMichael S. Tsirkin     pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err);
2336c20d332aSBharata B Rao     if (local_err) {
2337c20d332aSBharata B Rao         goto out;
2338c20d332aSBharata B Rao     }
2339c20d332aSBharata B Rao 
2340c20d332aSBharata B Rao     addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
2341c20d332aSBharata B Rao     if (local_err) {
2342c20d332aSBharata B Rao         pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
2343c20d332aSBharata B Rao         goto out;
2344c20d332aSBharata B Rao     }
2345c20d332aSBharata B Rao 
234679b78a6bSMichael Roth     spapr_add_lmbs(dev, addr, size, node,
234779b78a6bSMichael Roth                    spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
234879b78a6bSMichael Roth                    &error_abort);
2349c20d332aSBharata B Rao 
2350c20d332aSBharata B Rao out:
2351c20d332aSBharata B Rao     error_propagate(errp, local_err);
2352c20d332aSBharata B Rao }
2353c20d332aSBharata B Rao 
2354cf632463SBharata B Rao typedef struct sPAPRDIMMState {
2355cf632463SBharata B Rao     uint32_t nr_lmbs;
2356cf632463SBharata B Rao } sPAPRDIMMState;
2357cf632463SBharata B Rao 
2358cf632463SBharata B Rao static void spapr_lmb_release(DeviceState *dev, void *opaque)
2359cf632463SBharata B Rao {
2360cf632463SBharata B Rao     sPAPRDIMMState *ds = (sPAPRDIMMState *)opaque;
2361cf632463SBharata B Rao     HotplugHandler *hotplug_ctrl;
2362cf632463SBharata B Rao 
2363cf632463SBharata B Rao     if (--ds->nr_lmbs) {
2364cf632463SBharata B Rao         return;
2365cf632463SBharata B Rao     }
2366cf632463SBharata B Rao 
2367cf632463SBharata B Rao     g_free(ds);
2368cf632463SBharata B Rao 
2369cf632463SBharata B Rao     /*
2370cf632463SBharata B Rao      * Now that all the LMBs have been removed by the guest, call the
2371cf632463SBharata B Rao      * pc-dimm unplug handler to cleanup up the pc-dimm device.
2372cf632463SBharata B Rao      */
2373cf632463SBharata B Rao     hotplug_ctrl = qdev_get_hotplug_handler(dev);
2374cf632463SBharata B Rao     hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort);
2375cf632463SBharata B Rao }
2376cf632463SBharata B Rao 
2377cf632463SBharata B Rao static void spapr_del_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
2378cf632463SBharata B Rao                            Error **errp)
2379cf632463SBharata B Rao {
2380cf632463SBharata B Rao     sPAPRDRConnector *drc;
2381cf632463SBharata B Rao     sPAPRDRConnectorClass *drck;
2382cf632463SBharata B Rao     uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
2383cf632463SBharata B Rao     int i;
2384cf632463SBharata B Rao     sPAPRDIMMState *ds = g_malloc0(sizeof(sPAPRDIMMState));
2385cf632463SBharata B Rao     uint64_t addr = addr_start;
2386cf632463SBharata B Rao 
2387cf632463SBharata B Rao     ds->nr_lmbs = nr_lmbs;
2388cf632463SBharata B Rao     for (i = 0; i < nr_lmbs; i++) {
2389cf632463SBharata B Rao         drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
2390cf632463SBharata B Rao                 addr / SPAPR_MEMORY_BLOCK_SIZE);
2391cf632463SBharata B Rao         g_assert(drc);
2392cf632463SBharata B Rao 
2393cf632463SBharata B Rao         drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
2394cf632463SBharata B Rao         drck->detach(drc, dev, spapr_lmb_release, ds, errp);
2395cf632463SBharata B Rao         addr += SPAPR_MEMORY_BLOCK_SIZE;
2396cf632463SBharata B Rao     }
2397cf632463SBharata B Rao 
2398cf632463SBharata B Rao     drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
2399cf632463SBharata B Rao                                    addr_start / SPAPR_MEMORY_BLOCK_SIZE);
2400cf632463SBharata B Rao     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
2401cf632463SBharata B Rao     spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB,
2402cf632463SBharata B Rao                                               nr_lmbs,
2403cf632463SBharata B Rao                                               drck->get_index(drc));
2404cf632463SBharata B Rao }
2405cf632463SBharata B Rao 
2406cf632463SBharata B Rao static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
2407cf632463SBharata B Rao                                 Error **errp)
2408cf632463SBharata B Rao {
2409cf632463SBharata B Rao     sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
2410cf632463SBharata B Rao     PCDIMMDevice *dimm = PC_DIMM(dev);
2411cf632463SBharata B Rao     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
2412cf632463SBharata B Rao     MemoryRegion *mr = ddc->get_memory_region(dimm);
2413cf632463SBharata B Rao 
2414cf632463SBharata B Rao     pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr);
2415cf632463SBharata B Rao     object_unparent(OBJECT(dev));
2416cf632463SBharata B Rao }
2417cf632463SBharata B Rao 
2418cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
2419cf632463SBharata B Rao                                         DeviceState *dev, Error **errp)
2420cf632463SBharata B Rao {
2421cf632463SBharata B Rao     Error *local_err = NULL;
2422cf632463SBharata B Rao     PCDIMMDevice *dimm = PC_DIMM(dev);
2423cf632463SBharata B Rao     PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
2424cf632463SBharata B Rao     MemoryRegion *mr = ddc->get_memory_region(dimm);
2425cf632463SBharata B Rao     uint64_t size = memory_region_size(mr);
2426cf632463SBharata B Rao     uint64_t addr;
2427cf632463SBharata B Rao 
2428cf632463SBharata B Rao     addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
2429cf632463SBharata B Rao     if (local_err) {
2430cf632463SBharata B Rao         goto out;
2431cf632463SBharata B Rao     }
2432cf632463SBharata B Rao 
2433cf632463SBharata B Rao     spapr_del_lmbs(dev, addr, size, &error_abort);
2434cf632463SBharata B Rao out:
2435cf632463SBharata B Rao     error_propagate(errp, local_err);
2436cf632463SBharata B Rao }
2437cf632463SBharata B Rao 
2438af81cf32SBharata B Rao void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
2439af81cf32SBharata B Rao                                     sPAPRMachineState *spapr)
2440af81cf32SBharata B Rao {
2441af81cf32SBharata B Rao     PowerPCCPU *cpu = POWERPC_CPU(cs);
2442af81cf32SBharata B Rao     DeviceClass *dc = DEVICE_GET_CLASS(cs);
2443af81cf32SBharata B Rao     int id = ppc_get_vcpu_dt_id(cpu);
2444af81cf32SBharata B Rao     void *fdt;
2445af81cf32SBharata B Rao     int offset, fdt_size;
2446af81cf32SBharata B Rao     char *nodename;
2447af81cf32SBharata B Rao 
2448af81cf32SBharata B Rao     fdt = create_device_tree(&fdt_size);
2449af81cf32SBharata B Rao     nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
2450af81cf32SBharata B Rao     offset = fdt_add_subnode(fdt, 0, nodename);
2451af81cf32SBharata B Rao 
2452af81cf32SBharata B Rao     spapr_populate_cpu_dt(cs, fdt, offset, spapr);
2453af81cf32SBharata B Rao     g_free(nodename);
2454af81cf32SBharata B Rao 
2455af81cf32SBharata B Rao     *fdt_offset = offset;
2456af81cf32SBharata B Rao     return fdt;
2457af81cf32SBharata B Rao }
2458af81cf32SBharata B Rao 
2459c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
2460c20d332aSBharata B Rao                                       DeviceState *dev, Error **errp)
2461c20d332aSBharata B Rao {
2462c20d332aSBharata B Rao     sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine());
2463c20d332aSBharata B Rao 
2464c20d332aSBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
2465b556854bSBharata B Rao         int node;
2466c20d332aSBharata B Rao 
2467c20d332aSBharata B Rao         if (!smc->dr_lmb_enabled) {
2468c20d332aSBharata B Rao             error_setg(errp, "Memory hotplug not supported for this machine");
2469c20d332aSBharata B Rao             return;
2470c20d332aSBharata B Rao         }
2471c20d332aSBharata B Rao         node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp);
2472c20d332aSBharata B Rao         if (*errp) {
2473c20d332aSBharata B Rao             return;
2474c20d332aSBharata B Rao         }
24751a5512bbSGonglei         if (node < 0 || node >= MAX_NODES) {
24761a5512bbSGonglei             error_setg(errp, "Invaild node %d", node);
24771a5512bbSGonglei             return;
24781a5512bbSGonglei         }
2479c20d332aSBharata B Rao 
2480b556854bSBharata B Rao         /*
2481b556854bSBharata B Rao          * Currently PowerPC kernel doesn't allow hot-adding memory to
2482b556854bSBharata B Rao          * memory-less node, but instead will silently add the memory
2483b556854bSBharata B Rao          * to the first node that has some memory. This causes two
2484b556854bSBharata B Rao          * unexpected behaviours for the user.
2485b556854bSBharata B Rao          *
2486b556854bSBharata B Rao          * - Memory gets hotplugged to a different node than what the user
2487b556854bSBharata B Rao          *   specified.
2488b556854bSBharata B Rao          * - Since pc-dimm subsystem in QEMU still thinks that memory belongs
2489b556854bSBharata B Rao          *   to memory-less node, a reboot will set things accordingly
2490b556854bSBharata B Rao          *   and the previously hotplugged memory now ends in the right node.
2491b556854bSBharata B Rao          *   This appears as if some memory moved from one node to another.
2492b556854bSBharata B Rao          *
2493b556854bSBharata B Rao          * So until kernel starts supporting memory hotplug to memory-less
2494b556854bSBharata B Rao          * nodes, just prevent such attempts upfront in QEMU.
2495b556854bSBharata B Rao          */
2496b556854bSBharata B Rao         if (nb_numa_nodes && !numa_info[node].node_mem) {
2497b556854bSBharata B Rao             error_setg(errp, "Can't hotplug memory to memory-less node %d",
2498b556854bSBharata B Rao                        node);
2499b556854bSBharata B Rao             return;
2500b556854bSBharata B Rao         }
2501b556854bSBharata B Rao 
2502c20d332aSBharata B Rao         spapr_memory_plug(hotplug_dev, dev, node, errp);
2503af81cf32SBharata B Rao     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
2504af81cf32SBharata B Rao         spapr_core_plug(hotplug_dev, dev, errp);
2505c20d332aSBharata B Rao     }
2506c20d332aSBharata B Rao }
2507c20d332aSBharata B Rao 
2508c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
2509c20d332aSBharata B Rao                                       DeviceState *dev, Error **errp)
2510c20d332aSBharata B Rao {
2511cf632463SBharata B Rao     sPAPRMachineState *sms = SPAPR_MACHINE(qdev_get_machine());
25123c0c47e3SDavid Gibson     MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
25136f4b5c3eSBharata B Rao 
2514c20d332aSBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
2515cf632463SBharata B Rao         if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
2516cf632463SBharata B Rao             spapr_memory_unplug(hotplug_dev, dev, errp);
2517cf632463SBharata B Rao         } else {
2518cf632463SBharata B Rao             error_setg(errp, "Memory hot unplug not supported for this guest");
2519cf632463SBharata B Rao         }
2520cf632463SBharata B Rao     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
2521cf632463SBharata B Rao         if (!mc->query_hotpluggable_cpus) {
2522cf632463SBharata B Rao             error_setg(errp, "CPU hot unplug not supported on this machine");
2523cf632463SBharata B Rao             return;
2524cf632463SBharata B Rao         }
2525cf632463SBharata B Rao         spapr_core_unplug(hotplug_dev, dev, errp);
2526cf632463SBharata B Rao     }
2527cf632463SBharata B Rao }
2528cf632463SBharata B Rao 
2529cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
2530cf632463SBharata B Rao                                                 DeviceState *dev, Error **errp)
2531cf632463SBharata B Rao {
2532cf632463SBharata B Rao     sPAPRMachineState *sms = SPAPR_MACHINE(qdev_get_machine());
2533cf632463SBharata B Rao     MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
2534cf632463SBharata B Rao 
2535cf632463SBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
2536cf632463SBharata B Rao         if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
2537cf632463SBharata B Rao             spapr_memory_unplug_request(hotplug_dev, dev, errp);
2538cf632463SBharata B Rao         } else {
2539cf632463SBharata B Rao             /* NOTE: this means there is a window after guest reset, prior to
2540cf632463SBharata B Rao              * CAS negotiation, where unplug requests will fail due to the
2541cf632463SBharata B Rao              * capability not being detected yet. This is a bit different than
2542cf632463SBharata B Rao              * the case with PCI unplug, where the events will be queued and
2543cf632463SBharata B Rao              * eventually handled by the guest after boot
2544cf632463SBharata B Rao              */
2545cf632463SBharata B Rao             error_setg(errp, "Memory hot unplug not supported for this guest");
2546cf632463SBharata B Rao         }
25476f4b5c3eSBharata B Rao     } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
25483c0c47e3SDavid Gibson         if (!mc->query_hotpluggable_cpus) {
25496f4b5c3eSBharata B Rao             error_setg(errp, "CPU hot unplug not supported on this machine");
25506f4b5c3eSBharata B Rao             return;
25516f4b5c3eSBharata B Rao         }
25526f4b5c3eSBharata B Rao         spapr_core_unplug(hotplug_dev, dev, errp);
2553c20d332aSBharata B Rao     }
2554c20d332aSBharata B Rao }
2555c20d332aSBharata B Rao 
255694a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev,
255794a94e4cSBharata B Rao                                           DeviceState *dev, Error **errp)
255894a94e4cSBharata B Rao {
255994a94e4cSBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
256094a94e4cSBharata B Rao         spapr_core_pre_plug(hotplug_dev, dev, errp);
256194a94e4cSBharata B Rao     }
256294a94e4cSBharata B Rao }
256394a94e4cSBharata B Rao 
25647ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine,
2565c20d332aSBharata B Rao                                                  DeviceState *dev)
2566c20d332aSBharata B Rao {
256794a94e4cSBharata B Rao     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
256894a94e4cSBharata B Rao         object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
2569c20d332aSBharata B Rao         return HOTPLUG_HANDLER(machine);
2570c20d332aSBharata B Rao     }
2571c20d332aSBharata B Rao     return NULL;
2572c20d332aSBharata B Rao }
2573c20d332aSBharata B Rao 
257420bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index)
257520bb648dSDavid Gibson {
257620bb648dSDavid Gibson     /* Allocate to NUMA nodes on a "socket" basis (not that concept of
257720bb648dSDavid Gibson      * socket means much for the paravirtualized PAPR platform) */
257820bb648dSDavid Gibson     return cpu_index / smp_threads / smp_cores;
257920bb648dSDavid Gibson }
258020bb648dSDavid Gibson 
25812474bfd4SIgor Mammedov static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine)
25822474bfd4SIgor Mammedov {
25832474bfd4SIgor Mammedov     int i;
25842474bfd4SIgor Mammedov     HotpluggableCPUList *head = NULL;
25852474bfd4SIgor Mammedov     sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
25862474bfd4SIgor Mammedov     int spapr_max_cores = max_cpus / smp_threads;
25872474bfd4SIgor Mammedov 
25882474bfd4SIgor Mammedov     for (i = 0; i < spapr_max_cores; i++) {
25892474bfd4SIgor Mammedov         HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1);
25902474bfd4SIgor Mammedov         HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1);
25912474bfd4SIgor Mammedov         CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1);
25922474bfd4SIgor Mammedov 
25932474bfd4SIgor Mammedov         cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model);
25942474bfd4SIgor Mammedov         cpu_item->vcpus_count = smp_threads;
259527393c33SPeter Krempa         cpu_props->has_core_id = true;
259612bf2d33SGreg Kurz         cpu_props->core_id = i * smp_threads;
25972474bfd4SIgor Mammedov         /* TODO: add 'has_node/node' here to describe
25982474bfd4SIgor Mammedov            to which node core belongs */
25992474bfd4SIgor Mammedov 
26002474bfd4SIgor Mammedov         cpu_item->props = cpu_props;
26012474bfd4SIgor Mammedov         if (spapr->cores[i]) {
26022474bfd4SIgor Mammedov             cpu_item->has_qom_path = true;
26032474bfd4SIgor Mammedov             cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]);
26042474bfd4SIgor Mammedov         }
26052474bfd4SIgor Mammedov         list_item->value = cpu_item;
26062474bfd4SIgor Mammedov         list_item->next = head;
26072474bfd4SIgor Mammedov         head = list_item;
26082474bfd4SIgor Mammedov     }
26092474bfd4SIgor Mammedov     return head;
26102474bfd4SIgor Mammedov }
26112474bfd4SIgor Mammedov 
26126737d9adSDavid Gibson static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index,
2613daa23699SDavid Gibson                                 uint64_t *buid, hwaddr *pio,
2614daa23699SDavid Gibson                                 hwaddr *mmio32, hwaddr *mmio64,
26156737d9adSDavid Gibson                                 unsigned n_dma, uint32_t *liobns, Error **errp)
26166737d9adSDavid Gibson {
2617357d1e3bSDavid Gibson     /*
2618357d1e3bSDavid Gibson      * New-style PHB window placement.
2619357d1e3bSDavid Gibson      *
2620357d1e3bSDavid Gibson      * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window
2621357d1e3bSDavid Gibson      * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO
2622357d1e3bSDavid Gibson      * windows.
2623357d1e3bSDavid Gibson      *
2624357d1e3bSDavid Gibson      * Some guest kernels can't work with MMIO windows above 1<<46
2625357d1e3bSDavid Gibson      * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB
2626357d1e3bSDavid Gibson      *
2627357d1e3bSDavid Gibson      * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each
2628357d1e3bSDavid Gibson      * PHB stacked together.  (32TiB+2GiB)..(32TiB+64GiB) contains the
2629357d1e3bSDavid Gibson      * 2GiB 32-bit MMIO windows for each PHB.  Then 33..64TiB has the
2630357d1e3bSDavid Gibson      * 1TiB 64-bit MMIO windows for each PHB.
2631357d1e3bSDavid Gibson      */
26326737d9adSDavid Gibson     const uint64_t base_buid = 0x800000020000000ULL;
2633357d1e3bSDavid Gibson     const int max_phbs =
2634357d1e3bSDavid Gibson         (SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / SPAPR_PCI_MEM64_WIN_SIZE - 1;
26356737d9adSDavid Gibson     int i;
26366737d9adSDavid Gibson 
2637357d1e3bSDavid Gibson     /* Sanity check natural alignments */
2638357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
2639357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0);
2640357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0);
2641357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0);
2642357d1e3bSDavid Gibson     /* Sanity check bounds */
2643357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_IO_WIN_SIZE) > SPAPR_PCI_MEM32_WIN_SIZE);
2644357d1e3bSDavid Gibson     QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_MEM32_WIN_SIZE) > SPAPR_PCI_MEM64_WIN_SIZE);
26452efff1c0SDavid Gibson 
2646357d1e3bSDavid Gibson     if (index >= max_phbs) {
26476737d9adSDavid Gibson         error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
2648357d1e3bSDavid Gibson                    max_phbs - 1);
26496737d9adSDavid Gibson         return;
26506737d9adSDavid Gibson     }
26516737d9adSDavid Gibson 
26526737d9adSDavid Gibson     *buid = base_buid + index;
26536737d9adSDavid Gibson     for (i = 0; i < n_dma; ++i) {
26546737d9adSDavid Gibson         liobns[i] = SPAPR_PCI_LIOBN(index, i);
26556737d9adSDavid Gibson     }
26566737d9adSDavid Gibson 
2657357d1e3bSDavid Gibson     *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE;
2658357d1e3bSDavid Gibson     *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE;
2659357d1e3bSDavid Gibson     *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE;
26606737d9adSDavid Gibson }
26616737d9adSDavid Gibson 
266229ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data)
266353018216SPaolo Bonzini {
266429ee3247SAlexey Kardashevskiy     MachineClass *mc = MACHINE_CLASS(oc);
2665224245bfSDavid Gibson     sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc);
266671461b0fSAlexey Kardashevskiy     FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc);
266734316482SAlexey Kardashevskiy     NMIClass *nc = NMI_CLASS(oc);
2668c20d332aSBharata B Rao     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
266929ee3247SAlexey Kardashevskiy 
26700eb9054cSDavid Gibson     mc->desc = "pSeries Logical Partition (PAPR compliant)";
2671fc9f38c3SDavid Gibson 
2672fc9f38c3SDavid Gibson     /*
2673fc9f38c3SDavid Gibson      * We set up the default / latest behaviour here.  The class_init
2674fc9f38c3SDavid Gibson      * functions for the specific versioned machine types can override
2675fc9f38c3SDavid Gibson      * these details for backwards compatibility
2676fc9f38c3SDavid Gibson      */
2677958db90cSMarcel Apfelbaum     mc->init = ppc_spapr_init;
2678958db90cSMarcel Apfelbaum     mc->reset = ppc_spapr_reset;
2679958db90cSMarcel Apfelbaum     mc->block_default_type = IF_SCSI;
2680079019f2SIgor Mammedov     mc->max_cpus = 255;
2681958db90cSMarcel Apfelbaum     mc->no_parallel = 1;
26825b2128d2SAlexander Graf     mc->default_boot_order = "";
2683a34944feSNikunj A Dadhania     mc->default_ram_size = 512 * M_BYTE;
2684958db90cSMarcel Apfelbaum     mc->kvm_type = spapr_kvm_type;
26859e3f9733SAlexander Graf     mc->has_dynamic_sysbus = true;
2686e4024630SLaurent Vivier     mc->pci_allow_0_address = true;
26877ebaf795SBharata B Rao     mc->get_hotplug_handler = spapr_get_hotplug_handler;
268894a94e4cSBharata B Rao     hc->pre_plug = spapr_machine_device_pre_plug;
2689c20d332aSBharata B Rao     hc->plug = spapr_machine_device_plug;
2690c20d332aSBharata B Rao     hc->unplug = spapr_machine_device_unplug;
269120bb648dSDavid Gibson     mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id;
2692cf632463SBharata B Rao     hc->unplug_request = spapr_machine_device_unplug_request;
269300b4fbe2SMarcel Apfelbaum 
2694fc9f38c3SDavid Gibson     smc->dr_lmb_enabled = true;
26953daa4a9fSThomas Huth     smc->tcg_default_cpu = "POWER8";
26963c0c47e3SDavid Gibson     mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus;
269771461b0fSAlexey Kardashevskiy     fwc->get_dev_path = spapr_get_fw_dev_path;
269834316482SAlexey Kardashevskiy     nc->nmi_monitor_handler = spapr_nmi;
26996737d9adSDavid Gibson     smc->phb_placement = spapr_phb_placement;
270053018216SPaolo Bonzini }
270153018216SPaolo Bonzini 
270229ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = {
270329ee3247SAlexey Kardashevskiy     .name          = TYPE_SPAPR_MACHINE,
270429ee3247SAlexey Kardashevskiy     .parent        = TYPE_MACHINE,
27054aee7362SDavid Gibson     .abstract      = true,
27066ca1502eSAlexey Kardashevskiy     .instance_size = sizeof(sPAPRMachineState),
270723825581SEduardo Habkost     .instance_init = spapr_machine_initfn,
270887bbdd9cSDavid Gibson     .instance_finalize = spapr_machine_finalizefn,
2709183930c0SDavid Gibson     .class_size    = sizeof(sPAPRMachineClass),
271029ee3247SAlexey Kardashevskiy     .class_init    = spapr_machine_class_init,
271171461b0fSAlexey Kardashevskiy     .interfaces = (InterfaceInfo[]) {
271271461b0fSAlexey Kardashevskiy         { TYPE_FW_PATH_PROVIDER },
271334316482SAlexey Kardashevskiy         { TYPE_NMI },
2714c20d332aSBharata B Rao         { TYPE_HOTPLUG_HANDLER },
271571461b0fSAlexey Kardashevskiy         { }
271671461b0fSAlexey Kardashevskiy     },
271729ee3247SAlexey Kardashevskiy };
271829ee3247SAlexey Kardashevskiy 
2719fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest)                 \
27205013c547SDavid Gibson     static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \
27215013c547SDavid Gibson                                                     void *data)      \
27225013c547SDavid Gibson     {                                                                \
27235013c547SDavid Gibson         MachineClass *mc = MACHINE_CLASS(oc);                        \
27245013c547SDavid Gibson         spapr_machine_##suffix##_class_options(mc);                  \
2725fccbc785SDavid Gibson         if (latest) {                                                \
2726fccbc785SDavid Gibson             mc->alias = "pseries";                                   \
2727fccbc785SDavid Gibson             mc->is_default = 1;                                      \
2728fccbc785SDavid Gibson         }                                                            \
27295013c547SDavid Gibson     }                                                                \
27305013c547SDavid Gibson     static void spapr_machine_##suffix##_instance_init(Object *obj)  \
27315013c547SDavid Gibson     {                                                                \
27325013c547SDavid Gibson         MachineState *machine = MACHINE(obj);                        \
27335013c547SDavid Gibson         spapr_machine_##suffix##_instance_options(machine);          \
27345013c547SDavid Gibson     }                                                                \
27355013c547SDavid Gibson     static const TypeInfo spapr_machine_##suffix##_info = {          \
27365013c547SDavid Gibson         .name = MACHINE_TYPE_NAME("pseries-" verstr),                \
27375013c547SDavid Gibson         .parent = TYPE_SPAPR_MACHINE,                                \
27385013c547SDavid Gibson         .class_init = spapr_machine_##suffix##_class_init,           \
27395013c547SDavid Gibson         .instance_init = spapr_machine_##suffix##_instance_init,     \
27405013c547SDavid Gibson     };                                                               \
27415013c547SDavid Gibson     static void spapr_machine_register_##suffix(void)                \
27425013c547SDavid Gibson     {                                                                \
27435013c547SDavid Gibson         type_register(&spapr_machine_##suffix##_info);               \
27445013c547SDavid Gibson     }                                                                \
27450e6aac87SEduardo Habkost     type_init(spapr_machine_register_##suffix)
27465013c547SDavid Gibson 
27471c5f29bbSDavid Gibson /*
2748db800b21SDavid Gibson  * pseries-2.8
2749db800b21SDavid Gibson  */
2750db800b21SDavid Gibson static void spapr_machine_2_8_instance_options(MachineState *machine)
2751db800b21SDavid Gibson {
2752db800b21SDavid Gibson }
2753db800b21SDavid Gibson 
2754db800b21SDavid Gibson static void spapr_machine_2_8_class_options(MachineClass *mc)
2755db800b21SDavid Gibson {
2756db800b21SDavid Gibson     /* Defaults for the latest behaviour inherited from the base class */
2757db800b21SDavid Gibson }
2758db800b21SDavid Gibson 
2759db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", true);
2760db800b21SDavid Gibson 
2761db800b21SDavid Gibson /*
27621ea1eefcSBharata B Rao  * pseries-2.7
27631ea1eefcSBharata B Rao  */
2764db800b21SDavid Gibson #define SPAPR_COMPAT_2_7                            \
2765db800b21SDavid Gibson     HW_COMPAT_2_7                                   \
2766357d1e3bSDavid Gibson     {                                               \
2767357d1e3bSDavid Gibson         .driver   = TYPE_SPAPR_PCI_HOST_BRIDGE,     \
2768357d1e3bSDavid Gibson         .property = "mem_win_size",                 \
2769357d1e3bSDavid Gibson         .value    = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\
2770357d1e3bSDavid Gibson     },                                              \
2771357d1e3bSDavid Gibson     {                                               \
2772357d1e3bSDavid Gibson         .driver   = TYPE_SPAPR_PCI_HOST_BRIDGE,     \
2773357d1e3bSDavid Gibson         .property = "mem64_win_size",               \
2774357d1e3bSDavid Gibson         .value    = "0",                            \
2775146c11f1SDavid Gibson     },                                              \
2776146c11f1SDavid Gibson     {                                               \
2777146c11f1SDavid Gibson         .driver = TYPE_POWERPC_CPU,                 \
2778146c11f1SDavid Gibson         .property = "pre-2.8-migration",            \
2779146c11f1SDavid Gibson         .value    = "on",                           \
27805c4537bdSDavid Gibson     },                                              \
27815c4537bdSDavid Gibson     {                                               \
27825c4537bdSDavid Gibson         .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,       \
27835c4537bdSDavid Gibson         .property = "pre-2.8-migration",            \
27845c4537bdSDavid Gibson         .value    = "on",                           \
2785357d1e3bSDavid Gibson     },
2786357d1e3bSDavid Gibson 
2787357d1e3bSDavid Gibson static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index,
2788357d1e3bSDavid Gibson                               uint64_t *buid, hwaddr *pio,
2789357d1e3bSDavid Gibson                               hwaddr *mmio32, hwaddr *mmio64,
2790357d1e3bSDavid Gibson                               unsigned n_dma, uint32_t *liobns, Error **errp)
2791357d1e3bSDavid Gibson {
2792357d1e3bSDavid Gibson     /* Legacy PHB placement for pseries-2.7 and earlier machine types */
2793357d1e3bSDavid Gibson     const uint64_t base_buid = 0x800000020000000ULL;
2794357d1e3bSDavid Gibson     const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */
2795357d1e3bSDavid Gibson     const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */
2796357d1e3bSDavid Gibson     const hwaddr pio_offset = 0x80000000; /* 2 GiB */
2797357d1e3bSDavid Gibson     const uint32_t max_index = 255;
2798357d1e3bSDavid Gibson     const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */
2799357d1e3bSDavid Gibson 
2800357d1e3bSDavid Gibson     uint64_t ram_top = MACHINE(spapr)->ram_size;
2801357d1e3bSDavid Gibson     hwaddr phb0_base, phb_base;
2802357d1e3bSDavid Gibson     int i;
2803357d1e3bSDavid Gibson 
2804357d1e3bSDavid Gibson     /* Do we have hotpluggable memory? */
2805357d1e3bSDavid Gibson     if (MACHINE(spapr)->maxram_size > ram_top) {
2806357d1e3bSDavid Gibson         /* Can't just use maxram_size, because there may be an
2807357d1e3bSDavid Gibson          * alignment gap between normal and hotpluggable memory
2808357d1e3bSDavid Gibson          * regions */
2809357d1e3bSDavid Gibson         ram_top = spapr->hotplug_memory.base +
2810357d1e3bSDavid Gibson             memory_region_size(&spapr->hotplug_memory.mr);
2811357d1e3bSDavid Gibson     }
2812357d1e3bSDavid Gibson 
2813357d1e3bSDavid Gibson     phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment);
2814357d1e3bSDavid Gibson 
2815357d1e3bSDavid Gibson     if (index > max_index) {
2816357d1e3bSDavid Gibson         error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)",
2817357d1e3bSDavid Gibson                    max_index);
2818357d1e3bSDavid Gibson         return;
2819357d1e3bSDavid Gibson     }
2820357d1e3bSDavid Gibson 
2821357d1e3bSDavid Gibson     *buid = base_buid + index;
2822357d1e3bSDavid Gibson     for (i = 0; i < n_dma; ++i) {
2823357d1e3bSDavid Gibson         liobns[i] = SPAPR_PCI_LIOBN(index, i);
2824357d1e3bSDavid Gibson     }
2825357d1e3bSDavid Gibson 
2826357d1e3bSDavid Gibson     phb_base = phb0_base + index * phb_spacing;
2827357d1e3bSDavid Gibson     *pio = phb_base + pio_offset;
2828357d1e3bSDavid Gibson     *mmio32 = phb_base + mmio_offset;
2829357d1e3bSDavid Gibson     /*
2830357d1e3bSDavid Gibson      * We don't set the 64-bit MMIO window, relying on the PHB's
2831357d1e3bSDavid Gibson      * fallback behaviour of automatically splitting a large "32-bit"
2832357d1e3bSDavid Gibson      * window into contiguous 32-bit and 64-bit windows
2833357d1e3bSDavid Gibson      */
2834357d1e3bSDavid Gibson }
2835db800b21SDavid Gibson 
28361ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine)
28371ea1eefcSBharata B Rao {
2838f6229214SMichael Roth     sPAPRMachineState *spapr = SPAPR_MACHINE(machine);
2839f6229214SMichael Roth 
2840672de881SMichael Roth     spapr_machine_2_8_instance_options(machine);
2841f6229214SMichael Roth     spapr->use_hotplug_event_source = false;
28421ea1eefcSBharata B Rao }
28431ea1eefcSBharata B Rao 
28441ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc)
28451ea1eefcSBharata B Rao {
28463daa4a9fSThomas Huth     sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
28473daa4a9fSThomas Huth 
2848db800b21SDavid Gibson     spapr_machine_2_8_class_options(mc);
28493daa4a9fSThomas Huth     smc->tcg_default_cpu = "POWER7";
2850db800b21SDavid Gibson     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7);
2851357d1e3bSDavid Gibson     smc->phb_placement = phb_placement_2_7;
28521ea1eefcSBharata B Rao }
28531ea1eefcSBharata B Rao 
2854db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false);
28551ea1eefcSBharata B Rao 
28561ea1eefcSBharata B Rao /*
28574b23699cSDavid Gibson  * pseries-2.6
28584b23699cSDavid Gibson  */
28591ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \
2860ae4de14cSAlexey Kardashevskiy     HW_COMPAT_2_6 \
2861ae4de14cSAlexey Kardashevskiy     { \
2862ae4de14cSAlexey Kardashevskiy         .driver   = TYPE_SPAPR_PCI_HOST_BRIDGE,\
2863ae4de14cSAlexey Kardashevskiy         .property = "ddw",\
2864ae4de14cSAlexey Kardashevskiy         .value    = stringify(off),\
2865ae4de14cSAlexey Kardashevskiy     },
28661ea1eefcSBharata B Rao 
28674b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine)
28684b23699cSDavid Gibson {
2869672de881SMichael Roth     spapr_machine_2_7_instance_options(machine);
28704b23699cSDavid Gibson }
28714b23699cSDavid Gibson 
28724b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc)
28734b23699cSDavid Gibson {
28741ea1eefcSBharata B Rao     spapr_machine_2_7_class_options(mc);
28753c0c47e3SDavid Gibson     mc->query_hotpluggable_cpus = NULL;
28761ea1eefcSBharata B Rao     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6);
28774b23699cSDavid Gibson }
28784b23699cSDavid Gibson 
28791ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
28804b23699cSDavid Gibson 
28814b23699cSDavid Gibson /*
28821c5f29bbSDavid Gibson  * pseries-2.5
28831c5f29bbSDavid Gibson  */
28844b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \
288557c522f4SThomas Huth     HW_COMPAT_2_5 \
288657c522f4SThomas Huth     { \
288757c522f4SThomas Huth         .driver   = "spapr-vlan", \
288857c522f4SThomas Huth         .property = "use-rx-buffer-pools", \
288957c522f4SThomas Huth         .value    = "off", \
289057c522f4SThomas Huth     },
28914b23699cSDavid Gibson 
28925013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine)
28931c5f29bbSDavid Gibson {
2894672de881SMichael Roth     spapr_machine_2_6_instance_options(machine);
28955013c547SDavid Gibson }
28965013c547SDavid Gibson 
28975013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc)
28985013c547SDavid Gibson {
289957040d45SThomas Huth     sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
290057040d45SThomas Huth 
29014b23699cSDavid Gibson     spapr_machine_2_6_class_options(mc);
290257040d45SThomas Huth     smc->use_ohci_by_default = true;
29034b23699cSDavid Gibson     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5);
29041c5f29bbSDavid Gibson }
29051c5f29bbSDavid Gibson 
29064b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false);
29071c5f29bbSDavid Gibson 
29081c5f29bbSDavid Gibson /*
29091c5f29bbSDavid Gibson  * pseries-2.4
29101c5f29bbSDavid Gibson  */
291180fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \
291280fd50f9SCornelia Huck         HW_COMPAT_2_4
291380fd50f9SCornelia Huck 
29145013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine)
29151c5f29bbSDavid Gibson {
29165013c547SDavid Gibson     spapr_machine_2_5_instance_options(machine);
29175013c547SDavid Gibson }
29181c5f29bbSDavid Gibson 
29195013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc)
29205013c547SDavid Gibson {
2921fc9f38c3SDavid Gibson     sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
2922fc9f38c3SDavid Gibson 
2923fc9f38c3SDavid Gibson     spapr_machine_2_5_class_options(mc);
2924fc9f38c3SDavid Gibson     smc->dr_lmb_enabled = false;
2925f949b4e5SDavid Gibson     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4);
29261c5f29bbSDavid Gibson }
29271c5f29bbSDavid Gibson 
2928fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false);
29291c5f29bbSDavid Gibson 
29301c5f29bbSDavid Gibson /*
29311c5f29bbSDavid Gibson  * pseries-2.3
29321c5f29bbSDavid Gibson  */
293338ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \
29347619c7b0SMichael Roth         HW_COMPAT_2_3 \
29357619c7b0SMichael Roth         {\
29367619c7b0SMichael Roth             .driver   = "spapr-pci-host-bridge",\
29377619c7b0SMichael Roth             .property = "dynamic-reconfiguration",\
29387619c7b0SMichael Roth             .value    = "off",\
29397619c7b0SMichael Roth         },
294038ff32c6SEduardo Habkost 
29415013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine)
29421c5f29bbSDavid Gibson {
29435013c547SDavid Gibson     spapr_machine_2_4_instance_options(machine);
29441c5f29bbSDavid Gibson     savevm_skip_section_footers();
29451c5f29bbSDavid Gibson     global_state_set_optional();
294609b5e30dSGreg Kurz     savevm_skip_configuration();
29471c5f29bbSDavid Gibson }
29481c5f29bbSDavid Gibson 
29495013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc)
29501c5f29bbSDavid Gibson {
2951fc9f38c3SDavid Gibson     spapr_machine_2_4_class_options(mc);
2952f949b4e5SDavid Gibson     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3);
29531c5f29bbSDavid Gibson }
2954fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false);
29551c5f29bbSDavid Gibson 
29561c5f29bbSDavid Gibson /*
29571c5f29bbSDavid Gibson  * pseries-2.2
29581c5f29bbSDavid Gibson  */
29591c5f29bbSDavid Gibson 
2960b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \
29614dfd8eaaSEduardo Habkost         HW_COMPAT_2_2 \
2962b194df47SAlexey Kardashevskiy         {\
2963b194df47SAlexey Kardashevskiy             .driver   = TYPE_SPAPR_PCI_HOST_BRIDGE,\
2964b194df47SAlexey Kardashevskiy             .property = "mem_win_size",\
2965b194df47SAlexey Kardashevskiy             .value    = "0x20000000",\
2966dd754bafSEduardo Habkost         },
2967b194df47SAlexey Kardashevskiy 
29685013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine)
2969b0e966d0SJason Wang {
29705013c547SDavid Gibson     spapr_machine_2_3_instance_options(machine);
2971cba0e779SGreg Kurz     machine->suppress_vmdesc = true;
2972b0e966d0SJason Wang }
2973b0e966d0SJason Wang 
29745013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc)
2975b0e966d0SJason Wang {
2976fc9f38c3SDavid Gibson     spapr_machine_2_3_class_options(mc);
2977f949b4e5SDavid Gibson     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2);
29781c5f29bbSDavid Gibson }
2979fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false);
29801c5f29bbSDavid Gibson 
29811c5f29bbSDavid Gibson /*
29821c5f29bbSDavid Gibson  * pseries-2.1
29831c5f29bbSDavid Gibson  */
29841c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \
29851c5f29bbSDavid Gibson         HW_COMPAT_2_1
29861c5f29bbSDavid Gibson 
29875013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine)
29881c5f29bbSDavid Gibson {
29895013c547SDavid Gibson     spapr_machine_2_2_instance_options(machine);
29901c5f29bbSDavid Gibson }
29911c5f29bbSDavid Gibson 
29925013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc)
2993b0e966d0SJason Wang {
2994fc9f38c3SDavid Gibson     spapr_machine_2_2_class_options(mc);
2995f949b4e5SDavid Gibson     SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1);
29966026db45SAlexey Kardashevskiy }
2997fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false);
29986026db45SAlexey Kardashevskiy 
299929ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void)
300029ee3247SAlexey Kardashevskiy {
300129ee3247SAlexey Kardashevskiy     type_register_static(&spapr_machine_info);
300229ee3247SAlexey Kardashevskiy }
300329ee3247SAlexey Kardashevskiy 
300429ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types)
3005