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" 40c20d332aSBharata B Rao #include "sysemu/device_tree.h" 4153018216SPaolo Bonzini #include "kvm_ppc.h" 42ff14e817SDr. David Alan Gilbert #include "migration/migration.h" 434be21d56SDavid Gibson #include "mmu-hash64.h" 443794d548SAlexey Kardashevskiy #include "qom/cpu.h" 4553018216SPaolo Bonzini 4653018216SPaolo Bonzini #include "hw/boards.h" 470d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 4853018216SPaolo Bonzini #include "hw/loader.h" 4953018216SPaolo Bonzini 507804c353SCédric Le Goater #include "hw/ppc/fdt.h" 510d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 520d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 530d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 540d09e41aSPaolo Bonzini #include "hw/ppc/xics.h" 5553018216SPaolo Bonzini #include "hw/pci/msi.h" 5653018216SPaolo Bonzini 5753018216SPaolo Bonzini #include "hw/pci/pci.h" 5871461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 5971461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 6053018216SPaolo Bonzini 6153018216SPaolo Bonzini #include "exec/address-spaces.h" 6253018216SPaolo Bonzini #include "hw/usb.h" 6353018216SPaolo Bonzini #include "qemu/config-file.h" 64135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 652a6593cbSAlexey Kardashevskiy #include "trace.h" 6634316482SAlexey Kardashevskiy #include "hw/nmi.h" 6753018216SPaolo Bonzini 6868a27b20SMichael S. Tsirkin #include "hw/compat.h" 69f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 7094a94e4cSBharata B Rao #include "hw/ppc/spapr_cpu_core.h" 712474bfd4SIgor Mammedov #include "qmp-commands.h" 7268a27b20SMichael S. Tsirkin 7353018216SPaolo Bonzini #include <libfdt.h> 7453018216SPaolo Bonzini 7553018216SPaolo Bonzini /* SLOF memory layout: 7653018216SPaolo Bonzini * 7753018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 7853018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 7953018216SPaolo Bonzini * 8053018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 8153018216SPaolo Bonzini * and more 8253018216SPaolo Bonzini * 8353018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 8453018216SPaolo Bonzini */ 8538b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 8653018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 87b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 8853018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 8953018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 9053018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 9153018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 9253018216SPaolo Bonzini 9353018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 9453018216SPaolo Bonzini 9553018216SPaolo Bonzini #define PHANDLE_XICP 0x00001111 9653018216SPaolo Bonzini 9753018216SPaolo Bonzini #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) 9853018216SPaolo Bonzini 99c04d6cfaSAnthony Liguori static XICSState *try_create_xics(const char *type, int nr_servers, 10034f2af3dSMarkus Armbruster int nr_irqs, Error **errp) 101c04d6cfaSAnthony Liguori { 10234f2af3dSMarkus Armbruster Error *err = NULL; 103c04d6cfaSAnthony Liguori DeviceState *dev; 104c04d6cfaSAnthony Liguori 105c04d6cfaSAnthony Liguori dev = qdev_create(NULL, type); 106c04d6cfaSAnthony Liguori qdev_prop_set_uint32(dev, "nr_servers", nr_servers); 107c04d6cfaSAnthony Liguori qdev_prop_set_uint32(dev, "nr_irqs", nr_irqs); 10834f2af3dSMarkus Armbruster object_property_set_bool(OBJECT(dev), true, "realized", &err); 10934f2af3dSMarkus Armbruster if (err) { 11034f2af3dSMarkus Armbruster error_propagate(errp, err); 11134f2af3dSMarkus Armbruster object_unparent(OBJECT(dev)); 112c04d6cfaSAnthony Liguori return NULL; 113c04d6cfaSAnthony Liguori } 1145a3d7b23SAlexey Kardashevskiy return XICS_COMMON(dev); 115c04d6cfaSAnthony Liguori } 116c04d6cfaSAnthony Liguori 117446f16a6SMarcel Apfelbaum static XICSState *xics_system_init(MachineState *machine, 1181e49182dSDavid Gibson int nr_servers, int nr_irqs, Error **errp) 119c04d6cfaSAnthony Liguori { 12027f24582SBenjamin Herrenschmidt XICSState *xics = NULL; 121c04d6cfaSAnthony Liguori 12211ad93f6SDavid Gibson if (kvm_enabled()) { 12334f2af3dSMarkus Armbruster Error *err = NULL; 12434f2af3dSMarkus Armbruster 125446f16a6SMarcel Apfelbaum if (machine_kernel_irqchip_allowed(machine)) { 12627f24582SBenjamin Herrenschmidt xics = try_create_xics(TYPE_XICS_SPAPR_KVM, nr_servers, nr_irqs, 127161deaf2SBenjamin Herrenschmidt &err); 12811ad93f6SDavid Gibson } 12927f24582SBenjamin Herrenschmidt if (machine_kernel_irqchip_required(machine) && !xics) { 130b83baa60SMarkus Armbruster error_reportf_err(err, 131b83baa60SMarkus Armbruster "kernel_irqchip requested but unavailable: "); 132b83baa60SMarkus Armbruster } else { 133903a41d3SStefano Dong (董兴水) error_free(err); 13411ad93f6SDavid Gibson } 135b83baa60SMarkus Armbruster } 13611ad93f6SDavid Gibson 13727f24582SBenjamin Herrenschmidt if (!xics) { 13827f24582SBenjamin Herrenschmidt xics = try_create_xics(TYPE_XICS_SPAPR, nr_servers, nr_irqs, errp); 139c04d6cfaSAnthony Liguori } 140c04d6cfaSAnthony Liguori 14127f24582SBenjamin Herrenschmidt return xics; 142c04d6cfaSAnthony Liguori } 143c04d6cfaSAnthony Liguori 144833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 145833d4668SAlexey Kardashevskiy int smt_threads) 146833d4668SAlexey Kardashevskiy { 147833d4668SAlexey Kardashevskiy int i, ret = 0; 148833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 149833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 150833d4668SAlexey Kardashevskiy int index = ppc_get_vcpu_dt_id(cpu); 151833d4668SAlexey Kardashevskiy 1526d9412eaSAlexey Kardashevskiy if (cpu->cpu_version) { 1534bce526eSLaurent Dufour ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->cpu_version); 1546d9412eaSAlexey Kardashevskiy if (ret < 0) { 1556d9412eaSAlexey Kardashevskiy return ret; 1566d9412eaSAlexey Kardashevskiy } 1576d9412eaSAlexey Kardashevskiy } 1586d9412eaSAlexey Kardashevskiy 159833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 160833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 161833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 162833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 163833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 164833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 165833d4668SAlexey Kardashevskiy } 166833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 167833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 168833d4668SAlexey Kardashevskiy if (ret < 0) { 169833d4668SAlexey Kardashevskiy return ret; 170833d4668SAlexey Kardashevskiy } 171833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 172833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 173833d4668SAlexey Kardashevskiy 174833d4668SAlexey Kardashevskiy return ret; 175833d4668SAlexey Kardashevskiy } 176833d4668SAlexey Kardashevskiy 1770da6f3feSBharata B Rao static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, CPUState *cs) 1780da6f3feSBharata B Rao { 1790da6f3feSBharata B Rao int ret = 0; 1800da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 1810da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 1820da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 1830da6f3feSBharata B Rao cpu_to_be32(0x0), 1840da6f3feSBharata B Rao cpu_to_be32(0x0), 1850da6f3feSBharata B Rao cpu_to_be32(0x0), 1860da6f3feSBharata B Rao cpu_to_be32(cs->numa_node), 1870da6f3feSBharata B Rao cpu_to_be32(index)}; 1880da6f3feSBharata B Rao 1890da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 1900da6f3feSBharata B Rao if (nb_numa_nodes > 1) { 1910da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, 1920da6f3feSBharata B Rao sizeof(associativity)); 1930da6f3feSBharata B Rao } 1940da6f3feSBharata B Rao 1950da6f3feSBharata B Rao return ret; 1960da6f3feSBharata B Rao } 1970da6f3feSBharata B Rao 19828e02042SDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) 19953018216SPaolo Bonzini { 20082677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 20182677ed2SAlexey Kardashevskiy CPUState *cs; 20253018216SPaolo Bonzini char cpu_model[32]; 20353018216SPaolo Bonzini int smt = kvmppc_smt_threads(); 20453018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 20553018216SPaolo Bonzini 20682677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 20782677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 20882677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 20982677ed2SAlexey Kardashevskiy int index = ppc_get_vcpu_dt_id(cpu); 21053018216SPaolo Bonzini 2110f20ba62SAlexey Kardashevskiy if ((index % smt) != 0) { 21253018216SPaolo Bonzini continue; 21353018216SPaolo Bonzini } 21453018216SPaolo Bonzini 21582677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 21653018216SPaolo Bonzini 21782677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 21882677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 21982677ed2SAlexey Kardashevskiy cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), 22082677ed2SAlexey Kardashevskiy "cpus"); 22182677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 22282677ed2SAlexey Kardashevskiy return cpus_offset; 22382677ed2SAlexey Kardashevskiy } 22482677ed2SAlexey Kardashevskiy } 22582677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 22682677ed2SAlexey Kardashevskiy if (offset < 0) { 22782677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 22853018216SPaolo Bonzini if (offset < 0) { 22953018216SPaolo Bonzini return offset; 23053018216SPaolo Bonzini } 23182677ed2SAlexey Kardashevskiy } 23253018216SPaolo Bonzini 2330da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 2340da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 23553018216SPaolo Bonzini if (ret < 0) { 23653018216SPaolo Bonzini return ret; 23753018216SPaolo Bonzini } 23853018216SPaolo Bonzini 2390da6f3feSBharata B Rao ret = spapr_fixup_cpu_numa_dt(fdt, offset, cs); 24053018216SPaolo Bonzini if (ret < 0) { 24153018216SPaolo Bonzini return ret; 24253018216SPaolo Bonzini } 243833d4668SAlexey Kardashevskiy 24482677ed2SAlexey Kardashevskiy ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 2452a48d993SAlexey Kardashevskiy ppc_get_compat_smt_threads(cpu)); 246833d4668SAlexey Kardashevskiy if (ret < 0) { 247833d4668SAlexey Kardashevskiy return ret; 248833d4668SAlexey Kardashevskiy } 24953018216SPaolo Bonzini } 25053018216SPaolo Bonzini return ret; 25153018216SPaolo Bonzini } 25253018216SPaolo Bonzini 253b082d65aSAlexey Kardashevskiy static hwaddr spapr_node0_size(void) 254b082d65aSAlexey Kardashevskiy { 255fb164994SDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 256fb164994SDavid Gibson 257b082d65aSAlexey Kardashevskiy if (nb_numa_nodes) { 258b082d65aSAlexey Kardashevskiy int i; 259b082d65aSAlexey Kardashevskiy for (i = 0; i < nb_numa_nodes; ++i) { 260b082d65aSAlexey Kardashevskiy if (numa_info[i].node_mem) { 261fb164994SDavid Gibson return MIN(pow2floor(numa_info[i].node_mem), 262fb164994SDavid Gibson machine->ram_size); 263b082d65aSAlexey Kardashevskiy } 264b082d65aSAlexey Kardashevskiy } 265b082d65aSAlexey Kardashevskiy } 266fb164994SDavid Gibson return machine->ram_size; 267b082d65aSAlexey Kardashevskiy } 268b082d65aSAlexey Kardashevskiy 269a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 270a1d59c0fSAlexey Kardashevskiy { 271a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 272a1d59c0fSAlexey Kardashevskiy } 27353018216SPaolo Bonzini 2743bbf37f2SAndreas Färber static void *spapr_create_fdt_skel(hwaddr initrd_base, 27553018216SPaolo Bonzini hwaddr initrd_size, 27653018216SPaolo Bonzini hwaddr kernel_size, 27716457e7fSBenjamin Herrenschmidt bool little_endian, 27853018216SPaolo Bonzini const char *kernel_cmdline, 27953018216SPaolo Bonzini uint32_t epow_irq) 28053018216SPaolo Bonzini { 28153018216SPaolo Bonzini void *fdt; 28253018216SPaolo Bonzini uint32_t start_prop = cpu_to_be32(initrd_base); 28353018216SPaolo Bonzini uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); 284a1d59c0fSAlexey Kardashevskiy GString *hypertas = g_string_sized_new(256); 285a1d59c0fSAlexey Kardashevskiy GString *qemu_hypertas = g_string_sized_new(256); 28653018216SPaolo Bonzini uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; 2879e734e3dSBharata B Rao uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)}; 28853018216SPaolo Bonzini unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; 289ef951443SNikunj A Dadhania char *buf; 29053018216SPaolo Bonzini 291a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-pft"); 292a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-term"); 293a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-dabr"); 294a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-interrupt"); 295a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-tce"); 296a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-vio"); 297a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-splpar"); 298a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-bulk"); 299a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-set-mode"); 3006cc09e26SThomas Huth add_str(hypertas, "hcall-sprg0"); 3016cc09e26SThomas Huth add_str(hypertas, "hcall-copy"); 3026cc09e26SThomas Huth add_str(hypertas, "hcall-debug"); 303a1d59c0fSAlexey Kardashevskiy add_str(qemu_hypertas, "hcall-memop1"); 304a1d59c0fSAlexey Kardashevskiy 30553018216SPaolo Bonzini fdt = g_malloc0(FDT_MAX_SIZE); 30653018216SPaolo Bonzini _FDT((fdt_create(fdt, FDT_MAX_SIZE))); 30753018216SPaolo Bonzini 30853018216SPaolo Bonzini if (kernel_size) { 30953018216SPaolo Bonzini _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size))); 31053018216SPaolo Bonzini } 31153018216SPaolo Bonzini if (initrd_size) { 31253018216SPaolo Bonzini _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size))); 31353018216SPaolo Bonzini } 31453018216SPaolo Bonzini _FDT((fdt_finish_reservemap(fdt))); 31553018216SPaolo Bonzini 31653018216SPaolo Bonzini /* Root node */ 31753018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, ""))); 31853018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "chrp"))); 31953018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)"))); 320fa388916SAnthony Liguori _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries"))); 32153018216SPaolo Bonzini 322ef951443SNikunj A Dadhania /* 323ef951443SNikunj A Dadhania * Add info to guest to indentify which host is it being run on 324ef951443SNikunj A Dadhania * and what is the uuid of the guest 325ef951443SNikunj A Dadhania */ 326ef951443SNikunj A Dadhania if (kvmppc_get_host_model(&buf)) { 327ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "host-model", buf))); 328ef951443SNikunj A Dadhania g_free(buf); 329ef951443SNikunj A Dadhania } 330ef951443SNikunj A Dadhania if (kvmppc_get_host_serial(&buf)) { 331ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "host-serial", buf))); 332ef951443SNikunj A Dadhania g_free(buf); 333ef951443SNikunj A Dadhania } 334ef951443SNikunj A Dadhania 335ef951443SNikunj A Dadhania buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1], 336ef951443SNikunj A Dadhania qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], 337ef951443SNikunj A Dadhania qemu_uuid[5], qemu_uuid[6], qemu_uuid[7], 338ef951443SNikunj A Dadhania qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], 339ef951443SNikunj A Dadhania qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], 340ef951443SNikunj A Dadhania qemu_uuid[14], qemu_uuid[15]); 341ef951443SNikunj A Dadhania 342ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "vm,uuid", buf))); 3433dc0a66dSAlexey Kardashevskiy if (qemu_uuid_set) { 3443dc0a66dSAlexey Kardashevskiy _FDT((fdt_property_string(fdt, "system-id", buf))); 3453dc0a66dSAlexey Kardashevskiy } 346ef951443SNikunj A Dadhania g_free(buf); 347ef951443SNikunj A Dadhania 3482c1aaa81SSam Bobroff if (qemu_get_vm_name()) { 3492c1aaa81SSam Bobroff _FDT((fdt_property_string(fdt, "ibm,partition-name", 3502c1aaa81SSam Bobroff qemu_get_vm_name()))); 3512c1aaa81SSam Bobroff } 3522c1aaa81SSam Bobroff 35353018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x2))); 35453018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x2))); 35553018216SPaolo Bonzini 35653018216SPaolo Bonzini /* /chosen */ 35753018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "chosen"))); 35853018216SPaolo Bonzini 35953018216SPaolo Bonzini /* Set Form1_affinity */ 36053018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5)))); 36153018216SPaolo Bonzini 36253018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline))); 36353018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-start", 36453018216SPaolo Bonzini &start_prop, sizeof(start_prop)))); 36553018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-end", 36653018216SPaolo Bonzini &end_prop, sizeof(end_prop)))); 36753018216SPaolo Bonzini if (kernel_size) { 36853018216SPaolo Bonzini uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 36953018216SPaolo Bonzini cpu_to_be64(kernel_size) }; 37053018216SPaolo Bonzini 37153018216SPaolo Bonzini _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop)))); 37216457e7fSBenjamin Herrenschmidt if (little_endian) { 37316457e7fSBenjamin Herrenschmidt _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0))); 37416457e7fSBenjamin Herrenschmidt } 37553018216SPaolo Bonzini } 376cc84c0f3SAvik Sil if (boot_menu) { 377cc84c0f3SAvik Sil _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu))); 378cc84c0f3SAvik Sil } 37953018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width))); 38053018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height))); 38153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth))); 38253018216SPaolo Bonzini 38353018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 38453018216SPaolo Bonzini 38553018216SPaolo Bonzini /* RTAS */ 38653018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "rtas"))); 38753018216SPaolo Bonzini 388da95324eSAlexey Kardashevskiy if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 389da95324eSAlexey Kardashevskiy add_str(hypertas, "hcall-multi-tce"); 390da95324eSAlexey Kardashevskiy } 391a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str, 392a1d59c0fSAlexey Kardashevskiy hypertas->len))); 393a1d59c0fSAlexey Kardashevskiy g_string_free(hypertas, TRUE); 394a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str, 395a1d59c0fSAlexey Kardashevskiy qemu_hypertas->len))); 396a1d59c0fSAlexey Kardashevskiy g_string_free(qemu_hypertas, TRUE); 39753018216SPaolo Bonzini 39853018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,associativity-reference-points", 39953018216SPaolo Bonzini refpoints, sizeof(refpoints)))); 40053018216SPaolo Bonzini 40153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX))); 40279853e18STyrel Datwyler _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", 40379853e18STyrel Datwyler RTAS_EVENT_SCAN_RATE))); 40453018216SPaolo Bonzini 405226419d6SMichael S. Tsirkin if (msi_nonbroken) { 406a95f9922SSam Bobroff _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0))); 407a95f9922SSam Bobroff } 408a95f9922SSam Bobroff 4092e14072fSNikunj A Dadhania /* 4109d632f5fSzhanghailiang * According to PAPR, rtas ibm,os-term does not guarantee a return 4112e14072fSNikunj A Dadhania * back to the guest cpu. 4122e14072fSNikunj A Dadhania * 4132e14072fSNikunj A Dadhania * While an additional ibm,extended-os-term property indicates that 4142e14072fSNikunj A Dadhania * rtas call return will always occur. Set this property. 4152e14072fSNikunj A Dadhania */ 4162e14072fSNikunj A Dadhania _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0))); 4172e14072fSNikunj A Dadhania 41853018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 41953018216SPaolo Bonzini 42053018216SPaolo Bonzini /* interrupt controller */ 42153018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "interrupt-controller"))); 42253018216SPaolo Bonzini 42353018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", 42453018216SPaolo Bonzini "PowerPC-External-Interrupt-Presentation"))); 42553018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp"))); 42653018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 42753018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges", 42853018216SPaolo Bonzini interrupt_server_ranges_prop, 42953018216SPaolo Bonzini sizeof(interrupt_server_ranges_prop)))); 43053018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2))); 43153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP))); 43253018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP))); 43353018216SPaolo Bonzini 43453018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 43553018216SPaolo Bonzini 43653018216SPaolo Bonzini /* vdevice */ 43753018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "vdevice"))); 43853018216SPaolo Bonzini 43953018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "vdevice"))); 44053018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice"))); 44153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x1))); 44253018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x0))); 44353018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2))); 44453018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 44553018216SPaolo Bonzini 44653018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 44753018216SPaolo Bonzini 44853018216SPaolo Bonzini /* event-sources */ 44953018216SPaolo Bonzini spapr_events_fdt_skel(fdt, epow_irq); 45053018216SPaolo Bonzini 451f7d69146SAlexander Graf /* /hypervisor node */ 452f7d69146SAlexander Graf if (kvm_enabled()) { 453f7d69146SAlexander Graf uint8_t hypercall[16]; 454f7d69146SAlexander Graf 455f7d69146SAlexander Graf /* indicate KVM hypercall interface */ 456f7d69146SAlexander Graf _FDT((fdt_begin_node(fdt, "hypervisor"))); 457f7d69146SAlexander Graf _FDT((fdt_property_string(fdt, "compatible", "linux,kvm"))); 458f7d69146SAlexander Graf if (kvmppc_has_cap_fixup_hcalls()) { 459f7d69146SAlexander Graf /* 460f7d69146SAlexander Graf * Older KVM versions with older guest kernels were broken with the 461f7d69146SAlexander Graf * magic page, don't allow the guest to map it. 462f7d69146SAlexander Graf */ 4630ddbd053SAlexey Kardashevskiy if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 4640ddbd053SAlexey Kardashevskiy sizeof(hypercall))) { 465f7d69146SAlexander Graf _FDT((fdt_property(fdt, "hcall-instructions", hypercall, 466f7d69146SAlexander Graf sizeof(hypercall)))); 467f7d69146SAlexander Graf } 4680ddbd053SAlexey Kardashevskiy } 469f7d69146SAlexander Graf _FDT((fdt_end_node(fdt))); 470f7d69146SAlexander Graf } 471f7d69146SAlexander Graf 47253018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); /* close root node */ 47353018216SPaolo Bonzini _FDT((fdt_finish(fdt))); 47453018216SPaolo Bonzini 47553018216SPaolo Bonzini return fdt; 47653018216SPaolo Bonzini } 47753018216SPaolo Bonzini 47803d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 47926a8c353SAlexey Kardashevskiy hwaddr size) 48026a8c353SAlexey Kardashevskiy { 48126a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 48226a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 48326a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 484c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 48526a8c353SAlexey Kardashevskiy }; 48626a8c353SAlexey Kardashevskiy char mem_name[32]; 48726a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 48826a8c353SAlexey Kardashevskiy int off; 48926a8c353SAlexey Kardashevskiy 49026a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 49126a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 49226a8c353SAlexey Kardashevskiy 49326a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 49426a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 49526a8c353SAlexey Kardashevskiy _FDT(off); 49626a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 49726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 49826a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 49926a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 50026a8c353SAlexey Kardashevskiy sizeof(associativity)))); 50103d196b7SBharata B Rao return off; 50226a8c353SAlexey Kardashevskiy } 50326a8c353SAlexey Kardashevskiy 50428e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 50553018216SPaolo Bonzini { 506fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 5077db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 5087db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 5097db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 5107db8a127SAlexey Kardashevskiy NodeInfo ramnode; 51153018216SPaolo Bonzini 5127db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 5137db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 5147db8a127SAlexey Kardashevskiy nb_nodes = 1; 515fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 5167db8a127SAlexey Kardashevskiy nodes = &ramnode; 5175fe269b1SPaul Mackerras } 51853018216SPaolo Bonzini 5197db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 5207db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 5217db8a127SAlexey Kardashevskiy continue; 52253018216SPaolo Bonzini } 523fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 5245fe269b1SPaul Mackerras node_size = 0; 5255fe269b1SPaul Mackerras } else { 5267db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 527fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 528fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 5295fe269b1SPaul Mackerras } 5305fe269b1SPaul Mackerras } 5317db8a127SAlexey Kardashevskiy if (!mem_start) { 5327db8a127SAlexey Kardashevskiy /* ppc_spapr_init() checks for rma_size <= node0_size already */ 533e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 5347db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 5357db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 5367db8a127SAlexey Kardashevskiy } 5376010818cSAlexey Kardashevskiy for ( ; node_size; ) { 5386010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 5396010818cSAlexey Kardashevskiy 5406010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 5416010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 5426010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 5436010818cSAlexey Kardashevskiy } 5446010818cSAlexey Kardashevskiy 5456010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 5466010818cSAlexey Kardashevskiy node_size -= sizetmp; 5476010818cSAlexey Kardashevskiy mem_start += sizetmp; 5486010818cSAlexey Kardashevskiy } 54953018216SPaolo Bonzini } 55053018216SPaolo Bonzini 55153018216SPaolo Bonzini return 0; 55253018216SPaolo Bonzini } 55353018216SPaolo Bonzini 5540da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 5550da6f3feSBharata B Rao sPAPRMachineState *spapr) 5560da6f3feSBharata B Rao { 5570da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 5580da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 5590da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 5600da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 5610da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 5620da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 563afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 564afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 5650da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 5660da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 5670da6f3feSBharata B Rao size_t page_sizes_prop_size; 56822419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 5690da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 570af81cf32SBharata B Rao sPAPRDRConnector *drc; 571af81cf32SBharata B Rao sPAPRDRConnectorClass *drck; 572af81cf32SBharata B Rao int drc_index; 573af81cf32SBharata B Rao 574af81cf32SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); 575af81cf32SBharata B Rao if (drc) { 576af81cf32SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 577af81cf32SBharata B Rao drc_index = drck->get_index(drc); 578af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 579af81cf32SBharata B Rao } 5800da6f3feSBharata B Rao 58190da0d5aSBenjamin Herrenschmidt /* Note: we keep CI large pages off for now because a 64K capable guest 58290da0d5aSBenjamin Herrenschmidt * provisioned with large pages might otherwise try to map a qemu 58390da0d5aSBenjamin Herrenschmidt * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 58490da0d5aSBenjamin Herrenschmidt * even if that qemu runs on a 4k host. 58590da0d5aSBenjamin Herrenschmidt * 58690da0d5aSBenjamin Herrenschmidt * We can later add this bit back when we are confident this is not 58790da0d5aSBenjamin Herrenschmidt * an issue (!HV KVM or 64K host) 58890da0d5aSBenjamin Herrenschmidt */ 58990da0d5aSBenjamin Herrenschmidt uint8_t pa_features_206[] = { 6, 0, 59090da0d5aSBenjamin Herrenschmidt 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 59190da0d5aSBenjamin Herrenschmidt uint8_t pa_features_207[] = { 24, 0, 59290da0d5aSBenjamin Herrenschmidt 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 59390da0d5aSBenjamin Herrenschmidt 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 59490da0d5aSBenjamin Herrenschmidt 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 59590da0d5aSBenjamin Herrenschmidt 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 59690da0d5aSBenjamin Herrenschmidt uint8_t *pa_features; 59790da0d5aSBenjamin Herrenschmidt size_t pa_size; 59890da0d5aSBenjamin Herrenschmidt 5990da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6000da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6010da6f3feSBharata B Rao 6020da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 6030da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 6040da6f3feSBharata B Rao env->dcache_line_size))); 6050da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6060da6f3feSBharata B Rao env->dcache_line_size))); 6070da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6080da6f3feSBharata B Rao env->icache_line_size))); 6090da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6100da6f3feSBharata B Rao env->icache_line_size))); 6110da6f3feSBharata B Rao 6120da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 6130da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6140da6f3feSBharata B Rao pcc->l1_dcache_size))); 6150da6f3feSBharata B Rao } else { 616ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 dcache size for cpu"); 6170da6f3feSBharata B Rao } 6180da6f3feSBharata B Rao if (pcc->l1_icache_size) { 6190da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 6200da6f3feSBharata B Rao pcc->l1_icache_size))); 6210da6f3feSBharata B Rao } else { 622ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 icache size for cpu"); 6230da6f3feSBharata B Rao } 6240da6f3feSBharata B Rao 6250da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 6260da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 627fd5da5c4SThomas Huth _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); 6280da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 6290da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 6300da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 6310da6f3feSBharata B Rao 6320da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 6330da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 6340da6f3feSBharata B Rao } 6350da6f3feSBharata B Rao 6360da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 6370da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 6380da6f3feSBharata B Rao segs, sizeof(segs)))); 6390da6f3feSBharata B Rao } 6400da6f3feSBharata B Rao 6410da6f3feSBharata B Rao /* Advertise VMX/VSX (vector extensions) if available 6420da6f3feSBharata B Rao * 0 / no property == no vector extensions 6430da6f3feSBharata B Rao * 1 == VMX / Altivec available 6440da6f3feSBharata B Rao * 2 == VSX available */ 6450da6f3feSBharata B Rao if (env->insns_flags & PPC_ALTIVEC) { 6460da6f3feSBharata B Rao uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 6470da6f3feSBharata B Rao 6480da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 6490da6f3feSBharata B Rao } 6500da6f3feSBharata B Rao 6510da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 6520da6f3feSBharata B Rao * 0 / no property == no DFP 6530da6f3feSBharata B Rao * 1 == DFP available */ 6540da6f3feSBharata B Rao if (env->insns_flags2 & PPC2_DFP) { 6550da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 6560da6f3feSBharata B Rao } 6570da6f3feSBharata B Rao 658*3654fa95SCédric Le Goater page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, 6590da6f3feSBharata B Rao sizeof(page_sizes_prop)); 6600da6f3feSBharata B Rao if (page_sizes_prop_size) { 6610da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 6620da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 6630da6f3feSBharata B Rao } 6640da6f3feSBharata B Rao 66590da0d5aSBenjamin Herrenschmidt /* Do the ibm,pa-features property, adjust it for ci-large-pages */ 66690da0d5aSBenjamin Herrenschmidt if (env->mmu_model == POWERPC_MMU_2_06) { 66790da0d5aSBenjamin Herrenschmidt pa_features = pa_features_206; 66890da0d5aSBenjamin Herrenschmidt pa_size = sizeof(pa_features_206); 66990da0d5aSBenjamin Herrenschmidt } else /* env->mmu_model == POWERPC_MMU_2_07 */ { 67090da0d5aSBenjamin Herrenschmidt pa_features = pa_features_207; 67190da0d5aSBenjamin Herrenschmidt pa_size = sizeof(pa_features_207); 67290da0d5aSBenjamin Herrenschmidt } 67390da0d5aSBenjamin Herrenschmidt if (env->ci_large_pages) { 67490da0d5aSBenjamin Herrenschmidt pa_features[3] |= 0x20; 67590da0d5aSBenjamin Herrenschmidt } 67690da0d5aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 67790da0d5aSBenjamin Herrenschmidt 6780da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 67922419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 6800da6f3feSBharata B Rao 6810da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 6820da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 6830da6f3feSBharata B Rao 6840da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 6850da6f3feSBharata B Rao 6860da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 6870da6f3feSBharata B Rao ppc_get_compat_smt_threads(cpu))); 6880da6f3feSBharata B Rao } 6890da6f3feSBharata B Rao 6900da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 6910da6f3feSBharata B Rao { 6920da6f3feSBharata B Rao CPUState *cs; 6930da6f3feSBharata B Rao int cpus_offset; 6940da6f3feSBharata B Rao char *nodename; 6950da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 6960da6f3feSBharata B Rao 6970da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 6980da6f3feSBharata B Rao _FDT(cpus_offset); 6990da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 7000da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 7010da6f3feSBharata B Rao 7020da6f3feSBharata B Rao /* 7030da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 7040da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 7050da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 7060da6f3feSBharata B Rao */ 7070da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 7080da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 7090da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 7100da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 7110da6f3feSBharata B Rao int offset; 7120da6f3feSBharata B Rao 7130da6f3feSBharata B Rao if ((index % smt) != 0) { 7140da6f3feSBharata B Rao continue; 7150da6f3feSBharata B Rao } 7160da6f3feSBharata B Rao 7170da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 7180da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 7190da6f3feSBharata B Rao g_free(nodename); 7200da6f3feSBharata B Rao _FDT(offset); 7210da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 7220da6f3feSBharata B Rao } 7230da6f3feSBharata B Rao 7240da6f3feSBharata B Rao } 7250da6f3feSBharata B Rao 72603d196b7SBharata B Rao /* 72703d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 72803d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 72903d196b7SBharata B Rao * of this device tree node. 73003d196b7SBharata B Rao */ 73103d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 73203d196b7SBharata B Rao { 73303d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 73403d196b7SBharata B Rao int ret, i, offset; 73503d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 73603d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 737d0e5a8f2SBharata B Rao uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; 738d0e5a8f2SBharata B Rao uint32_t nr_lmbs = (spapr->hotplug_memory.base + 739d0e5a8f2SBharata B Rao memory_region_size(&spapr->hotplug_memory.mr)) / 740d0e5a8f2SBharata B Rao lmb_size; 74103d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 7426663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 74303d196b7SBharata B Rao 744ef001f06SThomas Huth /* 745d0e5a8f2SBharata B Rao * Don't create the node if there is no hotpluggable memory 74616c25aefSBharata B Rao */ 747d0e5a8f2SBharata B Rao if (machine->ram_size == machine->maxram_size) { 74816c25aefSBharata B Rao return 0; 74916c25aefSBharata B Rao } 75016c25aefSBharata B Rao 75116c25aefSBharata B Rao /* 752ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 753ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 754ef001f06SThomas Huth */ 755ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 756ef001f06SThomas Huth * sizeof(uint32_t); 75703d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 75803d196b7SBharata B Rao 75903d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 76003d196b7SBharata B Rao 76103d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 76203d196b7SBharata B Rao sizeof(prop_lmb_size)); 76303d196b7SBharata B Rao if (ret < 0) { 76403d196b7SBharata B Rao goto out; 76503d196b7SBharata B Rao } 76603d196b7SBharata B Rao 76703d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 76803d196b7SBharata B Rao if (ret < 0) { 76903d196b7SBharata B Rao goto out; 77003d196b7SBharata B Rao } 77103d196b7SBharata B Rao 77203d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 77303d196b7SBharata B Rao if (ret < 0) { 77403d196b7SBharata B Rao goto out; 77503d196b7SBharata B Rao } 77603d196b7SBharata B Rao 77703d196b7SBharata B Rao /* ibm,dynamic-memory */ 77803d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 77903d196b7SBharata B Rao cur_index++; 78003d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 781d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 78203d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 78303d196b7SBharata B Rao 784d0e5a8f2SBharata B Rao if (i >= hotplug_lmb_start) { 785d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 786d0e5a8f2SBharata B Rao sPAPRDRConnectorClass *drck; 787d0e5a8f2SBharata B Rao 788d0e5a8f2SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); 78903d196b7SBharata B Rao g_assert(drc); 79003d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 79103d196b7SBharata B Rao 79203d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 79303d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 79403d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 79503d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 79603d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 797d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 79803d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 79903d196b7SBharata B Rao } else { 80003d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 80103d196b7SBharata B Rao } 802d0e5a8f2SBharata B Rao } else { 803d0e5a8f2SBharata B Rao /* 804d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 805d0e5a8f2SBharata B Rao * hotplug memory region -- all these are marked as reserved 806d0e5a8f2SBharata B Rao * and as having no valid DRC. 807d0e5a8f2SBharata B Rao */ 808d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 809d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 810d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 811d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 812d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 813d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 814d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 815d0e5a8f2SBharata B Rao } 81603d196b7SBharata B Rao 81703d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 81803d196b7SBharata B Rao } 81903d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 82003d196b7SBharata B Rao if (ret < 0) { 82103d196b7SBharata B Rao goto out; 82203d196b7SBharata B Rao } 82303d196b7SBharata B Rao 82403d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 82503d196b7SBharata B Rao cur_index = int_buf; 8266663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 82703d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 82803d196b7SBharata B Rao cur_index += 2; 8296663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 83003d196b7SBharata B Rao uint32_t associativity[] = { 83103d196b7SBharata B Rao cpu_to_be32(0x0), 83203d196b7SBharata B Rao cpu_to_be32(0x0), 83303d196b7SBharata B Rao cpu_to_be32(0x0), 83403d196b7SBharata B Rao cpu_to_be32(i) 83503d196b7SBharata B Rao }; 83603d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 83703d196b7SBharata B Rao cur_index += 4; 83803d196b7SBharata B Rao } 83903d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 84003d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 84103d196b7SBharata B Rao out: 84203d196b7SBharata B Rao g_free(int_buf); 84303d196b7SBharata B Rao return ret; 84403d196b7SBharata B Rao } 84503d196b7SBharata B Rao 84603d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 84703d196b7SBharata B Rao target_ulong addr, target_ulong size, 84803d196b7SBharata B Rao bool cpu_update, bool memory_update) 84903d196b7SBharata B Rao { 85003d196b7SBharata B Rao void *fdt, *fdt_skel; 85103d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 85203d196b7SBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 85303d196b7SBharata B Rao 85403d196b7SBharata B Rao size -= sizeof(hdr); 85503d196b7SBharata B Rao 85603d196b7SBharata B Rao /* Create sceleton */ 85703d196b7SBharata B Rao fdt_skel = g_malloc0(size); 85803d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 85903d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 86003d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 86103d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 86203d196b7SBharata B Rao fdt = g_malloc0(size); 86303d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 86403d196b7SBharata B Rao g_free(fdt_skel); 86503d196b7SBharata B Rao 86603d196b7SBharata B Rao /* Fixup cpu nodes */ 86703d196b7SBharata B Rao if (cpu_update) { 86803d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 86903d196b7SBharata B Rao } 87003d196b7SBharata B Rao 87116c25aefSBharata B Rao /* Generate ibm,dynamic-reconfiguration-memory node if required */ 87203d196b7SBharata B Rao if (memory_update && smc->dr_lmb_enabled) { 87303d196b7SBharata B Rao _FDT((spapr_populate_drconf_memory(spapr, fdt))); 87403d196b7SBharata B Rao } 87503d196b7SBharata B Rao 87603d196b7SBharata B Rao /* Pack resulting tree */ 87703d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 87803d196b7SBharata B Rao 87903d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 88003d196b7SBharata B Rao trace_spapr_cas_failed(size); 88103d196b7SBharata B Rao return -1; 88203d196b7SBharata B Rao } 88303d196b7SBharata B Rao 88403d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 88503d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 88603d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 88703d196b7SBharata B Rao g_free(fdt); 88803d196b7SBharata B Rao 88903d196b7SBharata B Rao return 0; 89003d196b7SBharata B Rao } 89103d196b7SBharata B Rao 89228e02042SDavid Gibson static void spapr_finalize_fdt(sPAPRMachineState *spapr, 89353018216SPaolo Bonzini hwaddr fdt_addr, 89453018216SPaolo Bonzini hwaddr rtas_addr, 89553018216SPaolo Bonzini hwaddr rtas_size) 89653018216SPaolo Bonzini { 8975b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 8983c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 899c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 9005b2128d2SAlexander Graf const char *boot_device = machine->boot_order; 90171461b0fSAlexey Kardashevskiy int ret, i; 90271461b0fSAlexey Kardashevskiy size_t cb = 0; 90371461b0fSAlexey Kardashevskiy char *bootlist; 90453018216SPaolo Bonzini void *fdt; 90553018216SPaolo Bonzini sPAPRPHBState *phb; 90653018216SPaolo Bonzini 90753018216SPaolo Bonzini fdt = g_malloc(FDT_MAX_SIZE); 90853018216SPaolo Bonzini 90953018216SPaolo Bonzini /* open out the base tree into a temp buffer for the final tweaks */ 91053018216SPaolo Bonzini _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); 91153018216SPaolo Bonzini 912e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 913e8f986fcSBharata B Rao if (ret < 0) { 914ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 915e8f986fcSBharata B Rao exit(1); 91653018216SPaolo Bonzini } 91753018216SPaolo Bonzini 91853018216SPaolo Bonzini ret = spapr_populate_vdevice(spapr->vio_bus, fdt); 91953018216SPaolo Bonzini if (ret < 0) { 920ce9863b7SCédric Le Goater error_report("couldn't setup vio devices in fdt"); 92153018216SPaolo Bonzini exit(1); 92253018216SPaolo Bonzini } 92353018216SPaolo Bonzini 9244d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 9254d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 9264d9392beSThomas Huth if (ret < 0) { 927ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 9284d9392beSThomas Huth exit(1); 9294d9392beSThomas Huth } 9304d9392beSThomas Huth } 9314d9392beSThomas Huth 93253018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 93353018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 93453018216SPaolo Bonzini if (ret < 0) { 935da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 93653018216SPaolo Bonzini exit(1); 93753018216SPaolo Bonzini } 938da34fed7SThomas Huth } 93953018216SPaolo Bonzini 94053018216SPaolo Bonzini /* RTAS */ 94153018216SPaolo Bonzini ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); 94253018216SPaolo Bonzini if (ret < 0) { 943ce9863b7SCédric Le Goater error_report("Couldn't set up RTAS device tree properties"); 94453018216SPaolo Bonzini } 94553018216SPaolo Bonzini 9460da6f3feSBharata B Rao /* cpus */ 9470da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 94853018216SPaolo Bonzini 94971461b0fSAlexey Kardashevskiy bootlist = get_boot_devices_list(&cb, true); 95071461b0fSAlexey Kardashevskiy if (cb && bootlist) { 95171461b0fSAlexey Kardashevskiy int offset = fdt_path_offset(fdt, "/chosen"); 95271461b0fSAlexey Kardashevskiy if (offset < 0) { 95371461b0fSAlexey Kardashevskiy exit(1); 95471461b0fSAlexey Kardashevskiy } 95571461b0fSAlexey Kardashevskiy for (i = 0; i < cb; i++) { 95671461b0fSAlexey Kardashevskiy if (bootlist[i] == '\n') { 95771461b0fSAlexey Kardashevskiy bootlist[i] = ' '; 95871461b0fSAlexey Kardashevskiy } 95971461b0fSAlexey Kardashevskiy 96071461b0fSAlexey Kardashevskiy } 96171461b0fSAlexey Kardashevskiy ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); 96271461b0fSAlexey Kardashevskiy } 96371461b0fSAlexey Kardashevskiy 9645b2128d2SAlexander Graf if (boot_device && strlen(boot_device)) { 9655b2128d2SAlexander Graf int offset = fdt_path_offset(fdt, "/chosen"); 9665b2128d2SAlexander Graf 9675b2128d2SAlexander Graf if (offset < 0) { 9685b2128d2SAlexander Graf exit(1); 9695b2128d2SAlexander Graf } 9705b2128d2SAlexander Graf fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device); 9715b2128d2SAlexander Graf } 9725b2128d2SAlexander Graf 97353018216SPaolo Bonzini if (!spapr->has_graphics) { 97453018216SPaolo Bonzini spapr_populate_chosen_stdout(fdt, spapr->vio_bus); 97553018216SPaolo Bonzini } 97653018216SPaolo Bonzini 977c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 978c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 979c20d332aSBharata B Rao } 980c20d332aSBharata B Rao 9813c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 982af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 983af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 984af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 985af81cf32SBharata B Rao if (ret < 0) { 986af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 987af81cf32SBharata B Rao exit(1); 988af81cf32SBharata B Rao } 989af81cf32SBharata B Rao } 990af81cf32SBharata B Rao 99153018216SPaolo Bonzini _FDT((fdt_pack(fdt))); 99253018216SPaolo Bonzini 99353018216SPaolo Bonzini if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 994730fce59SThomas Huth error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 99553018216SPaolo Bonzini fdt_totalsize(fdt), FDT_MAX_SIZE); 99653018216SPaolo Bonzini exit(1); 99753018216SPaolo Bonzini } 99853018216SPaolo Bonzini 999ad440b4aSAndrew Jones qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 100053018216SPaolo Bonzini cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 100153018216SPaolo Bonzini 1002a21a7a70SGonglei g_free(bootlist); 100353018216SPaolo Bonzini g_free(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 11189e3f9733SAlexander Graf static int 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 return 0; 11339e3f9733SAlexander Graf } 11349e3f9733SAlexander Graf 113553018216SPaolo Bonzini static void ppc_spapr_reset(void) 113653018216SPaolo Bonzini { 1137c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1138c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1139182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1140b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1141259186a7SAndreas Färber 11429e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 11439e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 11449e3f9733SAlexander Graf 1145c5f54f3eSDavid Gibson /* Allocate and/or reset the hash page table */ 1146c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, 1147c5f54f3eSDavid Gibson spapr_hpt_shift_for_ramsize(machine->maxram_size), 1148c5f54f3eSDavid Gibson &error_fatal); 1149c5f54f3eSDavid Gibson 1150c5f54f3eSDavid Gibson /* Update the RMA size if necessary */ 1151c5f54f3eSDavid Gibson if (spapr->vrma_adjust) { 1152c5f54f3eSDavid Gibson spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1153c5f54f3eSDavid Gibson spapr->htab_shift); 1154c5f54f3eSDavid Gibson } 115553018216SPaolo Bonzini 115653018216SPaolo Bonzini qemu_devices_reset(); 115753018216SPaolo Bonzini 1158b7d1f77aSBenjamin Herrenschmidt /* 1159b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1160b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1161b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1162b7d1f77aSBenjamin Herrenschmidt */ 1163b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1164b7d1f77aSBenjamin Herrenschmidt spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1165b7d1f77aSBenjamin Herrenschmidt spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; 1166b7d1f77aSBenjamin Herrenschmidt 116753018216SPaolo Bonzini /* Load the fdt */ 116853018216SPaolo Bonzini spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr, 116953018216SPaolo Bonzini spapr->rtas_size); 117053018216SPaolo Bonzini 1171b7d1f77aSBenjamin Herrenschmidt /* Copy RTAS over */ 1172b7d1f77aSBenjamin Herrenschmidt cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob, 1173b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size); 1174b7d1f77aSBenjamin Herrenschmidt 117553018216SPaolo Bonzini /* Set up the entry state */ 1176182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1177182735efSAndreas Färber first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; 1178182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1179182735efSAndreas Färber first_cpu->halted = 0; 11801b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 118153018216SPaolo Bonzini 118253018216SPaolo Bonzini } 118353018216SPaolo Bonzini 118428e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 118553018216SPaolo Bonzini { 11862ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 11873978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 118853018216SPaolo Bonzini 11893978b863SPaolo Bonzini if (dinfo) { 11906231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 11916231a6daSMarkus Armbruster &error_fatal); 119253018216SPaolo Bonzini } 119353018216SPaolo Bonzini 119453018216SPaolo Bonzini qdev_init_nofail(dev); 119553018216SPaolo Bonzini 119653018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 119753018216SPaolo Bonzini } 119853018216SPaolo Bonzini 119928e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 120028df36a1SDavid Gibson { 120128df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 120228df36a1SDavid Gibson 120328df36a1SDavid Gibson qdev_init_nofail(dev); 120428df36a1SDavid Gibson spapr->rtc = dev; 120574e5ae28SDavid Gibson 120674e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 120774e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 120828df36a1SDavid Gibson } 120928df36a1SDavid Gibson 121053018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 121114c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 121253018216SPaolo Bonzini { 121353018216SPaolo Bonzini switch (vga_interface_type) { 121453018216SPaolo Bonzini case VGA_NONE: 12157effdaa3SMark Wu return false; 12167effdaa3SMark Wu case VGA_DEVICE: 12177effdaa3SMark Wu return true; 121853018216SPaolo Bonzini case VGA_STD: 1219b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 122053018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 122153018216SPaolo Bonzini default: 122214c6a894SDavid Gibson error_setg(errp, 122314c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 122414c6a894SDavid Gibson return false; 122553018216SPaolo Bonzini } 122653018216SPaolo Bonzini } 122753018216SPaolo Bonzini 1228880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1229880ae7deSDavid Gibson { 123028e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1231880ae7deSDavid Gibson int err = 0; 1232880ae7deSDavid Gibson 1233631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1234880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1235880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1236880ae7deSDavid Gibson * value into the RTC device */ 1237880ae7deSDavid Gibson if (version_id < 3) { 1238880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1239880ae7deSDavid Gibson } 1240880ae7deSDavid Gibson 1241880ae7deSDavid Gibson return err; 1242880ae7deSDavid Gibson } 1243880ae7deSDavid Gibson 1244880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1245880ae7deSDavid Gibson { 1246880ae7deSDavid Gibson return version_id < 3; 1247880ae7deSDavid Gibson } 1248880ae7deSDavid Gibson 12494be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 12504be21d56SDavid Gibson .name = "spapr", 1251880ae7deSDavid Gibson .version_id = 3, 12524be21d56SDavid Gibson .minimum_version_id = 1, 1253880ae7deSDavid Gibson .post_load = spapr_post_load, 12544be21d56SDavid Gibson .fields = (VMStateField[]) { 1255880ae7deSDavid Gibson /* used to be @next_irq */ 1256880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 12574be21d56SDavid Gibson 12584be21d56SDavid Gibson /* RTC offset */ 125928e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1260880ae7deSDavid Gibson 126128e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 12624be21d56SDavid Gibson VMSTATE_END_OF_LIST() 12634be21d56SDavid Gibson }, 12644be21d56SDavid Gibson }; 12654be21d56SDavid Gibson 12664be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 12674be21d56SDavid Gibson { 126828e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 12694be21d56SDavid Gibson 12704be21d56SDavid Gibson /* "Iteration" header */ 12714be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 12724be21d56SDavid Gibson 1273e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1274e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1275e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1276e68cb8b4SAlexey Kardashevskiy } else { 1277e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 12784be21d56SDavid Gibson } 12794be21d56SDavid Gibson 1280e68cb8b4SAlexey Kardashevskiy 1281e68cb8b4SAlexey Kardashevskiy return 0; 1282e68cb8b4SAlexey Kardashevskiy } 12834be21d56SDavid Gibson 128428e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 12854be21d56SDavid Gibson int64_t max_ns) 12864be21d56SDavid Gibson { 1287378bc217SDavid Gibson bool has_timeout = max_ns != -1; 12884be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 12894be21d56SDavid Gibson int index = spapr->htab_save_index; 1290bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 12914be21d56SDavid Gibson 12924be21d56SDavid Gibson assert(spapr->htab_first_pass); 12934be21d56SDavid Gibson 12944be21d56SDavid Gibson do { 12954be21d56SDavid Gibson int chunkstart; 12964be21d56SDavid Gibson 12974be21d56SDavid Gibson /* Consume invalid HPTEs */ 12984be21d56SDavid Gibson while ((index < htabslots) 12994be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13004be21d56SDavid Gibson index++; 13014be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13024be21d56SDavid Gibson } 13034be21d56SDavid Gibson 13044be21d56SDavid Gibson /* Consume valid HPTEs */ 13054be21d56SDavid Gibson chunkstart = index; 1306338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13074be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13084be21d56SDavid Gibson index++; 13094be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13104be21d56SDavid Gibson } 13114be21d56SDavid Gibson 13124be21d56SDavid Gibson if (index > chunkstart) { 13134be21d56SDavid Gibson int n_valid = index - chunkstart; 13144be21d56SDavid Gibson 13154be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13164be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13174be21d56SDavid Gibson qemu_put_be16(f, 0); 13184be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13194be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13204be21d56SDavid Gibson 1321378bc217SDavid Gibson if (has_timeout && 1322378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13234be21d56SDavid Gibson break; 13244be21d56SDavid Gibson } 13254be21d56SDavid Gibson } 13264be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 13274be21d56SDavid Gibson 13284be21d56SDavid Gibson if (index >= htabslots) { 13294be21d56SDavid Gibson assert(index == htabslots); 13304be21d56SDavid Gibson index = 0; 13314be21d56SDavid Gibson spapr->htab_first_pass = false; 13324be21d56SDavid Gibson } 13334be21d56SDavid Gibson spapr->htab_save_index = index; 13344be21d56SDavid Gibson } 13354be21d56SDavid Gibson 133628e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 13374be21d56SDavid Gibson int64_t max_ns) 13384be21d56SDavid Gibson { 13394be21d56SDavid Gibson bool final = max_ns < 0; 13404be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 13414be21d56SDavid Gibson int examined = 0, sent = 0; 13424be21d56SDavid Gibson int index = spapr->htab_save_index; 1343bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13444be21d56SDavid Gibson 13454be21d56SDavid Gibson assert(!spapr->htab_first_pass); 13464be21d56SDavid Gibson 13474be21d56SDavid Gibson do { 13484be21d56SDavid Gibson int chunkstart, invalidstart; 13494be21d56SDavid Gibson 13504be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 13514be21d56SDavid Gibson while ((index < htabslots) 13524be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 13534be21d56SDavid Gibson index++; 13544be21d56SDavid Gibson examined++; 13554be21d56SDavid Gibson } 13564be21d56SDavid Gibson 13574be21d56SDavid Gibson chunkstart = index; 13584be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1359338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13604be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13614be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13624be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13634be21d56SDavid Gibson index++; 13644be21d56SDavid Gibson examined++; 13654be21d56SDavid Gibson } 13664be21d56SDavid Gibson 13674be21d56SDavid Gibson invalidstart = index; 13684be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1369338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 13704be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13714be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13724be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13734be21d56SDavid Gibson index++; 13744be21d56SDavid Gibson examined++; 13754be21d56SDavid Gibson } 13764be21d56SDavid Gibson 13774be21d56SDavid Gibson if (index > chunkstart) { 13784be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 13794be21d56SDavid Gibson int n_invalid = index - invalidstart; 13804be21d56SDavid Gibson 13814be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13824be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13834be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 13844be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13854be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13864be21d56SDavid Gibson sent += index - chunkstart; 13874be21d56SDavid Gibson 1388bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13894be21d56SDavid Gibson break; 13904be21d56SDavid Gibson } 13914be21d56SDavid Gibson } 13924be21d56SDavid Gibson 13934be21d56SDavid Gibson if (examined >= htabslots) { 13944be21d56SDavid Gibson break; 13954be21d56SDavid Gibson } 13964be21d56SDavid Gibson 13974be21d56SDavid Gibson if (index >= htabslots) { 13984be21d56SDavid Gibson assert(index == htabslots); 13994be21d56SDavid Gibson index = 0; 14004be21d56SDavid Gibson } 14014be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 14024be21d56SDavid Gibson 14034be21d56SDavid Gibson if (index >= htabslots) { 14044be21d56SDavid Gibson assert(index == htabslots); 14054be21d56SDavid Gibson index = 0; 14064be21d56SDavid Gibson } 14074be21d56SDavid Gibson 14084be21d56SDavid Gibson spapr->htab_save_index = index; 14094be21d56SDavid Gibson 1410e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 14114be21d56SDavid Gibson } 14124be21d56SDavid Gibson 1413e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1414e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1415e68cb8b4SAlexey Kardashevskiy 14164be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 14174be21d56SDavid Gibson { 141828e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1419715c5407SDavid Gibson int fd; 1420e68cb8b4SAlexey Kardashevskiy int rc = 0; 14214be21d56SDavid Gibson 14224be21d56SDavid Gibson /* Iteration header */ 14234be21d56SDavid Gibson qemu_put_be32(f, 0); 14244be21d56SDavid Gibson 1425e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1426e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1427e68cb8b4SAlexey Kardashevskiy 1428715c5407SDavid Gibson fd = get_htab_fd(spapr); 1429715c5407SDavid Gibson if (fd < 0) { 1430715c5407SDavid Gibson return fd; 143101a57972SSamuel Mendoza-Jonas } 143201a57972SSamuel Mendoza-Jonas 1433715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1434e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1435e68cb8b4SAlexey Kardashevskiy return rc; 1436e68cb8b4SAlexey Kardashevskiy } 1437e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 14384be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 14394be21d56SDavid Gibson } else { 1440e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 14414be21d56SDavid Gibson } 14424be21d56SDavid Gibson 14434be21d56SDavid Gibson /* End marker */ 14444be21d56SDavid Gibson qemu_put_be32(f, 0); 14454be21d56SDavid Gibson qemu_put_be16(f, 0); 14464be21d56SDavid Gibson qemu_put_be16(f, 0); 14474be21d56SDavid Gibson 1448e68cb8b4SAlexey Kardashevskiy return rc; 14494be21d56SDavid Gibson } 14504be21d56SDavid Gibson 14514be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 14524be21d56SDavid Gibson { 145328e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1454715c5407SDavid Gibson int fd; 14554be21d56SDavid Gibson 14564be21d56SDavid Gibson /* Iteration header */ 14574be21d56SDavid Gibson qemu_put_be32(f, 0); 14584be21d56SDavid Gibson 1459e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1460e68cb8b4SAlexey Kardashevskiy int rc; 1461e68cb8b4SAlexey Kardashevskiy 1462e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1463e68cb8b4SAlexey Kardashevskiy 1464715c5407SDavid Gibson fd = get_htab_fd(spapr); 1465715c5407SDavid Gibson if (fd < 0) { 1466715c5407SDavid Gibson return fd; 146701a57972SSamuel Mendoza-Jonas } 146801a57972SSamuel Mendoza-Jonas 1469715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 1470e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1471e68cb8b4SAlexey Kardashevskiy return rc; 1472e68cb8b4SAlexey Kardashevskiy } 1473e68cb8b4SAlexey Kardashevskiy } else { 1474378bc217SDavid Gibson if (spapr->htab_first_pass) { 1475378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 1476378bc217SDavid Gibson } 14774be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1478e68cb8b4SAlexey Kardashevskiy } 14794be21d56SDavid Gibson 14804be21d56SDavid Gibson /* End marker */ 14814be21d56SDavid Gibson qemu_put_be32(f, 0); 14824be21d56SDavid Gibson qemu_put_be16(f, 0); 14834be21d56SDavid Gibson qemu_put_be16(f, 0); 14844be21d56SDavid Gibson 14854be21d56SDavid Gibson return 0; 14864be21d56SDavid Gibson } 14874be21d56SDavid Gibson 14884be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 14894be21d56SDavid Gibson { 149028e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 14914be21d56SDavid Gibson uint32_t section_hdr; 1492e68cb8b4SAlexey Kardashevskiy int fd = -1; 14934be21d56SDavid Gibson 14944be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 149598a5d100SDavid Gibson error_report("htab_load() bad version"); 14964be21d56SDavid Gibson return -EINVAL; 14974be21d56SDavid Gibson } 14984be21d56SDavid Gibson 14994be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 15004be21d56SDavid Gibson 15014be21d56SDavid Gibson if (section_hdr) { 15029897e462SGreg Kurz Error *local_err = NULL; 1503c5f54f3eSDavid Gibson 1504c5f54f3eSDavid Gibson /* First section gives the htab size */ 1505c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 1506c5f54f3eSDavid Gibson if (local_err) { 1507c5f54f3eSDavid Gibson error_report_err(local_err); 15084be21d56SDavid Gibson return -EINVAL; 15094be21d56SDavid Gibson } 15104be21d56SDavid Gibson return 0; 15114be21d56SDavid Gibson } 15124be21d56SDavid Gibson 1513e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1514e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1515e68cb8b4SAlexey Kardashevskiy 1516e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1517e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 151898a5d100SDavid Gibson error_report("Unable to open fd to restore KVM hash table: %s", 1519e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1520e68cb8b4SAlexey Kardashevskiy } 1521e68cb8b4SAlexey Kardashevskiy } 1522e68cb8b4SAlexey Kardashevskiy 15234be21d56SDavid Gibson while (true) { 15244be21d56SDavid Gibson uint32_t index; 15254be21d56SDavid Gibson uint16_t n_valid, n_invalid; 15264be21d56SDavid Gibson 15274be21d56SDavid Gibson index = qemu_get_be32(f); 15284be21d56SDavid Gibson n_valid = qemu_get_be16(f); 15294be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 15304be21d56SDavid Gibson 15314be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 15324be21d56SDavid Gibson /* End of Stream */ 15334be21d56SDavid Gibson break; 15344be21d56SDavid Gibson } 15354be21d56SDavid Gibson 1536e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 15374be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 15384be21d56SDavid Gibson /* Bad index in stream */ 153998a5d100SDavid Gibson error_report( 154098a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 154198a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 15424be21d56SDavid Gibson return -EINVAL; 15434be21d56SDavid Gibson } 15444be21d56SDavid Gibson 1545e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 15464be21d56SDavid Gibson if (n_valid) { 15474be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 15484be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 15494be21d56SDavid Gibson } 15504be21d56SDavid Gibson if (n_invalid) { 15514be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 15524be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 15534be21d56SDavid Gibson } 1554e68cb8b4SAlexey Kardashevskiy } else { 1555e68cb8b4SAlexey Kardashevskiy int rc; 1556e68cb8b4SAlexey Kardashevskiy 1557e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1558e68cb8b4SAlexey Kardashevskiy 1559e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1560e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1561e68cb8b4SAlexey Kardashevskiy return rc; 1562e68cb8b4SAlexey Kardashevskiy } 1563e68cb8b4SAlexey Kardashevskiy } 1564e68cb8b4SAlexey Kardashevskiy } 1565e68cb8b4SAlexey Kardashevskiy 1566e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1567e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1568e68cb8b4SAlexey Kardashevskiy close(fd); 15694be21d56SDavid Gibson } 15704be21d56SDavid Gibson 15714be21d56SDavid Gibson return 0; 15724be21d56SDavid Gibson } 15734be21d56SDavid Gibson 1574c573fc03SThomas Huth static void htab_cleanup(void *opaque) 1575c573fc03SThomas Huth { 1576c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 1577c573fc03SThomas Huth 1578c573fc03SThomas Huth close_htab_fd(spapr); 1579c573fc03SThomas Huth } 1580c573fc03SThomas Huth 15814be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 15824be21d56SDavid Gibson .save_live_setup = htab_save_setup, 15834be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 1584a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 1585c573fc03SThomas Huth .cleanup = htab_cleanup, 15864be21d56SDavid Gibson .load_state = htab_load, 15874be21d56SDavid Gibson }; 15884be21d56SDavid Gibson 15895b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 15905b2128d2SAlexander Graf Error **errp) 15915b2128d2SAlexander Graf { 15925b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 15935b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 15945b2128d2SAlexander Graf } 15955b2128d2SAlexander Graf 1596224245bfSDavid Gibson /* 1597224245bfSDavid Gibson * Reset routine for LMB DR devices. 1598224245bfSDavid Gibson * 1599224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1600224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1601224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1602224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1603224245bfSDavid Gibson */ 1604224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1605224245bfSDavid Gibson { 1606224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1607224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1608224245bfSDavid Gibson 1609224245bfSDavid Gibson if (d) { 1610224245bfSDavid Gibson device_reset(d); 1611224245bfSDavid Gibson } 1612224245bfSDavid Gibson } 1613224245bfSDavid Gibson 1614224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1615224245bfSDavid Gibson { 1616224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1617224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1618e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1619224245bfSDavid Gibson int i; 1620224245bfSDavid Gibson 1621224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1622224245bfSDavid Gibson sPAPRDRConnector *drc; 1623224245bfSDavid Gibson uint64_t addr; 1624224245bfSDavid Gibson 1625e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1626224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1627224245bfSDavid Gibson addr/lmb_size); 1628224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1629224245bfSDavid Gibson } 1630224245bfSDavid Gibson } 1631224245bfSDavid Gibson 1632224245bfSDavid Gibson /* 1633224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1634224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1635224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1636224245bfSDavid Gibson */ 16377c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 1638224245bfSDavid Gibson { 1639224245bfSDavid Gibson int i; 1640224245bfSDavid Gibson 16417c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16427c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 16437c150d6fSDavid Gibson " is not aligned to %llu MiB", 16447c150d6fSDavid Gibson machine->ram_size, 1645224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16467c150d6fSDavid Gibson return; 16477c150d6fSDavid Gibson } 16487c150d6fSDavid Gibson 16497c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16507c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 16517c150d6fSDavid Gibson " is not aligned to %llu MiB", 16527c150d6fSDavid Gibson machine->ram_size, 16537c150d6fSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16547c150d6fSDavid Gibson return; 1655224245bfSDavid Gibson } 1656224245bfSDavid Gibson 1657224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1658224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 16597c150d6fSDavid Gibson error_setg(errp, 16607c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 16617c150d6fSDavid Gibson " is not aligned to %llu MiB", 16627c150d6fSDavid Gibson i, numa_info[i].node_mem, 1663224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16647c150d6fSDavid Gibson return; 1665224245bfSDavid Gibson } 1666224245bfSDavid Gibson } 1667224245bfSDavid Gibson } 1668224245bfSDavid Gibson 166953018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 16703ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 167153018216SPaolo Bonzini { 167228e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 16733c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1674224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 16753ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 16763ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 16773ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 167853018216SPaolo Bonzini PCIHostState *phb; 167953018216SPaolo Bonzini int i; 168053018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 168153018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1682658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1683658fa66bSAlexey Kardashevskiy void *rma = NULL; 168453018216SPaolo Bonzini hwaddr rma_alloc_size; 1685b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 168653018216SPaolo Bonzini uint32_t initrd_base = 0; 168753018216SPaolo Bonzini long kernel_size = 0, initrd_size = 0; 1688b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 168916457e7fSBenjamin Herrenschmidt bool kernel_le = false; 169053018216SPaolo Bonzini char *filename; 169194a94e4cSBharata B Rao int smt = kvmppc_smt_threads(); 169294a94e4cSBharata B Rao int spapr_cores = smp_cpus / smp_threads; 169394a94e4cSBharata B Rao int spapr_max_cores = max_cpus / smp_threads; 169494a94e4cSBharata B Rao 16953c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 169694a94e4cSBharata B Rao if (smp_cpus % smp_threads) { 169794a94e4cSBharata B Rao error_report("smp_cpus (%u) must be multiple of threads (%u)", 169894a94e4cSBharata B Rao smp_cpus, smp_threads); 169994a94e4cSBharata B Rao exit(1); 170094a94e4cSBharata B Rao } 170194a94e4cSBharata B Rao if (max_cpus % smp_threads) { 170294a94e4cSBharata B Rao error_report("max_cpus (%u) must be multiple of threads (%u)", 170394a94e4cSBharata B Rao max_cpus, smp_threads); 170494a94e4cSBharata B Rao exit(1); 170594a94e4cSBharata B Rao } 170694a94e4cSBharata B Rao } 170753018216SPaolo Bonzini 1708226419d6SMichael S. Tsirkin msi_nonbroken = true; 170953018216SPaolo Bonzini 171053018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 171153018216SPaolo Bonzini 171253018216SPaolo Bonzini cpu_ppc_hypercall = emulate_spapr_hypercall; 171353018216SPaolo Bonzini 171453018216SPaolo Bonzini /* Allocate RMA if necessary */ 1715658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 171653018216SPaolo Bonzini 171753018216SPaolo Bonzini if (rma_alloc_size == -1) { 1718730fce59SThomas Huth error_report("Unable to create RMA"); 171953018216SPaolo Bonzini exit(1); 172053018216SPaolo Bonzini } 172153018216SPaolo Bonzini 1722c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 172353018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 172453018216SPaolo Bonzini } else { 1725c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 172653018216SPaolo Bonzini 172753018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 172853018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 172953018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 173053018216SPaolo Bonzini * 173153018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 173253018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 173353018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 173453018216SPaolo Bonzini * isn't determined yet. 173553018216SPaolo Bonzini */ 173653018216SPaolo Bonzini if (kvm_enabled()) { 173753018216SPaolo Bonzini spapr->vrma_adjust = 1; 173853018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 173953018216SPaolo Bonzini } 1740912acdf4SBenjamin Herrenschmidt 1741912acdf4SBenjamin Herrenschmidt /* Actually we don't support unbounded RMA anymore since we 1742912acdf4SBenjamin Herrenschmidt * added proper emulation of HV mode. The max we can get is 1743912acdf4SBenjamin Herrenschmidt * 16G which also happens to be what we configure for PAPR 1744912acdf4SBenjamin Herrenschmidt * mode so make sure we don't do anything bigger than that 1745912acdf4SBenjamin Herrenschmidt */ 1746912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 174753018216SPaolo Bonzini } 174853018216SPaolo Bonzini 1749c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 1750d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 1751c4177479SAlexey Kardashevskiy spapr->rma_size); 1752c4177479SAlexey Kardashevskiy exit(1); 1753c4177479SAlexey Kardashevskiy } 1754c4177479SAlexey Kardashevskiy 1755b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 1756b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 175753018216SPaolo Bonzini 17587b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 175927f24582SBenjamin Herrenschmidt spapr->xics = xics_system_init(machine, 176094a94e4cSBharata B Rao DIV_ROUND_UP(max_cpus * smt, smp_threads), 1761161deaf2SBenjamin Herrenschmidt XICS_IRQS_SPAPR, &error_fatal); 17627b565160SDavid Gibson 1763224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 17647c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 1765224245bfSDavid Gibson } 1766224245bfSDavid Gibson 176753018216SPaolo Bonzini /* init CPUs */ 176819fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 176919fb2c36SBharata B Rao machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; 177053018216SPaolo Bonzini } 177194a94e4cSBharata B Rao 1772e703d2f7SGreg Kurz ppc_cpu_parse_features(machine->cpu_model); 1773e703d2f7SGreg Kurz 17743c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 177594a94e4cSBharata B Rao char *type = spapr_get_cpu_core_type(machine->cpu_model); 177694a94e4cSBharata B Rao 17774babfaf0SThomas Huth if (type == NULL) { 1778caebf378SCédric Le Goater error_report("Unable to find sPAPR CPU Core definition"); 1779caebf378SCédric Le Goater exit(1); 1780caebf378SCédric Le Goater } 1781caebf378SCédric Le Goater 178294a94e4cSBharata B Rao spapr->cores = g_new0(Object *, spapr_max_cores); 1783af81cf32SBharata B Rao for (i = 0; i < spapr_max_cores; i++) { 178412bf2d33SGreg Kurz int core_id = i * smp_threads; 1785af81cf32SBharata B Rao sPAPRDRConnector *drc = 1786af81cf32SBharata B Rao spapr_dr_connector_new(OBJECT(spapr), 178712bf2d33SGreg Kurz SPAPR_DR_CONNECTOR_TYPE_CPU, 178812bf2d33SGreg Kurz (core_id / smp_threads) * smt); 1789af81cf32SBharata B Rao 1790af81cf32SBharata B Rao qemu_register_reset(spapr_drc_reset, drc); 1791af81cf32SBharata B Rao 1792af81cf32SBharata B Rao if (i < spapr_cores) { 1793caebf378SCédric Le Goater Object *core = object_new(type); 179494a94e4cSBharata B Rao object_property_set_int(core, smp_threads, "nr-threads", 179594a94e4cSBharata B Rao &error_fatal); 179612bf2d33SGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 179794a94e4cSBharata B Rao &error_fatal); 179894a94e4cSBharata B Rao object_property_set_bool(core, true, "realized", &error_fatal); 179994a94e4cSBharata B Rao } 1800af81cf32SBharata B Rao } 180194a94e4cSBharata B Rao g_free(type); 180294a94e4cSBharata B Rao } else { 180353018216SPaolo Bonzini for (i = 0; i < smp_cpus; i++) { 180494a94e4cSBharata B Rao PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model); 180553018216SPaolo Bonzini if (cpu == NULL) { 1806569f4967SDavid Gibson error_report("Unable to find PowerPC CPU definition"); 180753018216SPaolo Bonzini exit(1); 180853018216SPaolo Bonzini } 1809569f4967SDavid Gibson spapr_cpu_init(spapr, cpu, &error_fatal); 181053018216SPaolo Bonzini } 181194a94e4cSBharata B Rao } 181253018216SPaolo Bonzini 1813026bfd89SDavid Gibson if (kvm_enabled()) { 1814026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 1815026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 1816ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 1817026bfd89SDavid Gibson } 1818026bfd89SDavid Gibson 181953018216SPaolo Bonzini /* allocate RAM */ 1820f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 1821fb164994SDavid Gibson machine->ram_size); 1822f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 182353018216SPaolo Bonzini 1824658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 1825658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 1826658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 1827658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 1828658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 1829658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 1830658fa66bSAlexey Kardashevskiy } 1831658fa66bSAlexey Kardashevskiy 18324a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 18334a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 18344a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 183571c9a3ddSBharata B Rao /* 183671c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 183771c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 183871c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 183971c9a3ddSBharata B Rao */ 184071c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 184171c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 18424a1c9cf0SBharata B Rao 184371c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 184471c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 184571c9a3ddSBharata B Rao } 184671c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 1847d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 1848d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 184971c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 1850d54e4d76SDavid Gibson exit(1); 18514a1c9cf0SBharata B Rao } 18524a1c9cf0SBharata B Rao 18534a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 18544a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 18554a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 18564a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 18574a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 18584a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 18594a1c9cf0SBharata B Rao } 18604a1c9cf0SBharata B Rao 1861224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1862224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 1863224245bfSDavid Gibson } 1864224245bfSDavid Gibson 186553018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 18664c56440dSStefan Weil if (!filename) { 1867730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 18684c56440dSStefan Weil exit(1); 18694c56440dSStefan Weil } 1870b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 18718afc22a2SZhou Jie if (spapr->rtas_size < 0) { 18728afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 18738afc22a2SZhou Jie exit(1); 18748afc22a2SZhou Jie } 1875b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 1876b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 1877730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 187853018216SPaolo Bonzini exit(1); 187953018216SPaolo Bonzini } 188053018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 1881730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 18822f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 188353018216SPaolo Bonzini exit(1); 188453018216SPaolo Bonzini } 188553018216SPaolo Bonzini g_free(filename); 188653018216SPaolo Bonzini 188753018216SPaolo Bonzini /* Set up EPOW events infrastructure */ 188853018216SPaolo Bonzini spapr_events_init(spapr); 188953018216SPaolo Bonzini 189012f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 189128df36a1SDavid Gibson spapr_rtc_create(spapr); 189212f42174SDavid Gibson 189353018216SPaolo Bonzini /* Set up VIO bus */ 189453018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 189553018216SPaolo Bonzini 189653018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 189753018216SPaolo Bonzini if (serial_hds[i]) { 189853018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 189953018216SPaolo Bonzini } 190053018216SPaolo Bonzini } 190153018216SPaolo Bonzini 190253018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 190353018216SPaolo Bonzini spapr_create_nvram(spapr); 190453018216SPaolo Bonzini 190553018216SPaolo Bonzini /* Set up PCI */ 190653018216SPaolo Bonzini spapr_pci_rtas_init(); 190753018216SPaolo Bonzini 190889dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 190953018216SPaolo Bonzini 191053018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 191153018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 191253018216SPaolo Bonzini 191353018216SPaolo Bonzini if (!nd->model) { 191453018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 191553018216SPaolo Bonzini } 191653018216SPaolo Bonzini 191753018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 191853018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 191953018216SPaolo Bonzini } else { 192029b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 192153018216SPaolo Bonzini } 192253018216SPaolo Bonzini } 192353018216SPaolo Bonzini 192453018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 192553018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 192653018216SPaolo Bonzini } 192753018216SPaolo Bonzini 192853018216SPaolo Bonzini /* Graphics */ 192914c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 193053018216SPaolo Bonzini spapr->has_graphics = true; 1931c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 193253018216SPaolo Bonzini } 193353018216SPaolo Bonzini 19344ee9ced9SMarcel Apfelbaum if (machine->usb) { 193557040d45SThomas Huth if (smc->use_ohci_by_default) { 193653018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 193757040d45SThomas Huth } else { 193857040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 193957040d45SThomas Huth } 1940c86580b8SMarkus Armbruster 194153018216SPaolo Bonzini if (spapr->has_graphics) { 1942c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 1943c86580b8SMarkus Armbruster 1944c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 1945c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 194653018216SPaolo Bonzini } 194753018216SPaolo Bonzini } 194853018216SPaolo Bonzini 194953018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 1950d54e4d76SDavid Gibson error_report( 1951d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 1952d54e4d76SDavid Gibson MIN_RMA_SLOF); 195353018216SPaolo Bonzini exit(1); 195453018216SPaolo Bonzini } 195553018216SPaolo Bonzini 195653018216SPaolo Bonzini if (kernel_filename) { 195753018216SPaolo Bonzini uint64_t lowaddr = 0; 195853018216SPaolo Bonzini 195953018216SPaolo Bonzini kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, 19607ef295eaSPeter Crosthwaite NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 19617ef295eaSPeter Crosthwaite 0, 0); 19623b66da82SAlexey Kardashevskiy if (kernel_size == ELF_LOAD_WRONG_ENDIAN) { 196316457e7fSBenjamin Herrenschmidt kernel_size = load_elf(kernel_filename, 196416457e7fSBenjamin Herrenschmidt translate_kernel_address, NULL, 19657ef295eaSPeter Crosthwaite NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 19667ef295eaSPeter Crosthwaite 0, 0); 196716457e7fSBenjamin Herrenschmidt kernel_le = kernel_size > 0; 196816457e7fSBenjamin Herrenschmidt } 196916457e7fSBenjamin Herrenschmidt if (kernel_size < 0) { 1970d54e4d76SDavid Gibson error_report("error loading %s: %s", 19713b66da82SAlexey Kardashevskiy kernel_filename, load_elf_strerror(kernel_size)); 197253018216SPaolo Bonzini exit(1); 197353018216SPaolo Bonzini } 197453018216SPaolo Bonzini 197553018216SPaolo Bonzini /* load initrd */ 197653018216SPaolo Bonzini if (initrd_filename) { 197753018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 197853018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 197953018216SPaolo Bonzini */ 198053018216SPaolo Bonzini initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff; 198153018216SPaolo Bonzini initrd_size = load_image_targphys(initrd_filename, initrd_base, 198253018216SPaolo Bonzini load_limit - initrd_base); 198353018216SPaolo Bonzini if (initrd_size < 0) { 1984d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 198553018216SPaolo Bonzini initrd_filename); 198653018216SPaolo Bonzini exit(1); 198753018216SPaolo Bonzini } 198853018216SPaolo Bonzini } else { 198953018216SPaolo Bonzini initrd_base = 0; 199053018216SPaolo Bonzini initrd_size = 0; 199153018216SPaolo Bonzini } 199253018216SPaolo Bonzini } 199353018216SPaolo Bonzini 19948e7ea787SAndreas Färber if (bios_name == NULL) { 19958e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 19968e7ea787SAndreas Färber } 19978e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 19984c56440dSStefan Weil if (!filename) { 199968fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 20004c56440dSStefan Weil exit(1); 20014c56440dSStefan Weil } 200253018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 200368fea5a0SThomas Huth if (fw_size <= 0) { 200468fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 200553018216SPaolo Bonzini exit(1); 200653018216SPaolo Bonzini } 200753018216SPaolo Bonzini g_free(filename); 200853018216SPaolo Bonzini 200928e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 201028e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 201128e02042SDavid Gibson * which predated MachineState but had a similar function */ 20124be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 20134be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 20144be21d56SDavid Gibson &savevm_htab_handlers, spapr); 20154be21d56SDavid Gibson 201653018216SPaolo Bonzini /* Prepare the device tree */ 20173bbf37f2SAndreas Färber spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size, 201816457e7fSBenjamin Herrenschmidt kernel_size, kernel_le, 201931fe14d1SNathan Fontenot kernel_cmdline, 202031fe14d1SNathan Fontenot spapr->check_exception_irq); 202153018216SPaolo Bonzini assert(spapr->fdt_skel != NULL); 20225b2128d2SAlexander Graf 202346503c2bSMichael Roth /* used by RTAS */ 202446503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 202546503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 202646503c2bSMichael Roth 20275b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 202853018216SPaolo Bonzini } 202953018216SPaolo Bonzini 2030135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 2031135a129aSAneesh Kumar K.V { 2032135a129aSAneesh Kumar K.V if (!vm_type) { 2033135a129aSAneesh Kumar K.V return 0; 2034135a129aSAneesh Kumar K.V } 2035135a129aSAneesh Kumar K.V 2036135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 2037135a129aSAneesh Kumar K.V return 1; 2038135a129aSAneesh Kumar K.V } 2039135a129aSAneesh Kumar K.V 2040135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2041135a129aSAneesh Kumar K.V return 2; 2042135a129aSAneesh Kumar K.V } 2043135a129aSAneesh Kumar K.V 2044135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2045135a129aSAneesh Kumar K.V exit(1); 2046135a129aSAneesh Kumar K.V } 2047135a129aSAneesh Kumar K.V 204871461b0fSAlexey Kardashevskiy /* 2049627b84f4SGonglei * Implementation of an interface to adjust firmware path 205071461b0fSAlexey Kardashevskiy * for the bootindex property handling. 205171461b0fSAlexey Kardashevskiy */ 205271461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 205371461b0fSAlexey Kardashevskiy DeviceState *dev) 205471461b0fSAlexey Kardashevskiy { 205571461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 205671461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 205771461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 205871461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 205971461b0fSAlexey Kardashevskiy 206071461b0fSAlexey Kardashevskiy if (d) { 206171461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 206271461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 206371461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 206471461b0fSAlexey Kardashevskiy 206571461b0fSAlexey Kardashevskiy if (spapr) { 206671461b0fSAlexey Kardashevskiy /* 206771461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 206871461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 206971461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 207071461b0fSAlexey Kardashevskiy */ 207171461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 207271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 207371461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 207471461b0fSAlexey Kardashevskiy } else if (virtio) { 207571461b0fSAlexey Kardashevskiy /* 207671461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 207771461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 207871461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 207971461b0fSAlexey Kardashevskiy * the actual binding is: 208071461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 208171461b0fSAlexey Kardashevskiy */ 208271461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 208371461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 208471461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 208571461b0fSAlexey Kardashevskiy } else if (usb) { 208671461b0fSAlexey Kardashevskiy /* 208771461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 208871461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 208971461b0fSAlexey Kardashevskiy */ 209071461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 209171461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 209271461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 209371461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 209471461b0fSAlexey Kardashevskiy } 209571461b0fSAlexey Kardashevskiy } 209671461b0fSAlexey Kardashevskiy 209771461b0fSAlexey Kardashevskiy if (phb) { 209871461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 209971461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 210071461b0fSAlexey Kardashevskiy } 210171461b0fSAlexey Kardashevskiy 210271461b0fSAlexey Kardashevskiy return NULL; 210371461b0fSAlexey Kardashevskiy } 210471461b0fSAlexey Kardashevskiy 210523825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 210623825581SEduardo Habkost { 210728e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 210823825581SEduardo Habkost 210928e02042SDavid Gibson return g_strdup(spapr->kvm_type); 211023825581SEduardo Habkost } 211123825581SEduardo Habkost 211223825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 211323825581SEduardo Habkost { 211428e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 211523825581SEduardo Habkost 211628e02042SDavid Gibson g_free(spapr->kvm_type); 211728e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 211823825581SEduardo Habkost } 211923825581SEduardo Habkost 212023825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 212123825581SEduardo Habkost { 2122715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2123715c5407SDavid Gibson 2124715c5407SDavid Gibson spapr->htab_fd = -1; 212523825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 212623825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 212749d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 212849d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 212949d2e648SMarcel Apfelbaum NULL); 213023825581SEduardo Habkost } 213123825581SEduardo Habkost 213287bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 213387bbdd9cSDavid Gibson { 213487bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 213587bbdd9cSDavid Gibson 213687bbdd9cSDavid Gibson g_free(spapr->kvm_type); 213787bbdd9cSDavid Gibson } 213887bbdd9cSDavid Gibson 213934316482SAlexey Kardashevskiy static void ppc_cpu_do_nmi_on_cpu(void *arg) 214034316482SAlexey Kardashevskiy { 214134316482SAlexey Kardashevskiy CPUState *cs = arg; 214234316482SAlexey Kardashevskiy 214334316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 214434316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 214534316482SAlexey Kardashevskiy } 214634316482SAlexey Kardashevskiy 214734316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 214834316482SAlexey Kardashevskiy { 214934316482SAlexey Kardashevskiy CPUState *cs; 215034316482SAlexey Kardashevskiy 215134316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 215234316482SAlexey Kardashevskiy async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, cs); 215334316482SAlexey Kardashevskiy } 215434316482SAlexey Kardashevskiy } 215534316482SAlexey Kardashevskiy 2156c20d332aSBharata B Rao static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, 2157c20d332aSBharata B Rao uint32_t node, Error **errp) 2158c20d332aSBharata B Rao { 2159c20d332aSBharata B Rao sPAPRDRConnector *drc; 2160c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2161c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2162c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2163c20d332aSBharata B Rao void *fdt; 2164c20d332aSBharata B Rao 2165c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2166c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2167c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2168c20d332aSBharata B Rao g_assert(drc); 2169c20d332aSBharata B Rao 2170c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2171c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2172c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2173c20d332aSBharata B Rao 2174c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2175c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2176c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2177c20d332aSBharata B Rao } 21785dd5238cSJianjun Duan /* send hotplug notification to the 21795dd5238cSJianjun Duan * guest only in case of hotplugged memory 21805dd5238cSJianjun Duan */ 21815dd5238cSJianjun Duan if (dev->hotplugged) { 21820a417869SBharata B Rao spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); 2183c20d332aSBharata B Rao } 21845dd5238cSJianjun Duan } 2185c20d332aSBharata B Rao 2186c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2187c20d332aSBharata B Rao uint32_t node, Error **errp) 2188c20d332aSBharata B Rao { 2189c20d332aSBharata B Rao Error *local_err = NULL; 2190c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2191c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2192c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2193c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2194c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2195c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2196c20d332aSBharata B Rao uint64_t addr; 2197c20d332aSBharata B Rao 2198c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2199c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2200c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2201c20d332aSBharata B Rao goto out; 2202c20d332aSBharata B Rao } 2203c20d332aSBharata B Rao 2204d6a9b0b8SMichael S. Tsirkin pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 2205c20d332aSBharata B Rao if (local_err) { 2206c20d332aSBharata B Rao goto out; 2207c20d332aSBharata B Rao } 2208c20d332aSBharata B Rao 2209c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2210c20d332aSBharata B Rao if (local_err) { 2211c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2212c20d332aSBharata B Rao goto out; 2213c20d332aSBharata B Rao } 2214c20d332aSBharata B Rao 2215c20d332aSBharata B Rao spapr_add_lmbs(dev, addr, size, node, &error_abort); 2216c20d332aSBharata B Rao 2217c20d332aSBharata B Rao out: 2218c20d332aSBharata B Rao error_propagate(errp, local_err); 2219c20d332aSBharata B Rao } 2220c20d332aSBharata B Rao 2221af81cf32SBharata B Rao void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, 2222af81cf32SBharata B Rao sPAPRMachineState *spapr) 2223af81cf32SBharata B Rao { 2224af81cf32SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 2225af81cf32SBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 2226af81cf32SBharata B Rao int id = ppc_get_vcpu_dt_id(cpu); 2227af81cf32SBharata B Rao void *fdt; 2228af81cf32SBharata B Rao int offset, fdt_size; 2229af81cf32SBharata B Rao char *nodename; 2230af81cf32SBharata B Rao 2231af81cf32SBharata B Rao fdt = create_device_tree(&fdt_size); 2232af81cf32SBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 2233af81cf32SBharata B Rao offset = fdt_add_subnode(fdt, 0, nodename); 2234af81cf32SBharata B Rao 2235af81cf32SBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 2236af81cf32SBharata B Rao g_free(nodename); 2237af81cf32SBharata B Rao 2238af81cf32SBharata B Rao *fdt_offset = offset; 2239af81cf32SBharata B Rao return fdt; 2240af81cf32SBharata B Rao } 2241af81cf32SBharata B Rao 2242c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2243c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2244c20d332aSBharata B Rao { 2245c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2246c20d332aSBharata B Rao 2247c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2248b556854bSBharata B Rao int node; 2249c20d332aSBharata B Rao 2250c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2251c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2252c20d332aSBharata B Rao return; 2253c20d332aSBharata B Rao } 2254c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2255c20d332aSBharata B Rao if (*errp) { 2256c20d332aSBharata B Rao return; 2257c20d332aSBharata B Rao } 22581a5512bbSGonglei if (node < 0 || node >= MAX_NODES) { 22591a5512bbSGonglei error_setg(errp, "Invaild node %d", node); 22601a5512bbSGonglei return; 22611a5512bbSGonglei } 2262c20d332aSBharata B Rao 2263b556854bSBharata B Rao /* 2264b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2265b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2266b556854bSBharata B Rao * to the first node that has some memory. This causes two 2267b556854bSBharata B Rao * unexpected behaviours for the user. 2268b556854bSBharata B Rao * 2269b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2270b556854bSBharata B Rao * specified. 2271b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2272b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2273b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2274b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2275b556854bSBharata B Rao * 2276b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2277b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2278b556854bSBharata B Rao */ 2279b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2280b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2281b556854bSBharata B Rao node); 2282b556854bSBharata B Rao return; 2283b556854bSBharata B Rao } 2284b556854bSBharata B Rao 2285c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2286af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2287af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 2288c20d332aSBharata B Rao } 2289c20d332aSBharata B Rao } 2290c20d332aSBharata B Rao 2291c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2292c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2293c20d332aSBharata B Rao { 22943c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 22956f4b5c3eSBharata B Rao 2296c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2297c20d332aSBharata B Rao error_setg(errp, "Memory hot unplug not supported by sPAPR"); 22986f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 22993c0c47e3SDavid Gibson if (!mc->query_hotpluggable_cpus) { 23006f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 23016f4b5c3eSBharata B Rao return; 23026f4b5c3eSBharata B Rao } 23036f4b5c3eSBharata B Rao spapr_core_unplug(hotplug_dev, dev, errp); 2304c20d332aSBharata B Rao } 2305c20d332aSBharata B Rao } 2306c20d332aSBharata B Rao 230794a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 230894a94e4cSBharata B Rao DeviceState *dev, Error **errp) 230994a94e4cSBharata B Rao { 231094a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 231194a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 231294a94e4cSBharata B Rao } 231394a94e4cSBharata B Rao } 231494a94e4cSBharata B Rao 2315c20d332aSBharata B Rao static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, 2316c20d332aSBharata B Rao DeviceState *dev) 2317c20d332aSBharata B Rao { 231894a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 231994a94e4cSBharata B Rao object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2320c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2321c20d332aSBharata B Rao } 2322c20d332aSBharata B Rao return NULL; 2323c20d332aSBharata B Rao } 2324c20d332aSBharata B Rao 232520bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) 232620bb648dSDavid Gibson { 232720bb648dSDavid Gibson /* Allocate to NUMA nodes on a "socket" basis (not that concept of 232820bb648dSDavid Gibson * socket means much for the paravirtualized PAPR platform) */ 232920bb648dSDavid Gibson return cpu_index / smp_threads / smp_cores; 233020bb648dSDavid Gibson } 233120bb648dSDavid Gibson 23322474bfd4SIgor Mammedov static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine) 23332474bfd4SIgor Mammedov { 23342474bfd4SIgor Mammedov int i; 23352474bfd4SIgor Mammedov HotpluggableCPUList *head = NULL; 23362474bfd4SIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 23372474bfd4SIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 23382474bfd4SIgor Mammedov 23392474bfd4SIgor Mammedov for (i = 0; i < spapr_max_cores; i++) { 23402474bfd4SIgor Mammedov HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); 23412474bfd4SIgor Mammedov HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); 23422474bfd4SIgor Mammedov CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1); 23432474bfd4SIgor Mammedov 23442474bfd4SIgor Mammedov cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model); 23452474bfd4SIgor Mammedov cpu_item->vcpus_count = smp_threads; 234627393c33SPeter Krempa cpu_props->has_core_id = true; 234712bf2d33SGreg Kurz cpu_props->core_id = i * smp_threads; 23482474bfd4SIgor Mammedov /* TODO: add 'has_node/node' here to describe 23492474bfd4SIgor Mammedov to which node core belongs */ 23502474bfd4SIgor Mammedov 23512474bfd4SIgor Mammedov cpu_item->props = cpu_props; 23522474bfd4SIgor Mammedov if (spapr->cores[i]) { 23532474bfd4SIgor Mammedov cpu_item->has_qom_path = true; 23542474bfd4SIgor Mammedov cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]); 23552474bfd4SIgor Mammedov } 23562474bfd4SIgor Mammedov list_item->value = cpu_item; 23572474bfd4SIgor Mammedov list_item->next = head; 23582474bfd4SIgor Mammedov head = list_item; 23592474bfd4SIgor Mammedov } 23602474bfd4SIgor Mammedov return head; 23612474bfd4SIgor Mammedov } 23622474bfd4SIgor Mammedov 236329ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 236453018216SPaolo Bonzini { 236529ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 2366224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 236771461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 236834316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 2369c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 237029ee3247SAlexey Kardashevskiy 23710eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 2372fc9f38c3SDavid Gibson 2373fc9f38c3SDavid Gibson /* 2374fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 2375fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 2376fc9f38c3SDavid Gibson * these details for backwards compatibility 2377fc9f38c3SDavid Gibson */ 2378958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 2379958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 2380958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 238138b02bd8SAlexey Kardashevskiy mc->max_cpus = MAX_CPUMASK_BITS; 2382958db90cSMarcel Apfelbaum mc->no_parallel = 1; 23835b2128d2SAlexander Graf mc->default_boot_order = ""; 2384a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 2385958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 23869e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 2387e4024630SLaurent Vivier mc->pci_allow_0_address = true; 2388c20d332aSBharata B Rao mc->get_hotplug_handler = spapr_get_hotpug_handler; 238994a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 2390c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 2391c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 239220bb648dSDavid Gibson mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; 239300b4fbe2SMarcel Apfelbaum 2394fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 23953c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus; 239671461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 239734316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 239853018216SPaolo Bonzini } 239953018216SPaolo Bonzini 240029ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 240129ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 240229ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 24034aee7362SDavid Gibson .abstract = true, 24046ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 240523825581SEduardo Habkost .instance_init = spapr_machine_initfn, 240687bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 2407183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 240829ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 240971461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 241071461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 241134316482SAlexey Kardashevskiy { TYPE_NMI }, 2412c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 241371461b0fSAlexey Kardashevskiy { } 241471461b0fSAlexey Kardashevskiy }, 241529ee3247SAlexey Kardashevskiy }; 241629ee3247SAlexey Kardashevskiy 2417fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 24185013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 24195013c547SDavid Gibson void *data) \ 24205013c547SDavid Gibson { \ 24215013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 24225013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 2423fccbc785SDavid Gibson if (latest) { \ 2424fccbc785SDavid Gibson mc->alias = "pseries"; \ 2425fccbc785SDavid Gibson mc->is_default = 1; \ 2426fccbc785SDavid Gibson } \ 24275013c547SDavid Gibson } \ 24285013c547SDavid Gibson static void spapr_machine_##suffix##_instance_init(Object *obj) \ 24295013c547SDavid Gibson { \ 24305013c547SDavid Gibson MachineState *machine = MACHINE(obj); \ 24315013c547SDavid Gibson spapr_machine_##suffix##_instance_options(machine); \ 24325013c547SDavid Gibson } \ 24335013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 24345013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 24355013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 24365013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 24375013c547SDavid Gibson .instance_init = spapr_machine_##suffix##_instance_init, \ 24385013c547SDavid Gibson }; \ 24395013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 24405013c547SDavid Gibson { \ 24415013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 24425013c547SDavid Gibson } \ 24430e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 24445013c547SDavid Gibson 24451c5f29bbSDavid Gibson /* 24461ea1eefcSBharata B Rao * pseries-2.7 24471ea1eefcSBharata B Rao */ 24481ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine) 24491ea1eefcSBharata B Rao { 24501ea1eefcSBharata B Rao } 24511ea1eefcSBharata B Rao 24521ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 24531ea1eefcSBharata B Rao { 24541ea1eefcSBharata B Rao /* Defaults for the latest behaviour inherited from the base class */ 24551ea1eefcSBharata B Rao } 24561ea1eefcSBharata B Rao 24571ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_7, "2.7", true); 24581ea1eefcSBharata B Rao 24591ea1eefcSBharata B Rao /* 24604b23699cSDavid Gibson * pseries-2.6 24614b23699cSDavid Gibson */ 24621ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \ 2463ae4de14cSAlexey Kardashevskiy HW_COMPAT_2_6 \ 2464ae4de14cSAlexey Kardashevskiy { \ 2465ae4de14cSAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2466ae4de14cSAlexey Kardashevskiy .property = "ddw",\ 2467ae4de14cSAlexey Kardashevskiy .value = stringify(off),\ 2468ae4de14cSAlexey Kardashevskiy }, 24691ea1eefcSBharata B Rao 24704b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine) 24714b23699cSDavid Gibson { 24724b23699cSDavid Gibson } 24734b23699cSDavid Gibson 24744b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc) 24754b23699cSDavid Gibson { 24761ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 24773c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = NULL; 24781ea1eefcSBharata B Rao SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); 24794b23699cSDavid Gibson } 24804b23699cSDavid Gibson 24811ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 24824b23699cSDavid Gibson 24834b23699cSDavid Gibson /* 24841c5f29bbSDavid Gibson * pseries-2.5 24851c5f29bbSDavid Gibson */ 24864b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \ 248757c522f4SThomas Huth HW_COMPAT_2_5 \ 248857c522f4SThomas Huth { \ 248957c522f4SThomas Huth .driver = "spapr-vlan", \ 249057c522f4SThomas Huth .property = "use-rx-buffer-pools", \ 249157c522f4SThomas Huth .value = "off", \ 249257c522f4SThomas Huth }, 24934b23699cSDavid Gibson 24945013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine) 24951c5f29bbSDavid Gibson { 24965013c547SDavid Gibson } 24975013c547SDavid Gibson 24985013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc) 24995013c547SDavid Gibson { 250057040d45SThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 250157040d45SThomas Huth 25024b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 250357040d45SThomas Huth smc->use_ohci_by_default = true; 25044b23699cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5); 25051c5f29bbSDavid Gibson } 25061c5f29bbSDavid Gibson 25074b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 25081c5f29bbSDavid Gibson 25091c5f29bbSDavid Gibson /* 25101c5f29bbSDavid Gibson * pseries-2.4 25111c5f29bbSDavid Gibson */ 251280fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \ 251380fd50f9SCornelia Huck HW_COMPAT_2_4 251480fd50f9SCornelia Huck 25155013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine) 25161c5f29bbSDavid Gibson { 25175013c547SDavid Gibson spapr_machine_2_5_instance_options(machine); 25185013c547SDavid Gibson } 25191c5f29bbSDavid Gibson 25205013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 25215013c547SDavid Gibson { 2522fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 2523fc9f38c3SDavid Gibson 2524fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 2525fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 2526f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4); 25271c5f29bbSDavid Gibson } 25281c5f29bbSDavid Gibson 2529fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 25301c5f29bbSDavid Gibson 25311c5f29bbSDavid Gibson /* 25321c5f29bbSDavid Gibson * pseries-2.3 25331c5f29bbSDavid Gibson */ 253438ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 25357619c7b0SMichael Roth HW_COMPAT_2_3 \ 25367619c7b0SMichael Roth {\ 25377619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 25387619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 25397619c7b0SMichael Roth .value = "off",\ 25407619c7b0SMichael Roth }, 254138ff32c6SEduardo Habkost 25425013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine) 25431c5f29bbSDavid Gibson { 25445013c547SDavid Gibson spapr_machine_2_4_instance_options(machine); 25451c5f29bbSDavid Gibson savevm_skip_section_footers(); 25461c5f29bbSDavid Gibson global_state_set_optional(); 254709b5e30dSGreg Kurz savevm_skip_configuration(); 25481c5f29bbSDavid Gibson } 25491c5f29bbSDavid Gibson 25505013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc) 25511c5f29bbSDavid Gibson { 2552fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 2553f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3); 25541c5f29bbSDavid Gibson } 2555fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 25561c5f29bbSDavid Gibson 25571c5f29bbSDavid Gibson /* 25581c5f29bbSDavid Gibson * pseries-2.2 25591c5f29bbSDavid Gibson */ 25601c5f29bbSDavid Gibson 2561b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 25624dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 2563b194df47SAlexey Kardashevskiy {\ 2564b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2565b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 2566b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 2567dd754bafSEduardo Habkost }, 2568b194df47SAlexey Kardashevskiy 25695013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine) 2570b0e966d0SJason Wang { 25715013c547SDavid Gibson spapr_machine_2_3_instance_options(machine); 2572cba0e779SGreg Kurz machine->suppress_vmdesc = true; 2573b0e966d0SJason Wang } 2574b0e966d0SJason Wang 25755013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc) 2576b0e966d0SJason Wang { 2577fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 2578f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2); 25791c5f29bbSDavid Gibson } 2580fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 25811c5f29bbSDavid Gibson 25821c5f29bbSDavid Gibson /* 25831c5f29bbSDavid Gibson * pseries-2.1 25841c5f29bbSDavid Gibson */ 25851c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \ 25861c5f29bbSDavid Gibson HW_COMPAT_2_1 25871c5f29bbSDavid Gibson 25885013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine) 25891c5f29bbSDavid Gibson { 25905013c547SDavid Gibson spapr_machine_2_2_instance_options(machine); 25911c5f29bbSDavid Gibson } 25921c5f29bbSDavid Gibson 25935013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 2594b0e966d0SJason Wang { 2595fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 2596f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1); 25976026db45SAlexey Kardashevskiy } 2598fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 25996026db45SAlexey Kardashevskiy 260029ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 260129ee3247SAlexey Kardashevskiy { 260229ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 260329ee3247SAlexey Kardashevskiy } 260429ee3247SAlexey Kardashevskiy 260529ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 2606