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 3359c5ce8dbSFam Zheng buf = qemu_uuid_unparse_strdup(&qemu_uuid); 336ef951443SNikunj A Dadhania 337ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "vm,uuid", buf))); 3383dc0a66dSAlexey Kardashevskiy if (qemu_uuid_set) { 3393dc0a66dSAlexey Kardashevskiy _FDT((fdt_property_string(fdt, "system-id", buf))); 3403dc0a66dSAlexey Kardashevskiy } 341ef951443SNikunj A Dadhania g_free(buf); 342ef951443SNikunj A Dadhania 3432c1aaa81SSam Bobroff if (qemu_get_vm_name()) { 3442c1aaa81SSam Bobroff _FDT((fdt_property_string(fdt, "ibm,partition-name", 3452c1aaa81SSam Bobroff qemu_get_vm_name()))); 3462c1aaa81SSam Bobroff } 3472c1aaa81SSam Bobroff 34853018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x2))); 34953018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x2))); 35053018216SPaolo Bonzini 35153018216SPaolo Bonzini /* /chosen */ 35253018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "chosen"))); 35353018216SPaolo Bonzini 35453018216SPaolo Bonzini /* Set Form1_affinity */ 35553018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5)))); 35653018216SPaolo Bonzini 35753018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline))); 35853018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-start", 35953018216SPaolo Bonzini &start_prop, sizeof(start_prop)))); 36053018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-end", 36153018216SPaolo Bonzini &end_prop, sizeof(end_prop)))); 36253018216SPaolo Bonzini if (kernel_size) { 36353018216SPaolo Bonzini uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 36453018216SPaolo Bonzini cpu_to_be64(kernel_size) }; 36553018216SPaolo Bonzini 36653018216SPaolo Bonzini _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop)))); 36716457e7fSBenjamin Herrenschmidt if (little_endian) { 36816457e7fSBenjamin Herrenschmidt _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0))); 36916457e7fSBenjamin Herrenschmidt } 37053018216SPaolo Bonzini } 371cc84c0f3SAvik Sil if (boot_menu) { 372cc84c0f3SAvik Sil _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu))); 373cc84c0f3SAvik Sil } 37453018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width))); 37553018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height))); 37653018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth))); 37753018216SPaolo Bonzini 37853018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 37953018216SPaolo Bonzini 38053018216SPaolo Bonzini /* RTAS */ 38153018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "rtas"))); 38253018216SPaolo Bonzini 383da95324eSAlexey Kardashevskiy if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 384da95324eSAlexey Kardashevskiy add_str(hypertas, "hcall-multi-tce"); 385da95324eSAlexey Kardashevskiy } 386a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str, 387a1d59c0fSAlexey Kardashevskiy hypertas->len))); 388a1d59c0fSAlexey Kardashevskiy g_string_free(hypertas, TRUE); 389a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str, 390a1d59c0fSAlexey Kardashevskiy qemu_hypertas->len))); 391a1d59c0fSAlexey Kardashevskiy g_string_free(qemu_hypertas, TRUE); 39253018216SPaolo Bonzini 39353018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,associativity-reference-points", 39453018216SPaolo Bonzini refpoints, sizeof(refpoints)))); 39553018216SPaolo Bonzini 39653018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX))); 39779853e18STyrel Datwyler _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", 39879853e18STyrel Datwyler RTAS_EVENT_SCAN_RATE))); 39953018216SPaolo Bonzini 400226419d6SMichael S. Tsirkin if (msi_nonbroken) { 401a95f9922SSam Bobroff _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0))); 402a95f9922SSam Bobroff } 403a95f9922SSam Bobroff 4042e14072fSNikunj A Dadhania /* 4059d632f5fSzhanghailiang * According to PAPR, rtas ibm,os-term does not guarantee a return 4062e14072fSNikunj A Dadhania * back to the guest cpu. 4072e14072fSNikunj A Dadhania * 4082e14072fSNikunj A Dadhania * While an additional ibm,extended-os-term property indicates that 4092e14072fSNikunj A Dadhania * rtas call return will always occur. Set this property. 4102e14072fSNikunj A Dadhania */ 4112e14072fSNikunj A Dadhania _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0))); 4122e14072fSNikunj A Dadhania 41353018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 41453018216SPaolo Bonzini 41553018216SPaolo Bonzini /* interrupt controller */ 41653018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "interrupt-controller"))); 41753018216SPaolo Bonzini 41853018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", 41953018216SPaolo Bonzini "PowerPC-External-Interrupt-Presentation"))); 42053018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp"))); 42153018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 42253018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges", 42353018216SPaolo Bonzini interrupt_server_ranges_prop, 42453018216SPaolo Bonzini sizeof(interrupt_server_ranges_prop)))); 42553018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2))); 42653018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP))); 42753018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP))); 42853018216SPaolo Bonzini 42953018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 43053018216SPaolo Bonzini 43153018216SPaolo Bonzini /* vdevice */ 43253018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "vdevice"))); 43353018216SPaolo Bonzini 43453018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "vdevice"))); 43553018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice"))); 43653018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x1))); 43753018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x0))); 43853018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2))); 43953018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 44053018216SPaolo Bonzini 44153018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 44253018216SPaolo Bonzini 44353018216SPaolo Bonzini /* event-sources */ 44453018216SPaolo Bonzini spapr_events_fdt_skel(fdt, epow_irq); 44553018216SPaolo Bonzini 446f7d69146SAlexander Graf /* /hypervisor node */ 447f7d69146SAlexander Graf if (kvm_enabled()) { 448f7d69146SAlexander Graf uint8_t hypercall[16]; 449f7d69146SAlexander Graf 450f7d69146SAlexander Graf /* indicate KVM hypercall interface */ 451f7d69146SAlexander Graf _FDT((fdt_begin_node(fdt, "hypervisor"))); 452f7d69146SAlexander Graf _FDT((fdt_property_string(fdt, "compatible", "linux,kvm"))); 453f7d69146SAlexander Graf if (kvmppc_has_cap_fixup_hcalls()) { 454f7d69146SAlexander Graf /* 455f7d69146SAlexander Graf * Older KVM versions with older guest kernels were broken with the 456f7d69146SAlexander Graf * magic page, don't allow the guest to map it. 457f7d69146SAlexander Graf */ 4580ddbd053SAlexey Kardashevskiy if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 4590ddbd053SAlexey Kardashevskiy sizeof(hypercall))) { 460f7d69146SAlexander Graf _FDT((fdt_property(fdt, "hcall-instructions", hypercall, 461f7d69146SAlexander Graf sizeof(hypercall)))); 462f7d69146SAlexander Graf } 4630ddbd053SAlexey Kardashevskiy } 464f7d69146SAlexander Graf _FDT((fdt_end_node(fdt))); 465f7d69146SAlexander Graf } 466f7d69146SAlexander Graf 46753018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); /* close root node */ 46853018216SPaolo Bonzini _FDT((fdt_finish(fdt))); 46953018216SPaolo Bonzini 47053018216SPaolo Bonzini return fdt; 47153018216SPaolo Bonzini } 47253018216SPaolo Bonzini 47303d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 47426a8c353SAlexey Kardashevskiy hwaddr size) 47526a8c353SAlexey Kardashevskiy { 47626a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 47726a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 47826a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 479c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 48026a8c353SAlexey Kardashevskiy }; 48126a8c353SAlexey Kardashevskiy char mem_name[32]; 48226a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 48326a8c353SAlexey Kardashevskiy int off; 48426a8c353SAlexey Kardashevskiy 48526a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 48626a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 48726a8c353SAlexey Kardashevskiy 48826a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 48926a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 49026a8c353SAlexey Kardashevskiy _FDT(off); 49126a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 49226a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 49326a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 49426a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 49526a8c353SAlexey Kardashevskiy sizeof(associativity)))); 49603d196b7SBharata B Rao return off; 49726a8c353SAlexey Kardashevskiy } 49826a8c353SAlexey Kardashevskiy 49928e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 50053018216SPaolo Bonzini { 501fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 5027db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 5037db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 5047db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 5057db8a127SAlexey Kardashevskiy NodeInfo ramnode; 50653018216SPaolo Bonzini 5077db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 5087db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 5097db8a127SAlexey Kardashevskiy nb_nodes = 1; 510fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 5117db8a127SAlexey Kardashevskiy nodes = &ramnode; 5125fe269b1SPaul Mackerras } 51353018216SPaolo Bonzini 5147db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 5157db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 5167db8a127SAlexey Kardashevskiy continue; 51753018216SPaolo Bonzini } 518fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 5195fe269b1SPaul Mackerras node_size = 0; 5205fe269b1SPaul Mackerras } else { 5217db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 522fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 523fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 5245fe269b1SPaul Mackerras } 5255fe269b1SPaul Mackerras } 5267db8a127SAlexey Kardashevskiy if (!mem_start) { 5277db8a127SAlexey Kardashevskiy /* ppc_spapr_init() checks for rma_size <= node0_size already */ 528e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 5297db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 5307db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 5317db8a127SAlexey Kardashevskiy } 5326010818cSAlexey Kardashevskiy for ( ; node_size; ) { 5336010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 5346010818cSAlexey Kardashevskiy 5356010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 5366010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 5376010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 5386010818cSAlexey Kardashevskiy } 5396010818cSAlexey Kardashevskiy 5406010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 5416010818cSAlexey Kardashevskiy node_size -= sizetmp; 5426010818cSAlexey Kardashevskiy mem_start += sizetmp; 5436010818cSAlexey Kardashevskiy } 54453018216SPaolo Bonzini } 54553018216SPaolo Bonzini 54653018216SPaolo Bonzini return 0; 54753018216SPaolo Bonzini } 54853018216SPaolo Bonzini 549230bf719SThomas Huth /* Populate the "ibm,pa-features" property */ 550230bf719SThomas Huth static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset) 551230bf719SThomas Huth { 552230bf719SThomas Huth uint8_t pa_features_206[] = { 6, 0, 553230bf719SThomas Huth 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 554230bf719SThomas Huth uint8_t pa_features_207[] = { 24, 0, 555230bf719SThomas Huth 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 556230bf719SThomas Huth 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 557230bf719SThomas Huth 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 558bac3bf28SThomas Huth 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 559230bf719SThomas Huth uint8_t *pa_features; 560230bf719SThomas Huth size_t pa_size; 561230bf719SThomas Huth 5624cbec30dSThomas Huth switch (env->mmu_model) { 5634cbec30dSThomas Huth case POWERPC_MMU_2_06: 5644cbec30dSThomas Huth case POWERPC_MMU_2_06a: 565230bf719SThomas Huth pa_features = pa_features_206; 566230bf719SThomas Huth pa_size = sizeof(pa_features_206); 5674cbec30dSThomas Huth break; 5684cbec30dSThomas Huth case POWERPC_MMU_2_07: 5694cbec30dSThomas Huth case POWERPC_MMU_2_07a: 570230bf719SThomas Huth pa_features = pa_features_207; 571230bf719SThomas Huth pa_size = sizeof(pa_features_207); 5724cbec30dSThomas Huth break; 5734cbec30dSThomas Huth default: 5744cbec30dSThomas Huth return; 575230bf719SThomas Huth } 576230bf719SThomas Huth 577230bf719SThomas Huth if (env->ci_large_pages) { 578230bf719SThomas Huth /* 579230bf719SThomas Huth * Note: we keep CI large pages off by default because a 64K capable 580230bf719SThomas Huth * guest provisioned with large pages might otherwise try to map a qemu 581230bf719SThomas Huth * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 582230bf719SThomas Huth * even if that qemu runs on a 4k host. 583230bf719SThomas Huth * We dd this bit back here if we are confident this is not an issue 584230bf719SThomas Huth */ 585230bf719SThomas Huth pa_features[3] |= 0x20; 586230bf719SThomas Huth } 587bac3bf28SThomas Huth if (kvmppc_has_cap_htm() && pa_size > 24) { 588bac3bf28SThomas Huth pa_features[24] |= 0x80; /* Transactional memory support */ 589bac3bf28SThomas Huth } 590230bf719SThomas Huth 591230bf719SThomas Huth _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 592230bf719SThomas Huth } 593230bf719SThomas Huth 5940da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 5950da6f3feSBharata B Rao sPAPRMachineState *spapr) 5960da6f3feSBharata B Rao { 5970da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 5980da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 5990da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 6000da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 6010da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 6020da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 603afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 604afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 6050da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 6060da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 6070da6f3feSBharata B Rao size_t page_sizes_prop_size; 60822419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 6090da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 610af81cf32SBharata B Rao sPAPRDRConnector *drc; 611af81cf32SBharata B Rao sPAPRDRConnectorClass *drck; 612af81cf32SBharata B Rao int drc_index; 613af81cf32SBharata B Rao 614af81cf32SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); 615af81cf32SBharata B Rao if (drc) { 616af81cf32SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 617af81cf32SBharata B Rao drc_index = drck->get_index(drc); 618af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 619af81cf32SBharata B Rao } 6200da6f3feSBharata B Rao 6210da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6220da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6230da6f3feSBharata B Rao 6240da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 6250da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 6260da6f3feSBharata B Rao env->dcache_line_size))); 6270da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6280da6f3feSBharata B Rao env->dcache_line_size))); 6290da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6300da6f3feSBharata B Rao env->icache_line_size))); 6310da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6320da6f3feSBharata B Rao env->icache_line_size))); 6330da6f3feSBharata B Rao 6340da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 6350da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6360da6f3feSBharata B Rao pcc->l1_dcache_size))); 6370da6f3feSBharata B Rao } else { 638ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 dcache size for cpu"); 6390da6f3feSBharata B Rao } 6400da6f3feSBharata B Rao if (pcc->l1_icache_size) { 6410da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 6420da6f3feSBharata B Rao pcc->l1_icache_size))); 6430da6f3feSBharata B Rao } else { 644ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 icache size for cpu"); 6450da6f3feSBharata B Rao } 6460da6f3feSBharata B Rao 6470da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 6480da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 649fd5da5c4SThomas Huth _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); 6500da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 6510da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 6520da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 6530da6f3feSBharata B Rao 6540da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 6550da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 6560da6f3feSBharata B Rao } 6570da6f3feSBharata B Rao 6580da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 6590da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 6600da6f3feSBharata B Rao segs, sizeof(segs)))); 6610da6f3feSBharata B Rao } 6620da6f3feSBharata B Rao 6630da6f3feSBharata B Rao /* Advertise VMX/VSX (vector extensions) if available 6640da6f3feSBharata B Rao * 0 / no property == no vector extensions 6650da6f3feSBharata B Rao * 1 == VMX / Altivec available 6660da6f3feSBharata B Rao * 2 == VSX available */ 6670da6f3feSBharata B Rao if (env->insns_flags & PPC_ALTIVEC) { 6680da6f3feSBharata B Rao uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 6690da6f3feSBharata B Rao 6700da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 6710da6f3feSBharata B Rao } 6720da6f3feSBharata B Rao 6730da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 6740da6f3feSBharata B Rao * 0 / no property == no DFP 6750da6f3feSBharata B Rao * 1 == DFP available */ 6760da6f3feSBharata B Rao if (env->insns_flags2 & PPC2_DFP) { 6770da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 6780da6f3feSBharata B Rao } 6790da6f3feSBharata B Rao 6803654fa95SCédric Le Goater page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, 6810da6f3feSBharata B Rao sizeof(page_sizes_prop)); 6820da6f3feSBharata B Rao if (page_sizes_prop_size) { 6830da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 6840da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 6850da6f3feSBharata B Rao } 6860da6f3feSBharata B Rao 687230bf719SThomas Huth spapr_populate_pa_features(env, fdt, offset); 68890da0d5aSBenjamin Herrenschmidt 6890da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 69022419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 6910da6f3feSBharata B Rao 6920da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 6930da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 6940da6f3feSBharata B Rao 6950da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 6960da6f3feSBharata B Rao 6970da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 6980da6f3feSBharata B Rao ppc_get_compat_smt_threads(cpu))); 6990da6f3feSBharata B Rao } 7000da6f3feSBharata B Rao 7010da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 7020da6f3feSBharata B Rao { 7030da6f3feSBharata B Rao CPUState *cs; 7040da6f3feSBharata B Rao int cpus_offset; 7050da6f3feSBharata B Rao char *nodename; 7060da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 7070da6f3feSBharata B Rao 7080da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 7090da6f3feSBharata B Rao _FDT(cpus_offset); 7100da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 7110da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 7120da6f3feSBharata B Rao 7130da6f3feSBharata B Rao /* 7140da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 7150da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 7160da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 7170da6f3feSBharata B Rao */ 7180da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 7190da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 7200da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 7210da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 7220da6f3feSBharata B Rao int offset; 7230da6f3feSBharata B Rao 7240da6f3feSBharata B Rao if ((index % smt) != 0) { 7250da6f3feSBharata B Rao continue; 7260da6f3feSBharata B Rao } 7270da6f3feSBharata B Rao 7280da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 7290da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 7300da6f3feSBharata B Rao g_free(nodename); 7310da6f3feSBharata B Rao _FDT(offset); 7320da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 7330da6f3feSBharata B Rao } 7340da6f3feSBharata B Rao 7350da6f3feSBharata B Rao } 7360da6f3feSBharata B Rao 73703d196b7SBharata B Rao /* 73803d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 73903d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 74003d196b7SBharata B Rao * of this device tree node. 74103d196b7SBharata B Rao */ 74203d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 74303d196b7SBharata B Rao { 74403d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 74503d196b7SBharata B Rao int ret, i, offset; 74603d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 74703d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 748d0e5a8f2SBharata B Rao uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; 749d0e5a8f2SBharata B Rao uint32_t nr_lmbs = (spapr->hotplug_memory.base + 750d0e5a8f2SBharata B Rao memory_region_size(&spapr->hotplug_memory.mr)) / 751d0e5a8f2SBharata B Rao lmb_size; 75203d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 7536663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 75403d196b7SBharata B Rao 755ef001f06SThomas Huth /* 756d0e5a8f2SBharata B Rao * Don't create the node if there is no hotpluggable memory 75716c25aefSBharata B Rao */ 758d0e5a8f2SBharata B Rao if (machine->ram_size == machine->maxram_size) { 75916c25aefSBharata B Rao return 0; 76016c25aefSBharata B Rao } 76116c25aefSBharata B Rao 76216c25aefSBharata B Rao /* 763ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 764ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 765ef001f06SThomas Huth */ 766ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 767ef001f06SThomas Huth * sizeof(uint32_t); 76803d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 76903d196b7SBharata B Rao 77003d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 77103d196b7SBharata B Rao 77203d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 77303d196b7SBharata B Rao sizeof(prop_lmb_size)); 77403d196b7SBharata B Rao if (ret < 0) { 77503d196b7SBharata B Rao goto out; 77603d196b7SBharata B Rao } 77703d196b7SBharata B Rao 77803d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 77903d196b7SBharata B Rao if (ret < 0) { 78003d196b7SBharata B Rao goto out; 78103d196b7SBharata B Rao } 78203d196b7SBharata B Rao 78303d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 78403d196b7SBharata B Rao if (ret < 0) { 78503d196b7SBharata B Rao goto out; 78603d196b7SBharata B Rao } 78703d196b7SBharata B Rao 78803d196b7SBharata B Rao /* ibm,dynamic-memory */ 78903d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 79003d196b7SBharata B Rao cur_index++; 79103d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 792d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 79303d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 79403d196b7SBharata B Rao 795d0e5a8f2SBharata B Rao if (i >= hotplug_lmb_start) { 796d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 797d0e5a8f2SBharata B Rao sPAPRDRConnectorClass *drck; 798d0e5a8f2SBharata B Rao 799d0e5a8f2SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); 80003d196b7SBharata B Rao g_assert(drc); 80103d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 80203d196b7SBharata B Rao 80303d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 80403d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 80503d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 80603d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 80703d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 808d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 80903d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 81003d196b7SBharata B Rao } else { 81103d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 81203d196b7SBharata B Rao } 813d0e5a8f2SBharata B Rao } else { 814d0e5a8f2SBharata B Rao /* 815d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 816d0e5a8f2SBharata B Rao * hotplug memory region -- all these are marked as reserved 817d0e5a8f2SBharata B Rao * and as having no valid DRC. 818d0e5a8f2SBharata B Rao */ 819d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 820d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 821d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 822d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 823d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 824d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 825d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 826d0e5a8f2SBharata B Rao } 82703d196b7SBharata B Rao 82803d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 82903d196b7SBharata B Rao } 83003d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 83103d196b7SBharata B Rao if (ret < 0) { 83203d196b7SBharata B Rao goto out; 83303d196b7SBharata B Rao } 83403d196b7SBharata B Rao 83503d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 83603d196b7SBharata B Rao cur_index = int_buf; 8376663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 83803d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 83903d196b7SBharata B Rao cur_index += 2; 8406663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 84103d196b7SBharata B Rao uint32_t associativity[] = { 84203d196b7SBharata B Rao cpu_to_be32(0x0), 84303d196b7SBharata B Rao cpu_to_be32(0x0), 84403d196b7SBharata B Rao cpu_to_be32(0x0), 84503d196b7SBharata B Rao cpu_to_be32(i) 84603d196b7SBharata B Rao }; 84703d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 84803d196b7SBharata B Rao cur_index += 4; 84903d196b7SBharata B Rao } 85003d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 85103d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 85203d196b7SBharata B Rao out: 85303d196b7SBharata B Rao g_free(int_buf); 85403d196b7SBharata B Rao return ret; 85503d196b7SBharata B Rao } 85603d196b7SBharata B Rao 85703d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 85803d196b7SBharata B Rao target_ulong addr, target_ulong size, 85903d196b7SBharata B Rao bool cpu_update, bool memory_update) 86003d196b7SBharata B Rao { 86103d196b7SBharata B Rao void *fdt, *fdt_skel; 86203d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 86303d196b7SBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 86403d196b7SBharata B Rao 86503d196b7SBharata B Rao size -= sizeof(hdr); 86603d196b7SBharata B Rao 86703d196b7SBharata B Rao /* Create sceleton */ 86803d196b7SBharata B Rao fdt_skel = g_malloc0(size); 86903d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 87003d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 87103d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 87203d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 87303d196b7SBharata B Rao fdt = g_malloc0(size); 87403d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 87503d196b7SBharata B Rao g_free(fdt_skel); 87603d196b7SBharata B Rao 87703d196b7SBharata B Rao /* Fixup cpu nodes */ 87803d196b7SBharata B Rao if (cpu_update) { 87903d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 88003d196b7SBharata B Rao } 88103d196b7SBharata B Rao 88216c25aefSBharata B Rao /* Generate ibm,dynamic-reconfiguration-memory node if required */ 88303d196b7SBharata B Rao if (memory_update && smc->dr_lmb_enabled) { 88403d196b7SBharata B Rao _FDT((spapr_populate_drconf_memory(spapr, fdt))); 88503d196b7SBharata B Rao } 88603d196b7SBharata B Rao 88703d196b7SBharata B Rao /* Pack resulting tree */ 88803d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 88903d196b7SBharata B Rao 89003d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 89103d196b7SBharata B Rao trace_spapr_cas_failed(size); 89203d196b7SBharata B Rao return -1; 89303d196b7SBharata B Rao } 89403d196b7SBharata B Rao 89503d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 89603d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 89703d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 89803d196b7SBharata B Rao g_free(fdt); 89903d196b7SBharata B Rao 90003d196b7SBharata B Rao return 0; 90103d196b7SBharata B Rao } 90203d196b7SBharata B Rao 90328e02042SDavid Gibson static void spapr_finalize_fdt(sPAPRMachineState *spapr, 90453018216SPaolo Bonzini hwaddr fdt_addr, 90553018216SPaolo Bonzini hwaddr rtas_addr, 90653018216SPaolo Bonzini hwaddr rtas_size) 90753018216SPaolo Bonzini { 9085b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 9093c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 910c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 9115b2128d2SAlexander Graf const char *boot_device = machine->boot_order; 91271461b0fSAlexey Kardashevskiy int ret, i; 91371461b0fSAlexey Kardashevskiy size_t cb = 0; 91471461b0fSAlexey Kardashevskiy char *bootlist; 91553018216SPaolo Bonzini void *fdt; 91653018216SPaolo Bonzini sPAPRPHBState *phb; 91753018216SPaolo Bonzini 91853018216SPaolo Bonzini fdt = g_malloc(FDT_MAX_SIZE); 91953018216SPaolo Bonzini 92053018216SPaolo Bonzini /* open out the base tree into a temp buffer for the final tweaks */ 92153018216SPaolo Bonzini _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); 92253018216SPaolo Bonzini 923e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 924e8f986fcSBharata B Rao if (ret < 0) { 925ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 926e8f986fcSBharata B Rao exit(1); 92753018216SPaolo Bonzini } 92853018216SPaolo Bonzini 92953018216SPaolo Bonzini ret = spapr_populate_vdevice(spapr->vio_bus, fdt); 93053018216SPaolo Bonzini if (ret < 0) { 931ce9863b7SCédric Le Goater error_report("couldn't setup vio devices in fdt"); 93253018216SPaolo Bonzini exit(1); 93353018216SPaolo Bonzini } 93453018216SPaolo Bonzini 9354d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 9364d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 9374d9392beSThomas Huth if (ret < 0) { 938ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 9394d9392beSThomas Huth exit(1); 9404d9392beSThomas Huth } 9414d9392beSThomas Huth } 9424d9392beSThomas Huth 94353018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 94453018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 94553018216SPaolo Bonzini if (ret < 0) { 946da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 94753018216SPaolo Bonzini exit(1); 94853018216SPaolo Bonzini } 949da34fed7SThomas Huth } 95053018216SPaolo Bonzini 95153018216SPaolo Bonzini /* RTAS */ 95253018216SPaolo Bonzini ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); 95353018216SPaolo Bonzini if (ret < 0) { 954ce9863b7SCédric Le Goater error_report("Couldn't set up RTAS device tree properties"); 95553018216SPaolo Bonzini } 95653018216SPaolo Bonzini 9570da6f3feSBharata B Rao /* cpus */ 9580da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 95953018216SPaolo Bonzini 96071461b0fSAlexey Kardashevskiy bootlist = get_boot_devices_list(&cb, true); 96171461b0fSAlexey Kardashevskiy if (cb && bootlist) { 96271461b0fSAlexey Kardashevskiy int offset = fdt_path_offset(fdt, "/chosen"); 96371461b0fSAlexey Kardashevskiy if (offset < 0) { 96471461b0fSAlexey Kardashevskiy exit(1); 96571461b0fSAlexey Kardashevskiy } 96671461b0fSAlexey Kardashevskiy for (i = 0; i < cb; i++) { 96771461b0fSAlexey Kardashevskiy if (bootlist[i] == '\n') { 96871461b0fSAlexey Kardashevskiy bootlist[i] = ' '; 96971461b0fSAlexey Kardashevskiy } 97071461b0fSAlexey Kardashevskiy 97171461b0fSAlexey Kardashevskiy } 97271461b0fSAlexey Kardashevskiy ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); 97371461b0fSAlexey Kardashevskiy } 97471461b0fSAlexey Kardashevskiy 9755b2128d2SAlexander Graf if (boot_device && strlen(boot_device)) { 9765b2128d2SAlexander Graf int offset = fdt_path_offset(fdt, "/chosen"); 9775b2128d2SAlexander Graf 9785b2128d2SAlexander Graf if (offset < 0) { 9795b2128d2SAlexander Graf exit(1); 9805b2128d2SAlexander Graf } 9815b2128d2SAlexander Graf fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device); 9825b2128d2SAlexander Graf } 9835b2128d2SAlexander Graf 98453018216SPaolo Bonzini if (!spapr->has_graphics) { 98553018216SPaolo Bonzini spapr_populate_chosen_stdout(fdt, spapr->vio_bus); 98653018216SPaolo Bonzini } 98753018216SPaolo Bonzini 988c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 989c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 990c20d332aSBharata B Rao } 991c20d332aSBharata B Rao 9923c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 993af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 994af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 995af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 996af81cf32SBharata B Rao if (ret < 0) { 997af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 998af81cf32SBharata B Rao exit(1); 999af81cf32SBharata B Rao } 1000af81cf32SBharata B Rao } 1001af81cf32SBharata B Rao 100253018216SPaolo Bonzini _FDT((fdt_pack(fdt))); 100353018216SPaolo Bonzini 100453018216SPaolo Bonzini if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1005730fce59SThomas Huth error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 100653018216SPaolo Bonzini fdt_totalsize(fdt), FDT_MAX_SIZE); 100753018216SPaolo Bonzini exit(1); 100853018216SPaolo Bonzini } 100953018216SPaolo Bonzini 1010ad440b4aSAndrew Jones qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 101153018216SPaolo Bonzini cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 101253018216SPaolo Bonzini 1013a21a7a70SGonglei g_free(bootlist); 101453018216SPaolo Bonzini g_free(fdt); 101553018216SPaolo Bonzini } 101653018216SPaolo Bonzini 101753018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 101853018216SPaolo Bonzini { 101953018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 102053018216SPaolo Bonzini } 102153018216SPaolo Bonzini 102253018216SPaolo Bonzini static void emulate_spapr_hypercall(PowerPCCPU *cpu) 102353018216SPaolo Bonzini { 102453018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 102553018216SPaolo Bonzini 102653018216SPaolo Bonzini if (msr_pr) { 102753018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 102853018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 102953018216SPaolo Bonzini } else { 103053018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 103153018216SPaolo Bonzini } 103253018216SPaolo Bonzini } 103353018216SPaolo Bonzini 1034e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1035e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1036e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1037e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1038e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1039e6b8fd24SSamuel Mendoza-Jonas 1040715c5407SDavid Gibson /* 1041715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1042715c5407SDavid Gibson */ 1043715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr) 1044715c5407SDavid Gibson { 1045715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1046715c5407SDavid Gibson return spapr->htab_fd; 1047715c5407SDavid Gibson } 1048715c5407SDavid Gibson 1049715c5407SDavid Gibson spapr->htab_fd = kvmppc_get_htab_fd(false); 1050715c5407SDavid Gibson if (spapr->htab_fd < 0) { 1051715c5407SDavid Gibson error_report("Unable to open fd for reading hash table from KVM: %s", 1052715c5407SDavid Gibson strerror(errno)); 1053715c5407SDavid Gibson } 1054715c5407SDavid Gibson 1055715c5407SDavid Gibson return spapr->htab_fd; 1056715c5407SDavid Gibson } 1057715c5407SDavid Gibson 1058715c5407SDavid Gibson static void close_htab_fd(sPAPRMachineState *spapr) 1059715c5407SDavid Gibson { 1060715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1061715c5407SDavid Gibson close(spapr->htab_fd); 1062715c5407SDavid Gibson } 1063715c5407SDavid Gibson spapr->htab_fd = -1; 1064715c5407SDavid Gibson } 1065715c5407SDavid Gibson 10668dfe8e7fSDavid Gibson static int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 10678dfe8e7fSDavid Gibson { 10688dfe8e7fSDavid Gibson int shift; 10698dfe8e7fSDavid Gibson 10708dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 10718dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 10728dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 10738dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 10748dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 10758dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 10768dfe8e7fSDavid Gibson return shift; 10778dfe8e7fSDavid Gibson } 10788dfe8e7fSDavid Gibson 1079c5f54f3eSDavid Gibson static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, 1080c5f54f3eSDavid Gibson Error **errp) 108153018216SPaolo Bonzini { 1082c5f54f3eSDavid Gibson long rc; 108353018216SPaolo Bonzini 1084c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 1085c5f54f3eSDavid Gibson g_free(spapr->htab); 1086c5f54f3eSDavid Gibson spapr->htab = NULL; 1087c5f54f3eSDavid Gibson spapr->htab_shift = 0; 1088c5f54f3eSDavid Gibson close_htab_fd(spapr); 108953018216SPaolo Bonzini 1090c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1091c5f54f3eSDavid Gibson if (rc < 0) { 1092c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1093c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1094c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1095c5f54f3eSDavid Gibson shift); 1096c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1097c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1098c5f54f3eSDavid Gibson } else if (rc > 0) { 1099c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1100c5f54f3eSDavid Gibson if (rc != shift) { 1101c5f54f3eSDavid Gibson error_setg(errp, 1102c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1103c5f54f3eSDavid Gibson shift, rc); 11047735fedaSBharata B Rao } 11057735fedaSBharata B Rao 110653018216SPaolo Bonzini spapr->htab_shift = shift; 1107c18ad9a5SDavid Gibson spapr->htab = NULL; 1108b817772aSBharata B Rao } else { 1109c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1110c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1111c5f54f3eSDavid Gibson int i; 111201a57972SSamuel Mendoza-Jonas 1113c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1114c5f54f3eSDavid Gibson if (!spapr->htab) { 1115c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1116c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1117c5f54f3eSDavid Gibson return; 1118b817772aSBharata B Rao } 1119b817772aSBharata B Rao 1120c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1121c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1122b817772aSBharata B Rao 1123c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1124c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 11257735fedaSBharata B Rao } 112653018216SPaolo Bonzini } 112753018216SPaolo Bonzini } 112853018216SPaolo Bonzini 11294f01a637SDavid Gibson static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 11309e3f9733SAlexander Graf { 11319e3f9733SAlexander Graf bool matched = false; 11329e3f9733SAlexander Graf 11339e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 11349e3f9733SAlexander Graf matched = true; 11359e3f9733SAlexander Graf } 11369e3f9733SAlexander Graf 11379e3f9733SAlexander Graf if (!matched) { 11389e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 11399e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 11409e3f9733SAlexander Graf exit(1); 11419e3f9733SAlexander Graf } 11429e3f9733SAlexander Graf } 11439e3f9733SAlexander Graf 114453018216SPaolo Bonzini static void ppc_spapr_reset(void) 114553018216SPaolo Bonzini { 1146c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1147c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1148182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1149b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1150259186a7SAndreas Färber 11519e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 11529e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 11539e3f9733SAlexander Graf 1154c5f54f3eSDavid Gibson /* Allocate and/or reset the hash page table */ 1155c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, 1156c5f54f3eSDavid Gibson spapr_hpt_shift_for_ramsize(machine->maxram_size), 1157c5f54f3eSDavid Gibson &error_fatal); 1158c5f54f3eSDavid Gibson 1159c5f54f3eSDavid Gibson /* Update the RMA size if necessary */ 1160c5f54f3eSDavid Gibson if (spapr->vrma_adjust) { 1161c5f54f3eSDavid Gibson spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1162c5f54f3eSDavid Gibson spapr->htab_shift); 1163c5f54f3eSDavid Gibson } 116453018216SPaolo Bonzini 116553018216SPaolo Bonzini qemu_devices_reset(); 116653018216SPaolo Bonzini 1167b7d1f77aSBenjamin Herrenschmidt /* 1168b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1169b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1170b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1171b7d1f77aSBenjamin Herrenschmidt */ 1172b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1173b7d1f77aSBenjamin Herrenschmidt spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1174b7d1f77aSBenjamin Herrenschmidt spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; 1175b7d1f77aSBenjamin Herrenschmidt 117653018216SPaolo Bonzini /* Load the fdt */ 117753018216SPaolo Bonzini spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr, 117853018216SPaolo Bonzini spapr->rtas_size); 117953018216SPaolo Bonzini 1180b7d1f77aSBenjamin Herrenschmidt /* Copy RTAS over */ 1181b7d1f77aSBenjamin Herrenschmidt cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob, 1182b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size); 1183b7d1f77aSBenjamin Herrenschmidt 118453018216SPaolo Bonzini /* Set up the entry state */ 1185182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1186182735efSAndreas Färber first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; 1187182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1188182735efSAndreas Färber first_cpu->halted = 0; 11891b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 119053018216SPaolo Bonzini 119153018216SPaolo Bonzini } 119253018216SPaolo Bonzini 119328e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 119453018216SPaolo Bonzini { 11952ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 11963978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 119753018216SPaolo Bonzini 11983978b863SPaolo Bonzini if (dinfo) { 11996231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 12006231a6daSMarkus Armbruster &error_fatal); 120153018216SPaolo Bonzini } 120253018216SPaolo Bonzini 120353018216SPaolo Bonzini qdev_init_nofail(dev); 120453018216SPaolo Bonzini 120553018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 120653018216SPaolo Bonzini } 120753018216SPaolo Bonzini 120828e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 120928df36a1SDavid Gibson { 121028df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 121128df36a1SDavid Gibson 121228df36a1SDavid Gibson qdev_init_nofail(dev); 121328df36a1SDavid Gibson spapr->rtc = dev; 121474e5ae28SDavid Gibson 121574e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 121674e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 121728df36a1SDavid Gibson } 121828df36a1SDavid Gibson 121953018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 122014c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 122153018216SPaolo Bonzini { 122253018216SPaolo Bonzini switch (vga_interface_type) { 122353018216SPaolo Bonzini case VGA_NONE: 12247effdaa3SMark Wu return false; 12257effdaa3SMark Wu case VGA_DEVICE: 12267effdaa3SMark Wu return true; 122753018216SPaolo Bonzini case VGA_STD: 1228b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 122953018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 123053018216SPaolo Bonzini default: 123114c6a894SDavid Gibson error_setg(errp, 123214c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 123314c6a894SDavid Gibson return false; 123453018216SPaolo Bonzini } 123553018216SPaolo Bonzini } 123653018216SPaolo Bonzini 1237880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1238880ae7deSDavid Gibson { 123928e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1240880ae7deSDavid Gibson int err = 0; 1241880ae7deSDavid Gibson 1242631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1243880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1244880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1245880ae7deSDavid Gibson * value into the RTC device */ 1246880ae7deSDavid Gibson if (version_id < 3) { 1247880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1248880ae7deSDavid Gibson } 1249880ae7deSDavid Gibson 1250880ae7deSDavid Gibson return err; 1251880ae7deSDavid Gibson } 1252880ae7deSDavid Gibson 1253880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1254880ae7deSDavid Gibson { 1255880ae7deSDavid Gibson return version_id < 3; 1256880ae7deSDavid Gibson } 1257880ae7deSDavid Gibson 12584be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 12594be21d56SDavid Gibson .name = "spapr", 1260880ae7deSDavid Gibson .version_id = 3, 12614be21d56SDavid Gibson .minimum_version_id = 1, 1262880ae7deSDavid Gibson .post_load = spapr_post_load, 12634be21d56SDavid Gibson .fields = (VMStateField[]) { 1264880ae7deSDavid Gibson /* used to be @next_irq */ 1265880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 12664be21d56SDavid Gibson 12674be21d56SDavid Gibson /* RTC offset */ 126828e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1269880ae7deSDavid Gibson 127028e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 12714be21d56SDavid Gibson VMSTATE_END_OF_LIST() 12724be21d56SDavid Gibson }, 12734be21d56SDavid Gibson }; 12744be21d56SDavid Gibson 12754be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 12764be21d56SDavid Gibson { 127728e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 12784be21d56SDavid Gibson 12794be21d56SDavid Gibson /* "Iteration" header */ 12804be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 12814be21d56SDavid Gibson 1282e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1283e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1284e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1285e68cb8b4SAlexey Kardashevskiy } else { 1286e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 12874be21d56SDavid Gibson } 12884be21d56SDavid Gibson 1289e68cb8b4SAlexey Kardashevskiy 1290e68cb8b4SAlexey Kardashevskiy return 0; 1291e68cb8b4SAlexey Kardashevskiy } 12924be21d56SDavid Gibson 129328e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 12944be21d56SDavid Gibson int64_t max_ns) 12954be21d56SDavid Gibson { 1296378bc217SDavid Gibson bool has_timeout = max_ns != -1; 12974be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 12984be21d56SDavid Gibson int index = spapr->htab_save_index; 1299bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13004be21d56SDavid Gibson 13014be21d56SDavid Gibson assert(spapr->htab_first_pass); 13024be21d56SDavid Gibson 13034be21d56SDavid Gibson do { 13044be21d56SDavid Gibson int chunkstart; 13054be21d56SDavid Gibson 13064be21d56SDavid Gibson /* Consume invalid HPTEs */ 13074be21d56SDavid Gibson while ((index < htabslots) 13084be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13094be21d56SDavid Gibson index++; 13104be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13114be21d56SDavid Gibson } 13124be21d56SDavid Gibson 13134be21d56SDavid Gibson /* Consume valid HPTEs */ 13144be21d56SDavid Gibson chunkstart = index; 1315338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13164be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13174be21d56SDavid Gibson index++; 13184be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13194be21d56SDavid Gibson } 13204be21d56SDavid Gibson 13214be21d56SDavid Gibson if (index > chunkstart) { 13224be21d56SDavid Gibson int n_valid = index - chunkstart; 13234be21d56SDavid Gibson 13244be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13254be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13264be21d56SDavid Gibson qemu_put_be16(f, 0); 13274be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13284be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13294be21d56SDavid Gibson 1330378bc217SDavid Gibson if (has_timeout && 1331378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13324be21d56SDavid Gibson break; 13334be21d56SDavid Gibson } 13344be21d56SDavid Gibson } 13354be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 13364be21d56SDavid Gibson 13374be21d56SDavid Gibson if (index >= htabslots) { 13384be21d56SDavid Gibson assert(index == htabslots); 13394be21d56SDavid Gibson index = 0; 13404be21d56SDavid Gibson spapr->htab_first_pass = false; 13414be21d56SDavid Gibson } 13424be21d56SDavid Gibson spapr->htab_save_index = index; 13434be21d56SDavid Gibson } 13444be21d56SDavid Gibson 134528e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 13464be21d56SDavid Gibson int64_t max_ns) 13474be21d56SDavid Gibson { 13484be21d56SDavid Gibson bool final = max_ns < 0; 13494be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 13504be21d56SDavid Gibson int examined = 0, sent = 0; 13514be21d56SDavid Gibson int index = spapr->htab_save_index; 1352bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13534be21d56SDavid Gibson 13544be21d56SDavid Gibson assert(!spapr->htab_first_pass); 13554be21d56SDavid Gibson 13564be21d56SDavid Gibson do { 13574be21d56SDavid Gibson int chunkstart, invalidstart; 13584be21d56SDavid Gibson 13594be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 13604be21d56SDavid Gibson while ((index < htabslots) 13614be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 13624be21d56SDavid Gibson index++; 13634be21d56SDavid Gibson examined++; 13644be21d56SDavid Gibson } 13654be21d56SDavid Gibson 13664be21d56SDavid Gibson chunkstart = index; 13674be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1368338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13694be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13704be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13714be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13724be21d56SDavid Gibson index++; 13734be21d56SDavid Gibson examined++; 13744be21d56SDavid Gibson } 13754be21d56SDavid Gibson 13764be21d56SDavid Gibson invalidstart = index; 13774be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1378338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 13794be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13804be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13814be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13824be21d56SDavid Gibson index++; 13834be21d56SDavid Gibson examined++; 13844be21d56SDavid Gibson } 13854be21d56SDavid Gibson 13864be21d56SDavid Gibson if (index > chunkstart) { 13874be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 13884be21d56SDavid Gibson int n_invalid = index - invalidstart; 13894be21d56SDavid Gibson 13904be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13914be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13924be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 13934be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13944be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13954be21d56SDavid Gibson sent += index - chunkstart; 13964be21d56SDavid Gibson 1397bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13984be21d56SDavid Gibson break; 13994be21d56SDavid Gibson } 14004be21d56SDavid Gibson } 14014be21d56SDavid Gibson 14024be21d56SDavid Gibson if (examined >= htabslots) { 14034be21d56SDavid Gibson break; 14044be21d56SDavid Gibson } 14054be21d56SDavid Gibson 14064be21d56SDavid Gibson if (index >= htabslots) { 14074be21d56SDavid Gibson assert(index == htabslots); 14084be21d56SDavid Gibson index = 0; 14094be21d56SDavid Gibson } 14104be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 14114be21d56SDavid Gibson 14124be21d56SDavid Gibson if (index >= htabslots) { 14134be21d56SDavid Gibson assert(index == htabslots); 14144be21d56SDavid Gibson index = 0; 14154be21d56SDavid Gibson } 14164be21d56SDavid Gibson 14174be21d56SDavid Gibson spapr->htab_save_index = index; 14184be21d56SDavid Gibson 1419e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 14204be21d56SDavid Gibson } 14214be21d56SDavid Gibson 1422e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1423e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1424e68cb8b4SAlexey Kardashevskiy 14254be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 14264be21d56SDavid Gibson { 142728e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1428715c5407SDavid Gibson int fd; 1429e68cb8b4SAlexey Kardashevskiy int rc = 0; 14304be21d56SDavid Gibson 14314be21d56SDavid Gibson /* Iteration header */ 14324be21d56SDavid Gibson qemu_put_be32(f, 0); 14334be21d56SDavid Gibson 1434e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1435e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1436e68cb8b4SAlexey Kardashevskiy 1437715c5407SDavid Gibson fd = get_htab_fd(spapr); 1438715c5407SDavid Gibson if (fd < 0) { 1439715c5407SDavid Gibson return fd; 144001a57972SSamuel Mendoza-Jonas } 144101a57972SSamuel Mendoza-Jonas 1442715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1443e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1444e68cb8b4SAlexey Kardashevskiy return rc; 1445e68cb8b4SAlexey Kardashevskiy } 1446e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 14474be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 14484be21d56SDavid Gibson } else { 1449e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 14504be21d56SDavid Gibson } 14514be21d56SDavid Gibson 14524be21d56SDavid Gibson /* End marker */ 14534be21d56SDavid Gibson qemu_put_be32(f, 0); 14544be21d56SDavid Gibson qemu_put_be16(f, 0); 14554be21d56SDavid Gibson qemu_put_be16(f, 0); 14564be21d56SDavid Gibson 1457e68cb8b4SAlexey Kardashevskiy return rc; 14584be21d56SDavid Gibson } 14594be21d56SDavid Gibson 14604be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 14614be21d56SDavid Gibson { 146228e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1463715c5407SDavid Gibson int fd; 14644be21d56SDavid Gibson 14654be21d56SDavid Gibson /* Iteration header */ 14664be21d56SDavid Gibson qemu_put_be32(f, 0); 14674be21d56SDavid Gibson 1468e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1469e68cb8b4SAlexey Kardashevskiy int rc; 1470e68cb8b4SAlexey Kardashevskiy 1471e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1472e68cb8b4SAlexey Kardashevskiy 1473715c5407SDavid Gibson fd = get_htab_fd(spapr); 1474715c5407SDavid Gibson if (fd < 0) { 1475715c5407SDavid Gibson return fd; 147601a57972SSamuel Mendoza-Jonas } 147701a57972SSamuel Mendoza-Jonas 1478715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 1479e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1480e68cb8b4SAlexey Kardashevskiy return rc; 1481e68cb8b4SAlexey Kardashevskiy } 1482e68cb8b4SAlexey Kardashevskiy } else { 1483378bc217SDavid Gibson if (spapr->htab_first_pass) { 1484378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 1485378bc217SDavid Gibson } 14864be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1487e68cb8b4SAlexey Kardashevskiy } 14884be21d56SDavid Gibson 14894be21d56SDavid Gibson /* End marker */ 14904be21d56SDavid Gibson qemu_put_be32(f, 0); 14914be21d56SDavid Gibson qemu_put_be16(f, 0); 14924be21d56SDavid Gibson qemu_put_be16(f, 0); 14934be21d56SDavid Gibson 14944be21d56SDavid Gibson return 0; 14954be21d56SDavid Gibson } 14964be21d56SDavid Gibson 14974be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 14984be21d56SDavid Gibson { 149928e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 15004be21d56SDavid Gibson uint32_t section_hdr; 1501e68cb8b4SAlexey Kardashevskiy int fd = -1; 15024be21d56SDavid Gibson 15034be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 150498a5d100SDavid Gibson error_report("htab_load() bad version"); 15054be21d56SDavid Gibson return -EINVAL; 15064be21d56SDavid Gibson } 15074be21d56SDavid Gibson 15084be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 15094be21d56SDavid Gibson 15104be21d56SDavid Gibson if (section_hdr) { 15119897e462SGreg Kurz Error *local_err = NULL; 1512c5f54f3eSDavid Gibson 1513c5f54f3eSDavid Gibson /* First section gives the htab size */ 1514c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 1515c5f54f3eSDavid Gibson if (local_err) { 1516c5f54f3eSDavid Gibson error_report_err(local_err); 15174be21d56SDavid Gibson return -EINVAL; 15184be21d56SDavid Gibson } 15194be21d56SDavid Gibson return 0; 15204be21d56SDavid Gibson } 15214be21d56SDavid Gibson 1522e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1523e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1524e68cb8b4SAlexey Kardashevskiy 1525e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1526e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 152798a5d100SDavid Gibson error_report("Unable to open fd to restore KVM hash table: %s", 1528e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1529e68cb8b4SAlexey Kardashevskiy } 1530e68cb8b4SAlexey Kardashevskiy } 1531e68cb8b4SAlexey Kardashevskiy 15324be21d56SDavid Gibson while (true) { 15334be21d56SDavid Gibson uint32_t index; 15344be21d56SDavid Gibson uint16_t n_valid, n_invalid; 15354be21d56SDavid Gibson 15364be21d56SDavid Gibson index = qemu_get_be32(f); 15374be21d56SDavid Gibson n_valid = qemu_get_be16(f); 15384be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 15394be21d56SDavid Gibson 15404be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 15414be21d56SDavid Gibson /* End of Stream */ 15424be21d56SDavid Gibson break; 15434be21d56SDavid Gibson } 15444be21d56SDavid Gibson 1545e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 15464be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 15474be21d56SDavid Gibson /* Bad index in stream */ 154898a5d100SDavid Gibson error_report( 154998a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 155098a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 15514be21d56SDavid Gibson return -EINVAL; 15524be21d56SDavid Gibson } 15534be21d56SDavid Gibson 1554e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 15554be21d56SDavid Gibson if (n_valid) { 15564be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 15574be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 15584be21d56SDavid Gibson } 15594be21d56SDavid Gibson if (n_invalid) { 15604be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 15614be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 15624be21d56SDavid Gibson } 1563e68cb8b4SAlexey Kardashevskiy } else { 1564e68cb8b4SAlexey Kardashevskiy int rc; 1565e68cb8b4SAlexey Kardashevskiy 1566e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1567e68cb8b4SAlexey Kardashevskiy 1568e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1569e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1570e68cb8b4SAlexey Kardashevskiy return rc; 1571e68cb8b4SAlexey Kardashevskiy } 1572e68cb8b4SAlexey Kardashevskiy } 1573e68cb8b4SAlexey Kardashevskiy } 1574e68cb8b4SAlexey Kardashevskiy 1575e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1576e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1577e68cb8b4SAlexey Kardashevskiy close(fd); 15784be21d56SDavid Gibson } 15794be21d56SDavid Gibson 15804be21d56SDavid Gibson return 0; 15814be21d56SDavid Gibson } 15824be21d56SDavid Gibson 1583c573fc03SThomas Huth static void htab_cleanup(void *opaque) 1584c573fc03SThomas Huth { 1585c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 1586c573fc03SThomas Huth 1587c573fc03SThomas Huth close_htab_fd(spapr); 1588c573fc03SThomas Huth } 1589c573fc03SThomas Huth 15904be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 15914be21d56SDavid Gibson .save_live_setup = htab_save_setup, 15924be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 1593a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 1594c573fc03SThomas Huth .cleanup = htab_cleanup, 15954be21d56SDavid Gibson .load_state = htab_load, 15964be21d56SDavid Gibson }; 15974be21d56SDavid Gibson 15985b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 15995b2128d2SAlexander Graf Error **errp) 16005b2128d2SAlexander Graf { 16015b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 16025b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 16035b2128d2SAlexander Graf } 16045b2128d2SAlexander Graf 1605224245bfSDavid Gibson /* 1606224245bfSDavid Gibson * Reset routine for LMB DR devices. 1607224245bfSDavid Gibson * 1608224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1609224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1610224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1611224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1612224245bfSDavid Gibson */ 1613224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1614224245bfSDavid Gibson { 1615224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1616224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1617224245bfSDavid Gibson 1618224245bfSDavid Gibson if (d) { 1619224245bfSDavid Gibson device_reset(d); 1620224245bfSDavid Gibson } 1621224245bfSDavid Gibson } 1622224245bfSDavid Gibson 1623224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1624224245bfSDavid Gibson { 1625224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1626224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1627e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1628224245bfSDavid Gibson int i; 1629224245bfSDavid Gibson 1630224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1631224245bfSDavid Gibson sPAPRDRConnector *drc; 1632224245bfSDavid Gibson uint64_t addr; 1633224245bfSDavid Gibson 1634e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1635224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1636224245bfSDavid Gibson addr/lmb_size); 1637224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1638224245bfSDavid Gibson } 1639224245bfSDavid Gibson } 1640224245bfSDavid Gibson 1641224245bfSDavid Gibson /* 1642224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1643224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1644224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1645224245bfSDavid Gibson */ 16467c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 1647224245bfSDavid Gibson { 1648224245bfSDavid Gibson int i; 1649224245bfSDavid Gibson 16507c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16517c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 16527c150d6fSDavid Gibson " is not aligned to %llu MiB", 16537c150d6fSDavid Gibson machine->ram_size, 1654224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16557c150d6fSDavid Gibson return; 16567c150d6fSDavid Gibson } 16577c150d6fSDavid Gibson 16587c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16597c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 16607c150d6fSDavid Gibson " is not aligned to %llu MiB", 16617c150d6fSDavid Gibson machine->ram_size, 16627c150d6fSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16637c150d6fSDavid Gibson return; 1664224245bfSDavid Gibson } 1665224245bfSDavid Gibson 1666224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1667224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 16687c150d6fSDavid Gibson error_setg(errp, 16697c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 16707c150d6fSDavid Gibson " is not aligned to %llu MiB", 16717c150d6fSDavid Gibson i, numa_info[i].node_mem, 1672224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16737c150d6fSDavid Gibson return; 1674224245bfSDavid Gibson } 1675224245bfSDavid Gibson } 1676224245bfSDavid Gibson } 1677224245bfSDavid Gibson 167853018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 16793ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 168053018216SPaolo Bonzini { 168128e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 16823c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1683224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 16843ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 16853ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 16863ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 168753018216SPaolo Bonzini PCIHostState *phb; 168853018216SPaolo Bonzini int i; 168953018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 169053018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1691658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1692658fa66bSAlexey Kardashevskiy void *rma = NULL; 169353018216SPaolo Bonzini hwaddr rma_alloc_size; 1694b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 169553018216SPaolo Bonzini uint32_t initrd_base = 0; 169653018216SPaolo Bonzini long kernel_size = 0, initrd_size = 0; 1697b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 169816457e7fSBenjamin Herrenschmidt bool kernel_le = false; 169953018216SPaolo Bonzini char *filename; 170094a94e4cSBharata B Rao int smt = kvmppc_smt_threads(); 170194a94e4cSBharata B Rao int spapr_cores = smp_cpus / smp_threads; 170294a94e4cSBharata B Rao int spapr_max_cores = max_cpus / smp_threads; 170394a94e4cSBharata B Rao 17043c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 170594a94e4cSBharata B Rao if (smp_cpus % smp_threads) { 170694a94e4cSBharata B Rao error_report("smp_cpus (%u) must be multiple of threads (%u)", 170794a94e4cSBharata B Rao smp_cpus, smp_threads); 170894a94e4cSBharata B Rao exit(1); 170994a94e4cSBharata B Rao } 171094a94e4cSBharata B Rao if (max_cpus % smp_threads) { 171194a94e4cSBharata B Rao error_report("max_cpus (%u) must be multiple of threads (%u)", 171294a94e4cSBharata B Rao max_cpus, smp_threads); 171394a94e4cSBharata B Rao exit(1); 171494a94e4cSBharata B Rao } 171594a94e4cSBharata B Rao } 171653018216SPaolo Bonzini 1717226419d6SMichael S. Tsirkin msi_nonbroken = true; 171853018216SPaolo Bonzini 171953018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 172053018216SPaolo Bonzini 172153018216SPaolo Bonzini cpu_ppc_hypercall = emulate_spapr_hypercall; 172253018216SPaolo Bonzini 172353018216SPaolo Bonzini /* Allocate RMA if necessary */ 1724658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 172553018216SPaolo Bonzini 172653018216SPaolo Bonzini if (rma_alloc_size == -1) { 1727730fce59SThomas Huth error_report("Unable to create RMA"); 172853018216SPaolo Bonzini exit(1); 172953018216SPaolo Bonzini } 173053018216SPaolo Bonzini 1731c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 173253018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 173353018216SPaolo Bonzini } else { 1734c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 173553018216SPaolo Bonzini 173653018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 173753018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 173853018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 173953018216SPaolo Bonzini * 174053018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 174153018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 174253018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 174353018216SPaolo Bonzini * isn't determined yet. 174453018216SPaolo Bonzini */ 174553018216SPaolo Bonzini if (kvm_enabled()) { 174653018216SPaolo Bonzini spapr->vrma_adjust = 1; 174753018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 174853018216SPaolo Bonzini } 1749912acdf4SBenjamin Herrenschmidt 1750912acdf4SBenjamin Herrenschmidt /* Actually we don't support unbounded RMA anymore since we 1751912acdf4SBenjamin Herrenschmidt * added proper emulation of HV mode. The max we can get is 1752912acdf4SBenjamin Herrenschmidt * 16G which also happens to be what we configure for PAPR 1753912acdf4SBenjamin Herrenschmidt * mode so make sure we don't do anything bigger than that 1754912acdf4SBenjamin Herrenschmidt */ 1755912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 175653018216SPaolo Bonzini } 175753018216SPaolo Bonzini 1758c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 1759d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 1760c4177479SAlexey Kardashevskiy spapr->rma_size); 1761c4177479SAlexey Kardashevskiy exit(1); 1762c4177479SAlexey Kardashevskiy } 1763c4177479SAlexey Kardashevskiy 1764b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 1765b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 176653018216SPaolo Bonzini 17677b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 176827f24582SBenjamin Herrenschmidt spapr->xics = xics_system_init(machine, 176994a94e4cSBharata B Rao DIV_ROUND_UP(max_cpus * smt, smp_threads), 1770161deaf2SBenjamin Herrenschmidt XICS_IRQS_SPAPR, &error_fatal); 17717b565160SDavid Gibson 1772224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 17737c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 1774224245bfSDavid Gibson } 1775224245bfSDavid Gibson 177653018216SPaolo Bonzini /* init CPUs */ 177719fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 17783daa4a9fSThomas Huth machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu; 177953018216SPaolo Bonzini } 178094a94e4cSBharata B Rao 1781e703d2f7SGreg Kurz ppc_cpu_parse_features(machine->cpu_model); 1782e703d2f7SGreg Kurz 17833c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 178494a94e4cSBharata B Rao char *type = spapr_get_cpu_core_type(machine->cpu_model); 178594a94e4cSBharata B Rao 17864babfaf0SThomas Huth if (type == NULL) { 1787caebf378SCédric Le Goater error_report("Unable to find sPAPR CPU Core definition"); 1788caebf378SCédric Le Goater exit(1); 1789caebf378SCédric Le Goater } 1790caebf378SCédric Le Goater 179194a94e4cSBharata B Rao spapr->cores = g_new0(Object *, spapr_max_cores); 1792af81cf32SBharata B Rao for (i = 0; i < spapr_max_cores; i++) { 179312bf2d33SGreg Kurz int core_id = i * smp_threads; 1794af81cf32SBharata B Rao sPAPRDRConnector *drc = 1795af81cf32SBharata B Rao spapr_dr_connector_new(OBJECT(spapr), 179612bf2d33SGreg Kurz SPAPR_DR_CONNECTOR_TYPE_CPU, 179712bf2d33SGreg Kurz (core_id / smp_threads) * smt); 1798af81cf32SBharata B Rao 1799af81cf32SBharata B Rao qemu_register_reset(spapr_drc_reset, drc); 1800af81cf32SBharata B Rao 1801af81cf32SBharata B Rao if (i < spapr_cores) { 1802caebf378SCédric Le Goater Object *core = object_new(type); 180394a94e4cSBharata B Rao object_property_set_int(core, smp_threads, "nr-threads", 180494a94e4cSBharata B Rao &error_fatal); 180512bf2d33SGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 180694a94e4cSBharata B Rao &error_fatal); 180794a94e4cSBharata B Rao object_property_set_bool(core, true, "realized", &error_fatal); 180894a94e4cSBharata B Rao } 1809af81cf32SBharata B Rao } 181094a94e4cSBharata B Rao g_free(type); 181194a94e4cSBharata B Rao } else { 181253018216SPaolo Bonzini for (i = 0; i < smp_cpus; i++) { 181394a94e4cSBharata B Rao PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model); 181453018216SPaolo Bonzini if (cpu == NULL) { 1815569f4967SDavid Gibson error_report("Unable to find PowerPC CPU definition"); 181653018216SPaolo Bonzini exit(1); 181753018216SPaolo Bonzini } 1818569f4967SDavid Gibson spapr_cpu_init(spapr, cpu, &error_fatal); 181953018216SPaolo Bonzini } 182094a94e4cSBharata B Rao } 182153018216SPaolo Bonzini 1822026bfd89SDavid Gibson if (kvm_enabled()) { 1823026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 1824026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 1825ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 18265145ad4fSNathan Whitehorn 18275145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 18285145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 1829026bfd89SDavid Gibson } 1830026bfd89SDavid Gibson 183153018216SPaolo Bonzini /* allocate RAM */ 1832f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 1833fb164994SDavid Gibson machine->ram_size); 1834f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 183553018216SPaolo Bonzini 1836658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 1837658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 1838658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 1839658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 1840658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 1841658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 1842658fa66bSAlexey Kardashevskiy } 1843658fa66bSAlexey Kardashevskiy 18444a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 18454a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 18464a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 184771c9a3ddSBharata B Rao /* 184871c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 184971c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 185071c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 185171c9a3ddSBharata B Rao */ 185271c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 185371c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 18544a1c9cf0SBharata B Rao 185571c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 185671c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 185771c9a3ddSBharata B Rao } 185871c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 1859d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 1860d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 186171c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 1862d54e4d76SDavid Gibson exit(1); 18634a1c9cf0SBharata B Rao } 18644a1c9cf0SBharata B Rao 18654a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 18664a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 18674a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 18684a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 18694a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 18704a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 18714a1c9cf0SBharata B Rao } 18724a1c9cf0SBharata B Rao 1873224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1874224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 1875224245bfSDavid Gibson } 1876224245bfSDavid Gibson 187753018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 18784c56440dSStefan Weil if (!filename) { 1879730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 18804c56440dSStefan Weil exit(1); 18814c56440dSStefan Weil } 1882b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 18838afc22a2SZhou Jie if (spapr->rtas_size < 0) { 18848afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 18858afc22a2SZhou Jie exit(1); 18868afc22a2SZhou Jie } 1887b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 1888b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 1889730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 189053018216SPaolo Bonzini exit(1); 189153018216SPaolo Bonzini } 189253018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 1893730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 18942f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 189553018216SPaolo Bonzini exit(1); 189653018216SPaolo Bonzini } 189753018216SPaolo Bonzini g_free(filename); 189853018216SPaolo Bonzini 189953018216SPaolo Bonzini /* Set up EPOW events infrastructure */ 190053018216SPaolo Bonzini spapr_events_init(spapr); 190153018216SPaolo Bonzini 190212f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 190328df36a1SDavid Gibson spapr_rtc_create(spapr); 190412f42174SDavid Gibson 190553018216SPaolo Bonzini /* Set up VIO bus */ 190653018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 190753018216SPaolo Bonzini 190853018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 190953018216SPaolo Bonzini if (serial_hds[i]) { 191053018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 191153018216SPaolo Bonzini } 191253018216SPaolo Bonzini } 191353018216SPaolo Bonzini 191453018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 191553018216SPaolo Bonzini spapr_create_nvram(spapr); 191653018216SPaolo Bonzini 191753018216SPaolo Bonzini /* Set up PCI */ 191853018216SPaolo Bonzini spapr_pci_rtas_init(); 191953018216SPaolo Bonzini 192089dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 192153018216SPaolo Bonzini 192253018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 192353018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 192453018216SPaolo Bonzini 192553018216SPaolo Bonzini if (!nd->model) { 192653018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 192753018216SPaolo Bonzini } 192853018216SPaolo Bonzini 192953018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 193053018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 193153018216SPaolo Bonzini } else { 193229b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 193353018216SPaolo Bonzini } 193453018216SPaolo Bonzini } 193553018216SPaolo Bonzini 193653018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 193753018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 193853018216SPaolo Bonzini } 193953018216SPaolo Bonzini 194053018216SPaolo Bonzini /* Graphics */ 194114c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 194253018216SPaolo Bonzini spapr->has_graphics = true; 1943c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 194453018216SPaolo Bonzini } 194553018216SPaolo Bonzini 19464ee9ced9SMarcel Apfelbaum if (machine->usb) { 194757040d45SThomas Huth if (smc->use_ohci_by_default) { 194853018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 194957040d45SThomas Huth } else { 195057040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 195157040d45SThomas Huth } 1952c86580b8SMarkus Armbruster 195353018216SPaolo Bonzini if (spapr->has_graphics) { 1954c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 1955c86580b8SMarkus Armbruster 1956c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 1957c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 195853018216SPaolo Bonzini } 195953018216SPaolo Bonzini } 196053018216SPaolo Bonzini 196153018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 1962d54e4d76SDavid Gibson error_report( 1963d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 1964d54e4d76SDavid Gibson MIN_RMA_SLOF); 196553018216SPaolo Bonzini exit(1); 196653018216SPaolo Bonzini } 196753018216SPaolo Bonzini 196853018216SPaolo Bonzini if (kernel_filename) { 196953018216SPaolo Bonzini uint64_t lowaddr = 0; 197053018216SPaolo Bonzini 197153018216SPaolo Bonzini kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, 19727ef295eaSPeter Crosthwaite NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 19737ef295eaSPeter Crosthwaite 0, 0); 19743b66da82SAlexey Kardashevskiy if (kernel_size == ELF_LOAD_WRONG_ENDIAN) { 197516457e7fSBenjamin Herrenschmidt kernel_size = load_elf(kernel_filename, 197616457e7fSBenjamin Herrenschmidt translate_kernel_address, NULL, 19777ef295eaSPeter Crosthwaite NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 19787ef295eaSPeter Crosthwaite 0, 0); 197916457e7fSBenjamin Herrenschmidt kernel_le = kernel_size > 0; 198016457e7fSBenjamin Herrenschmidt } 198116457e7fSBenjamin Herrenschmidt if (kernel_size < 0) { 1982d54e4d76SDavid Gibson error_report("error loading %s: %s", 19833b66da82SAlexey Kardashevskiy kernel_filename, load_elf_strerror(kernel_size)); 198453018216SPaolo Bonzini exit(1); 198553018216SPaolo Bonzini } 198653018216SPaolo Bonzini 198753018216SPaolo Bonzini /* load initrd */ 198853018216SPaolo Bonzini if (initrd_filename) { 198953018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 199053018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 199153018216SPaolo Bonzini */ 199253018216SPaolo Bonzini initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff; 199353018216SPaolo Bonzini initrd_size = load_image_targphys(initrd_filename, initrd_base, 199453018216SPaolo Bonzini load_limit - initrd_base); 199553018216SPaolo Bonzini if (initrd_size < 0) { 1996d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 199753018216SPaolo Bonzini initrd_filename); 199853018216SPaolo Bonzini exit(1); 199953018216SPaolo Bonzini } 200053018216SPaolo Bonzini } else { 200153018216SPaolo Bonzini initrd_base = 0; 200253018216SPaolo Bonzini initrd_size = 0; 200353018216SPaolo Bonzini } 200453018216SPaolo Bonzini } 200553018216SPaolo Bonzini 20068e7ea787SAndreas Färber if (bios_name == NULL) { 20078e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 20088e7ea787SAndreas Färber } 20098e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 20104c56440dSStefan Weil if (!filename) { 201168fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 20124c56440dSStefan Weil exit(1); 20134c56440dSStefan Weil } 201453018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 201568fea5a0SThomas Huth if (fw_size <= 0) { 201668fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 201753018216SPaolo Bonzini exit(1); 201853018216SPaolo Bonzini } 201953018216SPaolo Bonzini g_free(filename); 202053018216SPaolo Bonzini 202128e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 202228e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 202328e02042SDavid Gibson * which predated MachineState but had a similar function */ 20244be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 20254be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 20264be21d56SDavid Gibson &savevm_htab_handlers, spapr); 20274be21d56SDavid Gibson 202853018216SPaolo Bonzini /* Prepare the device tree */ 20293bbf37f2SAndreas Färber spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size, 203016457e7fSBenjamin Herrenschmidt kernel_size, kernel_le, 203131fe14d1SNathan Fontenot kernel_cmdline, 203231fe14d1SNathan Fontenot spapr->check_exception_irq); 203353018216SPaolo Bonzini assert(spapr->fdt_skel != NULL); 20345b2128d2SAlexander Graf 203546503c2bSMichael Roth /* used by RTAS */ 203646503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 203746503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 203846503c2bSMichael Roth 20395b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 204053018216SPaolo Bonzini } 204153018216SPaolo Bonzini 2042135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 2043135a129aSAneesh Kumar K.V { 2044135a129aSAneesh Kumar K.V if (!vm_type) { 2045135a129aSAneesh Kumar K.V return 0; 2046135a129aSAneesh Kumar K.V } 2047135a129aSAneesh Kumar K.V 2048135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 2049135a129aSAneesh Kumar K.V return 1; 2050135a129aSAneesh Kumar K.V } 2051135a129aSAneesh Kumar K.V 2052135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2053135a129aSAneesh Kumar K.V return 2; 2054135a129aSAneesh Kumar K.V } 2055135a129aSAneesh Kumar K.V 2056135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2057135a129aSAneesh Kumar K.V exit(1); 2058135a129aSAneesh Kumar K.V } 2059135a129aSAneesh Kumar K.V 206071461b0fSAlexey Kardashevskiy /* 2061627b84f4SGonglei * Implementation of an interface to adjust firmware path 206271461b0fSAlexey Kardashevskiy * for the bootindex property handling. 206371461b0fSAlexey Kardashevskiy */ 206471461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 206571461b0fSAlexey Kardashevskiy DeviceState *dev) 206671461b0fSAlexey Kardashevskiy { 206771461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 206871461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 206971461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 207071461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 207171461b0fSAlexey Kardashevskiy 207271461b0fSAlexey Kardashevskiy if (d) { 207371461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 207471461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 207571461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 207671461b0fSAlexey Kardashevskiy 207771461b0fSAlexey Kardashevskiy if (spapr) { 207871461b0fSAlexey Kardashevskiy /* 207971461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 208071461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 208171461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 208271461b0fSAlexey Kardashevskiy */ 208371461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 208471461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 208571461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 208671461b0fSAlexey Kardashevskiy } else if (virtio) { 208771461b0fSAlexey Kardashevskiy /* 208871461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 208971461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 209071461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 209171461b0fSAlexey Kardashevskiy * the actual binding is: 209271461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 209371461b0fSAlexey Kardashevskiy */ 209471461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 209571461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 209671461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 209771461b0fSAlexey Kardashevskiy } else if (usb) { 209871461b0fSAlexey Kardashevskiy /* 209971461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 210071461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 210171461b0fSAlexey Kardashevskiy */ 210271461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 210371461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 210471461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 210571461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 210671461b0fSAlexey Kardashevskiy } 210771461b0fSAlexey Kardashevskiy } 210871461b0fSAlexey Kardashevskiy 210971461b0fSAlexey Kardashevskiy if (phb) { 211071461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 211171461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 211271461b0fSAlexey Kardashevskiy } 211371461b0fSAlexey Kardashevskiy 211471461b0fSAlexey Kardashevskiy return NULL; 211571461b0fSAlexey Kardashevskiy } 211671461b0fSAlexey Kardashevskiy 211723825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 211823825581SEduardo Habkost { 211928e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 212023825581SEduardo Habkost 212128e02042SDavid Gibson return g_strdup(spapr->kvm_type); 212223825581SEduardo Habkost } 212323825581SEduardo Habkost 212423825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 212523825581SEduardo Habkost { 212628e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 212723825581SEduardo Habkost 212828e02042SDavid Gibson g_free(spapr->kvm_type); 212928e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 213023825581SEduardo Habkost } 213123825581SEduardo Habkost 213223825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 213323825581SEduardo Habkost { 2134715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2135715c5407SDavid Gibson 2136715c5407SDavid Gibson spapr->htab_fd = -1; 213723825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 213823825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 213949d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 214049d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 214149d2e648SMarcel Apfelbaum NULL); 214223825581SEduardo Habkost } 214323825581SEduardo Habkost 214487bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 214587bbdd9cSDavid Gibson { 214687bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 214787bbdd9cSDavid Gibson 214887bbdd9cSDavid Gibson g_free(spapr->kvm_type); 214987bbdd9cSDavid Gibson } 215087bbdd9cSDavid Gibson 2151*14e6fe12SPaolo Bonzini static void ppc_cpu_do_nmi_on_cpu(CPUState *cs, run_on_cpu_data arg) 215234316482SAlexey Kardashevskiy { 215334316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 215434316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 215534316482SAlexey Kardashevskiy } 215634316482SAlexey Kardashevskiy 215734316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 215834316482SAlexey Kardashevskiy { 215934316482SAlexey Kardashevskiy CPUState *cs; 216034316482SAlexey Kardashevskiy 216134316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 2162*14e6fe12SPaolo Bonzini async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, RUN_ON_CPU_NULL); 216334316482SAlexey Kardashevskiy } 216434316482SAlexey Kardashevskiy } 216534316482SAlexey Kardashevskiy 2166c20d332aSBharata B Rao static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, 2167c20d332aSBharata B Rao uint32_t node, Error **errp) 2168c20d332aSBharata B Rao { 2169c20d332aSBharata B Rao sPAPRDRConnector *drc; 2170c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2171c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2172c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2173c20d332aSBharata B Rao void *fdt; 2174c20d332aSBharata B Rao 2175c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2176c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2177c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2178c20d332aSBharata B Rao g_assert(drc); 2179c20d332aSBharata B Rao 2180c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2181c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2182c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2183c20d332aSBharata B Rao 2184c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2185c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2186c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2187c20d332aSBharata B Rao } 21885dd5238cSJianjun Duan /* send hotplug notification to the 21895dd5238cSJianjun Duan * guest only in case of hotplugged memory 21905dd5238cSJianjun Duan */ 21915dd5238cSJianjun Duan if (dev->hotplugged) { 21920a417869SBharata B Rao spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); 2193c20d332aSBharata B Rao } 21945dd5238cSJianjun Duan } 2195c20d332aSBharata B Rao 2196c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2197c20d332aSBharata B Rao uint32_t node, Error **errp) 2198c20d332aSBharata B Rao { 2199c20d332aSBharata B Rao Error *local_err = NULL; 2200c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2201c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2202c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2203c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2204c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2205c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2206c20d332aSBharata B Rao uint64_t addr; 2207c20d332aSBharata B Rao 2208c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2209c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2210c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2211c20d332aSBharata B Rao goto out; 2212c20d332aSBharata B Rao } 2213c20d332aSBharata B Rao 2214d6a9b0b8SMichael S. Tsirkin pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 2215c20d332aSBharata B Rao if (local_err) { 2216c20d332aSBharata B Rao goto out; 2217c20d332aSBharata B Rao } 2218c20d332aSBharata B Rao 2219c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2220c20d332aSBharata B Rao if (local_err) { 2221c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2222c20d332aSBharata B Rao goto out; 2223c20d332aSBharata B Rao } 2224c20d332aSBharata B Rao 2225c20d332aSBharata B Rao spapr_add_lmbs(dev, addr, size, node, &error_abort); 2226c20d332aSBharata B Rao 2227c20d332aSBharata B Rao out: 2228c20d332aSBharata B Rao error_propagate(errp, local_err); 2229c20d332aSBharata B Rao } 2230c20d332aSBharata B Rao 2231af81cf32SBharata B Rao void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, 2232af81cf32SBharata B Rao sPAPRMachineState *spapr) 2233af81cf32SBharata B Rao { 2234af81cf32SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 2235af81cf32SBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 2236af81cf32SBharata B Rao int id = ppc_get_vcpu_dt_id(cpu); 2237af81cf32SBharata B Rao void *fdt; 2238af81cf32SBharata B Rao int offset, fdt_size; 2239af81cf32SBharata B Rao char *nodename; 2240af81cf32SBharata B Rao 2241af81cf32SBharata B Rao fdt = create_device_tree(&fdt_size); 2242af81cf32SBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 2243af81cf32SBharata B Rao offset = fdt_add_subnode(fdt, 0, nodename); 2244af81cf32SBharata B Rao 2245af81cf32SBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 2246af81cf32SBharata B Rao g_free(nodename); 2247af81cf32SBharata B Rao 2248af81cf32SBharata B Rao *fdt_offset = offset; 2249af81cf32SBharata B Rao return fdt; 2250af81cf32SBharata B Rao } 2251af81cf32SBharata B Rao 2252c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2253c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2254c20d332aSBharata B Rao { 2255c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2256c20d332aSBharata B Rao 2257c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2258b556854bSBharata B Rao int node; 2259c20d332aSBharata B Rao 2260c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2261c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2262c20d332aSBharata B Rao return; 2263c20d332aSBharata B Rao } 2264c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2265c20d332aSBharata B Rao if (*errp) { 2266c20d332aSBharata B Rao return; 2267c20d332aSBharata B Rao } 22681a5512bbSGonglei if (node < 0 || node >= MAX_NODES) { 22691a5512bbSGonglei error_setg(errp, "Invaild node %d", node); 22701a5512bbSGonglei return; 22711a5512bbSGonglei } 2272c20d332aSBharata B Rao 2273b556854bSBharata B Rao /* 2274b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2275b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2276b556854bSBharata B Rao * to the first node that has some memory. This causes two 2277b556854bSBharata B Rao * unexpected behaviours for the user. 2278b556854bSBharata B Rao * 2279b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2280b556854bSBharata B Rao * specified. 2281b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2282b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2283b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2284b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2285b556854bSBharata B Rao * 2286b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2287b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2288b556854bSBharata B Rao */ 2289b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2290b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2291b556854bSBharata B Rao node); 2292b556854bSBharata B Rao return; 2293b556854bSBharata B Rao } 2294b556854bSBharata B Rao 2295c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2296af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2297af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 2298c20d332aSBharata B Rao } 2299c20d332aSBharata B Rao } 2300c20d332aSBharata B Rao 2301c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2302c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2303c20d332aSBharata B Rao { 23043c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 23056f4b5c3eSBharata B Rao 2306c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2307c20d332aSBharata B Rao error_setg(errp, "Memory hot unplug not supported by sPAPR"); 23086f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 23093c0c47e3SDavid Gibson if (!mc->query_hotpluggable_cpus) { 23106f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 23116f4b5c3eSBharata B Rao return; 23126f4b5c3eSBharata B Rao } 23136f4b5c3eSBharata B Rao spapr_core_unplug(hotplug_dev, dev, errp); 2314c20d332aSBharata B Rao } 2315c20d332aSBharata B Rao } 2316c20d332aSBharata B Rao 231794a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 231894a94e4cSBharata B Rao DeviceState *dev, Error **errp) 231994a94e4cSBharata B Rao { 232094a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 232194a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 232294a94e4cSBharata B Rao } 232394a94e4cSBharata B Rao } 232494a94e4cSBharata B Rao 23257ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 2326c20d332aSBharata B Rao DeviceState *dev) 2327c20d332aSBharata B Rao { 232894a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 232994a94e4cSBharata B Rao object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2330c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2331c20d332aSBharata B Rao } 2332c20d332aSBharata B Rao return NULL; 2333c20d332aSBharata B Rao } 2334c20d332aSBharata B Rao 233520bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) 233620bb648dSDavid Gibson { 233720bb648dSDavid Gibson /* Allocate to NUMA nodes on a "socket" basis (not that concept of 233820bb648dSDavid Gibson * socket means much for the paravirtualized PAPR platform) */ 233920bb648dSDavid Gibson return cpu_index / smp_threads / smp_cores; 234020bb648dSDavid Gibson } 234120bb648dSDavid Gibson 23422474bfd4SIgor Mammedov static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine) 23432474bfd4SIgor Mammedov { 23442474bfd4SIgor Mammedov int i; 23452474bfd4SIgor Mammedov HotpluggableCPUList *head = NULL; 23462474bfd4SIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 23472474bfd4SIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 23482474bfd4SIgor Mammedov 23492474bfd4SIgor Mammedov for (i = 0; i < spapr_max_cores; i++) { 23502474bfd4SIgor Mammedov HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); 23512474bfd4SIgor Mammedov HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); 23522474bfd4SIgor Mammedov CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1); 23532474bfd4SIgor Mammedov 23542474bfd4SIgor Mammedov cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model); 23552474bfd4SIgor Mammedov cpu_item->vcpus_count = smp_threads; 235627393c33SPeter Krempa cpu_props->has_core_id = true; 235712bf2d33SGreg Kurz cpu_props->core_id = i * smp_threads; 23582474bfd4SIgor Mammedov /* TODO: add 'has_node/node' here to describe 23592474bfd4SIgor Mammedov to which node core belongs */ 23602474bfd4SIgor Mammedov 23612474bfd4SIgor Mammedov cpu_item->props = cpu_props; 23622474bfd4SIgor Mammedov if (spapr->cores[i]) { 23632474bfd4SIgor Mammedov cpu_item->has_qom_path = true; 23642474bfd4SIgor Mammedov cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]); 23652474bfd4SIgor Mammedov } 23662474bfd4SIgor Mammedov list_item->value = cpu_item; 23672474bfd4SIgor Mammedov list_item->next = head; 23682474bfd4SIgor Mammedov head = list_item; 23692474bfd4SIgor Mammedov } 23702474bfd4SIgor Mammedov return head; 23712474bfd4SIgor Mammedov } 23722474bfd4SIgor Mammedov 23736737d9adSDavid Gibson static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, 2374daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 2375daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 23766737d9adSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 23776737d9adSDavid Gibson { 2378357d1e3bSDavid Gibson /* 2379357d1e3bSDavid Gibson * New-style PHB window placement. 2380357d1e3bSDavid Gibson * 2381357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 2382357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 2383357d1e3bSDavid Gibson * windows. 2384357d1e3bSDavid Gibson * 2385357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 2386357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 2387357d1e3bSDavid Gibson * 2388357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 2389357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 2390357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 2391357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 2392357d1e3bSDavid Gibson */ 23936737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 2394357d1e3bSDavid Gibson const int max_phbs = 2395357d1e3bSDavid Gibson (SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / SPAPR_PCI_MEM64_WIN_SIZE - 1; 23966737d9adSDavid Gibson int i; 23976737d9adSDavid Gibson 2398357d1e3bSDavid Gibson /* Sanity check natural alignments */ 2399357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 2400357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 2401357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 2402357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 2403357d1e3bSDavid Gibson /* Sanity check bounds */ 2404357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_IO_WIN_SIZE) > SPAPR_PCI_MEM32_WIN_SIZE); 2405357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_MEM32_WIN_SIZE) > SPAPR_PCI_MEM64_WIN_SIZE); 24062efff1c0SDavid Gibson 2407357d1e3bSDavid Gibson if (index >= max_phbs) { 24086737d9adSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 2409357d1e3bSDavid Gibson max_phbs - 1); 24106737d9adSDavid Gibson return; 24116737d9adSDavid Gibson } 24126737d9adSDavid Gibson 24136737d9adSDavid Gibson *buid = base_buid + index; 24146737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 24156737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 24166737d9adSDavid Gibson } 24176737d9adSDavid Gibson 2418357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 2419357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 2420357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 24216737d9adSDavid Gibson } 24226737d9adSDavid Gibson 242329ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 242453018216SPaolo Bonzini { 242529ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 2426224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 242771461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 242834316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 2429c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 243029ee3247SAlexey Kardashevskiy 24310eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 2432fc9f38c3SDavid Gibson 2433fc9f38c3SDavid Gibson /* 2434fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 2435fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 2436fc9f38c3SDavid Gibson * these details for backwards compatibility 2437fc9f38c3SDavid Gibson */ 2438958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 2439958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 2440958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 2441079019f2SIgor Mammedov mc->max_cpus = 255; 2442958db90cSMarcel Apfelbaum mc->no_parallel = 1; 24435b2128d2SAlexander Graf mc->default_boot_order = ""; 2444a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 2445958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 24469e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 2447e4024630SLaurent Vivier mc->pci_allow_0_address = true; 24487ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 244994a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 2450c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 2451c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 245220bb648dSDavid Gibson mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; 245300b4fbe2SMarcel Apfelbaum 2454fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 24553daa4a9fSThomas Huth smc->tcg_default_cpu = "POWER8"; 24563c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus; 245771461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 245834316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 24596737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 246053018216SPaolo Bonzini } 246153018216SPaolo Bonzini 246229ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 246329ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 246429ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 24654aee7362SDavid Gibson .abstract = true, 24666ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 246723825581SEduardo Habkost .instance_init = spapr_machine_initfn, 246887bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 2469183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 247029ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 247171461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 247271461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 247334316482SAlexey Kardashevskiy { TYPE_NMI }, 2474c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 247571461b0fSAlexey Kardashevskiy { } 247671461b0fSAlexey Kardashevskiy }, 247729ee3247SAlexey Kardashevskiy }; 247829ee3247SAlexey Kardashevskiy 2479fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 24805013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 24815013c547SDavid Gibson void *data) \ 24825013c547SDavid Gibson { \ 24835013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 24845013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 2485fccbc785SDavid Gibson if (latest) { \ 2486fccbc785SDavid Gibson mc->alias = "pseries"; \ 2487fccbc785SDavid Gibson mc->is_default = 1; \ 2488fccbc785SDavid Gibson } \ 24895013c547SDavid Gibson } \ 24905013c547SDavid Gibson static void spapr_machine_##suffix##_instance_init(Object *obj) \ 24915013c547SDavid Gibson { \ 24925013c547SDavid Gibson MachineState *machine = MACHINE(obj); \ 24935013c547SDavid Gibson spapr_machine_##suffix##_instance_options(machine); \ 24945013c547SDavid Gibson } \ 24955013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 24965013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 24975013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 24985013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 24995013c547SDavid Gibson .instance_init = spapr_machine_##suffix##_instance_init, \ 25005013c547SDavid Gibson }; \ 25015013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 25025013c547SDavid Gibson { \ 25035013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 25045013c547SDavid Gibson } \ 25050e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 25065013c547SDavid Gibson 25071c5f29bbSDavid Gibson /* 2508db800b21SDavid Gibson * pseries-2.8 2509db800b21SDavid Gibson */ 2510db800b21SDavid Gibson static void spapr_machine_2_8_instance_options(MachineState *machine) 2511db800b21SDavid Gibson { 2512db800b21SDavid Gibson } 2513db800b21SDavid Gibson 2514db800b21SDavid Gibson static void spapr_machine_2_8_class_options(MachineClass *mc) 2515db800b21SDavid Gibson { 2516db800b21SDavid Gibson /* Defaults for the latest behaviour inherited from the base class */ 2517db800b21SDavid Gibson } 2518db800b21SDavid Gibson 2519db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", true); 2520db800b21SDavid Gibson 2521db800b21SDavid Gibson /* 25221ea1eefcSBharata B Rao * pseries-2.7 25231ea1eefcSBharata B Rao */ 2524db800b21SDavid Gibson #define SPAPR_COMPAT_2_7 \ 2525db800b21SDavid Gibson HW_COMPAT_2_7 \ 2526357d1e3bSDavid Gibson { \ 2527357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 2528357d1e3bSDavid Gibson .property = "mem_win_size", \ 2529357d1e3bSDavid Gibson .value = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\ 2530357d1e3bSDavid Gibson }, \ 2531357d1e3bSDavid Gibson { \ 2532357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 2533357d1e3bSDavid Gibson .property = "mem64_win_size", \ 2534357d1e3bSDavid Gibson .value = "0", \ 2535357d1e3bSDavid Gibson }, 2536357d1e3bSDavid Gibson 2537357d1e3bSDavid Gibson static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, 2538357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 2539357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 2540357d1e3bSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 2541357d1e3bSDavid Gibson { 2542357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 2543357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 2544357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 2545357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 2546357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 2547357d1e3bSDavid Gibson const uint32_t max_index = 255; 2548357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 2549357d1e3bSDavid Gibson 2550357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 2551357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 2552357d1e3bSDavid Gibson int i; 2553357d1e3bSDavid Gibson 2554357d1e3bSDavid Gibson /* Do we have hotpluggable memory? */ 2555357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 2556357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 2557357d1e3bSDavid Gibson * alignment gap between normal and hotpluggable memory 2558357d1e3bSDavid Gibson * regions */ 2559357d1e3bSDavid Gibson ram_top = spapr->hotplug_memory.base + 2560357d1e3bSDavid Gibson memory_region_size(&spapr->hotplug_memory.mr); 2561357d1e3bSDavid Gibson } 2562357d1e3bSDavid Gibson 2563357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 2564357d1e3bSDavid Gibson 2565357d1e3bSDavid Gibson if (index > max_index) { 2566357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 2567357d1e3bSDavid Gibson max_index); 2568357d1e3bSDavid Gibson return; 2569357d1e3bSDavid Gibson } 2570357d1e3bSDavid Gibson 2571357d1e3bSDavid Gibson *buid = base_buid + index; 2572357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 2573357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 2574357d1e3bSDavid Gibson } 2575357d1e3bSDavid Gibson 2576357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 2577357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 2578357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 2579357d1e3bSDavid Gibson /* 2580357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 2581357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 2582357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 2583357d1e3bSDavid Gibson */ 2584357d1e3bSDavid Gibson } 2585db800b21SDavid Gibson 25861ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine) 25871ea1eefcSBharata B Rao { 2588672de881SMichael Roth spapr_machine_2_8_instance_options(machine); 25891ea1eefcSBharata B Rao } 25901ea1eefcSBharata B Rao 25911ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 25921ea1eefcSBharata B Rao { 25933daa4a9fSThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 25943daa4a9fSThomas Huth 2595db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 25963daa4a9fSThomas Huth smc->tcg_default_cpu = "POWER7"; 2597db800b21SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7); 2598357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 25991ea1eefcSBharata B Rao } 26001ea1eefcSBharata B Rao 2601db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 26021ea1eefcSBharata B Rao 26031ea1eefcSBharata B Rao /* 26044b23699cSDavid Gibson * pseries-2.6 26054b23699cSDavid Gibson */ 26061ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \ 2607ae4de14cSAlexey Kardashevskiy HW_COMPAT_2_6 \ 2608ae4de14cSAlexey Kardashevskiy { \ 2609ae4de14cSAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2610ae4de14cSAlexey Kardashevskiy .property = "ddw",\ 2611ae4de14cSAlexey Kardashevskiy .value = stringify(off),\ 2612ae4de14cSAlexey Kardashevskiy }, 26131ea1eefcSBharata B Rao 26144b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine) 26154b23699cSDavid Gibson { 2616672de881SMichael Roth spapr_machine_2_7_instance_options(machine); 26174b23699cSDavid Gibson } 26184b23699cSDavid Gibson 26194b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc) 26204b23699cSDavid Gibson { 26211ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 26223c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = NULL; 26231ea1eefcSBharata B Rao SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); 26244b23699cSDavid Gibson } 26254b23699cSDavid Gibson 26261ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 26274b23699cSDavid Gibson 26284b23699cSDavid Gibson /* 26291c5f29bbSDavid Gibson * pseries-2.5 26301c5f29bbSDavid Gibson */ 26314b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \ 263257c522f4SThomas Huth HW_COMPAT_2_5 \ 263357c522f4SThomas Huth { \ 263457c522f4SThomas Huth .driver = "spapr-vlan", \ 263557c522f4SThomas Huth .property = "use-rx-buffer-pools", \ 263657c522f4SThomas Huth .value = "off", \ 263757c522f4SThomas Huth }, 26384b23699cSDavid Gibson 26395013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine) 26401c5f29bbSDavid Gibson { 2641672de881SMichael Roth spapr_machine_2_6_instance_options(machine); 26425013c547SDavid Gibson } 26435013c547SDavid Gibson 26445013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc) 26455013c547SDavid Gibson { 264657040d45SThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 264757040d45SThomas Huth 26484b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 264957040d45SThomas Huth smc->use_ohci_by_default = true; 26504b23699cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5); 26511c5f29bbSDavid Gibson } 26521c5f29bbSDavid Gibson 26534b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 26541c5f29bbSDavid Gibson 26551c5f29bbSDavid Gibson /* 26561c5f29bbSDavid Gibson * pseries-2.4 26571c5f29bbSDavid Gibson */ 265880fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \ 265980fd50f9SCornelia Huck HW_COMPAT_2_4 266080fd50f9SCornelia Huck 26615013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine) 26621c5f29bbSDavid Gibson { 26635013c547SDavid Gibson spapr_machine_2_5_instance_options(machine); 26645013c547SDavid Gibson } 26651c5f29bbSDavid Gibson 26665013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 26675013c547SDavid Gibson { 2668fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 2669fc9f38c3SDavid Gibson 2670fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 2671fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 2672f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4); 26731c5f29bbSDavid Gibson } 26741c5f29bbSDavid Gibson 2675fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 26761c5f29bbSDavid Gibson 26771c5f29bbSDavid Gibson /* 26781c5f29bbSDavid Gibson * pseries-2.3 26791c5f29bbSDavid Gibson */ 268038ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 26817619c7b0SMichael Roth HW_COMPAT_2_3 \ 26827619c7b0SMichael Roth {\ 26837619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 26847619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 26857619c7b0SMichael Roth .value = "off",\ 26867619c7b0SMichael Roth }, 268738ff32c6SEduardo Habkost 26885013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine) 26891c5f29bbSDavid Gibson { 26905013c547SDavid Gibson spapr_machine_2_4_instance_options(machine); 26911c5f29bbSDavid Gibson savevm_skip_section_footers(); 26921c5f29bbSDavid Gibson global_state_set_optional(); 269309b5e30dSGreg Kurz savevm_skip_configuration(); 26941c5f29bbSDavid Gibson } 26951c5f29bbSDavid Gibson 26965013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc) 26971c5f29bbSDavid Gibson { 2698fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 2699f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3); 27001c5f29bbSDavid Gibson } 2701fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 27021c5f29bbSDavid Gibson 27031c5f29bbSDavid Gibson /* 27041c5f29bbSDavid Gibson * pseries-2.2 27051c5f29bbSDavid Gibson */ 27061c5f29bbSDavid Gibson 2707b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 27084dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 2709b194df47SAlexey Kardashevskiy {\ 2710b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2711b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 2712b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 2713dd754bafSEduardo Habkost }, 2714b194df47SAlexey Kardashevskiy 27155013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine) 2716b0e966d0SJason Wang { 27175013c547SDavid Gibson spapr_machine_2_3_instance_options(machine); 2718cba0e779SGreg Kurz machine->suppress_vmdesc = true; 2719b0e966d0SJason Wang } 2720b0e966d0SJason Wang 27215013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc) 2722b0e966d0SJason Wang { 2723fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 2724f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2); 27251c5f29bbSDavid Gibson } 2726fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 27271c5f29bbSDavid Gibson 27281c5f29bbSDavid Gibson /* 27291c5f29bbSDavid Gibson * pseries-2.1 27301c5f29bbSDavid Gibson */ 27311c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \ 27321c5f29bbSDavid Gibson HW_COMPAT_2_1 27331c5f29bbSDavid Gibson 27345013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine) 27351c5f29bbSDavid Gibson { 27365013c547SDavid Gibson spapr_machine_2_2_instance_options(machine); 27371c5f29bbSDavid Gibson } 27381c5f29bbSDavid Gibson 27395013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 2740b0e966d0SJason Wang { 2741fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 2742f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1); 27436026db45SAlexey Kardashevskiy } 2744fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 27456026db45SAlexey Kardashevskiy 274629ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 274729ee3247SAlexey Kardashevskiy { 274829ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 274929ee3247SAlexey Kardashevskiy } 275029ee3247SAlexey Kardashevskiy 275129ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 2752