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