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" 39b3946626SVincent Palatin #include "sysemu/hw_accel.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" 666449da45SCédric Le Goater #include "hw/intc/intc.h" 6753018216SPaolo Bonzini 6868a27b20SMichael S. Tsirkin #include "hw/compat.h" 69f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 7094a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 712474bfd4SIgor Mammedov #include "qmp-commands.h" 7268a27b20SMichael S. Tsirkin 7353018216SPaolo Bonzini #include <libfdt.h> 7453018216SPaolo Bonzini 7553018216SPaolo Bonzini /* SLOF memory layout: 7653018216SPaolo Bonzini * 7753018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 7853018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 7953018216SPaolo Bonzini * 8053018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 8153018216SPaolo Bonzini * and more 8253018216SPaolo Bonzini * 8353018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 8453018216SPaolo Bonzini */ 8538b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 8653018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 87b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 8853018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 8953018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 9053018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 9153018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 9253018216SPaolo Bonzini 9353018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 9453018216SPaolo Bonzini 9553018216SPaolo Bonzini #define PHANDLE_XICP 0x00001111 9653018216SPaolo Bonzini 9753018216SPaolo Bonzini #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) 9853018216SPaolo Bonzini 99e6f7e110SCédric Le Goater static int try_create_xics(sPAPRMachineState *spapr, const char *type_ics, 100817bb6a4SCédric Le Goater const char *type_icp, int nr_servers, 101817bb6a4SCédric Le Goater int nr_irqs, Error **errp) 102c04d6cfaSAnthony Liguori { 1032cd908d0SCédric Le Goater XICSFabric *xi = XICS_FABRIC(spapr); 1044e4169f7SCédric Le Goater Error *err = NULL, *local_err = NULL; 1054e4169f7SCédric Le Goater ICSState *ics = NULL; 106817bb6a4SCédric Le Goater int i; 107c04d6cfaSAnthony Liguori 1084e4169f7SCédric Le Goater ics = ICS_SIMPLE(object_new(type_ics)); 109c79b2fddSCédric Le Goater qdev_set_parent_bus(DEVICE(ics), sysbus_get_default()); 110681bfadeSCédric Le Goater object_property_add_child(OBJECT(spapr), "ics", OBJECT(ics), NULL); 1114e4169f7SCédric Le Goater object_property_set_int(OBJECT(ics), nr_irqs, "nr-irqs", &err); 112b4f27d71SCédric Le Goater object_property_add_const_link(OBJECT(ics), "xics", OBJECT(xi), NULL); 1134e4169f7SCédric Le Goater object_property_set_bool(OBJECT(ics), true, "realized", &local_err); 1144e4169f7SCédric Le Goater error_propagate(&err, local_err); 1154e4169f7SCédric Le Goater if (err) { 1164e4169f7SCédric Le Goater goto error; 1174e4169f7SCédric Le Goater } 1184e4169f7SCédric Le Goater 119852ad27eSCédric Le Goater spapr->icps = g_malloc0(nr_servers * sizeof(ICPState)); 120852ad27eSCédric Le Goater spapr->nr_servers = nr_servers; 121817bb6a4SCédric Le Goater 122817bb6a4SCédric Le Goater for (i = 0; i < nr_servers; i++) { 123852ad27eSCédric Le Goater ICPState *icp = &spapr->icps[i]; 124817bb6a4SCédric Le Goater 125817bb6a4SCédric Le Goater object_initialize(icp, sizeof(*icp), type_icp); 12620147f2fSCédric Le Goater qdev_set_parent_bus(DEVICE(icp), sysbus_get_default()); 127852ad27eSCédric Le Goater object_property_add_child(OBJECT(spapr), "icp[*]", OBJECT(icp), NULL); 1282cd908d0SCédric Le Goater object_property_add_const_link(OBJECT(icp), "xics", OBJECT(xi), NULL); 129817bb6a4SCédric Le Goater object_property_set_bool(OBJECT(icp), true, "realized", &err); 130817bb6a4SCédric Le Goater if (err) { 131817bb6a4SCédric Le Goater goto error; 132817bb6a4SCédric Le Goater } 133817bb6a4SCédric Le Goater object_unref(OBJECT(icp)); 134817bb6a4SCédric Le Goater } 135817bb6a4SCédric Le Goater 136681bfadeSCédric Le Goater spapr->ics = ics; 137e6f7e110SCédric Le Goater return 0; 1384e4169f7SCédric Le Goater 1394e4169f7SCédric Le Goater error: 1404e4169f7SCédric Le Goater error_propagate(errp, err); 1414e4169f7SCédric Le Goater if (ics) { 1424e4169f7SCédric Le Goater object_unparent(OBJECT(ics)); 1434e4169f7SCédric Le Goater } 144e6f7e110SCédric Le Goater return -1; 145c04d6cfaSAnthony Liguori } 146c04d6cfaSAnthony Liguori 147e6f7e110SCédric Le Goater static int xics_system_init(MachineState *machine, 1481e49182dSDavid Gibson int nr_servers, int nr_irqs, Error **errp) 149c04d6cfaSAnthony Liguori { 150e6f7e110SCédric Le Goater int rc = -1; 151c04d6cfaSAnthony Liguori 15211ad93f6SDavid Gibson if (kvm_enabled()) { 15334f2af3dSMarkus Armbruster Error *err = NULL; 15434f2af3dSMarkus Armbruster 1552192a930SCédric Le Goater if (machine_kernel_irqchip_allowed(machine) && 1562192a930SCédric Le Goater !xics_kvm_init(SPAPR_MACHINE(machine), errp)) { 157e6f7e110SCédric Le Goater rc = try_create_xics(SPAPR_MACHINE(machine), TYPE_ICS_KVM, 158817bb6a4SCédric Le Goater TYPE_KVM_ICP, nr_servers, nr_irqs, &err); 15911ad93f6SDavid Gibson } 160e6f7e110SCédric Le Goater if (machine_kernel_irqchip_required(machine) && rc < 0) { 161b83baa60SMarkus Armbruster error_reportf_err(err, 162b83baa60SMarkus Armbruster "kernel_irqchip requested but unavailable: "); 163b83baa60SMarkus Armbruster } else { 164903a41d3SStefano Dong (董兴水) error_free(err); 16511ad93f6SDavid Gibson } 166b83baa60SMarkus Armbruster } 16711ad93f6SDavid Gibson 168e6f7e110SCédric Le Goater if (rc < 0) { 1692192a930SCédric Le Goater xics_spapr_init(SPAPR_MACHINE(machine), errp); 170e6f7e110SCédric Le Goater rc = try_create_xics(SPAPR_MACHINE(machine), TYPE_ICS_SIMPLE, 171681bfadeSCédric Le Goater TYPE_ICP, nr_servers, nr_irqs, errp); 172c04d6cfaSAnthony Liguori } 173c04d6cfaSAnthony Liguori 174e6f7e110SCédric Le Goater return rc; 175c04d6cfaSAnthony Liguori } 176c04d6cfaSAnthony Liguori 177833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 178833d4668SAlexey Kardashevskiy int smt_threads) 179833d4668SAlexey Kardashevskiy { 180833d4668SAlexey Kardashevskiy int i, ret = 0; 181833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 182833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 183833d4668SAlexey Kardashevskiy int index = ppc_get_vcpu_dt_id(cpu); 184833d4668SAlexey Kardashevskiy 185d6e166c0SDavid Gibson if (cpu->compat_pvr) { 186d6e166c0SDavid Gibson ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->compat_pvr); 1876d9412eaSAlexey Kardashevskiy if (ret < 0) { 1886d9412eaSAlexey Kardashevskiy return ret; 1896d9412eaSAlexey Kardashevskiy } 1906d9412eaSAlexey Kardashevskiy } 1916d9412eaSAlexey Kardashevskiy 192833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 193833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 194833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 195833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 196833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 197833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 198833d4668SAlexey Kardashevskiy } 199833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 200833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 201833d4668SAlexey Kardashevskiy if (ret < 0) { 202833d4668SAlexey Kardashevskiy return ret; 203833d4668SAlexey Kardashevskiy } 204833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 205833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 206833d4668SAlexey Kardashevskiy 207833d4668SAlexey Kardashevskiy return ret; 208833d4668SAlexey Kardashevskiy } 209833d4668SAlexey Kardashevskiy 2100da6f3feSBharata B Rao static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, CPUState *cs) 2110da6f3feSBharata B Rao { 2120da6f3feSBharata B Rao int ret = 0; 2130da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 2140da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 2150da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 2160da6f3feSBharata B Rao cpu_to_be32(0x0), 2170da6f3feSBharata B Rao cpu_to_be32(0x0), 2180da6f3feSBharata B Rao cpu_to_be32(0x0), 2190da6f3feSBharata B Rao cpu_to_be32(cs->numa_node), 2200da6f3feSBharata B Rao cpu_to_be32(index)}; 2210da6f3feSBharata B Rao 2220da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 2230da6f3feSBharata B Rao if (nb_numa_nodes > 1) { 2240da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, 2250da6f3feSBharata B Rao sizeof(associativity)); 2260da6f3feSBharata B Rao } 2270da6f3feSBharata B Rao 2280da6f3feSBharata B Rao return ret; 2290da6f3feSBharata B Rao } 2300da6f3feSBharata B Rao 23128e02042SDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) 23253018216SPaolo Bonzini { 23382677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 23482677ed2SAlexey Kardashevskiy CPUState *cs; 23553018216SPaolo Bonzini char cpu_model[32]; 23653018216SPaolo Bonzini int smt = kvmppc_smt_threads(); 23753018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 23853018216SPaolo Bonzini 23982677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 24082677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 24182677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 24282677ed2SAlexey Kardashevskiy int index = ppc_get_vcpu_dt_id(cpu); 24312dbeb16SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu)); 24453018216SPaolo Bonzini 2450f20ba62SAlexey Kardashevskiy if ((index % smt) != 0) { 24653018216SPaolo Bonzini continue; 24753018216SPaolo Bonzini } 24853018216SPaolo Bonzini 24982677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 25053018216SPaolo Bonzini 25182677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 25282677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 25382677ed2SAlexey Kardashevskiy cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), 25482677ed2SAlexey Kardashevskiy "cpus"); 25582677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 25682677ed2SAlexey Kardashevskiy return cpus_offset; 25782677ed2SAlexey Kardashevskiy } 25882677ed2SAlexey Kardashevskiy } 25982677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 26082677ed2SAlexey Kardashevskiy if (offset < 0) { 26182677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 26253018216SPaolo Bonzini if (offset < 0) { 26353018216SPaolo Bonzini return offset; 26453018216SPaolo Bonzini } 26582677ed2SAlexey Kardashevskiy } 26653018216SPaolo Bonzini 2670da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 2680da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 26953018216SPaolo Bonzini if (ret < 0) { 27053018216SPaolo Bonzini return ret; 27153018216SPaolo Bonzini } 27253018216SPaolo Bonzini 2730da6f3feSBharata B Rao ret = spapr_fixup_cpu_numa_dt(fdt, offset, cs); 27453018216SPaolo Bonzini if (ret < 0) { 27553018216SPaolo Bonzini return ret; 27653018216SPaolo Bonzini } 277833d4668SAlexey Kardashevskiy 27812dbeb16SDavid Gibson ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt); 279833d4668SAlexey Kardashevskiy if (ret < 0) { 280833d4668SAlexey Kardashevskiy return ret; 281833d4668SAlexey Kardashevskiy } 28253018216SPaolo Bonzini } 28353018216SPaolo Bonzini return ret; 28453018216SPaolo Bonzini } 28553018216SPaolo Bonzini 286b082d65aSAlexey Kardashevskiy static hwaddr spapr_node0_size(void) 287b082d65aSAlexey Kardashevskiy { 288fb164994SDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 289fb164994SDavid Gibson 290b082d65aSAlexey Kardashevskiy if (nb_numa_nodes) { 291b082d65aSAlexey Kardashevskiy int i; 292b082d65aSAlexey Kardashevskiy for (i = 0; i < nb_numa_nodes; ++i) { 293b082d65aSAlexey Kardashevskiy if (numa_info[i].node_mem) { 294fb164994SDavid Gibson return MIN(pow2floor(numa_info[i].node_mem), 295fb164994SDavid Gibson machine->ram_size); 296b082d65aSAlexey Kardashevskiy } 297b082d65aSAlexey Kardashevskiy } 298b082d65aSAlexey Kardashevskiy } 299fb164994SDavid Gibson return machine->ram_size; 300b082d65aSAlexey Kardashevskiy } 301b082d65aSAlexey Kardashevskiy 302a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 303a1d59c0fSAlexey Kardashevskiy { 304a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 305a1d59c0fSAlexey Kardashevskiy } 30653018216SPaolo Bonzini 30703d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 30826a8c353SAlexey Kardashevskiy hwaddr size) 30926a8c353SAlexey Kardashevskiy { 31026a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 31126a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 31226a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 313c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 31426a8c353SAlexey Kardashevskiy }; 31526a8c353SAlexey Kardashevskiy char mem_name[32]; 31626a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 31726a8c353SAlexey Kardashevskiy int off; 31826a8c353SAlexey Kardashevskiy 31926a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 32026a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 32126a8c353SAlexey Kardashevskiy 32226a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 32326a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 32426a8c353SAlexey Kardashevskiy _FDT(off); 32526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 32626a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 32726a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 32826a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 32926a8c353SAlexey Kardashevskiy sizeof(associativity)))); 33003d196b7SBharata B Rao return off; 33126a8c353SAlexey Kardashevskiy } 33226a8c353SAlexey Kardashevskiy 33328e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 33453018216SPaolo Bonzini { 335fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 3367db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 3377db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 3387db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 3397db8a127SAlexey Kardashevskiy NodeInfo ramnode; 34053018216SPaolo Bonzini 3417db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 3427db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 3437db8a127SAlexey Kardashevskiy nb_nodes = 1; 344fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 3457db8a127SAlexey Kardashevskiy nodes = &ramnode; 3465fe269b1SPaul Mackerras } 34753018216SPaolo Bonzini 3487db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 3497db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 3507db8a127SAlexey Kardashevskiy continue; 35153018216SPaolo Bonzini } 352fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 3535fe269b1SPaul Mackerras node_size = 0; 3545fe269b1SPaul Mackerras } else { 3557db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 356fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 357fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 3585fe269b1SPaul Mackerras } 3595fe269b1SPaul Mackerras } 3607db8a127SAlexey Kardashevskiy if (!mem_start) { 3617db8a127SAlexey Kardashevskiy /* ppc_spapr_init() checks for rma_size <= node0_size already */ 362e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 3637db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 3647db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 3657db8a127SAlexey Kardashevskiy } 3666010818cSAlexey Kardashevskiy for ( ; node_size; ) { 3676010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 3686010818cSAlexey Kardashevskiy 3696010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 3706010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 3716010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 3726010818cSAlexey Kardashevskiy } 3736010818cSAlexey Kardashevskiy 3746010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 3756010818cSAlexey Kardashevskiy node_size -= sizetmp; 3766010818cSAlexey Kardashevskiy mem_start += sizetmp; 3776010818cSAlexey Kardashevskiy } 37853018216SPaolo Bonzini } 37953018216SPaolo Bonzini 38053018216SPaolo Bonzini return 0; 38153018216SPaolo Bonzini } 38253018216SPaolo Bonzini 383230bf719SThomas Huth /* Populate the "ibm,pa-features" property */ 384230bf719SThomas Huth static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset) 385230bf719SThomas Huth { 386230bf719SThomas Huth uint8_t pa_features_206[] = { 6, 0, 387230bf719SThomas Huth 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 388230bf719SThomas Huth uint8_t pa_features_207[] = { 24, 0, 389230bf719SThomas Huth 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 390230bf719SThomas Huth 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 391230bf719SThomas Huth 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 392bac3bf28SThomas Huth 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 393*4975c098SSuraj Jitindar Singh /* Currently we don't advertise any of the "new" ISAv3.00 functionality */ 394*4975c098SSuraj Jitindar Singh uint8_t pa_features_300[] = { 64, 0, 395*4975c098SSuraj Jitindar Singh 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */ 396*4975c098SSuraj Jitindar Singh 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */ 397*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */ 398*4975c098SSuraj Jitindar Singh 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */ 399*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24 - 29 */ 400*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 35 */ 401*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 41 */ 402*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 - 47 */ 403*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 - 53 */ 404*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 54 - 59 */ 405*4975c098SSuraj Jitindar Singh 0x00, 0x00, 0x00, 0x00 }; /* 60 - 63 */ 406*4975c098SSuraj Jitindar Singh 407230bf719SThomas Huth uint8_t *pa_features; 408230bf719SThomas Huth size_t pa_size; 409230bf719SThomas Huth 4104cbec30dSThomas Huth switch (env->mmu_model) { 4114cbec30dSThomas Huth case POWERPC_MMU_2_06: 4124cbec30dSThomas Huth case POWERPC_MMU_2_06a: 413230bf719SThomas Huth pa_features = pa_features_206; 414230bf719SThomas Huth pa_size = sizeof(pa_features_206); 4154cbec30dSThomas Huth break; 4164cbec30dSThomas Huth case POWERPC_MMU_2_07: 4174cbec30dSThomas Huth case POWERPC_MMU_2_07a: 418230bf719SThomas Huth pa_features = pa_features_207; 419230bf719SThomas Huth pa_size = sizeof(pa_features_207); 4204cbec30dSThomas Huth break; 421*4975c098SSuraj Jitindar Singh case POWERPC_MMU_3_00: 422*4975c098SSuraj Jitindar Singh pa_features = pa_features_300; 423*4975c098SSuraj Jitindar Singh pa_size = sizeof(pa_features_300); 424*4975c098SSuraj Jitindar Singh break; 4254cbec30dSThomas Huth default: 4264cbec30dSThomas Huth return; 427230bf719SThomas Huth } 428230bf719SThomas Huth 429230bf719SThomas Huth if (env->ci_large_pages) { 430230bf719SThomas Huth /* 431230bf719SThomas Huth * Note: we keep CI large pages off by default because a 64K capable 432230bf719SThomas Huth * guest provisioned with large pages might otherwise try to map a qemu 433230bf719SThomas Huth * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 434230bf719SThomas Huth * even if that qemu runs on a 4k host. 435230bf719SThomas Huth * We dd this bit back here if we are confident this is not an issue 436230bf719SThomas Huth */ 437230bf719SThomas Huth pa_features[3] |= 0x20; 438230bf719SThomas Huth } 439bac3bf28SThomas Huth if (kvmppc_has_cap_htm() && pa_size > 24) { 440bac3bf28SThomas Huth pa_features[24] |= 0x80; /* Transactional memory support */ 441bac3bf28SThomas Huth } 442230bf719SThomas Huth 443230bf719SThomas Huth _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 444230bf719SThomas Huth } 445230bf719SThomas Huth 4460da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 4470da6f3feSBharata B Rao sPAPRMachineState *spapr) 4480da6f3feSBharata B Rao { 4490da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 4500da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 4510da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 4520da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 4530da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 4540da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 455afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 456afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 4570da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 4580da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 4590da6f3feSBharata B Rao size_t page_sizes_prop_size; 46022419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 4610da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 46212dbeb16SDavid Gibson int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu)); 463af81cf32SBharata B Rao sPAPRDRConnector *drc; 464af81cf32SBharata B Rao sPAPRDRConnectorClass *drck; 465af81cf32SBharata B Rao int drc_index; 466af81cf32SBharata B Rao 467af81cf32SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); 468af81cf32SBharata B Rao if (drc) { 469af81cf32SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 470af81cf32SBharata B Rao drc_index = drck->get_index(drc); 471af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 472af81cf32SBharata B Rao } 4730da6f3feSBharata B Rao 4740da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 4750da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 4760da6f3feSBharata B Rao 4770da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 4780da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 4790da6f3feSBharata B Rao env->dcache_line_size))); 4800da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 4810da6f3feSBharata B Rao env->dcache_line_size))); 4820da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 4830da6f3feSBharata B Rao env->icache_line_size))); 4840da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 4850da6f3feSBharata B Rao env->icache_line_size))); 4860da6f3feSBharata B Rao 4870da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 4880da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 4890da6f3feSBharata B Rao pcc->l1_dcache_size))); 4900da6f3feSBharata B Rao } else { 491ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 dcache size for cpu"); 4920da6f3feSBharata B Rao } 4930da6f3feSBharata B Rao if (pcc->l1_icache_size) { 4940da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 4950da6f3feSBharata B Rao pcc->l1_icache_size))); 4960da6f3feSBharata B Rao } else { 497ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 icache size for cpu"); 4980da6f3feSBharata B Rao } 4990da6f3feSBharata B Rao 5000da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 5010da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 502fd5da5c4SThomas Huth _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); 5030da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 5040da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 5050da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 5060da6f3feSBharata B Rao 5070da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 5080da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 5090da6f3feSBharata B Rao } 5100da6f3feSBharata B Rao 5110da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 5120da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 5130da6f3feSBharata B Rao segs, sizeof(segs)))); 5140da6f3feSBharata B Rao } 5150da6f3feSBharata B Rao 5160da6f3feSBharata B Rao /* Advertise VMX/VSX (vector extensions) if available 5170da6f3feSBharata B Rao * 0 / no property == no vector extensions 5180da6f3feSBharata B Rao * 1 == VMX / Altivec available 5190da6f3feSBharata B Rao * 2 == VSX available */ 5200da6f3feSBharata B Rao if (env->insns_flags & PPC_ALTIVEC) { 5210da6f3feSBharata B Rao uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 5220da6f3feSBharata B Rao 5230da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 5240da6f3feSBharata B Rao } 5250da6f3feSBharata B Rao 5260da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 5270da6f3feSBharata B Rao * 0 / no property == no DFP 5280da6f3feSBharata B Rao * 1 == DFP available */ 5290da6f3feSBharata B Rao if (env->insns_flags2 & PPC2_DFP) { 5300da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 5310da6f3feSBharata B Rao } 5320da6f3feSBharata B Rao 5333654fa95SCédric Le Goater page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, 5340da6f3feSBharata B Rao sizeof(page_sizes_prop)); 5350da6f3feSBharata B Rao if (page_sizes_prop_size) { 5360da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 5370da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 5380da6f3feSBharata B Rao } 5390da6f3feSBharata B Rao 540230bf719SThomas Huth spapr_populate_pa_features(env, fdt, offset); 54190da0d5aSBenjamin Herrenschmidt 5420da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 54322419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 5440da6f3feSBharata B Rao 5450da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 5460da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 5470da6f3feSBharata B Rao 5480da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 5490da6f3feSBharata B Rao 55012dbeb16SDavid Gibson _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); 5510da6f3feSBharata B Rao } 5520da6f3feSBharata B Rao 5530da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 5540da6f3feSBharata B Rao { 5550da6f3feSBharata B Rao CPUState *cs; 5560da6f3feSBharata B Rao int cpus_offset; 5570da6f3feSBharata B Rao char *nodename; 5580da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 5590da6f3feSBharata B Rao 5600da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 5610da6f3feSBharata B Rao _FDT(cpus_offset); 5620da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 5630da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 5640da6f3feSBharata B Rao 5650da6f3feSBharata B Rao /* 5660da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 5670da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 5680da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 5690da6f3feSBharata B Rao */ 5700da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 5710da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 5720da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 5730da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 5740da6f3feSBharata B Rao int offset; 5750da6f3feSBharata B Rao 5760da6f3feSBharata B Rao if ((index % smt) != 0) { 5770da6f3feSBharata B Rao continue; 5780da6f3feSBharata B Rao } 5790da6f3feSBharata B Rao 5800da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 5810da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 5820da6f3feSBharata B Rao g_free(nodename); 5830da6f3feSBharata B Rao _FDT(offset); 5840da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 5850da6f3feSBharata B Rao } 5860da6f3feSBharata B Rao 5870da6f3feSBharata B Rao } 5880da6f3feSBharata B Rao 58903d196b7SBharata B Rao /* 59003d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 59103d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 59203d196b7SBharata B Rao * of this device tree node. 59303d196b7SBharata B Rao */ 59403d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 59503d196b7SBharata B Rao { 59603d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 59703d196b7SBharata B Rao int ret, i, offset; 59803d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 59903d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 600d0e5a8f2SBharata B Rao uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; 601d0e5a8f2SBharata B Rao uint32_t nr_lmbs = (spapr->hotplug_memory.base + 602d0e5a8f2SBharata B Rao memory_region_size(&spapr->hotplug_memory.mr)) / 603d0e5a8f2SBharata B Rao lmb_size; 60403d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 6056663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 60603d196b7SBharata B Rao 607ef001f06SThomas Huth /* 608d0e5a8f2SBharata B Rao * Don't create the node if there is no hotpluggable memory 60916c25aefSBharata B Rao */ 610d0e5a8f2SBharata B Rao if (machine->ram_size == machine->maxram_size) { 61116c25aefSBharata B Rao return 0; 61216c25aefSBharata B Rao } 61316c25aefSBharata B Rao 61416c25aefSBharata B Rao /* 615ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 616ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 617ef001f06SThomas Huth */ 618ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 619ef001f06SThomas Huth * sizeof(uint32_t); 62003d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 62103d196b7SBharata B Rao 62203d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 62303d196b7SBharata B Rao 62403d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 62503d196b7SBharata B Rao sizeof(prop_lmb_size)); 62603d196b7SBharata B Rao if (ret < 0) { 62703d196b7SBharata B Rao goto out; 62803d196b7SBharata B Rao } 62903d196b7SBharata B Rao 63003d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 63103d196b7SBharata B Rao if (ret < 0) { 63203d196b7SBharata B Rao goto out; 63303d196b7SBharata B Rao } 63403d196b7SBharata B Rao 63503d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 63603d196b7SBharata B Rao if (ret < 0) { 63703d196b7SBharata B Rao goto out; 63803d196b7SBharata B Rao } 63903d196b7SBharata B Rao 64003d196b7SBharata B Rao /* ibm,dynamic-memory */ 64103d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 64203d196b7SBharata B Rao cur_index++; 64303d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 644d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 64503d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 64603d196b7SBharata B Rao 647d0e5a8f2SBharata B Rao if (i >= hotplug_lmb_start) { 648d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 649d0e5a8f2SBharata B Rao sPAPRDRConnectorClass *drck; 650d0e5a8f2SBharata B Rao 651d0e5a8f2SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); 65203d196b7SBharata B Rao g_assert(drc); 65303d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 65403d196b7SBharata B Rao 65503d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 65603d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 65703d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 65803d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 65903d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 660d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 66103d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 66203d196b7SBharata B Rao } else { 66303d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 66403d196b7SBharata B Rao } 665d0e5a8f2SBharata B Rao } else { 666d0e5a8f2SBharata B Rao /* 667d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 668d0e5a8f2SBharata B Rao * hotplug memory region -- all these are marked as reserved 669d0e5a8f2SBharata B Rao * and as having no valid DRC. 670d0e5a8f2SBharata B Rao */ 671d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 672d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 673d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 674d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 675d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 676d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 677d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 678d0e5a8f2SBharata B Rao } 67903d196b7SBharata B Rao 68003d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 68103d196b7SBharata B Rao } 68203d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 68303d196b7SBharata B Rao if (ret < 0) { 68403d196b7SBharata B Rao goto out; 68503d196b7SBharata B Rao } 68603d196b7SBharata B Rao 68703d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 68803d196b7SBharata B Rao cur_index = int_buf; 6896663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 69003d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 69103d196b7SBharata B Rao cur_index += 2; 6926663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 69303d196b7SBharata B Rao uint32_t associativity[] = { 69403d196b7SBharata B Rao cpu_to_be32(0x0), 69503d196b7SBharata B Rao cpu_to_be32(0x0), 69603d196b7SBharata B Rao cpu_to_be32(0x0), 69703d196b7SBharata B Rao cpu_to_be32(i) 69803d196b7SBharata B Rao }; 69903d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 70003d196b7SBharata B Rao cur_index += 4; 70103d196b7SBharata B Rao } 70203d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 70303d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 70403d196b7SBharata B Rao out: 70503d196b7SBharata B Rao g_free(int_buf); 70603d196b7SBharata B Rao return ret; 70703d196b7SBharata B Rao } 70803d196b7SBharata B Rao 7096787d27bSMichael Roth static int spapr_dt_cas_updates(sPAPRMachineState *spapr, void *fdt, 7106787d27bSMichael Roth sPAPROptionVector *ov5_updates) 7116787d27bSMichael Roth { 7126787d27bSMichael Roth sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); 713417ece33SMichael Roth int ret = 0, offset; 7146787d27bSMichael Roth 7156787d27bSMichael Roth /* Generate ibm,dynamic-reconfiguration-memory node if required */ 7166787d27bSMichael Roth if (spapr_ovec_test(ov5_updates, OV5_DRCONF_MEMORY)) { 7176787d27bSMichael Roth g_assert(smc->dr_lmb_enabled); 7186787d27bSMichael Roth ret = spapr_populate_drconf_memory(spapr, fdt); 719417ece33SMichael Roth if (ret) { 720417ece33SMichael Roth goto out; 721417ece33SMichael Roth } 7226787d27bSMichael Roth } 7236787d27bSMichael Roth 724417ece33SMichael Roth offset = fdt_path_offset(fdt, "/chosen"); 725417ece33SMichael Roth if (offset < 0) { 726417ece33SMichael Roth offset = fdt_add_subnode(fdt, 0, "chosen"); 727417ece33SMichael Roth if (offset < 0) { 728417ece33SMichael Roth return offset; 729417ece33SMichael Roth } 730417ece33SMichael Roth } 731417ece33SMichael Roth ret = spapr_ovec_populate_dt(fdt, offset, spapr->ov5_cas, 732417ece33SMichael Roth "ibm,architecture-vec-5"); 733417ece33SMichael Roth 734417ece33SMichael Roth out: 7356787d27bSMichael Roth return ret; 7366787d27bSMichael Roth } 7376787d27bSMichael Roth 73803d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 73903d196b7SBharata B Rao target_ulong addr, target_ulong size, 7406787d27bSMichael Roth sPAPROptionVector *ov5_updates) 74103d196b7SBharata B Rao { 74203d196b7SBharata B Rao void *fdt, *fdt_skel; 74303d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 74403d196b7SBharata B Rao 74503d196b7SBharata B Rao size -= sizeof(hdr); 74603d196b7SBharata B Rao 74703d196b7SBharata B Rao /* Create sceleton */ 74803d196b7SBharata B Rao fdt_skel = g_malloc0(size); 74903d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 75003d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 75103d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 75203d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 75303d196b7SBharata B Rao fdt = g_malloc0(size); 75403d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 75503d196b7SBharata B Rao g_free(fdt_skel); 75603d196b7SBharata B Rao 75703d196b7SBharata B Rao /* Fixup cpu nodes */ 75803d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 75903d196b7SBharata B Rao 7606787d27bSMichael Roth if (spapr_dt_cas_updates(spapr, fdt, ov5_updates)) { 7616787d27bSMichael Roth return -1; 76203d196b7SBharata B Rao } 76303d196b7SBharata B Rao 76403d196b7SBharata B Rao /* Pack resulting tree */ 76503d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 76603d196b7SBharata B Rao 76703d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 76803d196b7SBharata B Rao trace_spapr_cas_failed(size); 76903d196b7SBharata B Rao return -1; 77003d196b7SBharata B Rao } 77103d196b7SBharata B Rao 77203d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 77303d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 77403d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 77503d196b7SBharata B Rao g_free(fdt); 77603d196b7SBharata B Rao 77703d196b7SBharata B Rao return 0; 77803d196b7SBharata B Rao } 77903d196b7SBharata B Rao 7803f5dabceSDavid Gibson static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) 7813f5dabceSDavid Gibson { 7823f5dabceSDavid Gibson int rtas; 7833f5dabceSDavid Gibson GString *hypertas = g_string_sized_new(256); 7843f5dabceSDavid Gibson GString *qemu_hypertas = g_string_sized_new(256); 7853f5dabceSDavid Gibson uint32_t refpoints[] = { cpu_to_be32(0x4), cpu_to_be32(0x4) }; 7863f5dabceSDavid Gibson uint64_t max_hotplug_addr = spapr->hotplug_memory.base + 7873f5dabceSDavid Gibson memory_region_size(&spapr->hotplug_memory.mr); 7883f5dabceSDavid Gibson uint32_t lrdr_capacity[] = { 7893f5dabceSDavid Gibson cpu_to_be32(max_hotplug_addr >> 32), 7903f5dabceSDavid Gibson cpu_to_be32(max_hotplug_addr & 0xffffffff), 7913f5dabceSDavid Gibson 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), 7923f5dabceSDavid Gibson cpu_to_be32(max_cpus / smp_threads), 7933f5dabceSDavid Gibson }; 7943f5dabceSDavid Gibson 7953f5dabceSDavid Gibson _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); 7963f5dabceSDavid Gibson 7973f5dabceSDavid Gibson /* hypertas */ 7983f5dabceSDavid Gibson add_str(hypertas, "hcall-pft"); 7993f5dabceSDavid Gibson add_str(hypertas, "hcall-term"); 8003f5dabceSDavid Gibson add_str(hypertas, "hcall-dabr"); 8013f5dabceSDavid Gibson add_str(hypertas, "hcall-interrupt"); 8023f5dabceSDavid Gibson add_str(hypertas, "hcall-tce"); 8033f5dabceSDavid Gibson add_str(hypertas, "hcall-vio"); 8043f5dabceSDavid Gibson add_str(hypertas, "hcall-splpar"); 8053f5dabceSDavid Gibson add_str(hypertas, "hcall-bulk"); 8063f5dabceSDavid Gibson add_str(hypertas, "hcall-set-mode"); 8073f5dabceSDavid Gibson add_str(hypertas, "hcall-sprg0"); 8083f5dabceSDavid Gibson add_str(hypertas, "hcall-copy"); 8093f5dabceSDavid Gibson add_str(hypertas, "hcall-debug"); 8103f5dabceSDavid Gibson add_str(qemu_hypertas, "hcall-memop1"); 8113f5dabceSDavid Gibson 8123f5dabceSDavid Gibson if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 8133f5dabceSDavid Gibson add_str(hypertas, "hcall-multi-tce"); 8143f5dabceSDavid Gibson } 8153f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,hypertas-functions", 8163f5dabceSDavid Gibson hypertas->str, hypertas->len)); 8173f5dabceSDavid Gibson g_string_free(hypertas, TRUE); 8183f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "qemu,hypertas-functions", 8193f5dabceSDavid Gibson qemu_hypertas->str, qemu_hypertas->len)); 8203f5dabceSDavid Gibson g_string_free(qemu_hypertas, TRUE); 8213f5dabceSDavid Gibson 8223f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,associativity-reference-points", 8233f5dabceSDavid Gibson refpoints, sizeof(refpoints))); 8243f5dabceSDavid Gibson 8253f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-error-log-max", 8263f5dabceSDavid Gibson RTAS_ERROR_LOG_MAX)); 8273f5dabceSDavid Gibson _FDT(fdt_setprop_cell(fdt, rtas, "rtas-event-scan-rate", 8283f5dabceSDavid Gibson RTAS_EVENT_SCAN_RATE)); 8293f5dabceSDavid Gibson 8303f5dabceSDavid Gibson if (msi_nonbroken) { 8313f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,change-msix-capable", NULL, 0)); 8323f5dabceSDavid Gibson } 8333f5dabceSDavid Gibson 8343f5dabceSDavid Gibson /* 8353f5dabceSDavid Gibson * According to PAPR, rtas ibm,os-term does not guarantee a return 8363f5dabceSDavid Gibson * back to the guest cpu. 8373f5dabceSDavid Gibson * 8383f5dabceSDavid Gibson * While an additional ibm,extended-os-term property indicates 8393f5dabceSDavid Gibson * that rtas call return will always occur. Set this property. 8403f5dabceSDavid Gibson */ 8413f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,extended-os-term", NULL, 0)); 8423f5dabceSDavid Gibson 8433f5dabceSDavid Gibson _FDT(fdt_setprop(fdt, rtas, "ibm,lrdr-capacity", 8443f5dabceSDavid Gibson lrdr_capacity, sizeof(lrdr_capacity))); 8453f5dabceSDavid Gibson 8463f5dabceSDavid Gibson spapr_dt_rtas_tokens(fdt, rtas); 8473f5dabceSDavid Gibson } 8483f5dabceSDavid Gibson 8497c866c6aSDavid Gibson static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt) 8507c866c6aSDavid Gibson { 8517c866c6aSDavid Gibson MachineState *machine = MACHINE(spapr); 8527c866c6aSDavid Gibson int chosen; 8537c866c6aSDavid Gibson const char *boot_device = machine->boot_order; 8547c866c6aSDavid Gibson char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus); 8557c866c6aSDavid Gibson size_t cb = 0; 8567c866c6aSDavid Gibson char *bootlist = get_boot_devices_list(&cb, true); 8577c866c6aSDavid Gibson 8587c866c6aSDavid Gibson _FDT(chosen = fdt_add_subnode(fdt, 0, "chosen")); 8597c866c6aSDavid Gibson 8607c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "bootargs", machine->kernel_cmdline)); 8617c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-start", 8627c866c6aSDavid Gibson spapr->initrd_base)); 8637c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "linux,initrd-end", 8647c866c6aSDavid Gibson spapr->initrd_base + spapr->initrd_size)); 8657c866c6aSDavid Gibson 8667c866c6aSDavid Gibson if (spapr->kernel_size) { 8677c866c6aSDavid Gibson uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 8687c866c6aSDavid Gibson cpu_to_be64(spapr->kernel_size) }; 8697c866c6aSDavid Gibson 8707c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel", 8717c866c6aSDavid Gibson &kprop, sizeof(kprop))); 8727c866c6aSDavid Gibson if (spapr->kernel_le) { 8737c866c6aSDavid Gibson _FDT(fdt_setprop(fdt, chosen, "qemu,boot-kernel-le", NULL, 0)); 8747c866c6aSDavid Gibson } 8757c866c6aSDavid Gibson } 8767c866c6aSDavid Gibson if (boot_menu) { 8777c866c6aSDavid Gibson _FDT((fdt_setprop_cell(fdt, chosen, "qemu,boot-menu", boot_menu))); 8787c866c6aSDavid Gibson } 8797c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-width", graphic_width)); 8807c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-height", graphic_height)); 8817c866c6aSDavid Gibson _FDT(fdt_setprop_cell(fdt, chosen, "qemu,graphic-depth", graphic_depth)); 8827c866c6aSDavid Gibson 8837c866c6aSDavid Gibson if (cb && bootlist) { 8847c866c6aSDavid Gibson int i; 8857c866c6aSDavid Gibson 8867c866c6aSDavid Gibson for (i = 0; i < cb; i++) { 8877c866c6aSDavid Gibson if (bootlist[i] == '\n') { 8887c866c6aSDavid Gibson bootlist[i] = ' '; 8897c866c6aSDavid Gibson } 8907c866c6aSDavid Gibson } 8917c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-list", bootlist)); 8927c866c6aSDavid Gibson } 8937c866c6aSDavid Gibson 8947c866c6aSDavid Gibson if (boot_device && strlen(boot_device)) { 8957c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "qemu,boot-device", boot_device)); 8967c866c6aSDavid Gibson } 8977c866c6aSDavid Gibson 8987c866c6aSDavid Gibson if (!spapr->has_graphics && stdout_path) { 8997c866c6aSDavid Gibson _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path)); 9007c866c6aSDavid Gibson } 9017c866c6aSDavid Gibson 9027c866c6aSDavid Gibson g_free(stdout_path); 9037c866c6aSDavid Gibson g_free(bootlist); 9047c866c6aSDavid Gibson } 9057c866c6aSDavid Gibson 906fca5f2dcSDavid Gibson static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt) 907fca5f2dcSDavid Gibson { 908fca5f2dcSDavid Gibson /* The /hypervisor node isn't in PAPR - this is a hack to allow PR 909fca5f2dcSDavid Gibson * KVM to work under pHyp with some guest co-operation */ 910fca5f2dcSDavid Gibson int hypervisor; 911fca5f2dcSDavid Gibson uint8_t hypercall[16]; 912fca5f2dcSDavid Gibson 913fca5f2dcSDavid Gibson _FDT(hypervisor = fdt_add_subnode(fdt, 0, "hypervisor")); 914fca5f2dcSDavid Gibson /* indicate KVM hypercall interface */ 915fca5f2dcSDavid Gibson _FDT(fdt_setprop_string(fdt, hypervisor, "compatible", "linux,kvm")); 916fca5f2dcSDavid Gibson if (kvmppc_has_cap_fixup_hcalls()) { 917fca5f2dcSDavid Gibson /* 918fca5f2dcSDavid Gibson * Older KVM versions with older guest kernels were broken 919fca5f2dcSDavid Gibson * with the magic page, don't allow the guest to map it. 920fca5f2dcSDavid Gibson */ 921fca5f2dcSDavid Gibson if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 922fca5f2dcSDavid Gibson sizeof(hypercall))) { 923fca5f2dcSDavid Gibson _FDT(fdt_setprop(fdt, hypervisor, "hcall-instructions", 924fca5f2dcSDavid Gibson hypercall, sizeof(hypercall))); 925fca5f2dcSDavid Gibson } 926fca5f2dcSDavid Gibson } 927fca5f2dcSDavid Gibson } 928fca5f2dcSDavid Gibson 929997b6cfcSDavid Gibson static void *spapr_build_fdt(sPAPRMachineState *spapr, 93053018216SPaolo Bonzini hwaddr rtas_addr, 93153018216SPaolo Bonzini hwaddr rtas_size) 93253018216SPaolo Bonzini { 9335b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 9343c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 935c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 9367c866c6aSDavid Gibson int ret; 93753018216SPaolo Bonzini void *fdt; 93853018216SPaolo Bonzini sPAPRPHBState *phb; 939398a0bd5SDavid Gibson char *buf; 94053018216SPaolo Bonzini 941398a0bd5SDavid Gibson fdt = g_malloc0(FDT_MAX_SIZE); 942398a0bd5SDavid Gibson _FDT((fdt_create_empty_tree(fdt, FDT_MAX_SIZE))); 94353018216SPaolo Bonzini 944398a0bd5SDavid Gibson /* Root node */ 945398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "device_type", "chrp")); 946398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "model", "IBM pSeries (emulated by qemu)")); 947398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "compatible", "qemu,pseries")); 948398a0bd5SDavid Gibson 949398a0bd5SDavid Gibson /* 950398a0bd5SDavid Gibson * Add info to guest to indentify which host is it being run on 951398a0bd5SDavid Gibson * and what is the uuid of the guest 952398a0bd5SDavid Gibson */ 953398a0bd5SDavid Gibson if (kvmppc_get_host_model(&buf)) { 954398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-model", buf)); 955398a0bd5SDavid Gibson g_free(buf); 956398a0bd5SDavid Gibson } 957398a0bd5SDavid Gibson if (kvmppc_get_host_serial(&buf)) { 958398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "host-serial", buf)); 959398a0bd5SDavid Gibson g_free(buf); 960398a0bd5SDavid Gibson } 961398a0bd5SDavid Gibson 962398a0bd5SDavid Gibson buf = qemu_uuid_unparse_strdup(&qemu_uuid); 963398a0bd5SDavid Gibson 964398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "vm,uuid", buf)); 965398a0bd5SDavid Gibson if (qemu_uuid_set) { 966398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "system-id", buf)); 967398a0bd5SDavid Gibson } 968398a0bd5SDavid Gibson g_free(buf); 969398a0bd5SDavid Gibson 970398a0bd5SDavid Gibson if (qemu_get_vm_name()) { 971398a0bd5SDavid Gibson _FDT(fdt_setprop_string(fdt, 0, "ibm,partition-name", 972398a0bd5SDavid Gibson qemu_get_vm_name())); 973398a0bd5SDavid Gibson } 974398a0bd5SDavid Gibson 975398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#address-cells", 2)); 976398a0bd5SDavid Gibson _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); 97753018216SPaolo Bonzini 9789b9a1908SDavid Gibson /* /interrupt controller */ 979852ad27eSCédric Le Goater spapr_dt_xics(spapr->nr_servers, fdt, PHANDLE_XICP); 9809b9a1908SDavid Gibson 981e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 982e8f986fcSBharata B Rao if (ret < 0) { 983ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 984e8f986fcSBharata B Rao exit(1); 98553018216SPaolo Bonzini } 98653018216SPaolo Bonzini 987bf5a6696SDavid Gibson /* /vdevice */ 988bf5a6696SDavid Gibson spapr_dt_vdevice(spapr->vio_bus, fdt); 98953018216SPaolo Bonzini 9904d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 9914d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 9924d9392beSThomas Huth if (ret < 0) { 993ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 9944d9392beSThomas Huth exit(1); 9954d9392beSThomas Huth } 9964d9392beSThomas Huth } 9974d9392beSThomas Huth 99853018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 99953018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 100053018216SPaolo Bonzini if (ret < 0) { 1001da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 100253018216SPaolo Bonzini exit(1); 100353018216SPaolo Bonzini } 1004da34fed7SThomas Huth } 100553018216SPaolo Bonzini 10060da6f3feSBharata B Rao /* cpus */ 10070da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 100853018216SPaolo Bonzini 1009c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 1010c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 1011c20d332aSBharata B Rao } 1012c20d332aSBharata B Rao 1013c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 1014af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 1015af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 1016af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 1017af81cf32SBharata B Rao if (ret < 0) { 1018af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 1019af81cf32SBharata B Rao exit(1); 1020af81cf32SBharata B Rao } 1021af81cf32SBharata B Rao } 1022af81cf32SBharata B Rao 1023ffb1e275SDavid Gibson /* /event-sources */ 1024ffbb1705SMichael Roth spapr_dt_events(spapr, fdt); 1025ffb1e275SDavid Gibson 10263f5dabceSDavid Gibson /* /rtas */ 10273f5dabceSDavid Gibson spapr_dt_rtas(spapr, fdt); 10283f5dabceSDavid Gibson 10297c866c6aSDavid Gibson /* /chosen */ 10307c866c6aSDavid Gibson spapr_dt_chosen(spapr, fdt); 1031cf6e5223SDavid Gibson 1032fca5f2dcSDavid Gibson /* /hypervisor */ 1033fca5f2dcSDavid Gibson if (kvm_enabled()) { 1034fca5f2dcSDavid Gibson spapr_dt_hypervisor(spapr, fdt); 1035fca5f2dcSDavid Gibson } 1036fca5f2dcSDavid Gibson 1037cf6e5223SDavid Gibson /* Build memory reserve map */ 1038cf6e5223SDavid Gibson if (spapr->kernel_size) { 1039cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size))); 1040cf6e5223SDavid Gibson } 1041cf6e5223SDavid Gibson if (spapr->initrd_size) { 1042cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size))); 1043cf6e5223SDavid Gibson } 1044cf6e5223SDavid Gibson 10456787d27bSMichael Roth /* ibm,client-architecture-support updates */ 10466787d27bSMichael Roth ret = spapr_dt_cas_updates(spapr, fdt, spapr->ov5_cas); 10476787d27bSMichael Roth if (ret < 0) { 10486787d27bSMichael Roth error_report("couldn't setup CAS properties fdt"); 10496787d27bSMichael Roth exit(1); 10506787d27bSMichael Roth } 10516787d27bSMichael Roth 1052997b6cfcSDavid Gibson return fdt; 105353018216SPaolo Bonzini } 105453018216SPaolo Bonzini 105553018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 105653018216SPaolo Bonzini { 105753018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 105853018216SPaolo Bonzini } 105953018216SPaolo Bonzini 10601d1be34dSDavid Gibson static void emulate_spapr_hypercall(PPCVirtualHypervisor *vhyp, 10611d1be34dSDavid Gibson PowerPCCPU *cpu) 106253018216SPaolo Bonzini { 106353018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 106453018216SPaolo Bonzini 10658d04fb55SJan Kiszka /* The TCG path should also be holding the BQL at this point */ 10668d04fb55SJan Kiszka g_assert(qemu_mutex_iothread_locked()); 10678d04fb55SJan Kiszka 106853018216SPaolo Bonzini if (msr_pr) { 106953018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 107053018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 107153018216SPaolo Bonzini } else { 107253018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 107353018216SPaolo Bonzini } 107453018216SPaolo Bonzini } 107553018216SPaolo Bonzini 10769861bb3eSSuraj Jitindar Singh static uint64_t spapr_get_patbe(PPCVirtualHypervisor *vhyp) 10779861bb3eSSuraj Jitindar Singh { 10789861bb3eSSuraj Jitindar Singh sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 10799861bb3eSSuraj Jitindar Singh 10809861bb3eSSuraj Jitindar Singh return spapr->patb_entry; 10819861bb3eSSuraj Jitindar Singh } 10829861bb3eSSuraj Jitindar Singh 1083e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1084e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1085e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1086e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1087e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1088e6b8fd24SSamuel Mendoza-Jonas 1089715c5407SDavid Gibson /* 1090715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1091715c5407SDavid Gibson */ 1092715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr) 1093715c5407SDavid Gibson { 1094715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1095715c5407SDavid Gibson return spapr->htab_fd; 1096715c5407SDavid Gibson } 1097715c5407SDavid Gibson 1098715c5407SDavid Gibson spapr->htab_fd = kvmppc_get_htab_fd(false); 1099715c5407SDavid Gibson if (spapr->htab_fd < 0) { 1100715c5407SDavid Gibson error_report("Unable to open fd for reading hash table from KVM: %s", 1101715c5407SDavid Gibson strerror(errno)); 1102715c5407SDavid Gibson } 1103715c5407SDavid Gibson 1104715c5407SDavid Gibson return spapr->htab_fd; 1105715c5407SDavid Gibson } 1106715c5407SDavid Gibson 1107715c5407SDavid Gibson static void close_htab_fd(sPAPRMachineState *spapr) 1108715c5407SDavid Gibson { 1109715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1110715c5407SDavid Gibson close(spapr->htab_fd); 1111715c5407SDavid Gibson } 1112715c5407SDavid Gibson spapr->htab_fd = -1; 1113715c5407SDavid Gibson } 1114715c5407SDavid Gibson 1115e57ca75cSDavid Gibson static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) 1116e57ca75cSDavid Gibson { 1117e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1118e57ca75cSDavid Gibson 1119e57ca75cSDavid Gibson return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; 1120e57ca75cSDavid Gibson } 1121e57ca75cSDavid Gibson 1122e57ca75cSDavid Gibson static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, 1123e57ca75cSDavid Gibson hwaddr ptex, int n) 1124e57ca75cSDavid Gibson { 1125e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1126e57ca75cSDavid Gibson hwaddr pte_offset = ptex * HASH_PTE_SIZE_64; 1127e57ca75cSDavid Gibson 1128e57ca75cSDavid Gibson if (!spapr->htab) { 1129e57ca75cSDavid Gibson /* 1130e57ca75cSDavid Gibson * HTAB is controlled by KVM. Fetch into temporary buffer 1131e57ca75cSDavid Gibson */ 1132e57ca75cSDavid Gibson ppc_hash_pte64_t *hptes = g_malloc(n * HASH_PTE_SIZE_64); 1133e57ca75cSDavid Gibson kvmppc_read_hptes(hptes, ptex, n); 1134e57ca75cSDavid Gibson return hptes; 1135e57ca75cSDavid Gibson } 1136e57ca75cSDavid Gibson 1137e57ca75cSDavid Gibson /* 1138e57ca75cSDavid Gibson * HTAB is controlled by QEMU. Just point to the internally 1139e57ca75cSDavid Gibson * accessible PTEG. 1140e57ca75cSDavid Gibson */ 1141e57ca75cSDavid Gibson return (const ppc_hash_pte64_t *)(spapr->htab + pte_offset); 1142e57ca75cSDavid Gibson } 1143e57ca75cSDavid Gibson 1144e57ca75cSDavid Gibson static void spapr_unmap_hptes(PPCVirtualHypervisor *vhyp, 1145e57ca75cSDavid Gibson const ppc_hash_pte64_t *hptes, 1146e57ca75cSDavid Gibson hwaddr ptex, int n) 1147e57ca75cSDavid Gibson { 1148e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1149e57ca75cSDavid Gibson 1150e57ca75cSDavid Gibson if (!spapr->htab) { 1151e57ca75cSDavid Gibson g_free((void *)hptes); 1152e57ca75cSDavid Gibson } 1153e57ca75cSDavid Gibson 1154e57ca75cSDavid Gibson /* Nothing to do for qemu managed HPT */ 1155e57ca75cSDavid Gibson } 1156e57ca75cSDavid Gibson 1157e57ca75cSDavid Gibson static void spapr_store_hpte(PPCVirtualHypervisor *vhyp, hwaddr ptex, 1158e57ca75cSDavid Gibson uint64_t pte0, uint64_t pte1) 1159e57ca75cSDavid Gibson { 1160e57ca75cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); 1161e57ca75cSDavid Gibson hwaddr offset = ptex * HASH_PTE_SIZE_64; 1162e57ca75cSDavid Gibson 1163e57ca75cSDavid Gibson if (!spapr->htab) { 1164e57ca75cSDavid Gibson kvmppc_write_hpte(ptex, pte0, pte1); 1165e57ca75cSDavid Gibson } else { 1166e57ca75cSDavid Gibson stq_p(spapr->htab + offset, pte0); 1167e57ca75cSDavid Gibson stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); 1168e57ca75cSDavid Gibson } 1169e57ca75cSDavid Gibson } 1170e57ca75cSDavid Gibson 11718dfe8e7fSDavid Gibson static int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 11728dfe8e7fSDavid Gibson { 11738dfe8e7fSDavid Gibson int shift; 11748dfe8e7fSDavid Gibson 11758dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 11768dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 11778dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 11788dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 11798dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 11808dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 11818dfe8e7fSDavid Gibson return shift; 11828dfe8e7fSDavid Gibson } 11838dfe8e7fSDavid Gibson 1184c5f54f3eSDavid Gibson static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, 1185c5f54f3eSDavid Gibson Error **errp) 118653018216SPaolo Bonzini { 1187c5f54f3eSDavid Gibson long rc; 118853018216SPaolo Bonzini 1189c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 1190c5f54f3eSDavid Gibson g_free(spapr->htab); 1191c5f54f3eSDavid Gibson spapr->htab = NULL; 1192c5f54f3eSDavid Gibson spapr->htab_shift = 0; 1193c5f54f3eSDavid Gibson close_htab_fd(spapr); 119453018216SPaolo Bonzini 1195c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1196c5f54f3eSDavid Gibson if (rc < 0) { 1197c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1198c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1199c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1200c5f54f3eSDavid Gibson shift); 1201c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1202c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1203c5f54f3eSDavid Gibson } else if (rc > 0) { 1204c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1205c5f54f3eSDavid Gibson if (rc != shift) { 1206c5f54f3eSDavid Gibson error_setg(errp, 1207c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1208c5f54f3eSDavid Gibson shift, rc); 12097735fedaSBharata B Rao } 12107735fedaSBharata B Rao 121153018216SPaolo Bonzini spapr->htab_shift = shift; 1212c18ad9a5SDavid Gibson spapr->htab = NULL; 1213b817772aSBharata B Rao } else { 1214c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1215c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1216c5f54f3eSDavid Gibson int i; 121701a57972SSamuel Mendoza-Jonas 1218c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1219c5f54f3eSDavid Gibson if (!spapr->htab) { 1220c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1221c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1222c5f54f3eSDavid Gibson return; 1223b817772aSBharata B Rao } 1224b817772aSBharata B Rao 1225c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1226c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1227b817772aSBharata B Rao 1228c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1229c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 12307735fedaSBharata B Rao } 123153018216SPaolo Bonzini } 123253018216SPaolo Bonzini } 123353018216SPaolo Bonzini 12344f01a637SDavid Gibson static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 12359e3f9733SAlexander Graf { 12369e3f9733SAlexander Graf bool matched = false; 12379e3f9733SAlexander Graf 12389e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 12399e3f9733SAlexander Graf matched = true; 12409e3f9733SAlexander Graf } 12419e3f9733SAlexander Graf 12429e3f9733SAlexander Graf if (!matched) { 12439e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 12449e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 12459e3f9733SAlexander Graf exit(1); 12469e3f9733SAlexander Graf } 12479e3f9733SAlexander Graf } 12489e3f9733SAlexander Graf 124953018216SPaolo Bonzini static void ppc_spapr_reset(void) 125053018216SPaolo Bonzini { 1251c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1252c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1253182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1254b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1255cae172abSDavid Gibson hwaddr rtas_addr, fdt_addr; 1256997b6cfcSDavid Gibson void *fdt; 1257997b6cfcSDavid Gibson int rc; 1258259186a7SAndreas Färber 12599e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 12609e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 12619e3f9733SAlexander Graf 12629861bb3eSSuraj Jitindar Singh spapr->patb_entry = 0; 12639861bb3eSSuraj Jitindar Singh 1264c5f54f3eSDavid Gibson /* Allocate and/or reset the hash page table */ 1265c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, 1266c5f54f3eSDavid Gibson spapr_hpt_shift_for_ramsize(machine->maxram_size), 1267c5f54f3eSDavid Gibson &error_fatal); 1268c5f54f3eSDavid Gibson 1269c5f54f3eSDavid Gibson /* Update the RMA size if necessary */ 1270c5f54f3eSDavid Gibson if (spapr->vrma_adjust) { 1271c5f54f3eSDavid Gibson spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1272c5f54f3eSDavid Gibson spapr->htab_shift); 1273c5f54f3eSDavid Gibson } 127453018216SPaolo Bonzini 127553018216SPaolo Bonzini qemu_devices_reset(); 127653018216SPaolo Bonzini 1277b7d1f77aSBenjamin Herrenschmidt /* 1278b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1279b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1280b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1281b7d1f77aSBenjamin Herrenschmidt */ 1282b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1283cae172abSDavid Gibson rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1284cae172abSDavid Gibson fdt_addr = rtas_addr - FDT_MAX_SIZE; 1285b7d1f77aSBenjamin Herrenschmidt 12866787d27bSMichael Roth /* if this reset wasn't generated by CAS, we should reset our 12876787d27bSMichael Roth * negotiated options and start from scratch */ 12886787d27bSMichael Roth if (!spapr->cas_reboot) { 12896787d27bSMichael Roth spapr_ovec_cleanup(spapr->ov5_cas); 12906787d27bSMichael Roth spapr->ov5_cas = spapr_ovec_new(); 12916787d27bSMichael Roth } 12926787d27bSMichael Roth 1293cae172abSDavid Gibson fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size); 129453018216SPaolo Bonzini 12952cac78c1SDavid Gibson spapr_load_rtas(spapr, fdt, rtas_addr); 1296b7d1f77aSBenjamin Herrenschmidt 1297997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1298997b6cfcSDavid Gibson 1299997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1300997b6cfcSDavid Gibson assert(rc == 0); 1301997b6cfcSDavid Gibson 1302997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1303997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1304997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1305997b6cfcSDavid Gibson exit(1); 1306997b6cfcSDavid Gibson } 1307997b6cfcSDavid Gibson 1308997b6cfcSDavid Gibson /* Load the fdt */ 1309997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1310cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1311997b6cfcSDavid Gibson g_free(fdt); 1312997b6cfcSDavid Gibson 131353018216SPaolo Bonzini /* Set up the entry state */ 1314182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1315cae172abSDavid Gibson first_ppc_cpu->env.gpr[3] = fdt_addr; 1316182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1317182735efSAndreas Färber first_cpu->halted = 0; 13181b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 131953018216SPaolo Bonzini 13206787d27bSMichael Roth spapr->cas_reboot = false; 132153018216SPaolo Bonzini } 132253018216SPaolo Bonzini 132328e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 132453018216SPaolo Bonzini { 13252ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 13263978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 132753018216SPaolo Bonzini 13283978b863SPaolo Bonzini if (dinfo) { 13296231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 13306231a6daSMarkus Armbruster &error_fatal); 133153018216SPaolo Bonzini } 133253018216SPaolo Bonzini 133353018216SPaolo Bonzini qdev_init_nofail(dev); 133453018216SPaolo Bonzini 133553018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 133653018216SPaolo Bonzini } 133753018216SPaolo Bonzini 133828e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 133928df36a1SDavid Gibson { 134028df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 134128df36a1SDavid Gibson 134228df36a1SDavid Gibson qdev_init_nofail(dev); 134328df36a1SDavid Gibson spapr->rtc = dev; 134474e5ae28SDavid Gibson 134574e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 134674e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 134728df36a1SDavid Gibson } 134828df36a1SDavid Gibson 134953018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 135014c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 135153018216SPaolo Bonzini { 135253018216SPaolo Bonzini switch (vga_interface_type) { 135353018216SPaolo Bonzini case VGA_NONE: 13547effdaa3SMark Wu return false; 13557effdaa3SMark Wu case VGA_DEVICE: 13567effdaa3SMark Wu return true; 135753018216SPaolo Bonzini case VGA_STD: 1358b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 135953018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 136053018216SPaolo Bonzini default: 136114c6a894SDavid Gibson error_setg(errp, 136214c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 136314c6a894SDavid Gibson return false; 136453018216SPaolo Bonzini } 136553018216SPaolo Bonzini } 136653018216SPaolo Bonzini 1367880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1368880ae7deSDavid Gibson { 136928e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1370880ae7deSDavid Gibson int err = 0; 1371880ae7deSDavid Gibson 1372a7ff1212SCédric Le Goater if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) { 1373a7ff1212SCédric Le Goater int i; 1374a7ff1212SCédric Le Goater for (i = 0; i < spapr->nr_servers; i++) { 1375a7ff1212SCédric Le Goater icp_resend(&spapr->icps[i]); 1376a7ff1212SCédric Le Goater } 1377a7ff1212SCédric Le Goater } 1378a7ff1212SCédric Le Goater 1379631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1380880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1381880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1382880ae7deSDavid Gibson * value into the RTC device */ 1383880ae7deSDavid Gibson if (version_id < 3) { 1384880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1385880ae7deSDavid Gibson } 1386880ae7deSDavid Gibson 1387880ae7deSDavid Gibson return err; 1388880ae7deSDavid Gibson } 1389880ae7deSDavid Gibson 1390880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1391880ae7deSDavid Gibson { 1392880ae7deSDavid Gibson return version_id < 3; 1393880ae7deSDavid Gibson } 1394880ae7deSDavid Gibson 139562ef3760SMichael Roth static bool spapr_ov5_cas_needed(void *opaque) 139662ef3760SMichael Roth { 139762ef3760SMichael Roth sPAPRMachineState *spapr = opaque; 139862ef3760SMichael Roth sPAPROptionVector *ov5_mask = spapr_ovec_new(); 139962ef3760SMichael Roth sPAPROptionVector *ov5_legacy = spapr_ovec_new(); 140062ef3760SMichael Roth sPAPROptionVector *ov5_removed = spapr_ovec_new(); 140162ef3760SMichael Roth bool cas_needed; 140262ef3760SMichael Roth 140362ef3760SMichael Roth /* Prior to the introduction of sPAPROptionVector, we had two option 140462ef3760SMichael Roth * vectors we dealt with: OV5_FORM1_AFFINITY, and OV5_DRCONF_MEMORY. 140562ef3760SMichael Roth * Both of these options encode machine topology into the device-tree 140662ef3760SMichael Roth * in such a way that the now-booted OS should still be able to interact 140762ef3760SMichael Roth * appropriately with QEMU regardless of what options were actually 140862ef3760SMichael Roth * negotiatied on the source side. 140962ef3760SMichael Roth * 141062ef3760SMichael Roth * As such, we can avoid migrating the CAS-negotiated options if these 141162ef3760SMichael Roth * are the only options available on the current machine/platform. 141262ef3760SMichael Roth * Since these are the only options available for pseries-2.7 and 141362ef3760SMichael Roth * earlier, this allows us to maintain old->new/new->old migration 141462ef3760SMichael Roth * compatibility. 141562ef3760SMichael Roth * 141662ef3760SMichael Roth * For QEMU 2.8+, there are additional CAS-negotiatable options available 141762ef3760SMichael Roth * via default pseries-2.8 machines and explicit command-line parameters. 141862ef3760SMichael Roth * Some of these options, like OV5_HP_EVT, *do* require QEMU to be aware 141962ef3760SMichael Roth * of the actual CAS-negotiated values to continue working properly. For 142062ef3760SMichael Roth * example, availability of memory unplug depends on knowing whether 142162ef3760SMichael Roth * OV5_HP_EVT was negotiated via CAS. 142262ef3760SMichael Roth * 142362ef3760SMichael Roth * Thus, for any cases where the set of available CAS-negotiatable 142462ef3760SMichael Roth * options extends beyond OV5_FORM1_AFFINITY and OV5_DRCONF_MEMORY, we 142562ef3760SMichael Roth * include the CAS-negotiated options in the migration stream. 142662ef3760SMichael Roth */ 142762ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_FORM1_AFFINITY); 142862ef3760SMichael Roth spapr_ovec_set(ov5_mask, OV5_DRCONF_MEMORY); 142962ef3760SMichael Roth 143062ef3760SMichael Roth /* spapr_ovec_diff returns true if bits were removed. we avoid using 143162ef3760SMichael Roth * the mask itself since in the future it's possible "legacy" bits may be 143262ef3760SMichael Roth * removed via machine options, which could generate a false positive 143362ef3760SMichael Roth * that breaks migration. 143462ef3760SMichael Roth */ 143562ef3760SMichael Roth spapr_ovec_intersect(ov5_legacy, spapr->ov5, ov5_mask); 143662ef3760SMichael Roth cas_needed = spapr_ovec_diff(ov5_removed, spapr->ov5, ov5_legacy); 143762ef3760SMichael Roth 143862ef3760SMichael Roth spapr_ovec_cleanup(ov5_mask); 143962ef3760SMichael Roth spapr_ovec_cleanup(ov5_legacy); 144062ef3760SMichael Roth spapr_ovec_cleanup(ov5_removed); 144162ef3760SMichael Roth 144262ef3760SMichael Roth return cas_needed; 144362ef3760SMichael Roth } 144462ef3760SMichael Roth 144562ef3760SMichael Roth static const VMStateDescription vmstate_spapr_ov5_cas = { 144662ef3760SMichael Roth .name = "spapr_option_vector_ov5_cas", 144762ef3760SMichael Roth .version_id = 1, 144862ef3760SMichael Roth .minimum_version_id = 1, 144962ef3760SMichael Roth .needed = spapr_ov5_cas_needed, 145062ef3760SMichael Roth .fields = (VMStateField[]) { 145162ef3760SMichael Roth VMSTATE_STRUCT_POINTER_V(ov5_cas, sPAPRMachineState, 1, 145262ef3760SMichael Roth vmstate_spapr_ovec, sPAPROptionVector), 145362ef3760SMichael Roth VMSTATE_END_OF_LIST() 145462ef3760SMichael Roth }, 145562ef3760SMichael Roth }; 145662ef3760SMichael Roth 14579861bb3eSSuraj Jitindar Singh static bool spapr_patb_entry_needed(void *opaque) 14589861bb3eSSuraj Jitindar Singh { 14599861bb3eSSuraj Jitindar Singh sPAPRMachineState *spapr = opaque; 14609861bb3eSSuraj Jitindar Singh 14619861bb3eSSuraj Jitindar Singh return !!spapr->patb_entry; 14629861bb3eSSuraj Jitindar Singh } 14639861bb3eSSuraj Jitindar Singh 14649861bb3eSSuraj Jitindar Singh static const VMStateDescription vmstate_spapr_patb_entry = { 14659861bb3eSSuraj Jitindar Singh .name = "spapr_patb_entry", 14669861bb3eSSuraj Jitindar Singh .version_id = 1, 14679861bb3eSSuraj Jitindar Singh .minimum_version_id = 1, 14689861bb3eSSuraj Jitindar Singh .needed = spapr_patb_entry_needed, 14699861bb3eSSuraj Jitindar Singh .fields = (VMStateField[]) { 14709861bb3eSSuraj Jitindar Singh VMSTATE_UINT64(patb_entry, sPAPRMachineState), 14719861bb3eSSuraj Jitindar Singh VMSTATE_END_OF_LIST() 14729861bb3eSSuraj Jitindar Singh }, 14739861bb3eSSuraj Jitindar Singh }; 14749861bb3eSSuraj Jitindar Singh 14754be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 14764be21d56SDavid Gibson .name = "spapr", 1477880ae7deSDavid Gibson .version_id = 3, 14784be21d56SDavid Gibson .minimum_version_id = 1, 1479880ae7deSDavid Gibson .post_load = spapr_post_load, 14804be21d56SDavid Gibson .fields = (VMStateField[]) { 1481880ae7deSDavid Gibson /* used to be @next_irq */ 1482880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 14834be21d56SDavid Gibson 14844be21d56SDavid Gibson /* RTC offset */ 148528e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1486880ae7deSDavid Gibson 148728e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 14884be21d56SDavid Gibson VMSTATE_END_OF_LIST() 14894be21d56SDavid Gibson }, 149062ef3760SMichael Roth .subsections = (const VMStateDescription*[]) { 149162ef3760SMichael Roth &vmstate_spapr_ov5_cas, 14929861bb3eSSuraj Jitindar Singh &vmstate_spapr_patb_entry, 149362ef3760SMichael Roth NULL 149462ef3760SMichael Roth } 14954be21d56SDavid Gibson }; 14964be21d56SDavid Gibson 14974be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 14984be21d56SDavid Gibson { 149928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 15004be21d56SDavid Gibson 15014be21d56SDavid Gibson /* "Iteration" header */ 15024be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 15034be21d56SDavid Gibson 1504e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1505e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1506e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1507e68cb8b4SAlexey Kardashevskiy } else { 1508e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 15094be21d56SDavid Gibson } 15104be21d56SDavid Gibson 1511e68cb8b4SAlexey Kardashevskiy 1512e68cb8b4SAlexey Kardashevskiy return 0; 1513e68cb8b4SAlexey Kardashevskiy } 15144be21d56SDavid Gibson 151528e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 15164be21d56SDavid Gibson int64_t max_ns) 15174be21d56SDavid Gibson { 1518378bc217SDavid Gibson bool has_timeout = max_ns != -1; 15194be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 15204be21d56SDavid Gibson int index = spapr->htab_save_index; 1521bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 15224be21d56SDavid Gibson 15234be21d56SDavid Gibson assert(spapr->htab_first_pass); 15244be21d56SDavid Gibson 15254be21d56SDavid Gibson do { 15264be21d56SDavid Gibson int chunkstart; 15274be21d56SDavid Gibson 15284be21d56SDavid Gibson /* Consume invalid HPTEs */ 15294be21d56SDavid Gibson while ((index < htabslots) 15304be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 15314be21d56SDavid Gibson index++; 15324be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 15334be21d56SDavid Gibson } 15344be21d56SDavid Gibson 15354be21d56SDavid Gibson /* Consume valid HPTEs */ 15364be21d56SDavid Gibson chunkstart = index; 1537338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 15384be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 15394be21d56SDavid Gibson index++; 15404be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 15414be21d56SDavid Gibson } 15424be21d56SDavid Gibson 15434be21d56SDavid Gibson if (index > chunkstart) { 15444be21d56SDavid Gibson int n_valid = index - chunkstart; 15454be21d56SDavid Gibson 15464be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 15474be21d56SDavid Gibson qemu_put_be16(f, n_valid); 15484be21d56SDavid Gibson qemu_put_be16(f, 0); 15494be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 15504be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 15514be21d56SDavid Gibson 1552378bc217SDavid Gibson if (has_timeout && 1553378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 15544be21d56SDavid Gibson break; 15554be21d56SDavid Gibson } 15564be21d56SDavid Gibson } 15574be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 15584be21d56SDavid Gibson 15594be21d56SDavid Gibson if (index >= htabslots) { 15604be21d56SDavid Gibson assert(index == htabslots); 15614be21d56SDavid Gibson index = 0; 15624be21d56SDavid Gibson spapr->htab_first_pass = false; 15634be21d56SDavid Gibson } 15644be21d56SDavid Gibson spapr->htab_save_index = index; 15654be21d56SDavid Gibson } 15664be21d56SDavid Gibson 156728e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 15684be21d56SDavid Gibson int64_t max_ns) 15694be21d56SDavid Gibson { 15704be21d56SDavid Gibson bool final = max_ns < 0; 15714be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 15724be21d56SDavid Gibson int examined = 0, sent = 0; 15734be21d56SDavid Gibson int index = spapr->htab_save_index; 1574bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 15754be21d56SDavid Gibson 15764be21d56SDavid Gibson assert(!spapr->htab_first_pass); 15774be21d56SDavid Gibson 15784be21d56SDavid Gibson do { 15794be21d56SDavid Gibson int chunkstart, invalidstart; 15804be21d56SDavid Gibson 15814be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 15824be21d56SDavid Gibson while ((index < htabslots) 15834be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 15844be21d56SDavid Gibson index++; 15854be21d56SDavid Gibson examined++; 15864be21d56SDavid Gibson } 15874be21d56SDavid Gibson 15884be21d56SDavid Gibson chunkstart = index; 15894be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1590338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 15914be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 15924be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 15934be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 15944be21d56SDavid Gibson index++; 15954be21d56SDavid Gibson examined++; 15964be21d56SDavid Gibson } 15974be21d56SDavid Gibson 15984be21d56SDavid Gibson invalidstart = index; 15994be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1600338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 16014be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 16024be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 16034be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 16044be21d56SDavid Gibson index++; 16054be21d56SDavid Gibson examined++; 16064be21d56SDavid Gibson } 16074be21d56SDavid Gibson 16084be21d56SDavid Gibson if (index > chunkstart) { 16094be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 16104be21d56SDavid Gibson int n_invalid = index - invalidstart; 16114be21d56SDavid Gibson 16124be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 16134be21d56SDavid Gibson qemu_put_be16(f, n_valid); 16144be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 16154be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 16164be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 16174be21d56SDavid Gibson sent += index - chunkstart; 16184be21d56SDavid Gibson 1619bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 16204be21d56SDavid Gibson break; 16214be21d56SDavid Gibson } 16224be21d56SDavid Gibson } 16234be21d56SDavid Gibson 16244be21d56SDavid Gibson if (examined >= htabslots) { 16254be21d56SDavid Gibson break; 16264be21d56SDavid Gibson } 16274be21d56SDavid Gibson 16284be21d56SDavid Gibson if (index >= htabslots) { 16294be21d56SDavid Gibson assert(index == htabslots); 16304be21d56SDavid Gibson index = 0; 16314be21d56SDavid Gibson } 16324be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 16334be21d56SDavid Gibson 16344be21d56SDavid Gibson if (index >= htabslots) { 16354be21d56SDavid Gibson assert(index == htabslots); 16364be21d56SDavid Gibson index = 0; 16374be21d56SDavid Gibson } 16384be21d56SDavid Gibson 16394be21d56SDavid Gibson spapr->htab_save_index = index; 16404be21d56SDavid Gibson 1641e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 16424be21d56SDavid Gibson } 16434be21d56SDavid Gibson 1644e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1645e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1646e68cb8b4SAlexey Kardashevskiy 16474be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 16484be21d56SDavid Gibson { 164928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1650715c5407SDavid Gibson int fd; 1651e68cb8b4SAlexey Kardashevskiy int rc = 0; 16524be21d56SDavid Gibson 16534be21d56SDavid Gibson /* Iteration header */ 16544be21d56SDavid Gibson qemu_put_be32(f, 0); 16554be21d56SDavid Gibson 1656e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1657e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1658e68cb8b4SAlexey Kardashevskiy 1659715c5407SDavid Gibson fd = get_htab_fd(spapr); 1660715c5407SDavid Gibson if (fd < 0) { 1661715c5407SDavid Gibson return fd; 166201a57972SSamuel Mendoza-Jonas } 166301a57972SSamuel Mendoza-Jonas 1664715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1665e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1666e68cb8b4SAlexey Kardashevskiy return rc; 1667e68cb8b4SAlexey Kardashevskiy } 1668e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 16694be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 16704be21d56SDavid Gibson } else { 1671e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 16724be21d56SDavid Gibson } 16734be21d56SDavid Gibson 16744be21d56SDavid Gibson /* End marker */ 16754be21d56SDavid Gibson qemu_put_be32(f, 0); 16764be21d56SDavid Gibson qemu_put_be16(f, 0); 16774be21d56SDavid Gibson qemu_put_be16(f, 0); 16784be21d56SDavid Gibson 1679e68cb8b4SAlexey Kardashevskiy return rc; 16804be21d56SDavid Gibson } 16814be21d56SDavid Gibson 16824be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 16834be21d56SDavid Gibson { 168428e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1685715c5407SDavid Gibson int fd; 16864be21d56SDavid Gibson 16874be21d56SDavid Gibson /* Iteration header */ 16884be21d56SDavid Gibson qemu_put_be32(f, 0); 16894be21d56SDavid Gibson 1690e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1691e68cb8b4SAlexey Kardashevskiy int rc; 1692e68cb8b4SAlexey Kardashevskiy 1693e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1694e68cb8b4SAlexey Kardashevskiy 1695715c5407SDavid Gibson fd = get_htab_fd(spapr); 1696715c5407SDavid Gibson if (fd < 0) { 1697715c5407SDavid Gibson return fd; 169801a57972SSamuel Mendoza-Jonas } 169901a57972SSamuel Mendoza-Jonas 1700715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 1701e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1702e68cb8b4SAlexey Kardashevskiy return rc; 1703e68cb8b4SAlexey Kardashevskiy } 1704e68cb8b4SAlexey Kardashevskiy } else { 1705378bc217SDavid Gibson if (spapr->htab_first_pass) { 1706378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 1707378bc217SDavid Gibson } 17084be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1709e68cb8b4SAlexey Kardashevskiy } 17104be21d56SDavid Gibson 17114be21d56SDavid Gibson /* End marker */ 17124be21d56SDavid Gibson qemu_put_be32(f, 0); 17134be21d56SDavid Gibson qemu_put_be16(f, 0); 17144be21d56SDavid Gibson qemu_put_be16(f, 0); 17154be21d56SDavid Gibson 17164be21d56SDavid Gibson return 0; 17174be21d56SDavid Gibson } 17184be21d56SDavid Gibson 17194be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 17204be21d56SDavid Gibson { 172128e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 17224be21d56SDavid Gibson uint32_t section_hdr; 1723e68cb8b4SAlexey Kardashevskiy int fd = -1; 17244be21d56SDavid Gibson 17254be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 172698a5d100SDavid Gibson error_report("htab_load() bad version"); 17274be21d56SDavid Gibson return -EINVAL; 17284be21d56SDavid Gibson } 17294be21d56SDavid Gibson 17304be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 17314be21d56SDavid Gibson 17324be21d56SDavid Gibson if (section_hdr) { 17339897e462SGreg Kurz Error *local_err = NULL; 1734c5f54f3eSDavid Gibson 1735c5f54f3eSDavid Gibson /* First section gives the htab size */ 1736c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 1737c5f54f3eSDavid Gibson if (local_err) { 1738c5f54f3eSDavid Gibson error_report_err(local_err); 17394be21d56SDavid Gibson return -EINVAL; 17404be21d56SDavid Gibson } 17414be21d56SDavid Gibson return 0; 17424be21d56SDavid Gibson } 17434be21d56SDavid Gibson 1744e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1745e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1746e68cb8b4SAlexey Kardashevskiy 1747e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1748e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 174998a5d100SDavid Gibson error_report("Unable to open fd to restore KVM hash table: %s", 1750e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1751e68cb8b4SAlexey Kardashevskiy } 1752e68cb8b4SAlexey Kardashevskiy } 1753e68cb8b4SAlexey Kardashevskiy 17544be21d56SDavid Gibson while (true) { 17554be21d56SDavid Gibson uint32_t index; 17564be21d56SDavid Gibson uint16_t n_valid, n_invalid; 17574be21d56SDavid Gibson 17584be21d56SDavid Gibson index = qemu_get_be32(f); 17594be21d56SDavid Gibson n_valid = qemu_get_be16(f); 17604be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 17614be21d56SDavid Gibson 17624be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 17634be21d56SDavid Gibson /* End of Stream */ 17644be21d56SDavid Gibson break; 17654be21d56SDavid Gibson } 17664be21d56SDavid Gibson 1767e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 17684be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 17694be21d56SDavid Gibson /* Bad index in stream */ 177098a5d100SDavid Gibson error_report( 177198a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 177298a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 17734be21d56SDavid Gibson return -EINVAL; 17744be21d56SDavid Gibson } 17754be21d56SDavid Gibson 1776e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 17774be21d56SDavid Gibson if (n_valid) { 17784be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 17794be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 17804be21d56SDavid Gibson } 17814be21d56SDavid Gibson if (n_invalid) { 17824be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 17834be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 17844be21d56SDavid Gibson } 1785e68cb8b4SAlexey Kardashevskiy } else { 1786e68cb8b4SAlexey Kardashevskiy int rc; 1787e68cb8b4SAlexey Kardashevskiy 1788e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1789e68cb8b4SAlexey Kardashevskiy 1790e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1791e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1792e68cb8b4SAlexey Kardashevskiy return rc; 1793e68cb8b4SAlexey Kardashevskiy } 1794e68cb8b4SAlexey Kardashevskiy } 1795e68cb8b4SAlexey Kardashevskiy } 1796e68cb8b4SAlexey Kardashevskiy 1797e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1798e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1799e68cb8b4SAlexey Kardashevskiy close(fd); 18004be21d56SDavid Gibson } 18014be21d56SDavid Gibson 18024be21d56SDavid Gibson return 0; 18034be21d56SDavid Gibson } 18044be21d56SDavid Gibson 1805c573fc03SThomas Huth static void htab_cleanup(void *opaque) 1806c573fc03SThomas Huth { 1807c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 1808c573fc03SThomas Huth 1809c573fc03SThomas Huth close_htab_fd(spapr); 1810c573fc03SThomas Huth } 1811c573fc03SThomas Huth 18124be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 18134be21d56SDavid Gibson .save_live_setup = htab_save_setup, 18144be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 1815a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 1816c573fc03SThomas Huth .cleanup = htab_cleanup, 18174be21d56SDavid Gibson .load_state = htab_load, 18184be21d56SDavid Gibson }; 18194be21d56SDavid Gibson 18205b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 18215b2128d2SAlexander Graf Error **errp) 18225b2128d2SAlexander Graf { 18235b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 18245b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 18255b2128d2SAlexander Graf } 18265b2128d2SAlexander Graf 1827224245bfSDavid Gibson /* 1828224245bfSDavid Gibson * Reset routine for LMB DR devices. 1829224245bfSDavid Gibson * 1830224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1831224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1832224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1833224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1834224245bfSDavid Gibson */ 1835224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1836224245bfSDavid Gibson { 1837224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1838224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1839224245bfSDavid Gibson 1840224245bfSDavid Gibson if (d) { 1841224245bfSDavid Gibson device_reset(d); 1842224245bfSDavid Gibson } 1843224245bfSDavid Gibson } 1844224245bfSDavid Gibson 1845224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1846224245bfSDavid Gibson { 1847224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1848224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1849e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1850224245bfSDavid Gibson int i; 1851224245bfSDavid Gibson 1852224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1853224245bfSDavid Gibson sPAPRDRConnector *drc; 1854224245bfSDavid Gibson uint64_t addr; 1855224245bfSDavid Gibson 1856e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1857224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1858224245bfSDavid Gibson addr/lmb_size); 1859224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1860224245bfSDavid Gibson } 1861224245bfSDavid Gibson } 1862224245bfSDavid Gibson 1863224245bfSDavid Gibson /* 1864224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1865224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1866224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1867224245bfSDavid Gibson */ 18687c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 1869224245bfSDavid Gibson { 1870224245bfSDavid Gibson int i; 1871224245bfSDavid Gibson 18727c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 18737c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 18747c150d6fSDavid Gibson " is not aligned to %llu MiB", 18757c150d6fSDavid Gibson machine->ram_size, 1876224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 18777c150d6fSDavid Gibson return; 18787c150d6fSDavid Gibson } 18797c150d6fSDavid Gibson 18807c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 18817c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 18827c150d6fSDavid Gibson " is not aligned to %llu MiB", 18837c150d6fSDavid Gibson machine->ram_size, 18847c150d6fSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 18857c150d6fSDavid Gibson return; 1886224245bfSDavid Gibson } 1887224245bfSDavid Gibson 1888224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1889224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 18907c150d6fSDavid Gibson error_setg(errp, 18917c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 18927c150d6fSDavid Gibson " is not aligned to %llu MiB", 18937c150d6fSDavid Gibson i, numa_info[i].node_mem, 1894224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 18957c150d6fSDavid Gibson return; 1896224245bfSDavid Gibson } 1897224245bfSDavid Gibson } 1898224245bfSDavid Gibson } 1899224245bfSDavid Gibson 1900535455fdSIgor Mammedov /* find cpu slot in machine->possible_cpus by core_id */ 1901535455fdSIgor Mammedov static CPUArchId *spapr_find_cpu_slot(MachineState *ms, uint32_t id, int *idx) 1902535455fdSIgor Mammedov { 1903535455fdSIgor Mammedov int index = id / smp_threads; 1904535455fdSIgor Mammedov 1905535455fdSIgor Mammedov if (index >= ms->possible_cpus->len) { 1906535455fdSIgor Mammedov return NULL; 1907535455fdSIgor Mammedov } 1908535455fdSIgor Mammedov if (idx) { 1909535455fdSIgor Mammedov *idx = index; 1910535455fdSIgor Mammedov } 1911535455fdSIgor Mammedov return &ms->possible_cpus->cpus[index]; 1912535455fdSIgor Mammedov } 1913535455fdSIgor Mammedov 19140c86d0fdSDavid Gibson static void spapr_init_cpus(sPAPRMachineState *spapr) 19150c86d0fdSDavid Gibson { 19160c86d0fdSDavid Gibson MachineState *machine = MACHINE(spapr); 19170c86d0fdSDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 19180c86d0fdSDavid Gibson char *type = spapr_get_cpu_core_type(machine->cpu_model); 19190c86d0fdSDavid Gibson int smt = kvmppc_smt_threads(); 1920535455fdSIgor Mammedov const CPUArchIdList *possible_cpus; 1921535455fdSIgor Mammedov int boot_cores_nr = smp_cpus / smp_threads; 19220c86d0fdSDavid Gibson int i; 19230c86d0fdSDavid Gibson 19240c86d0fdSDavid Gibson if (!type) { 19250c86d0fdSDavid Gibson error_report("Unable to find sPAPR CPU Core definition"); 19260c86d0fdSDavid Gibson exit(1); 19270c86d0fdSDavid Gibson } 19280c86d0fdSDavid Gibson 1929535455fdSIgor Mammedov possible_cpus = mc->possible_cpu_arch_ids(machine); 1930c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 19310c86d0fdSDavid Gibson if (smp_cpus % smp_threads) { 19320c86d0fdSDavid Gibson error_report("smp_cpus (%u) must be multiple of threads (%u)", 19330c86d0fdSDavid Gibson smp_cpus, smp_threads); 19340c86d0fdSDavid Gibson exit(1); 19350c86d0fdSDavid Gibson } 19360c86d0fdSDavid Gibson if (max_cpus % smp_threads) { 19370c86d0fdSDavid Gibson error_report("max_cpus (%u) must be multiple of threads (%u)", 19380c86d0fdSDavid Gibson max_cpus, smp_threads); 19390c86d0fdSDavid Gibson exit(1); 19400c86d0fdSDavid Gibson } 19410c86d0fdSDavid Gibson } else { 19420c86d0fdSDavid Gibson if (max_cpus != smp_cpus) { 19430c86d0fdSDavid Gibson error_report("This machine version does not support CPU hotplug"); 19440c86d0fdSDavid Gibson exit(1); 19450c86d0fdSDavid Gibson } 1946535455fdSIgor Mammedov boot_cores_nr = possible_cpus->len; 19470c86d0fdSDavid Gibson } 19480c86d0fdSDavid Gibson 1949535455fdSIgor Mammedov for (i = 0; i < possible_cpus->len; i++) { 19500c86d0fdSDavid Gibson int core_id = i * smp_threads; 19510c86d0fdSDavid Gibson 1952c5514d0eSIgor Mammedov if (mc->has_hotpluggable_cpus) { 19530c86d0fdSDavid Gibson sPAPRDRConnector *drc = 19540c86d0fdSDavid Gibson spapr_dr_connector_new(OBJECT(spapr), 19550c86d0fdSDavid Gibson SPAPR_DR_CONNECTOR_TYPE_CPU, 19560c86d0fdSDavid Gibson (core_id / smp_threads) * smt); 19570c86d0fdSDavid Gibson 19580c86d0fdSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 19590c86d0fdSDavid Gibson } 19600c86d0fdSDavid Gibson 1961535455fdSIgor Mammedov if (i < boot_cores_nr) { 19620c86d0fdSDavid Gibson Object *core = object_new(type); 19630c86d0fdSDavid Gibson int nr_threads = smp_threads; 19640c86d0fdSDavid Gibson 19650c86d0fdSDavid Gibson /* Handle the partially filled core for older machine types */ 19660c86d0fdSDavid Gibson if ((i + 1) * smp_threads >= smp_cpus) { 19670c86d0fdSDavid Gibson nr_threads = smp_cpus - i * smp_threads; 19680c86d0fdSDavid Gibson } 19690c86d0fdSDavid Gibson 19700c86d0fdSDavid Gibson object_property_set_int(core, nr_threads, "nr-threads", 19710c86d0fdSDavid Gibson &error_fatal); 19720c86d0fdSDavid Gibson object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 19730c86d0fdSDavid Gibson &error_fatal); 19740c86d0fdSDavid Gibson object_property_set_bool(core, true, "realized", &error_fatal); 19750c86d0fdSDavid Gibson } 19760c86d0fdSDavid Gibson } 19770c86d0fdSDavid Gibson g_free(type); 19780c86d0fdSDavid Gibson } 19790c86d0fdSDavid Gibson 198053018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 19813ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 198253018216SPaolo Bonzini { 198328e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1984224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 19853ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 19863ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 198753018216SPaolo Bonzini PCIHostState *phb; 198853018216SPaolo Bonzini int i; 198953018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 199053018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1991658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1992658fa66bSAlexey Kardashevskiy void *rma = NULL; 199353018216SPaolo Bonzini hwaddr rma_alloc_size; 1994b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 1995b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 199653018216SPaolo Bonzini char *filename; 199794a94e4cSBharata B Rao int smt = kvmppc_smt_threads(); 199853018216SPaolo Bonzini 1999226419d6SMichael S. Tsirkin msi_nonbroken = true; 200053018216SPaolo Bonzini 200153018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 200253018216SPaolo Bonzini 200353018216SPaolo Bonzini /* Allocate RMA if necessary */ 2004658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 200553018216SPaolo Bonzini 200653018216SPaolo Bonzini if (rma_alloc_size == -1) { 2007730fce59SThomas Huth error_report("Unable to create RMA"); 200853018216SPaolo Bonzini exit(1); 200953018216SPaolo Bonzini } 201053018216SPaolo Bonzini 2011c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 201253018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 201353018216SPaolo Bonzini } else { 2014c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 201553018216SPaolo Bonzini 201653018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 201753018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 201853018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 201953018216SPaolo Bonzini * 202053018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 202153018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 202253018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 202353018216SPaolo Bonzini * isn't determined yet. 202453018216SPaolo Bonzini */ 202553018216SPaolo Bonzini if (kvm_enabled()) { 202653018216SPaolo Bonzini spapr->vrma_adjust = 1; 202753018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 202853018216SPaolo Bonzini } 2029912acdf4SBenjamin Herrenschmidt 2030912acdf4SBenjamin Herrenschmidt /* Actually we don't support unbounded RMA anymore since we 2031912acdf4SBenjamin Herrenschmidt * added proper emulation of HV mode. The max we can get is 2032912acdf4SBenjamin Herrenschmidt * 16G which also happens to be what we configure for PAPR 2033912acdf4SBenjamin Herrenschmidt * mode so make sure we don't do anything bigger than that 2034912acdf4SBenjamin Herrenschmidt */ 2035912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 203653018216SPaolo Bonzini } 203753018216SPaolo Bonzini 2038c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 2039d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 2040c4177479SAlexey Kardashevskiy spapr->rma_size); 2041c4177479SAlexey Kardashevskiy exit(1); 2042c4177479SAlexey Kardashevskiy } 2043c4177479SAlexey Kardashevskiy 2044b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 2045b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 204653018216SPaolo Bonzini 20477b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 2048e6f7e110SCédric Le Goater xics_system_init(machine, DIV_ROUND_UP(max_cpus * smt, smp_threads), 2049161deaf2SBenjamin Herrenschmidt XICS_IRQS_SPAPR, &error_fatal); 20507b565160SDavid Gibson 2051facdb8b6SMichael Roth /* Set up containers for ibm,client-set-architecture negotiated options */ 2052facdb8b6SMichael Roth spapr->ov5 = spapr_ovec_new(); 2053facdb8b6SMichael Roth spapr->ov5_cas = spapr_ovec_new(); 2054facdb8b6SMichael Roth 2055224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2056facdb8b6SMichael Roth spapr_ovec_set(spapr->ov5, OV5_DRCONF_MEMORY); 20577c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 2058224245bfSDavid Gibson } 2059224245bfSDavid Gibson 2060417ece33SMichael Roth spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY); 2061417ece33SMichael Roth 2062ffbb1705SMichael Roth /* advertise support for dedicated HP event source to guests */ 2063ffbb1705SMichael Roth if (spapr->use_hotplug_event_source) { 2064ffbb1705SMichael Roth spapr_ovec_set(spapr->ov5, OV5_HP_EVT); 2065ffbb1705SMichael Roth } 2066ffbb1705SMichael Roth 206753018216SPaolo Bonzini /* init CPUs */ 206819fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 20693daa4a9fSThomas Huth machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu; 207053018216SPaolo Bonzini } 207194a94e4cSBharata B Rao 2072e703d2f7SGreg Kurz ppc_cpu_parse_features(machine->cpu_model); 2073e703d2f7SGreg Kurz 20740c86d0fdSDavid Gibson spapr_init_cpus(spapr); 207553018216SPaolo Bonzini 2076026bfd89SDavid Gibson if (kvm_enabled()) { 2077026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 2078026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 2079ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 20805145ad4fSNathan Whitehorn 20815145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 20825145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 2083026bfd89SDavid Gibson } 2084026bfd89SDavid Gibson 208553018216SPaolo Bonzini /* allocate RAM */ 2086f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 2087fb164994SDavid Gibson machine->ram_size); 2088f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 208953018216SPaolo Bonzini 2090658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 2091658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 2092658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 2093658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 2094658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 2095658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 2096658fa66bSAlexey Kardashevskiy } 2097658fa66bSAlexey Kardashevskiy 20984a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 20994a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 21004a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 210171c9a3ddSBharata B Rao /* 210271c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 210371c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 210471c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 210571c9a3ddSBharata B Rao */ 210671c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 210771c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 21084a1c9cf0SBharata B Rao 210971c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 211071c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 211171c9a3ddSBharata B Rao } 211271c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 2113d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 2114d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 211571c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 2116d54e4d76SDavid Gibson exit(1); 21174a1c9cf0SBharata B Rao } 21184a1c9cf0SBharata B Rao 21194a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 21204a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 21214a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 21224a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 21234a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 21244a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 21254a1c9cf0SBharata B Rao } 21264a1c9cf0SBharata B Rao 2127224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 2128224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 2129224245bfSDavid Gibson } 2130224245bfSDavid Gibson 213153018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 21324c56440dSStefan Weil if (!filename) { 2133730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 21344c56440dSStefan Weil exit(1); 21354c56440dSStefan Weil } 2136b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 21378afc22a2SZhou Jie if (spapr->rtas_size < 0) { 21388afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 21398afc22a2SZhou Jie exit(1); 21408afc22a2SZhou Jie } 2141b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 2142b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 2143730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 214453018216SPaolo Bonzini exit(1); 214553018216SPaolo Bonzini } 214653018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 2147730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 21482f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 214953018216SPaolo Bonzini exit(1); 215053018216SPaolo Bonzini } 215153018216SPaolo Bonzini g_free(filename); 215253018216SPaolo Bonzini 2153ffbb1705SMichael Roth /* Set up RTAS event infrastructure */ 215453018216SPaolo Bonzini spapr_events_init(spapr); 215553018216SPaolo Bonzini 215612f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 215728df36a1SDavid Gibson spapr_rtc_create(spapr); 215812f42174SDavid Gibson 215953018216SPaolo Bonzini /* Set up VIO bus */ 216053018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 216153018216SPaolo Bonzini 216253018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 216353018216SPaolo Bonzini if (serial_hds[i]) { 216453018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 216553018216SPaolo Bonzini } 216653018216SPaolo Bonzini } 216753018216SPaolo Bonzini 216853018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 216953018216SPaolo Bonzini spapr_create_nvram(spapr); 217053018216SPaolo Bonzini 217153018216SPaolo Bonzini /* Set up PCI */ 217253018216SPaolo Bonzini spapr_pci_rtas_init(); 217353018216SPaolo Bonzini 217489dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 217553018216SPaolo Bonzini 217653018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 217753018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 217853018216SPaolo Bonzini 217953018216SPaolo Bonzini if (!nd->model) { 218053018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 218153018216SPaolo Bonzini } 218253018216SPaolo Bonzini 218353018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 218453018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 218553018216SPaolo Bonzini } else { 218629b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 218753018216SPaolo Bonzini } 218853018216SPaolo Bonzini } 218953018216SPaolo Bonzini 219053018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 219153018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 219253018216SPaolo Bonzini } 219353018216SPaolo Bonzini 219453018216SPaolo Bonzini /* Graphics */ 219514c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 219653018216SPaolo Bonzini spapr->has_graphics = true; 2197c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 219853018216SPaolo Bonzini } 219953018216SPaolo Bonzini 22004ee9ced9SMarcel Apfelbaum if (machine->usb) { 220157040d45SThomas Huth if (smc->use_ohci_by_default) { 220253018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 220357040d45SThomas Huth } else { 220457040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 220557040d45SThomas Huth } 2206c86580b8SMarkus Armbruster 220753018216SPaolo Bonzini if (spapr->has_graphics) { 2208c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 2209c86580b8SMarkus Armbruster 2210c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 2211c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 221253018216SPaolo Bonzini } 221353018216SPaolo Bonzini } 221453018216SPaolo Bonzini 221553018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 2216d54e4d76SDavid Gibson error_report( 2217d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 2218d54e4d76SDavid Gibson MIN_RMA_SLOF); 221953018216SPaolo Bonzini exit(1); 222053018216SPaolo Bonzini } 222153018216SPaolo Bonzini 222253018216SPaolo Bonzini if (kernel_filename) { 222353018216SPaolo Bonzini uint64_t lowaddr = 0; 222453018216SPaolo Bonzini 2225a19f7fb0SDavid Gibson spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address, 2226a19f7fb0SDavid Gibson NULL, NULL, &lowaddr, NULL, 1, 2227a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 2228a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 2229a19f7fb0SDavid Gibson spapr->kernel_size = load_elf(kernel_filename, 2230a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 2231a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 22327ef295eaSPeter Crosthwaite 0, 0); 2233a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 223416457e7fSBenjamin Herrenschmidt } 2235a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 2236a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 2237a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 223853018216SPaolo Bonzini exit(1); 223953018216SPaolo Bonzini } 224053018216SPaolo Bonzini 224153018216SPaolo Bonzini /* load initrd */ 224253018216SPaolo Bonzini if (initrd_filename) { 224353018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 224453018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 224553018216SPaolo Bonzini */ 2246a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 2247a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 2248a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 2249a19f7fb0SDavid Gibson spapr->initrd_base, 2250a19f7fb0SDavid Gibson load_limit 2251a19f7fb0SDavid Gibson - spapr->initrd_base); 2252a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 2253d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 225453018216SPaolo Bonzini initrd_filename); 225553018216SPaolo Bonzini exit(1); 225653018216SPaolo Bonzini } 225753018216SPaolo Bonzini } 225853018216SPaolo Bonzini } 225953018216SPaolo Bonzini 22608e7ea787SAndreas Färber if (bios_name == NULL) { 22618e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 22628e7ea787SAndreas Färber } 22638e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 22644c56440dSStefan Weil if (!filename) { 226568fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 22664c56440dSStefan Weil exit(1); 22674c56440dSStefan Weil } 226853018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 226968fea5a0SThomas Huth if (fw_size <= 0) { 227068fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 227153018216SPaolo Bonzini exit(1); 227253018216SPaolo Bonzini } 227353018216SPaolo Bonzini g_free(filename); 227453018216SPaolo Bonzini 227528e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 227628e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 227728e02042SDavid Gibson * which predated MachineState but had a similar function */ 22784be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 22794be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 22804be21d56SDavid Gibson &savevm_htab_handlers, spapr); 22814be21d56SDavid Gibson 228246503c2bSMichael Roth /* used by RTAS */ 228346503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 228446503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 228546503c2bSMichael Roth 22865b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 228742043e4fSLaurent Vivier 228842043e4fSLaurent Vivier /* to stop and start vmclock */ 228942043e4fSLaurent Vivier if (kvm_enabled()) { 229042043e4fSLaurent Vivier qemu_add_vm_change_state_handler(cpu_ppc_clock_vm_state_change, 229142043e4fSLaurent Vivier &spapr->tb); 229242043e4fSLaurent Vivier } 229353018216SPaolo Bonzini } 229453018216SPaolo Bonzini 2295135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 2296135a129aSAneesh Kumar K.V { 2297135a129aSAneesh Kumar K.V if (!vm_type) { 2298135a129aSAneesh Kumar K.V return 0; 2299135a129aSAneesh Kumar K.V } 2300135a129aSAneesh Kumar K.V 2301135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 2302135a129aSAneesh Kumar K.V return 1; 2303135a129aSAneesh Kumar K.V } 2304135a129aSAneesh Kumar K.V 2305135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2306135a129aSAneesh Kumar K.V return 2; 2307135a129aSAneesh Kumar K.V } 2308135a129aSAneesh Kumar K.V 2309135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2310135a129aSAneesh Kumar K.V exit(1); 2311135a129aSAneesh Kumar K.V } 2312135a129aSAneesh Kumar K.V 231371461b0fSAlexey Kardashevskiy /* 2314627b84f4SGonglei * Implementation of an interface to adjust firmware path 231571461b0fSAlexey Kardashevskiy * for the bootindex property handling. 231671461b0fSAlexey Kardashevskiy */ 231771461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 231871461b0fSAlexey Kardashevskiy DeviceState *dev) 231971461b0fSAlexey Kardashevskiy { 232071461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 232171461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 232271461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 232371461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 232471461b0fSAlexey Kardashevskiy 232571461b0fSAlexey Kardashevskiy if (d) { 232671461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 232771461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 232871461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 232971461b0fSAlexey Kardashevskiy 233071461b0fSAlexey Kardashevskiy if (spapr) { 233171461b0fSAlexey Kardashevskiy /* 233271461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 233371461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 233471461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 233571461b0fSAlexey Kardashevskiy */ 233671461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 233771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 233871461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 233971461b0fSAlexey Kardashevskiy } else if (virtio) { 234071461b0fSAlexey Kardashevskiy /* 234171461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 234271461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 234371461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 234471461b0fSAlexey Kardashevskiy * the actual binding is: 234571461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 234671461b0fSAlexey Kardashevskiy */ 234771461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 234871461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 234971461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 235071461b0fSAlexey Kardashevskiy } else if (usb) { 235171461b0fSAlexey Kardashevskiy /* 235271461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 235371461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 235471461b0fSAlexey Kardashevskiy */ 235571461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 235671461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 235771461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 235871461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 235971461b0fSAlexey Kardashevskiy } 236071461b0fSAlexey Kardashevskiy } 236171461b0fSAlexey Kardashevskiy 2362b99260ebSThomas Huth /* 2363b99260ebSThomas Huth * SLOF probes the USB devices, and if it recognizes that the device is a 2364b99260ebSThomas Huth * storage device, it changes its name to "storage" instead of "usb-host", 2365b99260ebSThomas Huth * and additionally adds a child node for the SCSI LUN, so the correct 2366b99260ebSThomas Huth * boot path in SLOF is something like .../storage@1/disk@xxx" instead. 2367b99260ebSThomas Huth */ 2368b99260ebSThomas Huth if (strcmp("usb-host", qdev_fw_name(dev)) == 0) { 2369b99260ebSThomas Huth USBDevice *usbdev = CAST(USBDevice, dev, TYPE_USB_DEVICE); 2370b99260ebSThomas Huth if (usb_host_dev_is_scsi_storage(usbdev)) { 2371b99260ebSThomas Huth return g_strdup_printf("storage@%s/disk", usbdev->port->path); 2372b99260ebSThomas Huth } 2373b99260ebSThomas Huth } 2374b99260ebSThomas Huth 237571461b0fSAlexey Kardashevskiy if (phb) { 237671461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 237771461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 237871461b0fSAlexey Kardashevskiy } 237971461b0fSAlexey Kardashevskiy 238071461b0fSAlexey Kardashevskiy return NULL; 238171461b0fSAlexey Kardashevskiy } 238271461b0fSAlexey Kardashevskiy 238323825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 238423825581SEduardo Habkost { 238528e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 238623825581SEduardo Habkost 238728e02042SDavid Gibson return g_strdup(spapr->kvm_type); 238823825581SEduardo Habkost } 238923825581SEduardo Habkost 239023825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 239123825581SEduardo Habkost { 239228e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 239323825581SEduardo Habkost 239428e02042SDavid Gibson g_free(spapr->kvm_type); 239528e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 239623825581SEduardo Habkost } 239723825581SEduardo Habkost 2398f6229214SMichael Roth static bool spapr_get_modern_hotplug_events(Object *obj, Error **errp) 2399f6229214SMichael Roth { 2400f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2401f6229214SMichael Roth 2402f6229214SMichael Roth return spapr->use_hotplug_event_source; 2403f6229214SMichael Roth } 2404f6229214SMichael Roth 2405f6229214SMichael Roth static void spapr_set_modern_hotplug_events(Object *obj, bool value, 2406f6229214SMichael Roth Error **errp) 2407f6229214SMichael Roth { 2408f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2409f6229214SMichael Roth 2410f6229214SMichael Roth spapr->use_hotplug_event_source = value; 2411f6229214SMichael Roth } 2412f6229214SMichael Roth 241323825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 241423825581SEduardo Habkost { 2415715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2416715c5407SDavid Gibson 2417715c5407SDavid Gibson spapr->htab_fd = -1; 2418f6229214SMichael Roth spapr->use_hotplug_event_source = true; 241923825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 242023825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 242149d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 242249d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 242349d2e648SMarcel Apfelbaum NULL); 2424f6229214SMichael Roth object_property_add_bool(obj, "modern-hotplug-events", 2425f6229214SMichael Roth spapr_get_modern_hotplug_events, 2426f6229214SMichael Roth spapr_set_modern_hotplug_events, 2427f6229214SMichael Roth NULL); 2428f6229214SMichael Roth object_property_set_description(obj, "modern-hotplug-events", 2429f6229214SMichael Roth "Use dedicated hotplug event mechanism in" 2430f6229214SMichael Roth " place of standard EPOW events when possible" 2431f6229214SMichael Roth " (required for memory hot-unplug support)", 2432f6229214SMichael Roth NULL); 243323825581SEduardo Habkost } 243423825581SEduardo Habkost 243587bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 243687bbdd9cSDavid Gibson { 243787bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 243887bbdd9cSDavid Gibson 243987bbdd9cSDavid Gibson g_free(spapr->kvm_type); 244087bbdd9cSDavid Gibson } 244187bbdd9cSDavid Gibson 24421c7ad77eSNicholas Piggin void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg) 244334316482SAlexey Kardashevskiy { 244434316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 244534316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 244634316482SAlexey Kardashevskiy } 244734316482SAlexey Kardashevskiy 244834316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 244934316482SAlexey Kardashevskiy { 245034316482SAlexey Kardashevskiy CPUState *cs; 245134316482SAlexey Kardashevskiy 245234316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 24531c7ad77eSNicholas Piggin async_run_on_cpu(cs, spapr_do_system_reset_on_cpu, RUN_ON_CPU_NULL); 245434316482SAlexey Kardashevskiy } 245534316482SAlexey Kardashevskiy } 245634316482SAlexey Kardashevskiy 245779b78a6bSMichael Roth static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 245879b78a6bSMichael Roth uint32_t node, bool dedicated_hp_event_source, 245979b78a6bSMichael Roth Error **errp) 2460c20d332aSBharata B Rao { 2461c20d332aSBharata B Rao sPAPRDRConnector *drc; 2462c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2463c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2464c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2465c20d332aSBharata B Rao void *fdt; 246679b78a6bSMichael Roth uint64_t addr = addr_start; 2467c20d332aSBharata B Rao 2468c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2469c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2470c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2471c20d332aSBharata B Rao g_assert(drc); 2472c20d332aSBharata B Rao 2473c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2474c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2475c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2476c20d332aSBharata B Rao 2477c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2478c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2479c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 24805c0139a8SMichael Roth if (!dev->hotplugged) { 24815c0139a8SMichael Roth /* guests expect coldplugged LMBs to be pre-allocated */ 24825c0139a8SMichael Roth drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE); 24835c0139a8SMichael Roth drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED); 24845c0139a8SMichael Roth } 2485c20d332aSBharata B Rao } 24865dd5238cSJianjun Duan /* send hotplug notification to the 24875dd5238cSJianjun Duan * guest only in case of hotplugged memory 24885dd5238cSJianjun Duan */ 24895dd5238cSJianjun Duan if (dev->hotplugged) { 249079b78a6bSMichael Roth if (dedicated_hp_event_source) { 249179b78a6bSMichael Roth drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 249279b78a6bSMichael Roth addr_start / SPAPR_MEMORY_BLOCK_SIZE); 249379b78a6bSMichael Roth drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 249479b78a6bSMichael Roth spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 249579b78a6bSMichael Roth nr_lmbs, 249679b78a6bSMichael Roth drck->get_index(drc)); 249779b78a6bSMichael Roth } else { 249879b78a6bSMichael Roth spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, 249979b78a6bSMichael Roth nr_lmbs); 250079b78a6bSMichael Roth } 2501c20d332aSBharata B Rao } 25025dd5238cSJianjun Duan } 2503c20d332aSBharata B Rao 2504c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2505c20d332aSBharata B Rao uint32_t node, Error **errp) 2506c20d332aSBharata B Rao { 2507c20d332aSBharata B Rao Error *local_err = NULL; 2508c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2509c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2510c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2511c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2512c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2513c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2514c20d332aSBharata B Rao uint64_t addr; 2515df587133SThomas Huth char *mem_dev; 2516c20d332aSBharata B Rao 2517c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2518c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2519c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2520c20d332aSBharata B Rao goto out; 2521c20d332aSBharata B Rao } 2522c20d332aSBharata B Rao 2523df587133SThomas Huth mem_dev = object_property_get_str(OBJECT(dimm), PC_DIMM_MEMDEV_PROP, NULL); 2524df587133SThomas Huth if (mem_dev && !kvmppc_is_mem_backend_page_size_ok(mem_dev)) { 2525df587133SThomas Huth error_setg(&local_err, "Memory backend has bad page size. " 2526df587133SThomas Huth "Use 'memory-backend-file' with correct mem-path."); 2527df587133SThomas Huth goto out; 2528df587133SThomas Huth } 2529df587133SThomas Huth 2530d6a9b0b8SMichael S. Tsirkin pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 2531c20d332aSBharata B Rao if (local_err) { 2532c20d332aSBharata B Rao goto out; 2533c20d332aSBharata B Rao } 2534c20d332aSBharata B Rao 2535c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2536c20d332aSBharata B Rao if (local_err) { 2537c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2538c20d332aSBharata B Rao goto out; 2539c20d332aSBharata B Rao } 2540c20d332aSBharata B Rao 254179b78a6bSMichael Roth spapr_add_lmbs(dev, addr, size, node, 254279b78a6bSMichael Roth spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), 254379b78a6bSMichael Roth &error_abort); 2544c20d332aSBharata B Rao 2545c20d332aSBharata B Rao out: 2546c20d332aSBharata B Rao error_propagate(errp, local_err); 2547c20d332aSBharata B Rao } 2548c20d332aSBharata B Rao 2549cf632463SBharata B Rao typedef struct sPAPRDIMMState { 2550cf632463SBharata B Rao uint32_t nr_lmbs; 2551cf632463SBharata B Rao } sPAPRDIMMState; 2552cf632463SBharata B Rao 2553cf632463SBharata B Rao static void spapr_lmb_release(DeviceState *dev, void *opaque) 2554cf632463SBharata B Rao { 2555cf632463SBharata B Rao sPAPRDIMMState *ds = (sPAPRDIMMState *)opaque; 2556cf632463SBharata B Rao HotplugHandler *hotplug_ctrl; 2557cf632463SBharata B Rao 2558cf632463SBharata B Rao if (--ds->nr_lmbs) { 2559cf632463SBharata B Rao return; 2560cf632463SBharata B Rao } 2561cf632463SBharata B Rao 2562cf632463SBharata B Rao g_free(ds); 2563cf632463SBharata B Rao 2564cf632463SBharata B Rao /* 2565cf632463SBharata B Rao * Now that all the LMBs have been removed by the guest, call the 2566cf632463SBharata B Rao * pc-dimm unplug handler to cleanup up the pc-dimm device. 2567cf632463SBharata B Rao */ 2568cf632463SBharata B Rao hotplug_ctrl = qdev_get_hotplug_handler(dev); 2569cf632463SBharata B Rao hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 2570cf632463SBharata B Rao } 2571cf632463SBharata B Rao 2572cf632463SBharata B Rao static void spapr_del_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, 2573cf632463SBharata B Rao Error **errp) 2574cf632463SBharata B Rao { 2575cf632463SBharata B Rao sPAPRDRConnector *drc; 2576cf632463SBharata B Rao sPAPRDRConnectorClass *drck; 2577cf632463SBharata B Rao uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE; 2578cf632463SBharata B Rao int i; 2579cf632463SBharata B Rao sPAPRDIMMState *ds = g_malloc0(sizeof(sPAPRDIMMState)); 2580cf632463SBharata B Rao uint64_t addr = addr_start; 2581cf632463SBharata B Rao 2582cf632463SBharata B Rao ds->nr_lmbs = nr_lmbs; 2583cf632463SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2584cf632463SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2585cf632463SBharata B Rao addr / SPAPR_MEMORY_BLOCK_SIZE); 2586cf632463SBharata B Rao g_assert(drc); 2587cf632463SBharata B Rao 2588cf632463SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2589cf632463SBharata B Rao drck->detach(drc, dev, spapr_lmb_release, ds, errp); 2590cf632463SBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2591cf632463SBharata B Rao } 2592cf632463SBharata B Rao 2593cf632463SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2594cf632463SBharata B Rao addr_start / SPAPR_MEMORY_BLOCK_SIZE); 2595cf632463SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2596cf632463SBharata B Rao spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, 2597cf632463SBharata B Rao nr_lmbs, 2598cf632463SBharata B Rao drck->get_index(drc)); 2599cf632463SBharata B Rao } 2600cf632463SBharata B Rao 2601cf632463SBharata B Rao static void spapr_memory_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, 2602cf632463SBharata B Rao Error **errp) 2603cf632463SBharata B Rao { 2604cf632463SBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2605cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2606cf632463SBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2607cf632463SBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2608cf632463SBharata B Rao 2609cf632463SBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2610cf632463SBharata B Rao object_unparent(OBJECT(dev)); 2611cf632463SBharata B Rao } 2612cf632463SBharata B Rao 2613cf632463SBharata B Rao static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, 2614cf632463SBharata B Rao DeviceState *dev, Error **errp) 2615cf632463SBharata B Rao { 2616cf632463SBharata B Rao Error *local_err = NULL; 2617cf632463SBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2618cf632463SBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2619cf632463SBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2620cf632463SBharata B Rao uint64_t size = memory_region_size(mr); 2621cf632463SBharata B Rao uint64_t addr; 2622cf632463SBharata B Rao 2623cf632463SBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2624cf632463SBharata B Rao if (local_err) { 2625cf632463SBharata B Rao goto out; 2626cf632463SBharata B Rao } 2627cf632463SBharata B Rao 2628cf632463SBharata B Rao spapr_del_lmbs(dev, addr, size, &error_abort); 2629cf632463SBharata B Rao out: 2630cf632463SBharata B Rao error_propagate(errp, local_err); 2631cf632463SBharata B Rao } 2632cf632463SBharata B Rao 2633af81cf32SBharata B Rao void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, 2634af81cf32SBharata B Rao sPAPRMachineState *spapr) 2635af81cf32SBharata B Rao { 2636af81cf32SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 2637af81cf32SBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 2638af81cf32SBharata B Rao int id = ppc_get_vcpu_dt_id(cpu); 2639af81cf32SBharata B Rao void *fdt; 2640af81cf32SBharata B Rao int offset, fdt_size; 2641af81cf32SBharata B Rao char *nodename; 2642af81cf32SBharata B Rao 2643af81cf32SBharata B Rao fdt = create_device_tree(&fdt_size); 2644af81cf32SBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 2645af81cf32SBharata B Rao offset = fdt_add_subnode(fdt, 0, nodename); 2646af81cf32SBharata B Rao 2647af81cf32SBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 2648af81cf32SBharata B Rao g_free(nodename); 2649af81cf32SBharata B Rao 2650af81cf32SBharata B Rao *fdt_offset = offset; 2651af81cf32SBharata B Rao return fdt; 2652af81cf32SBharata B Rao } 2653af81cf32SBharata B Rao 2654115debf2SIgor Mammedov static void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, 2655115debf2SIgor Mammedov Error **errp) 2656ff9006ddSIgor Mammedov { 2657535455fdSIgor Mammedov MachineState *ms = MACHINE(qdev_get_machine()); 2658ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 2659535455fdSIgor Mammedov CPUArchId *core_slot = spapr_find_cpu_slot(ms, cc->core_id, NULL); 2660ff9006ddSIgor Mammedov 2661535455fdSIgor Mammedov core_slot->cpu = NULL; 2662ff9006ddSIgor Mammedov object_unparent(OBJECT(dev)); 2663ff9006ddSIgor Mammedov } 2664ff9006ddSIgor Mammedov 2665115debf2SIgor Mammedov static void spapr_core_release(DeviceState *dev, void *opaque) 2666115debf2SIgor Mammedov { 2667115debf2SIgor Mammedov HotplugHandler *hotplug_ctrl; 2668115debf2SIgor Mammedov 2669115debf2SIgor Mammedov hotplug_ctrl = qdev_get_hotplug_handler(dev); 2670115debf2SIgor Mammedov hotplug_handler_unplug(hotplug_ctrl, dev, &error_abort); 2671115debf2SIgor Mammedov } 2672115debf2SIgor Mammedov 2673115debf2SIgor Mammedov static 2674115debf2SIgor Mammedov void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, 2675ff9006ddSIgor Mammedov Error **errp) 2676ff9006ddSIgor Mammedov { 2677535455fdSIgor Mammedov int index; 2678535455fdSIgor Mammedov sPAPRDRConnector *drc; 2679ff9006ddSIgor Mammedov sPAPRDRConnectorClass *drck; 2680ff9006ddSIgor Mammedov Error *local_err = NULL; 2681535455fdSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 2682535455fdSIgor Mammedov int smt = kvmppc_smt_threads(); 2683ff9006ddSIgor Mammedov 2684535455fdSIgor Mammedov if (!spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index)) { 2685535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 2686535455fdSIgor Mammedov cc->core_id); 2687535455fdSIgor Mammedov return; 2688535455fdSIgor Mammedov } 2689ff9006ddSIgor Mammedov if (index == 0) { 2690ff9006ddSIgor Mammedov error_setg(errp, "Boot CPU core may not be unplugged"); 2691ff9006ddSIgor Mammedov return; 2692ff9006ddSIgor Mammedov } 2693ff9006ddSIgor Mammedov 2694535455fdSIgor Mammedov drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt); 2695ff9006ddSIgor Mammedov g_assert(drc); 2696ff9006ddSIgor Mammedov 2697ff9006ddSIgor Mammedov drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2698ff9006ddSIgor Mammedov drck->detach(drc, dev, spapr_core_release, NULL, &local_err); 2699ff9006ddSIgor Mammedov if (local_err) { 2700ff9006ddSIgor Mammedov error_propagate(errp, local_err); 2701ff9006ddSIgor Mammedov return; 2702ff9006ddSIgor Mammedov } 2703ff9006ddSIgor Mammedov 2704ff9006ddSIgor Mammedov spapr_hotplug_req_remove_by_index(drc); 2705ff9006ddSIgor Mammedov } 2706ff9006ddSIgor Mammedov 2707ff9006ddSIgor Mammedov static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2708ff9006ddSIgor Mammedov Error **errp) 2709ff9006ddSIgor Mammedov { 2710ff9006ddSIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); 2711ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(spapr); 2712ff9006ddSIgor Mammedov sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev)); 2713ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 2714ff9006ddSIgor Mammedov CPUState *cs = CPU(core->threads); 2715ff9006ddSIgor Mammedov sPAPRDRConnector *drc; 2716ff9006ddSIgor Mammedov Error *local_err = NULL; 2717ff9006ddSIgor Mammedov void *fdt = NULL; 2718ff9006ddSIgor Mammedov int fdt_offset = 0; 2719ff9006ddSIgor Mammedov int smt = kvmppc_smt_threads(); 2720535455fdSIgor Mammedov CPUArchId *core_slot; 2721535455fdSIgor Mammedov int index; 2722ff9006ddSIgor Mammedov 2723535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 2724535455fdSIgor Mammedov if (!core_slot) { 2725535455fdSIgor Mammedov error_setg(errp, "Unable to find CPU core with core-id: %d", 2726535455fdSIgor Mammedov cc->core_id); 2727535455fdSIgor Mammedov return; 2728535455fdSIgor Mammedov } 2729ff9006ddSIgor Mammedov drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt); 2730ff9006ddSIgor Mammedov 2731c5514d0eSIgor Mammedov g_assert(drc || !mc->has_hotpluggable_cpus); 2732ff9006ddSIgor Mammedov 2733ff9006ddSIgor Mammedov /* 2734ff9006ddSIgor Mammedov * Setup CPU DT entries only for hotplugged CPUs. For boot time or 2735ff9006ddSIgor Mammedov * coldplugged CPUs DT entries are setup in spapr_build_fdt(). 2736ff9006ddSIgor Mammedov */ 2737ff9006ddSIgor Mammedov if (dev->hotplugged) { 2738ff9006ddSIgor Mammedov fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr); 2739ff9006ddSIgor Mammedov } 2740ff9006ddSIgor Mammedov 2741ff9006ddSIgor Mammedov if (drc) { 2742ff9006ddSIgor Mammedov sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2743ff9006ddSIgor Mammedov drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, &local_err); 2744ff9006ddSIgor Mammedov if (local_err) { 2745ff9006ddSIgor Mammedov g_free(fdt); 2746ff9006ddSIgor Mammedov error_propagate(errp, local_err); 2747ff9006ddSIgor Mammedov return; 2748ff9006ddSIgor Mammedov } 2749ff9006ddSIgor Mammedov } 2750ff9006ddSIgor Mammedov 2751ff9006ddSIgor Mammedov if (dev->hotplugged) { 2752ff9006ddSIgor Mammedov /* 2753ff9006ddSIgor Mammedov * Send hotplug notification interrupt to the guest only in case 2754ff9006ddSIgor Mammedov * of hotplugged CPUs. 2755ff9006ddSIgor Mammedov */ 2756ff9006ddSIgor Mammedov spapr_hotplug_req_add_by_index(drc); 2757ff9006ddSIgor Mammedov } else { 2758ff9006ddSIgor Mammedov /* 2759ff9006ddSIgor Mammedov * Set the right DRC states for cold plugged CPU. 2760ff9006ddSIgor Mammedov */ 2761ff9006ddSIgor Mammedov if (drc) { 2762ff9006ddSIgor Mammedov sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2763ff9006ddSIgor Mammedov drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE); 2764ff9006ddSIgor Mammedov drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED); 2765ff9006ddSIgor Mammedov } 2766ff9006ddSIgor Mammedov } 2767535455fdSIgor Mammedov core_slot->cpu = OBJECT(dev); 2768ff9006ddSIgor Mammedov } 2769ff9006ddSIgor Mammedov 2770ff9006ddSIgor Mammedov static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2771ff9006ddSIgor Mammedov Error **errp) 2772ff9006ddSIgor Mammedov { 2773ff9006ddSIgor Mammedov MachineState *machine = MACHINE(OBJECT(hotplug_dev)); 2774ff9006ddSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); 2775ff9006ddSIgor Mammedov Error *local_err = NULL; 2776ff9006ddSIgor Mammedov CPUCore *cc = CPU_CORE(dev); 2777ff9006ddSIgor Mammedov char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model); 2778ff9006ddSIgor Mammedov const char *type = object_get_typename(OBJECT(dev)); 2779535455fdSIgor Mammedov CPUArchId *core_slot; 2780535455fdSIgor Mammedov int index; 2781ff9006ddSIgor Mammedov 2782c5514d0eSIgor Mammedov if (dev->hotplugged && !mc->has_hotpluggable_cpus) { 2783ff9006ddSIgor Mammedov error_setg(&local_err, "CPU hotplug not supported for this machine"); 2784ff9006ddSIgor Mammedov goto out; 2785ff9006ddSIgor Mammedov } 2786ff9006ddSIgor Mammedov 2787ff9006ddSIgor Mammedov if (strcmp(base_core_type, type)) { 2788ff9006ddSIgor Mammedov error_setg(&local_err, "CPU core type should be %s", base_core_type); 2789ff9006ddSIgor Mammedov goto out; 2790ff9006ddSIgor Mammedov } 2791ff9006ddSIgor Mammedov 2792ff9006ddSIgor Mammedov if (cc->core_id % smp_threads) { 2793ff9006ddSIgor Mammedov error_setg(&local_err, "invalid core id %d", cc->core_id); 2794ff9006ddSIgor Mammedov goto out; 2795ff9006ddSIgor Mammedov } 2796ff9006ddSIgor Mammedov 2797535455fdSIgor Mammedov core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, &index); 2798535455fdSIgor Mammedov if (!core_slot) { 2799ff9006ddSIgor Mammedov error_setg(&local_err, "core id %d out of range", cc->core_id); 2800ff9006ddSIgor Mammedov goto out; 2801ff9006ddSIgor Mammedov } 2802ff9006ddSIgor Mammedov 2803535455fdSIgor Mammedov if (core_slot->cpu) { 2804ff9006ddSIgor Mammedov error_setg(&local_err, "core %d already populated", cc->core_id); 2805ff9006ddSIgor Mammedov goto out; 2806ff9006ddSIgor Mammedov } 2807ff9006ddSIgor Mammedov 2808ff9006ddSIgor Mammedov out: 2809ff9006ddSIgor Mammedov g_free(base_core_type); 2810ff9006ddSIgor Mammedov error_propagate(errp, local_err); 2811ff9006ddSIgor Mammedov } 2812ff9006ddSIgor Mammedov 2813c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2814c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2815c20d332aSBharata B Rao { 2816c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2817c20d332aSBharata B Rao 2818c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2819b556854bSBharata B Rao int node; 2820c20d332aSBharata B Rao 2821c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2822c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2823c20d332aSBharata B Rao return; 2824c20d332aSBharata B Rao } 2825c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2826c20d332aSBharata B Rao if (*errp) { 2827c20d332aSBharata B Rao return; 2828c20d332aSBharata B Rao } 28291a5512bbSGonglei if (node < 0 || node >= MAX_NODES) { 28301a5512bbSGonglei error_setg(errp, "Invaild node %d", node); 28311a5512bbSGonglei return; 28321a5512bbSGonglei } 2833c20d332aSBharata B Rao 2834b556854bSBharata B Rao /* 2835b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2836b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2837b556854bSBharata B Rao * to the first node that has some memory. This causes two 2838b556854bSBharata B Rao * unexpected behaviours for the user. 2839b556854bSBharata B Rao * 2840b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2841b556854bSBharata B Rao * specified. 2842b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2843b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2844b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2845b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2846b556854bSBharata B Rao * 2847b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2848b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2849b556854bSBharata B Rao */ 2850b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2851b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2852b556854bSBharata B Rao node); 2853b556854bSBharata B Rao return; 2854b556854bSBharata B Rao } 2855b556854bSBharata B Rao 2856c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2857af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2858af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 2859c20d332aSBharata B Rao } 2860c20d332aSBharata B Rao } 2861c20d332aSBharata B Rao 2862c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2863c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2864c20d332aSBharata B Rao { 2865cf632463SBharata B Rao sPAPRMachineState *sms = SPAPR_MACHINE(qdev_get_machine()); 28663c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 28676f4b5c3eSBharata B Rao 2868c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2869cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 2870cf632463SBharata B Rao spapr_memory_unplug(hotplug_dev, dev, errp); 2871cf632463SBharata B Rao } else { 2872cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 2873cf632463SBharata B Rao } 2874cf632463SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2875c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 2876cf632463SBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 2877cf632463SBharata B Rao return; 2878cf632463SBharata B Rao } 2879cf632463SBharata B Rao spapr_core_unplug(hotplug_dev, dev, errp); 2880cf632463SBharata B Rao } 2881cf632463SBharata B Rao } 2882cf632463SBharata B Rao 2883cf632463SBharata B Rao static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev, 2884cf632463SBharata B Rao DeviceState *dev, Error **errp) 2885cf632463SBharata B Rao { 2886cf632463SBharata B Rao sPAPRMachineState *sms = SPAPR_MACHINE(qdev_get_machine()); 2887cf632463SBharata B Rao MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 2888cf632463SBharata B Rao 2889cf632463SBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2890cf632463SBharata B Rao if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) { 2891cf632463SBharata B Rao spapr_memory_unplug_request(hotplug_dev, dev, errp); 2892cf632463SBharata B Rao } else { 2893cf632463SBharata B Rao /* NOTE: this means there is a window after guest reset, prior to 2894cf632463SBharata B Rao * CAS negotiation, where unplug requests will fail due to the 2895cf632463SBharata B Rao * capability not being detected yet. This is a bit different than 2896cf632463SBharata B Rao * the case with PCI unplug, where the events will be queued and 2897cf632463SBharata B Rao * eventually handled by the guest after boot 2898cf632463SBharata B Rao */ 2899cf632463SBharata B Rao error_setg(errp, "Memory hot unplug not supported for this guest"); 2900cf632463SBharata B Rao } 29016f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2902c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 29036f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 29046f4b5c3eSBharata B Rao return; 29056f4b5c3eSBharata B Rao } 2906115debf2SIgor Mammedov spapr_core_unplug_request(hotplug_dev, dev, errp); 2907c20d332aSBharata B Rao } 2908c20d332aSBharata B Rao } 2909c20d332aSBharata B Rao 291094a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 291194a94e4cSBharata B Rao DeviceState *dev, Error **errp) 291294a94e4cSBharata B Rao { 291394a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 291494a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 291594a94e4cSBharata B Rao } 291694a94e4cSBharata B Rao } 291794a94e4cSBharata B Rao 29187ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 2919c20d332aSBharata B Rao DeviceState *dev) 2920c20d332aSBharata B Rao { 292194a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 292294a94e4cSBharata B Rao object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2923c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2924c20d332aSBharata B Rao } 2925c20d332aSBharata B Rao return NULL; 2926c20d332aSBharata B Rao } 2927c20d332aSBharata B Rao 292820bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) 292920bb648dSDavid Gibson { 293020bb648dSDavid Gibson /* Allocate to NUMA nodes on a "socket" basis (not that concept of 293120bb648dSDavid Gibson * socket means much for the paravirtualized PAPR platform) */ 293220bb648dSDavid Gibson return cpu_index / smp_threads / smp_cores; 293320bb648dSDavid Gibson } 293420bb648dSDavid Gibson 2935535455fdSIgor Mammedov static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) 2936535455fdSIgor Mammedov { 2937535455fdSIgor Mammedov int i; 2938535455fdSIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 2939535455fdSIgor Mammedov MachineClass *mc = MACHINE_GET_CLASS(machine); 2940535455fdSIgor Mammedov 2941c5514d0eSIgor Mammedov if (!mc->has_hotpluggable_cpus) { 2942535455fdSIgor Mammedov spapr_max_cores = QEMU_ALIGN_UP(smp_cpus, smp_threads) / smp_threads; 2943535455fdSIgor Mammedov } 2944535455fdSIgor Mammedov if (machine->possible_cpus) { 2945535455fdSIgor Mammedov assert(machine->possible_cpus->len == spapr_max_cores); 2946535455fdSIgor Mammedov return machine->possible_cpus; 2947535455fdSIgor Mammedov } 2948535455fdSIgor Mammedov 2949535455fdSIgor Mammedov machine->possible_cpus = g_malloc0(sizeof(CPUArchIdList) + 2950535455fdSIgor Mammedov sizeof(CPUArchId) * spapr_max_cores); 2951535455fdSIgor Mammedov machine->possible_cpus->len = spapr_max_cores; 2952535455fdSIgor Mammedov for (i = 0; i < machine->possible_cpus->len; i++) { 2953535455fdSIgor Mammedov int core_id = i * smp_threads; 2954535455fdSIgor Mammedov 2955f2d672c2SIgor Mammedov machine->possible_cpus->cpus[i].vcpus_count = smp_threads; 2956535455fdSIgor Mammedov machine->possible_cpus->cpus[i].arch_id = core_id; 2957535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.has_core_id = true; 2958535455fdSIgor Mammedov machine->possible_cpus->cpus[i].props.core_id = core_id; 2959535455fdSIgor Mammedov /* TODO: add 'has_node/node' here to describe 2960535455fdSIgor Mammedov to which node core belongs */ 2961535455fdSIgor Mammedov } 2962535455fdSIgor Mammedov return machine->possible_cpus; 2963535455fdSIgor Mammedov } 2964535455fdSIgor Mammedov 29656737d9adSDavid Gibson static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, 2966daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 2967daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 29686737d9adSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 29696737d9adSDavid Gibson { 2970357d1e3bSDavid Gibson /* 2971357d1e3bSDavid Gibson * New-style PHB window placement. 2972357d1e3bSDavid Gibson * 2973357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 2974357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 2975357d1e3bSDavid Gibson * windows. 2976357d1e3bSDavid Gibson * 2977357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 2978357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 2979357d1e3bSDavid Gibson * 2980357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 2981357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 2982357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 2983357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 2984357d1e3bSDavid Gibson */ 29856737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 298625e6a118SMichael S. Tsirkin #define SPAPR_MAX_PHBS ((SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / \ 298725e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE - 1) 29886737d9adSDavid Gibson int i; 29896737d9adSDavid Gibson 2990357d1e3bSDavid Gibson /* Sanity check natural alignments */ 2991357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 2992357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 2993357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 2994357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 2995357d1e3bSDavid Gibson /* Sanity check bounds */ 299625e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_IO_WIN_SIZE) > 299725e6a118SMichael S. Tsirkin SPAPR_PCI_MEM32_WIN_SIZE); 299825e6a118SMichael S. Tsirkin QEMU_BUILD_BUG_ON((SPAPR_MAX_PHBS * SPAPR_PCI_MEM32_WIN_SIZE) > 299925e6a118SMichael S. Tsirkin SPAPR_PCI_MEM64_WIN_SIZE); 30002efff1c0SDavid Gibson 300125e6a118SMichael S. Tsirkin if (index >= SPAPR_MAX_PHBS) { 300225e6a118SMichael S. Tsirkin error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", 300325e6a118SMichael S. Tsirkin SPAPR_MAX_PHBS - 1); 30046737d9adSDavid Gibson return; 30056737d9adSDavid Gibson } 30066737d9adSDavid Gibson 30076737d9adSDavid Gibson *buid = base_buid + index; 30086737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 30096737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 30106737d9adSDavid Gibson } 30116737d9adSDavid Gibson 3012357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 3013357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 3014357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 30156737d9adSDavid Gibson } 30166737d9adSDavid Gibson 30177844e12bSCédric Le Goater static ICSState *spapr_ics_get(XICSFabric *dev, int irq) 30187844e12bSCédric Le Goater { 30197844e12bSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(dev); 30207844e12bSCédric Le Goater 30217844e12bSCédric Le Goater return ics_valid_irq(spapr->ics, irq) ? spapr->ics : NULL; 30227844e12bSCédric Le Goater } 30237844e12bSCédric Le Goater 30247844e12bSCédric Le Goater static void spapr_ics_resend(XICSFabric *dev) 30257844e12bSCédric Le Goater { 30267844e12bSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(dev); 30277844e12bSCédric Le Goater 30287844e12bSCédric Le Goater ics_resend(spapr->ics); 30297844e12bSCédric Le Goater } 30307844e12bSCédric Le Goater 3031b2fc59aaSCédric Le Goater static ICPState *spapr_icp_get(XICSFabric *xi, int server) 3032b2fc59aaSCédric Le Goater { 3033b2fc59aaSCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(xi); 3034b2fc59aaSCédric Le Goater 3035852ad27eSCédric Le Goater return (server < spapr->nr_servers) ? &spapr->icps[server] : NULL; 3036b2fc59aaSCédric Le Goater } 3037b2fc59aaSCédric Le Goater 30386449da45SCédric Le Goater static void spapr_pic_print_info(InterruptStatsProvider *obj, 30396449da45SCédric Le Goater Monitor *mon) 30406449da45SCédric Le Goater { 30416449da45SCédric Le Goater sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 30426449da45SCédric Le Goater int i; 30436449da45SCédric Le Goater 30446449da45SCédric Le Goater for (i = 0; i < spapr->nr_servers; i++) { 30456449da45SCédric Le Goater icp_pic_print_info(&spapr->icps[i], mon); 30466449da45SCédric Le Goater } 30476449da45SCédric Le Goater 30486449da45SCédric Le Goater ics_pic_print_info(spapr->ics, mon); 30496449da45SCédric Le Goater } 30506449da45SCédric Le Goater 305129ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 305253018216SPaolo Bonzini { 305329ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 3054224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 305571461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 305634316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 3057c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 30581d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = PPC_VIRTUAL_HYPERVISOR_CLASS(oc); 30597844e12bSCédric Le Goater XICSFabricClass *xic = XICS_FABRIC_CLASS(oc); 30606449da45SCédric Le Goater InterruptStatsProviderClass *ispc = INTERRUPT_STATS_PROVIDER_CLASS(oc); 306129ee3247SAlexey Kardashevskiy 30620eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 3063fc9f38c3SDavid Gibson 3064fc9f38c3SDavid Gibson /* 3065fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 3066fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 3067fc9f38c3SDavid Gibson * these details for backwards compatibility 3068fc9f38c3SDavid Gibson */ 3069958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 3070958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 3071958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 30726244bb7eSGreg Kurz mc->max_cpus = 1024; 3073958db90cSMarcel Apfelbaum mc->no_parallel = 1; 30745b2128d2SAlexander Graf mc->default_boot_order = ""; 3075a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 3076958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 30779e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 3078e4024630SLaurent Vivier mc->pci_allow_0_address = true; 30797ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 308094a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 3081c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 3082c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 308320bb648dSDavid Gibson mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; 3084535455fdSIgor Mammedov mc->possible_cpu_arch_ids = spapr_possible_cpu_arch_ids; 3085cf632463SBharata B Rao hc->unplug_request = spapr_machine_device_unplug_request; 308600b4fbe2SMarcel Apfelbaum 3087fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 30883daa4a9fSThomas Huth smc->tcg_default_cpu = "POWER8"; 3089c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = true; 309071461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 309134316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 30926737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 30931d1be34dSDavid Gibson vhc->hypercall = emulate_spapr_hypercall; 3094e57ca75cSDavid Gibson vhc->hpt_mask = spapr_hpt_mask; 3095e57ca75cSDavid Gibson vhc->map_hptes = spapr_map_hptes; 3096e57ca75cSDavid Gibson vhc->unmap_hptes = spapr_unmap_hptes; 3097e57ca75cSDavid Gibson vhc->store_hpte = spapr_store_hpte; 30989861bb3eSSuraj Jitindar Singh vhc->get_patbe = spapr_get_patbe; 30997844e12bSCédric Le Goater xic->ics_get = spapr_ics_get; 31007844e12bSCédric Le Goater xic->ics_resend = spapr_ics_resend; 3101b2fc59aaSCédric Le Goater xic->icp_get = spapr_icp_get; 31026449da45SCédric Le Goater ispc->print_info = spapr_pic_print_info; 310353018216SPaolo Bonzini } 310453018216SPaolo Bonzini 310529ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 310629ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 310729ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 31084aee7362SDavid Gibson .abstract = true, 31096ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 311023825581SEduardo Habkost .instance_init = spapr_machine_initfn, 311187bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 3112183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 311329ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 311471461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 311571461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 311634316482SAlexey Kardashevskiy { TYPE_NMI }, 3117c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 31181d1be34dSDavid Gibson { TYPE_PPC_VIRTUAL_HYPERVISOR }, 31197844e12bSCédric Le Goater { TYPE_XICS_FABRIC }, 31206449da45SCédric Le Goater { TYPE_INTERRUPT_STATS_PROVIDER }, 312171461b0fSAlexey Kardashevskiy { } 312271461b0fSAlexey Kardashevskiy }, 312329ee3247SAlexey Kardashevskiy }; 312429ee3247SAlexey Kardashevskiy 3125fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 31265013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 31275013c547SDavid Gibson void *data) \ 31285013c547SDavid Gibson { \ 31295013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 31305013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 3131fccbc785SDavid Gibson if (latest) { \ 3132fccbc785SDavid Gibson mc->alias = "pseries"; \ 3133fccbc785SDavid Gibson mc->is_default = 1; \ 3134fccbc785SDavid Gibson } \ 31355013c547SDavid Gibson } \ 31365013c547SDavid Gibson static void spapr_machine_##suffix##_instance_init(Object *obj) \ 31375013c547SDavid Gibson { \ 31385013c547SDavid Gibson MachineState *machine = MACHINE(obj); \ 31395013c547SDavid Gibson spapr_machine_##suffix##_instance_options(machine); \ 31405013c547SDavid Gibson } \ 31415013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 31425013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 31435013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 31445013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 31455013c547SDavid Gibson .instance_init = spapr_machine_##suffix##_instance_init, \ 31465013c547SDavid Gibson }; \ 31475013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 31485013c547SDavid Gibson { \ 31495013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 31505013c547SDavid Gibson } \ 31510e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 31525013c547SDavid Gibson 31531c5f29bbSDavid Gibson /* 3154fa325e6cSDavid Gibson * pseries-2.9 3155db800b21SDavid Gibson */ 3156fa325e6cSDavid Gibson static void spapr_machine_2_9_instance_options(MachineState *machine) 3157db800b21SDavid Gibson { 3158db800b21SDavid Gibson } 3159db800b21SDavid Gibson 3160fa325e6cSDavid Gibson static void spapr_machine_2_9_class_options(MachineClass *mc) 3161db800b21SDavid Gibson { 3162db800b21SDavid Gibson /* Defaults for the latest behaviour inherited from the base class */ 3163db800b21SDavid Gibson } 3164db800b21SDavid Gibson 3165fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_9, "2.9", true); 3166fa325e6cSDavid Gibson 3167fa325e6cSDavid Gibson /* 3168fa325e6cSDavid Gibson * pseries-2.8 3169fa325e6cSDavid Gibson */ 3170fa325e6cSDavid Gibson #define SPAPR_COMPAT_2_8 \ 3171fa325e6cSDavid Gibson HW_COMPAT_2_8 3172fa325e6cSDavid Gibson 3173fa325e6cSDavid Gibson static void spapr_machine_2_8_instance_options(MachineState *machine) 3174fa325e6cSDavid Gibson { 3175fa325e6cSDavid Gibson spapr_machine_2_9_instance_options(machine); 3176fa325e6cSDavid Gibson } 3177fa325e6cSDavid Gibson 3178fa325e6cSDavid Gibson static void spapr_machine_2_8_class_options(MachineClass *mc) 3179fa325e6cSDavid Gibson { 3180fa325e6cSDavid Gibson spapr_machine_2_9_class_options(mc); 3181fa325e6cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_8); 3182fa325e6cSDavid Gibson } 3183fa325e6cSDavid Gibson 3184fa325e6cSDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", false); 3185db800b21SDavid Gibson 3186db800b21SDavid Gibson /* 31871ea1eefcSBharata B Rao * pseries-2.7 31881ea1eefcSBharata B Rao */ 3189db800b21SDavid Gibson #define SPAPR_COMPAT_2_7 \ 3190db800b21SDavid Gibson HW_COMPAT_2_7 \ 3191357d1e3bSDavid Gibson { \ 3192357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 3193357d1e3bSDavid Gibson .property = "mem_win_size", \ 3194357d1e3bSDavid Gibson .value = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\ 3195357d1e3bSDavid Gibson }, \ 3196357d1e3bSDavid Gibson { \ 3197357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 3198357d1e3bSDavid Gibson .property = "mem64_win_size", \ 3199357d1e3bSDavid Gibson .value = "0", \ 3200146c11f1SDavid Gibson }, \ 3201146c11f1SDavid Gibson { \ 3202146c11f1SDavid Gibson .driver = TYPE_POWERPC_CPU, \ 3203146c11f1SDavid Gibson .property = "pre-2.8-migration", \ 3204146c11f1SDavid Gibson .value = "on", \ 32055c4537bdSDavid Gibson }, \ 32065c4537bdSDavid Gibson { \ 32075c4537bdSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 32085c4537bdSDavid Gibson .property = "pre-2.8-migration", \ 32095c4537bdSDavid Gibson .value = "on", \ 3210357d1e3bSDavid Gibson }, 3211357d1e3bSDavid Gibson 3212357d1e3bSDavid Gibson static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, 3213357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 3214357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 3215357d1e3bSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 3216357d1e3bSDavid Gibson { 3217357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 3218357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 3219357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 3220357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 3221357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 3222357d1e3bSDavid Gibson const uint32_t max_index = 255; 3223357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 3224357d1e3bSDavid Gibson 3225357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 3226357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 3227357d1e3bSDavid Gibson int i; 3228357d1e3bSDavid Gibson 3229357d1e3bSDavid Gibson /* Do we have hotpluggable memory? */ 3230357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 3231357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 3232357d1e3bSDavid Gibson * alignment gap between normal and hotpluggable memory 3233357d1e3bSDavid Gibson * regions */ 3234357d1e3bSDavid Gibson ram_top = spapr->hotplug_memory.base + 3235357d1e3bSDavid Gibson memory_region_size(&spapr->hotplug_memory.mr); 3236357d1e3bSDavid Gibson } 3237357d1e3bSDavid Gibson 3238357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 3239357d1e3bSDavid Gibson 3240357d1e3bSDavid Gibson if (index > max_index) { 3241357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 3242357d1e3bSDavid Gibson max_index); 3243357d1e3bSDavid Gibson return; 3244357d1e3bSDavid Gibson } 3245357d1e3bSDavid Gibson 3246357d1e3bSDavid Gibson *buid = base_buid + index; 3247357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 3248357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 3249357d1e3bSDavid Gibson } 3250357d1e3bSDavid Gibson 3251357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 3252357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 3253357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 3254357d1e3bSDavid Gibson /* 3255357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 3256357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 3257357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 3258357d1e3bSDavid Gibson */ 3259357d1e3bSDavid Gibson } 3260db800b21SDavid Gibson 32611ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine) 32621ea1eefcSBharata B Rao { 3263f6229214SMichael Roth sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 3264f6229214SMichael Roth 3265672de881SMichael Roth spapr_machine_2_8_instance_options(machine); 3266f6229214SMichael Roth spapr->use_hotplug_event_source = false; 32671ea1eefcSBharata B Rao } 32681ea1eefcSBharata B Rao 32691ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 32701ea1eefcSBharata B Rao { 32713daa4a9fSThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 32723daa4a9fSThomas Huth 3273db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 32743daa4a9fSThomas Huth smc->tcg_default_cpu = "POWER7"; 3275db800b21SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7); 3276357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 32771ea1eefcSBharata B Rao } 32781ea1eefcSBharata B Rao 3279db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 32801ea1eefcSBharata B Rao 32811ea1eefcSBharata B Rao /* 32824b23699cSDavid Gibson * pseries-2.6 32834b23699cSDavid Gibson */ 32841ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \ 3285ae4de14cSAlexey Kardashevskiy HW_COMPAT_2_6 \ 3286ae4de14cSAlexey Kardashevskiy { \ 3287ae4de14cSAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 3288ae4de14cSAlexey Kardashevskiy .property = "ddw",\ 3289ae4de14cSAlexey Kardashevskiy .value = stringify(off),\ 3290ae4de14cSAlexey Kardashevskiy }, 32911ea1eefcSBharata B Rao 32924b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine) 32934b23699cSDavid Gibson { 3294672de881SMichael Roth spapr_machine_2_7_instance_options(machine); 32954b23699cSDavid Gibson } 32964b23699cSDavid Gibson 32974b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc) 32984b23699cSDavid Gibson { 32991ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 3300c5514d0eSIgor Mammedov mc->has_hotpluggable_cpus = false; 33011ea1eefcSBharata B Rao SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); 33024b23699cSDavid Gibson } 33034b23699cSDavid Gibson 33041ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 33054b23699cSDavid Gibson 33064b23699cSDavid Gibson /* 33071c5f29bbSDavid Gibson * pseries-2.5 33081c5f29bbSDavid Gibson */ 33094b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \ 331057c522f4SThomas Huth HW_COMPAT_2_5 \ 331157c522f4SThomas Huth { \ 331257c522f4SThomas Huth .driver = "spapr-vlan", \ 331357c522f4SThomas Huth .property = "use-rx-buffer-pools", \ 331457c522f4SThomas Huth .value = "off", \ 331557c522f4SThomas Huth }, 33164b23699cSDavid Gibson 33175013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine) 33181c5f29bbSDavid Gibson { 3319672de881SMichael Roth spapr_machine_2_6_instance_options(machine); 33205013c547SDavid Gibson } 33215013c547SDavid Gibson 33225013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc) 33235013c547SDavid Gibson { 332457040d45SThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 332557040d45SThomas Huth 33264b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 332757040d45SThomas Huth smc->use_ohci_by_default = true; 33284b23699cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5); 33291c5f29bbSDavid Gibson } 33301c5f29bbSDavid Gibson 33314b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 33321c5f29bbSDavid Gibson 33331c5f29bbSDavid Gibson /* 33341c5f29bbSDavid Gibson * pseries-2.4 33351c5f29bbSDavid Gibson */ 333680fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \ 333780fd50f9SCornelia Huck HW_COMPAT_2_4 333880fd50f9SCornelia Huck 33395013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine) 33401c5f29bbSDavid Gibson { 33415013c547SDavid Gibson spapr_machine_2_5_instance_options(machine); 33425013c547SDavid Gibson } 33431c5f29bbSDavid Gibson 33445013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 33455013c547SDavid Gibson { 3346fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 3347fc9f38c3SDavid Gibson 3348fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 3349fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 3350f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4); 33511c5f29bbSDavid Gibson } 33521c5f29bbSDavid Gibson 3353fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 33541c5f29bbSDavid Gibson 33551c5f29bbSDavid Gibson /* 33561c5f29bbSDavid Gibson * pseries-2.3 33571c5f29bbSDavid Gibson */ 335838ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 33597619c7b0SMichael Roth HW_COMPAT_2_3 \ 33607619c7b0SMichael Roth {\ 33617619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 33627619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 33637619c7b0SMichael Roth .value = "off",\ 33647619c7b0SMichael Roth }, 336538ff32c6SEduardo Habkost 33665013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine) 33671c5f29bbSDavid Gibson { 33685013c547SDavid Gibson spapr_machine_2_4_instance_options(machine); 33691c5f29bbSDavid Gibson savevm_skip_section_footers(); 33701c5f29bbSDavid Gibson global_state_set_optional(); 337109b5e30dSGreg Kurz savevm_skip_configuration(); 33721c5f29bbSDavid Gibson } 33731c5f29bbSDavid Gibson 33745013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc) 33751c5f29bbSDavid Gibson { 3376fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 3377f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3); 33781c5f29bbSDavid Gibson } 3379fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 33801c5f29bbSDavid Gibson 33811c5f29bbSDavid Gibson /* 33821c5f29bbSDavid Gibson * pseries-2.2 33831c5f29bbSDavid Gibson */ 33841c5f29bbSDavid Gibson 3385b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 33864dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 3387b194df47SAlexey Kardashevskiy {\ 3388b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 3389b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 3390b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 3391dd754bafSEduardo Habkost }, 3392b194df47SAlexey Kardashevskiy 33935013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine) 3394b0e966d0SJason Wang { 33955013c547SDavid Gibson spapr_machine_2_3_instance_options(machine); 3396cba0e779SGreg Kurz machine->suppress_vmdesc = true; 3397b0e966d0SJason Wang } 3398b0e966d0SJason Wang 33995013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc) 3400b0e966d0SJason Wang { 3401fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 3402f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2); 34031c5f29bbSDavid Gibson } 3404fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 34051c5f29bbSDavid Gibson 34061c5f29bbSDavid Gibson /* 34071c5f29bbSDavid Gibson * pseries-2.1 34081c5f29bbSDavid Gibson */ 34091c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \ 34101c5f29bbSDavid Gibson HW_COMPAT_2_1 34111c5f29bbSDavid Gibson 34125013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine) 34131c5f29bbSDavid Gibson { 34145013c547SDavid Gibson spapr_machine_2_2_instance_options(machine); 34151c5f29bbSDavid Gibson } 34161c5f29bbSDavid Gibson 34175013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 3418b0e966d0SJason Wang { 3419fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 3420f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1); 34216026db45SAlexey Kardashevskiy } 3422fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 34236026db45SAlexey Kardashevskiy 342429ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 342529ee3247SAlexey Kardashevskiy { 342629ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 342729ee3247SAlexey Kardashevskiy } 342829ee3247SAlexey Kardashevskiy 342929ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 3430