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 5490da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 5500da6f3feSBharata B Rao sPAPRMachineState *spapr) 5510da6f3feSBharata B Rao { 5520da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 5530da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 5540da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 5550da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 5560da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 5570da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 558afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 559afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 5600da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 5610da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 5620da6f3feSBharata B Rao size_t page_sizes_prop_size; 56322419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 5640da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 565af81cf32SBharata B Rao sPAPRDRConnector *drc; 566af81cf32SBharata B Rao sPAPRDRConnectorClass *drck; 567af81cf32SBharata B Rao int drc_index; 568af81cf32SBharata B Rao 569af81cf32SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); 570af81cf32SBharata B Rao if (drc) { 571af81cf32SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 572af81cf32SBharata B Rao drc_index = drck->get_index(drc); 573af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 574af81cf32SBharata B Rao } 5750da6f3feSBharata B Rao 57690da0d5aSBenjamin Herrenschmidt /* Note: we keep CI large pages off for now because a 64K capable guest 57790da0d5aSBenjamin Herrenschmidt * provisioned with large pages might otherwise try to map a qemu 57890da0d5aSBenjamin Herrenschmidt * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 57990da0d5aSBenjamin Herrenschmidt * even if that qemu runs on a 4k host. 58090da0d5aSBenjamin Herrenschmidt * 58190da0d5aSBenjamin Herrenschmidt * We can later add this bit back when we are confident this is not 58290da0d5aSBenjamin Herrenschmidt * an issue (!HV KVM or 64K host) 58390da0d5aSBenjamin Herrenschmidt */ 58490da0d5aSBenjamin Herrenschmidt uint8_t pa_features_206[] = { 6, 0, 58590da0d5aSBenjamin Herrenschmidt 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 58690da0d5aSBenjamin Herrenschmidt uint8_t pa_features_207[] = { 24, 0, 58790da0d5aSBenjamin Herrenschmidt 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 58890da0d5aSBenjamin Herrenschmidt 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 58990da0d5aSBenjamin Herrenschmidt 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 59090da0d5aSBenjamin Herrenschmidt 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 59190da0d5aSBenjamin Herrenschmidt uint8_t *pa_features; 59290da0d5aSBenjamin Herrenschmidt size_t pa_size; 59390da0d5aSBenjamin Herrenschmidt 5940da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 5950da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 5960da6f3feSBharata B Rao 5970da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 5980da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 5990da6f3feSBharata B Rao env->dcache_line_size))); 6000da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6010da6f3feSBharata B Rao env->dcache_line_size))); 6020da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6030da6f3feSBharata B Rao env->icache_line_size))); 6040da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6050da6f3feSBharata B Rao env->icache_line_size))); 6060da6f3feSBharata B Rao 6070da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 6080da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6090da6f3feSBharata B Rao pcc->l1_dcache_size))); 6100da6f3feSBharata B Rao } else { 611ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 dcache size for cpu"); 6120da6f3feSBharata B Rao } 6130da6f3feSBharata B Rao if (pcc->l1_icache_size) { 6140da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 6150da6f3feSBharata B Rao pcc->l1_icache_size))); 6160da6f3feSBharata B Rao } else { 617ce9863b7SCédric Le Goater error_report("Warning: Unknown L1 icache size for cpu"); 6180da6f3feSBharata B Rao } 6190da6f3feSBharata B Rao 6200da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 6210da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 622fd5da5c4SThomas Huth _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); 6230da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 6240da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 6250da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 6260da6f3feSBharata B Rao 6270da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 6280da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 6290da6f3feSBharata B Rao } 6300da6f3feSBharata B Rao 6310da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 6320da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 6330da6f3feSBharata B Rao segs, sizeof(segs)))); 6340da6f3feSBharata B Rao } 6350da6f3feSBharata B Rao 6360da6f3feSBharata B Rao /* Advertise VMX/VSX (vector extensions) if available 6370da6f3feSBharata B Rao * 0 / no property == no vector extensions 6380da6f3feSBharata B Rao * 1 == VMX / Altivec available 6390da6f3feSBharata B Rao * 2 == VSX available */ 6400da6f3feSBharata B Rao if (env->insns_flags & PPC_ALTIVEC) { 6410da6f3feSBharata B Rao uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 6420da6f3feSBharata B Rao 6430da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 6440da6f3feSBharata B Rao } 6450da6f3feSBharata B Rao 6460da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 6470da6f3feSBharata B Rao * 0 / no property == no DFP 6480da6f3feSBharata B Rao * 1 == DFP available */ 6490da6f3feSBharata B Rao if (env->insns_flags2 & PPC2_DFP) { 6500da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 6510da6f3feSBharata B Rao } 6520da6f3feSBharata B Rao 6533654fa95SCédric Le Goater page_sizes_prop_size = ppc_create_page_sizes_prop(env, page_sizes_prop, 6540da6f3feSBharata B Rao sizeof(page_sizes_prop)); 6550da6f3feSBharata B Rao if (page_sizes_prop_size) { 6560da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 6570da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 6580da6f3feSBharata B Rao } 6590da6f3feSBharata B Rao 66090da0d5aSBenjamin Herrenschmidt /* Do the ibm,pa-features property, adjust it for ci-large-pages */ 66190da0d5aSBenjamin Herrenschmidt if (env->mmu_model == POWERPC_MMU_2_06) { 66290da0d5aSBenjamin Herrenschmidt pa_features = pa_features_206; 66390da0d5aSBenjamin Herrenschmidt pa_size = sizeof(pa_features_206); 66490da0d5aSBenjamin Herrenschmidt } else /* env->mmu_model == POWERPC_MMU_2_07 */ { 66590da0d5aSBenjamin Herrenschmidt pa_features = pa_features_207; 66690da0d5aSBenjamin Herrenschmidt pa_size = sizeof(pa_features_207); 66790da0d5aSBenjamin Herrenschmidt } 66890da0d5aSBenjamin Herrenschmidt if (env->ci_large_pages) { 66990da0d5aSBenjamin Herrenschmidt pa_features[3] |= 0x20; 67090da0d5aSBenjamin Herrenschmidt } 67190da0d5aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 67290da0d5aSBenjamin Herrenschmidt 6730da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 67422419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 6750da6f3feSBharata B Rao 6760da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 6770da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 6780da6f3feSBharata B Rao 6790da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 6800da6f3feSBharata B Rao 6810da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 6820da6f3feSBharata B Rao ppc_get_compat_smt_threads(cpu))); 6830da6f3feSBharata B Rao } 6840da6f3feSBharata B Rao 6850da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 6860da6f3feSBharata B Rao { 6870da6f3feSBharata B Rao CPUState *cs; 6880da6f3feSBharata B Rao int cpus_offset; 6890da6f3feSBharata B Rao char *nodename; 6900da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 6910da6f3feSBharata B Rao 6920da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 6930da6f3feSBharata B Rao _FDT(cpus_offset); 6940da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 6950da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 6960da6f3feSBharata B Rao 6970da6f3feSBharata B Rao /* 6980da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 6990da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 7000da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 7010da6f3feSBharata B Rao */ 7020da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 7030da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 7040da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 7050da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 7060da6f3feSBharata B Rao int offset; 7070da6f3feSBharata B Rao 7080da6f3feSBharata B Rao if ((index % smt) != 0) { 7090da6f3feSBharata B Rao continue; 7100da6f3feSBharata B Rao } 7110da6f3feSBharata B Rao 7120da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 7130da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 7140da6f3feSBharata B Rao g_free(nodename); 7150da6f3feSBharata B Rao _FDT(offset); 7160da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 7170da6f3feSBharata B Rao } 7180da6f3feSBharata B Rao 7190da6f3feSBharata B Rao } 7200da6f3feSBharata B Rao 72103d196b7SBharata B Rao /* 72203d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 72303d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 72403d196b7SBharata B Rao * of this device tree node. 72503d196b7SBharata B Rao */ 72603d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 72703d196b7SBharata B Rao { 72803d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 72903d196b7SBharata B Rao int ret, i, offset; 73003d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 73103d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 732d0e5a8f2SBharata B Rao uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; 733d0e5a8f2SBharata B Rao uint32_t nr_lmbs = (spapr->hotplug_memory.base + 734d0e5a8f2SBharata B Rao memory_region_size(&spapr->hotplug_memory.mr)) / 735d0e5a8f2SBharata B Rao lmb_size; 73603d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 7376663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 73803d196b7SBharata B Rao 739ef001f06SThomas Huth /* 740d0e5a8f2SBharata B Rao * Don't create the node if there is no hotpluggable memory 74116c25aefSBharata B Rao */ 742d0e5a8f2SBharata B Rao if (machine->ram_size == machine->maxram_size) { 74316c25aefSBharata B Rao return 0; 74416c25aefSBharata B Rao } 74516c25aefSBharata B Rao 74616c25aefSBharata B Rao /* 747ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 748ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 749ef001f06SThomas Huth */ 750ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 751ef001f06SThomas Huth * sizeof(uint32_t); 75203d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 75303d196b7SBharata B Rao 75403d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 75503d196b7SBharata B Rao 75603d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 75703d196b7SBharata B Rao sizeof(prop_lmb_size)); 75803d196b7SBharata B Rao if (ret < 0) { 75903d196b7SBharata B Rao goto out; 76003d196b7SBharata B Rao } 76103d196b7SBharata B Rao 76203d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 76303d196b7SBharata B Rao if (ret < 0) { 76403d196b7SBharata B Rao goto out; 76503d196b7SBharata B Rao } 76603d196b7SBharata B Rao 76703d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 76803d196b7SBharata B Rao if (ret < 0) { 76903d196b7SBharata B Rao goto out; 77003d196b7SBharata B Rao } 77103d196b7SBharata B Rao 77203d196b7SBharata B Rao /* ibm,dynamic-memory */ 77303d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 77403d196b7SBharata B Rao cur_index++; 77503d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 776d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 77703d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 77803d196b7SBharata B Rao 779d0e5a8f2SBharata B Rao if (i >= hotplug_lmb_start) { 780d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 781d0e5a8f2SBharata B Rao sPAPRDRConnectorClass *drck; 782d0e5a8f2SBharata B Rao 783d0e5a8f2SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); 78403d196b7SBharata B Rao g_assert(drc); 78503d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 78603d196b7SBharata B Rao 78703d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 78803d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 78903d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 79003d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 79103d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 792d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 79303d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 79403d196b7SBharata B Rao } else { 79503d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 79603d196b7SBharata B Rao } 797d0e5a8f2SBharata B Rao } else { 798d0e5a8f2SBharata B Rao /* 799d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 800d0e5a8f2SBharata B Rao * hotplug memory region -- all these are marked as reserved 801d0e5a8f2SBharata B Rao * and as having no valid DRC. 802d0e5a8f2SBharata B Rao */ 803d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 804d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 805d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 806d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 807d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 808d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 809d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 810d0e5a8f2SBharata B Rao } 81103d196b7SBharata B Rao 81203d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 81303d196b7SBharata B Rao } 81403d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 81503d196b7SBharata B Rao if (ret < 0) { 81603d196b7SBharata B Rao goto out; 81703d196b7SBharata B Rao } 81803d196b7SBharata B Rao 81903d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 82003d196b7SBharata B Rao cur_index = int_buf; 8216663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 82203d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 82303d196b7SBharata B Rao cur_index += 2; 8246663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 82503d196b7SBharata B Rao uint32_t associativity[] = { 82603d196b7SBharata B Rao cpu_to_be32(0x0), 82703d196b7SBharata B Rao cpu_to_be32(0x0), 82803d196b7SBharata B Rao cpu_to_be32(0x0), 82903d196b7SBharata B Rao cpu_to_be32(i) 83003d196b7SBharata B Rao }; 83103d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 83203d196b7SBharata B Rao cur_index += 4; 83303d196b7SBharata B Rao } 83403d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 83503d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 83603d196b7SBharata B Rao out: 83703d196b7SBharata B Rao g_free(int_buf); 83803d196b7SBharata B Rao return ret; 83903d196b7SBharata B Rao } 84003d196b7SBharata B Rao 84103d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 84203d196b7SBharata B Rao target_ulong addr, target_ulong size, 84303d196b7SBharata B Rao bool cpu_update, bool memory_update) 84403d196b7SBharata B Rao { 84503d196b7SBharata B Rao void *fdt, *fdt_skel; 84603d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 84703d196b7SBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 84803d196b7SBharata B Rao 84903d196b7SBharata B Rao size -= sizeof(hdr); 85003d196b7SBharata B Rao 85103d196b7SBharata B Rao /* Create sceleton */ 85203d196b7SBharata B Rao fdt_skel = g_malloc0(size); 85303d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 85403d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 85503d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 85603d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 85703d196b7SBharata B Rao fdt = g_malloc0(size); 85803d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 85903d196b7SBharata B Rao g_free(fdt_skel); 86003d196b7SBharata B Rao 86103d196b7SBharata B Rao /* Fixup cpu nodes */ 86203d196b7SBharata B Rao if (cpu_update) { 86303d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 86403d196b7SBharata B Rao } 86503d196b7SBharata B Rao 86616c25aefSBharata B Rao /* Generate ibm,dynamic-reconfiguration-memory node if required */ 86703d196b7SBharata B Rao if (memory_update && smc->dr_lmb_enabled) { 86803d196b7SBharata B Rao _FDT((spapr_populate_drconf_memory(spapr, fdt))); 86903d196b7SBharata B Rao } 87003d196b7SBharata B Rao 87103d196b7SBharata B Rao /* Pack resulting tree */ 87203d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 87303d196b7SBharata B Rao 87403d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 87503d196b7SBharata B Rao trace_spapr_cas_failed(size); 87603d196b7SBharata B Rao return -1; 87703d196b7SBharata B Rao } 87803d196b7SBharata B Rao 87903d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 88003d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 88103d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 88203d196b7SBharata B Rao g_free(fdt); 88303d196b7SBharata B Rao 88403d196b7SBharata B Rao return 0; 88503d196b7SBharata B Rao } 88603d196b7SBharata B Rao 88728e02042SDavid Gibson static void spapr_finalize_fdt(sPAPRMachineState *spapr, 88853018216SPaolo Bonzini hwaddr fdt_addr, 88953018216SPaolo Bonzini hwaddr rtas_addr, 89053018216SPaolo Bonzini hwaddr rtas_size) 89153018216SPaolo Bonzini { 8925b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 8933c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 894c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 8955b2128d2SAlexander Graf const char *boot_device = machine->boot_order; 89671461b0fSAlexey Kardashevskiy int ret, i; 89771461b0fSAlexey Kardashevskiy size_t cb = 0; 89871461b0fSAlexey Kardashevskiy char *bootlist; 89953018216SPaolo Bonzini void *fdt; 90053018216SPaolo Bonzini sPAPRPHBState *phb; 90153018216SPaolo Bonzini 90253018216SPaolo Bonzini fdt = g_malloc(FDT_MAX_SIZE); 90353018216SPaolo Bonzini 90453018216SPaolo Bonzini /* open out the base tree into a temp buffer for the final tweaks */ 90553018216SPaolo Bonzini _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); 90653018216SPaolo Bonzini 907e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 908e8f986fcSBharata B Rao if (ret < 0) { 909ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 910e8f986fcSBharata B Rao exit(1); 91153018216SPaolo Bonzini } 91253018216SPaolo Bonzini 91353018216SPaolo Bonzini ret = spapr_populate_vdevice(spapr->vio_bus, fdt); 91453018216SPaolo Bonzini if (ret < 0) { 915ce9863b7SCédric Le Goater error_report("couldn't setup vio devices in fdt"); 91653018216SPaolo Bonzini exit(1); 91753018216SPaolo Bonzini } 91853018216SPaolo Bonzini 9194d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 9204d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 9214d9392beSThomas Huth if (ret < 0) { 922ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 9234d9392beSThomas Huth exit(1); 9244d9392beSThomas Huth } 9254d9392beSThomas Huth } 9264d9392beSThomas Huth 92753018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 92853018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 92953018216SPaolo Bonzini if (ret < 0) { 930da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 93153018216SPaolo Bonzini exit(1); 93253018216SPaolo Bonzini } 933da34fed7SThomas Huth } 93453018216SPaolo Bonzini 93553018216SPaolo Bonzini /* RTAS */ 93653018216SPaolo Bonzini ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); 93753018216SPaolo Bonzini if (ret < 0) { 938ce9863b7SCédric Le Goater error_report("Couldn't set up RTAS device tree properties"); 93953018216SPaolo Bonzini } 94053018216SPaolo Bonzini 9410da6f3feSBharata B Rao /* cpus */ 9420da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 94353018216SPaolo Bonzini 94471461b0fSAlexey Kardashevskiy bootlist = get_boot_devices_list(&cb, true); 94571461b0fSAlexey Kardashevskiy if (cb && bootlist) { 94671461b0fSAlexey Kardashevskiy int offset = fdt_path_offset(fdt, "/chosen"); 94771461b0fSAlexey Kardashevskiy if (offset < 0) { 94871461b0fSAlexey Kardashevskiy exit(1); 94971461b0fSAlexey Kardashevskiy } 95071461b0fSAlexey Kardashevskiy for (i = 0; i < cb; i++) { 95171461b0fSAlexey Kardashevskiy if (bootlist[i] == '\n') { 95271461b0fSAlexey Kardashevskiy bootlist[i] = ' '; 95371461b0fSAlexey Kardashevskiy } 95471461b0fSAlexey Kardashevskiy 95571461b0fSAlexey Kardashevskiy } 95671461b0fSAlexey Kardashevskiy ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); 95771461b0fSAlexey Kardashevskiy } 95871461b0fSAlexey Kardashevskiy 9595b2128d2SAlexander Graf if (boot_device && strlen(boot_device)) { 9605b2128d2SAlexander Graf int offset = fdt_path_offset(fdt, "/chosen"); 9615b2128d2SAlexander Graf 9625b2128d2SAlexander Graf if (offset < 0) { 9635b2128d2SAlexander Graf exit(1); 9645b2128d2SAlexander Graf } 9655b2128d2SAlexander Graf fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device); 9665b2128d2SAlexander Graf } 9675b2128d2SAlexander Graf 96853018216SPaolo Bonzini if (!spapr->has_graphics) { 96953018216SPaolo Bonzini spapr_populate_chosen_stdout(fdt, spapr->vio_bus); 97053018216SPaolo Bonzini } 97153018216SPaolo Bonzini 972c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 973c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 974c20d332aSBharata B Rao } 975c20d332aSBharata B Rao 9763c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 977af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 978af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 979af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 980af81cf32SBharata B Rao if (ret < 0) { 981af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 982af81cf32SBharata B Rao exit(1); 983af81cf32SBharata B Rao } 984af81cf32SBharata B Rao } 985af81cf32SBharata B Rao 98653018216SPaolo Bonzini _FDT((fdt_pack(fdt))); 98753018216SPaolo Bonzini 98853018216SPaolo Bonzini if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 989730fce59SThomas Huth error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 99053018216SPaolo Bonzini fdt_totalsize(fdt), FDT_MAX_SIZE); 99153018216SPaolo Bonzini exit(1); 99253018216SPaolo Bonzini } 99353018216SPaolo Bonzini 994ad440b4aSAndrew Jones qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 99553018216SPaolo Bonzini cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 99653018216SPaolo Bonzini 997a21a7a70SGonglei g_free(bootlist); 99853018216SPaolo Bonzini g_free(fdt); 99953018216SPaolo Bonzini } 100053018216SPaolo Bonzini 100153018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 100253018216SPaolo Bonzini { 100353018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 100453018216SPaolo Bonzini } 100553018216SPaolo Bonzini 100653018216SPaolo Bonzini static void emulate_spapr_hypercall(PowerPCCPU *cpu) 100753018216SPaolo Bonzini { 100853018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 100953018216SPaolo Bonzini 101053018216SPaolo Bonzini if (msr_pr) { 101153018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 101253018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 101353018216SPaolo Bonzini } else { 101453018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 101553018216SPaolo Bonzini } 101653018216SPaolo Bonzini } 101753018216SPaolo Bonzini 1018e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1019e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1020e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1021e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1022e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1023e6b8fd24SSamuel Mendoza-Jonas 1024715c5407SDavid Gibson /* 1025715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1026715c5407SDavid Gibson */ 1027715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr) 1028715c5407SDavid Gibson { 1029715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1030715c5407SDavid Gibson return spapr->htab_fd; 1031715c5407SDavid Gibson } 1032715c5407SDavid Gibson 1033715c5407SDavid Gibson spapr->htab_fd = kvmppc_get_htab_fd(false); 1034715c5407SDavid Gibson if (spapr->htab_fd < 0) { 1035715c5407SDavid Gibson error_report("Unable to open fd for reading hash table from KVM: %s", 1036715c5407SDavid Gibson strerror(errno)); 1037715c5407SDavid Gibson } 1038715c5407SDavid Gibson 1039715c5407SDavid Gibson return spapr->htab_fd; 1040715c5407SDavid Gibson } 1041715c5407SDavid Gibson 1042715c5407SDavid Gibson static void close_htab_fd(sPAPRMachineState *spapr) 1043715c5407SDavid Gibson { 1044715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1045715c5407SDavid Gibson close(spapr->htab_fd); 1046715c5407SDavid Gibson } 1047715c5407SDavid Gibson spapr->htab_fd = -1; 1048715c5407SDavid Gibson } 1049715c5407SDavid Gibson 10508dfe8e7fSDavid Gibson static int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 10518dfe8e7fSDavid Gibson { 10528dfe8e7fSDavid Gibson int shift; 10538dfe8e7fSDavid Gibson 10548dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 10558dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 10568dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 10578dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 10588dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 10598dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 10608dfe8e7fSDavid Gibson return shift; 10618dfe8e7fSDavid Gibson } 10628dfe8e7fSDavid Gibson 1063c5f54f3eSDavid Gibson static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, 1064c5f54f3eSDavid Gibson Error **errp) 106553018216SPaolo Bonzini { 1066c5f54f3eSDavid Gibson long rc; 106753018216SPaolo Bonzini 1068c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 1069c5f54f3eSDavid Gibson g_free(spapr->htab); 1070c5f54f3eSDavid Gibson spapr->htab = NULL; 1071c5f54f3eSDavid Gibson spapr->htab_shift = 0; 1072c5f54f3eSDavid Gibson close_htab_fd(spapr); 107353018216SPaolo Bonzini 1074c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1075c5f54f3eSDavid Gibson if (rc < 0) { 1076c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1077c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1078c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1079c5f54f3eSDavid Gibson shift); 1080c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1081c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1082c5f54f3eSDavid Gibson } else if (rc > 0) { 1083c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1084c5f54f3eSDavid Gibson if (rc != shift) { 1085c5f54f3eSDavid Gibson error_setg(errp, 1086c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1087c5f54f3eSDavid Gibson shift, rc); 10887735fedaSBharata B Rao } 10897735fedaSBharata B Rao 109053018216SPaolo Bonzini spapr->htab_shift = shift; 1091c18ad9a5SDavid Gibson spapr->htab = NULL; 1092b817772aSBharata B Rao } else { 1093c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1094c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1095c5f54f3eSDavid Gibson int i; 109601a57972SSamuel Mendoza-Jonas 1097c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1098c5f54f3eSDavid Gibson if (!spapr->htab) { 1099c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1100c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1101c5f54f3eSDavid Gibson return; 1102b817772aSBharata B Rao } 1103b817772aSBharata B Rao 1104c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1105c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1106b817772aSBharata B Rao 1107c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1108c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 11097735fedaSBharata B Rao } 111053018216SPaolo Bonzini } 111153018216SPaolo Bonzini } 111253018216SPaolo Bonzini 11139e3f9733SAlexander Graf static int find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 11149e3f9733SAlexander Graf { 11159e3f9733SAlexander Graf bool matched = false; 11169e3f9733SAlexander Graf 11179e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 11189e3f9733SAlexander Graf matched = true; 11199e3f9733SAlexander Graf } 11209e3f9733SAlexander Graf 11219e3f9733SAlexander Graf if (!matched) { 11229e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 11239e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 11249e3f9733SAlexander Graf exit(1); 11259e3f9733SAlexander Graf } 11269e3f9733SAlexander Graf 11279e3f9733SAlexander Graf return 0; 11289e3f9733SAlexander Graf } 11299e3f9733SAlexander Graf 113053018216SPaolo Bonzini static void ppc_spapr_reset(void) 113153018216SPaolo Bonzini { 1132c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1133c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1134182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1135b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1136259186a7SAndreas Färber 11379e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 11389e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 11399e3f9733SAlexander Graf 1140c5f54f3eSDavid Gibson /* Allocate and/or reset the hash page table */ 1141c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, 1142c5f54f3eSDavid Gibson spapr_hpt_shift_for_ramsize(machine->maxram_size), 1143c5f54f3eSDavid Gibson &error_fatal); 1144c5f54f3eSDavid Gibson 1145c5f54f3eSDavid Gibson /* Update the RMA size if necessary */ 1146c5f54f3eSDavid Gibson if (spapr->vrma_adjust) { 1147c5f54f3eSDavid Gibson spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1148c5f54f3eSDavid Gibson spapr->htab_shift); 1149c5f54f3eSDavid Gibson } 115053018216SPaolo Bonzini 115153018216SPaolo Bonzini qemu_devices_reset(); 115253018216SPaolo Bonzini 1153b7d1f77aSBenjamin Herrenschmidt /* 1154b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1155b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1156b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1157b7d1f77aSBenjamin Herrenschmidt */ 1158b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1159b7d1f77aSBenjamin Herrenschmidt spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1160b7d1f77aSBenjamin Herrenschmidt spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; 1161b7d1f77aSBenjamin Herrenschmidt 116253018216SPaolo Bonzini /* Load the fdt */ 116353018216SPaolo Bonzini spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr, 116453018216SPaolo Bonzini spapr->rtas_size); 116553018216SPaolo Bonzini 1166b7d1f77aSBenjamin Herrenschmidt /* Copy RTAS over */ 1167b7d1f77aSBenjamin Herrenschmidt cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob, 1168b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size); 1169b7d1f77aSBenjamin Herrenschmidt 117053018216SPaolo Bonzini /* Set up the entry state */ 1171182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1172182735efSAndreas Färber first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; 1173182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1174182735efSAndreas Färber first_cpu->halted = 0; 11751b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 117653018216SPaolo Bonzini 117753018216SPaolo Bonzini } 117853018216SPaolo Bonzini 117928e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 118053018216SPaolo Bonzini { 11812ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 11823978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 118353018216SPaolo Bonzini 11843978b863SPaolo Bonzini if (dinfo) { 11856231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 11866231a6daSMarkus Armbruster &error_fatal); 118753018216SPaolo Bonzini } 118853018216SPaolo Bonzini 118953018216SPaolo Bonzini qdev_init_nofail(dev); 119053018216SPaolo Bonzini 119153018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 119253018216SPaolo Bonzini } 119353018216SPaolo Bonzini 119428e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 119528df36a1SDavid Gibson { 119628df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 119728df36a1SDavid Gibson 119828df36a1SDavid Gibson qdev_init_nofail(dev); 119928df36a1SDavid Gibson spapr->rtc = dev; 120074e5ae28SDavid Gibson 120174e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 120274e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 120328df36a1SDavid Gibson } 120428df36a1SDavid Gibson 120553018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 120614c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 120753018216SPaolo Bonzini { 120853018216SPaolo Bonzini switch (vga_interface_type) { 120953018216SPaolo Bonzini case VGA_NONE: 12107effdaa3SMark Wu return false; 12117effdaa3SMark Wu case VGA_DEVICE: 12127effdaa3SMark Wu return true; 121353018216SPaolo Bonzini case VGA_STD: 1214b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 121553018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 121653018216SPaolo Bonzini default: 121714c6a894SDavid Gibson error_setg(errp, 121814c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 121914c6a894SDavid Gibson return false; 122053018216SPaolo Bonzini } 122153018216SPaolo Bonzini } 122253018216SPaolo Bonzini 1223880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1224880ae7deSDavid Gibson { 122528e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1226880ae7deSDavid Gibson int err = 0; 1227880ae7deSDavid Gibson 1228631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1229880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1230880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1231880ae7deSDavid Gibson * value into the RTC device */ 1232880ae7deSDavid Gibson if (version_id < 3) { 1233880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1234880ae7deSDavid Gibson } 1235880ae7deSDavid Gibson 1236880ae7deSDavid Gibson return err; 1237880ae7deSDavid Gibson } 1238880ae7deSDavid Gibson 1239880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1240880ae7deSDavid Gibson { 1241880ae7deSDavid Gibson return version_id < 3; 1242880ae7deSDavid Gibson } 1243880ae7deSDavid Gibson 12444be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 12454be21d56SDavid Gibson .name = "spapr", 1246880ae7deSDavid Gibson .version_id = 3, 12474be21d56SDavid Gibson .minimum_version_id = 1, 1248880ae7deSDavid Gibson .post_load = spapr_post_load, 12494be21d56SDavid Gibson .fields = (VMStateField[]) { 1250880ae7deSDavid Gibson /* used to be @next_irq */ 1251880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 12524be21d56SDavid Gibson 12534be21d56SDavid Gibson /* RTC offset */ 125428e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1255880ae7deSDavid Gibson 125628e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 12574be21d56SDavid Gibson VMSTATE_END_OF_LIST() 12584be21d56SDavid Gibson }, 12594be21d56SDavid Gibson }; 12604be21d56SDavid Gibson 12614be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 12624be21d56SDavid Gibson { 126328e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 12644be21d56SDavid Gibson 12654be21d56SDavid Gibson /* "Iteration" header */ 12664be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 12674be21d56SDavid Gibson 1268e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1269e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1270e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1271e68cb8b4SAlexey Kardashevskiy } else { 1272e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 12734be21d56SDavid Gibson } 12744be21d56SDavid Gibson 1275e68cb8b4SAlexey Kardashevskiy 1276e68cb8b4SAlexey Kardashevskiy return 0; 1277e68cb8b4SAlexey Kardashevskiy } 12784be21d56SDavid Gibson 127928e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 12804be21d56SDavid Gibson int64_t max_ns) 12814be21d56SDavid Gibson { 1282378bc217SDavid Gibson bool has_timeout = max_ns != -1; 12834be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 12844be21d56SDavid Gibson int index = spapr->htab_save_index; 1285bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 12864be21d56SDavid Gibson 12874be21d56SDavid Gibson assert(spapr->htab_first_pass); 12884be21d56SDavid Gibson 12894be21d56SDavid Gibson do { 12904be21d56SDavid Gibson int chunkstart; 12914be21d56SDavid Gibson 12924be21d56SDavid Gibson /* Consume invalid HPTEs */ 12934be21d56SDavid Gibson while ((index < htabslots) 12944be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 12954be21d56SDavid Gibson index++; 12964be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 12974be21d56SDavid Gibson } 12984be21d56SDavid Gibson 12994be21d56SDavid Gibson /* Consume valid HPTEs */ 13004be21d56SDavid Gibson chunkstart = index; 1301338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13024be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13034be21d56SDavid Gibson index++; 13044be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13054be21d56SDavid Gibson } 13064be21d56SDavid Gibson 13074be21d56SDavid Gibson if (index > chunkstart) { 13084be21d56SDavid Gibson int n_valid = index - chunkstart; 13094be21d56SDavid Gibson 13104be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13114be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13124be21d56SDavid Gibson qemu_put_be16(f, 0); 13134be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13144be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13154be21d56SDavid Gibson 1316378bc217SDavid Gibson if (has_timeout && 1317378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13184be21d56SDavid Gibson break; 13194be21d56SDavid Gibson } 13204be21d56SDavid Gibson } 13214be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 13224be21d56SDavid Gibson 13234be21d56SDavid Gibson if (index >= htabslots) { 13244be21d56SDavid Gibson assert(index == htabslots); 13254be21d56SDavid Gibson index = 0; 13264be21d56SDavid Gibson spapr->htab_first_pass = false; 13274be21d56SDavid Gibson } 13284be21d56SDavid Gibson spapr->htab_save_index = index; 13294be21d56SDavid Gibson } 13304be21d56SDavid Gibson 133128e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 13324be21d56SDavid Gibson int64_t max_ns) 13334be21d56SDavid Gibson { 13344be21d56SDavid Gibson bool final = max_ns < 0; 13354be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 13364be21d56SDavid Gibson int examined = 0, sent = 0; 13374be21d56SDavid Gibson int index = spapr->htab_save_index; 1338bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13394be21d56SDavid Gibson 13404be21d56SDavid Gibson assert(!spapr->htab_first_pass); 13414be21d56SDavid Gibson 13424be21d56SDavid Gibson do { 13434be21d56SDavid Gibson int chunkstart, invalidstart; 13444be21d56SDavid Gibson 13454be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 13464be21d56SDavid Gibson while ((index < htabslots) 13474be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 13484be21d56SDavid Gibson index++; 13494be21d56SDavid Gibson examined++; 13504be21d56SDavid Gibson } 13514be21d56SDavid Gibson 13524be21d56SDavid Gibson chunkstart = index; 13534be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1354338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13554be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13564be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13574be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13584be21d56SDavid Gibson index++; 13594be21d56SDavid Gibson examined++; 13604be21d56SDavid Gibson } 13614be21d56SDavid Gibson 13624be21d56SDavid Gibson invalidstart = index; 13634be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1364338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 13654be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13664be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13674be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13684be21d56SDavid Gibson index++; 13694be21d56SDavid Gibson examined++; 13704be21d56SDavid Gibson } 13714be21d56SDavid Gibson 13724be21d56SDavid Gibson if (index > chunkstart) { 13734be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 13744be21d56SDavid Gibson int n_invalid = index - invalidstart; 13754be21d56SDavid Gibson 13764be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13774be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13784be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 13794be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13804be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13814be21d56SDavid Gibson sent += index - chunkstart; 13824be21d56SDavid Gibson 1383bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13844be21d56SDavid Gibson break; 13854be21d56SDavid Gibson } 13864be21d56SDavid Gibson } 13874be21d56SDavid Gibson 13884be21d56SDavid Gibson if (examined >= htabslots) { 13894be21d56SDavid Gibson break; 13904be21d56SDavid Gibson } 13914be21d56SDavid Gibson 13924be21d56SDavid Gibson if (index >= htabslots) { 13934be21d56SDavid Gibson assert(index == htabslots); 13944be21d56SDavid Gibson index = 0; 13954be21d56SDavid Gibson } 13964be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 13974be21d56SDavid Gibson 13984be21d56SDavid Gibson if (index >= htabslots) { 13994be21d56SDavid Gibson assert(index == htabslots); 14004be21d56SDavid Gibson index = 0; 14014be21d56SDavid Gibson } 14024be21d56SDavid Gibson 14034be21d56SDavid Gibson spapr->htab_save_index = index; 14044be21d56SDavid Gibson 1405e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 14064be21d56SDavid Gibson } 14074be21d56SDavid Gibson 1408e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1409e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1410e68cb8b4SAlexey Kardashevskiy 14114be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 14124be21d56SDavid Gibson { 141328e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1414715c5407SDavid Gibson int fd; 1415e68cb8b4SAlexey Kardashevskiy int rc = 0; 14164be21d56SDavid Gibson 14174be21d56SDavid Gibson /* Iteration header */ 14184be21d56SDavid Gibson qemu_put_be32(f, 0); 14194be21d56SDavid Gibson 1420e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1421e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1422e68cb8b4SAlexey Kardashevskiy 1423715c5407SDavid Gibson fd = get_htab_fd(spapr); 1424715c5407SDavid Gibson if (fd < 0) { 1425715c5407SDavid Gibson return fd; 142601a57972SSamuel Mendoza-Jonas } 142701a57972SSamuel Mendoza-Jonas 1428715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1429e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1430e68cb8b4SAlexey Kardashevskiy return rc; 1431e68cb8b4SAlexey Kardashevskiy } 1432e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 14334be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 14344be21d56SDavid Gibson } else { 1435e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 14364be21d56SDavid Gibson } 14374be21d56SDavid Gibson 14384be21d56SDavid Gibson /* End marker */ 14394be21d56SDavid Gibson qemu_put_be32(f, 0); 14404be21d56SDavid Gibson qemu_put_be16(f, 0); 14414be21d56SDavid Gibson qemu_put_be16(f, 0); 14424be21d56SDavid Gibson 1443e68cb8b4SAlexey Kardashevskiy return rc; 14444be21d56SDavid Gibson } 14454be21d56SDavid Gibson 14464be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 14474be21d56SDavid Gibson { 144828e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1449715c5407SDavid Gibson int fd; 14504be21d56SDavid Gibson 14514be21d56SDavid Gibson /* Iteration header */ 14524be21d56SDavid Gibson qemu_put_be32(f, 0); 14534be21d56SDavid Gibson 1454e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1455e68cb8b4SAlexey Kardashevskiy int rc; 1456e68cb8b4SAlexey Kardashevskiy 1457e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1458e68cb8b4SAlexey Kardashevskiy 1459715c5407SDavid Gibson fd = get_htab_fd(spapr); 1460715c5407SDavid Gibson if (fd < 0) { 1461715c5407SDavid Gibson return fd; 146201a57972SSamuel Mendoza-Jonas } 146301a57972SSamuel Mendoza-Jonas 1464715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 1465e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1466e68cb8b4SAlexey Kardashevskiy return rc; 1467e68cb8b4SAlexey Kardashevskiy } 1468e68cb8b4SAlexey Kardashevskiy } else { 1469378bc217SDavid Gibson if (spapr->htab_first_pass) { 1470378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 1471378bc217SDavid Gibson } 14724be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1473e68cb8b4SAlexey Kardashevskiy } 14744be21d56SDavid Gibson 14754be21d56SDavid Gibson /* End marker */ 14764be21d56SDavid Gibson qemu_put_be32(f, 0); 14774be21d56SDavid Gibson qemu_put_be16(f, 0); 14784be21d56SDavid Gibson qemu_put_be16(f, 0); 14794be21d56SDavid Gibson 14804be21d56SDavid Gibson return 0; 14814be21d56SDavid Gibson } 14824be21d56SDavid Gibson 14834be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 14844be21d56SDavid Gibson { 148528e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 14864be21d56SDavid Gibson uint32_t section_hdr; 1487e68cb8b4SAlexey Kardashevskiy int fd = -1; 14884be21d56SDavid Gibson 14894be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 149098a5d100SDavid Gibson error_report("htab_load() bad version"); 14914be21d56SDavid Gibson return -EINVAL; 14924be21d56SDavid Gibson } 14934be21d56SDavid Gibson 14944be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 14954be21d56SDavid Gibson 14964be21d56SDavid Gibson if (section_hdr) { 14979897e462SGreg Kurz Error *local_err = NULL; 1498c5f54f3eSDavid Gibson 1499c5f54f3eSDavid Gibson /* First section gives the htab size */ 1500c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 1501c5f54f3eSDavid Gibson if (local_err) { 1502c5f54f3eSDavid Gibson error_report_err(local_err); 15034be21d56SDavid Gibson return -EINVAL; 15044be21d56SDavid Gibson } 15054be21d56SDavid Gibson return 0; 15064be21d56SDavid Gibson } 15074be21d56SDavid Gibson 1508e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1509e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1510e68cb8b4SAlexey Kardashevskiy 1511e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1512e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 151398a5d100SDavid Gibson error_report("Unable to open fd to restore KVM hash table: %s", 1514e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1515e68cb8b4SAlexey Kardashevskiy } 1516e68cb8b4SAlexey Kardashevskiy } 1517e68cb8b4SAlexey Kardashevskiy 15184be21d56SDavid Gibson while (true) { 15194be21d56SDavid Gibson uint32_t index; 15204be21d56SDavid Gibson uint16_t n_valid, n_invalid; 15214be21d56SDavid Gibson 15224be21d56SDavid Gibson index = qemu_get_be32(f); 15234be21d56SDavid Gibson n_valid = qemu_get_be16(f); 15244be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 15254be21d56SDavid Gibson 15264be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 15274be21d56SDavid Gibson /* End of Stream */ 15284be21d56SDavid Gibson break; 15294be21d56SDavid Gibson } 15304be21d56SDavid Gibson 1531e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 15324be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 15334be21d56SDavid Gibson /* Bad index in stream */ 153498a5d100SDavid Gibson error_report( 153598a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 153698a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 15374be21d56SDavid Gibson return -EINVAL; 15384be21d56SDavid Gibson } 15394be21d56SDavid Gibson 1540e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 15414be21d56SDavid Gibson if (n_valid) { 15424be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 15434be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 15444be21d56SDavid Gibson } 15454be21d56SDavid Gibson if (n_invalid) { 15464be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 15474be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 15484be21d56SDavid Gibson } 1549e68cb8b4SAlexey Kardashevskiy } else { 1550e68cb8b4SAlexey Kardashevskiy int rc; 1551e68cb8b4SAlexey Kardashevskiy 1552e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1553e68cb8b4SAlexey Kardashevskiy 1554e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1555e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1556e68cb8b4SAlexey Kardashevskiy return rc; 1557e68cb8b4SAlexey Kardashevskiy } 1558e68cb8b4SAlexey Kardashevskiy } 1559e68cb8b4SAlexey Kardashevskiy } 1560e68cb8b4SAlexey Kardashevskiy 1561e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1562e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1563e68cb8b4SAlexey Kardashevskiy close(fd); 15644be21d56SDavid Gibson } 15654be21d56SDavid Gibson 15664be21d56SDavid Gibson return 0; 15674be21d56SDavid Gibson } 15684be21d56SDavid Gibson 1569c573fc03SThomas Huth static void htab_cleanup(void *opaque) 1570c573fc03SThomas Huth { 1571c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 1572c573fc03SThomas Huth 1573c573fc03SThomas Huth close_htab_fd(spapr); 1574c573fc03SThomas Huth } 1575c573fc03SThomas Huth 15764be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 15774be21d56SDavid Gibson .save_live_setup = htab_save_setup, 15784be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 1579a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 1580c573fc03SThomas Huth .cleanup = htab_cleanup, 15814be21d56SDavid Gibson .load_state = htab_load, 15824be21d56SDavid Gibson }; 15834be21d56SDavid Gibson 15845b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 15855b2128d2SAlexander Graf Error **errp) 15865b2128d2SAlexander Graf { 15875b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 15885b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 15895b2128d2SAlexander Graf } 15905b2128d2SAlexander Graf 1591224245bfSDavid Gibson /* 1592224245bfSDavid Gibson * Reset routine for LMB DR devices. 1593224245bfSDavid Gibson * 1594224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1595224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1596224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1597224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1598224245bfSDavid Gibson */ 1599224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1600224245bfSDavid Gibson { 1601224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1602224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1603224245bfSDavid Gibson 1604224245bfSDavid Gibson if (d) { 1605224245bfSDavid Gibson device_reset(d); 1606224245bfSDavid Gibson } 1607224245bfSDavid Gibson } 1608224245bfSDavid Gibson 1609224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1610224245bfSDavid Gibson { 1611224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1612224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1613e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1614224245bfSDavid Gibson int i; 1615224245bfSDavid Gibson 1616224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1617224245bfSDavid Gibson sPAPRDRConnector *drc; 1618224245bfSDavid Gibson uint64_t addr; 1619224245bfSDavid Gibson 1620e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1621224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1622224245bfSDavid Gibson addr/lmb_size); 1623224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1624224245bfSDavid Gibson } 1625224245bfSDavid Gibson } 1626224245bfSDavid Gibson 1627224245bfSDavid Gibson /* 1628224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1629224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1630224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1631224245bfSDavid Gibson */ 16327c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 1633224245bfSDavid Gibson { 1634224245bfSDavid Gibson int i; 1635224245bfSDavid Gibson 16367c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16377c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 16387c150d6fSDavid Gibson " is not aligned to %llu MiB", 16397c150d6fSDavid Gibson machine->ram_size, 1640224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16417c150d6fSDavid Gibson return; 16427c150d6fSDavid Gibson } 16437c150d6fSDavid Gibson 16447c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16457c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 16467c150d6fSDavid Gibson " is not aligned to %llu MiB", 16477c150d6fSDavid Gibson machine->ram_size, 16487c150d6fSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16497c150d6fSDavid Gibson return; 1650224245bfSDavid Gibson } 1651224245bfSDavid Gibson 1652224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1653224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 16547c150d6fSDavid Gibson error_setg(errp, 16557c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 16567c150d6fSDavid Gibson " is not aligned to %llu MiB", 16577c150d6fSDavid Gibson i, numa_info[i].node_mem, 1658224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16597c150d6fSDavid Gibson return; 1660224245bfSDavid Gibson } 1661224245bfSDavid Gibson } 1662224245bfSDavid Gibson } 1663224245bfSDavid Gibson 166453018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 16653ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 166653018216SPaolo Bonzini { 166728e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 16683c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1669224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 16703ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 16713ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 16723ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 167353018216SPaolo Bonzini PCIHostState *phb; 167453018216SPaolo Bonzini int i; 167553018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 167653018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1677658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1678658fa66bSAlexey Kardashevskiy void *rma = NULL; 167953018216SPaolo Bonzini hwaddr rma_alloc_size; 1680b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 168153018216SPaolo Bonzini uint32_t initrd_base = 0; 168253018216SPaolo Bonzini long kernel_size = 0, initrd_size = 0; 1683b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 168416457e7fSBenjamin Herrenschmidt bool kernel_le = false; 168553018216SPaolo Bonzini char *filename; 168694a94e4cSBharata B Rao int smt = kvmppc_smt_threads(); 168794a94e4cSBharata B Rao int spapr_cores = smp_cpus / smp_threads; 168894a94e4cSBharata B Rao int spapr_max_cores = max_cpus / smp_threads; 168994a94e4cSBharata B Rao 16903c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 169194a94e4cSBharata B Rao if (smp_cpus % smp_threads) { 169294a94e4cSBharata B Rao error_report("smp_cpus (%u) must be multiple of threads (%u)", 169394a94e4cSBharata B Rao smp_cpus, smp_threads); 169494a94e4cSBharata B Rao exit(1); 169594a94e4cSBharata B Rao } 169694a94e4cSBharata B Rao if (max_cpus % smp_threads) { 169794a94e4cSBharata B Rao error_report("max_cpus (%u) must be multiple of threads (%u)", 169894a94e4cSBharata B Rao max_cpus, smp_threads); 169994a94e4cSBharata B Rao exit(1); 170094a94e4cSBharata B Rao } 170194a94e4cSBharata B Rao } 170253018216SPaolo Bonzini 1703226419d6SMichael S. Tsirkin msi_nonbroken = true; 170453018216SPaolo Bonzini 170553018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 170653018216SPaolo Bonzini 170753018216SPaolo Bonzini cpu_ppc_hypercall = emulate_spapr_hypercall; 170853018216SPaolo Bonzini 170953018216SPaolo Bonzini /* Allocate RMA if necessary */ 1710658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 171153018216SPaolo Bonzini 171253018216SPaolo Bonzini if (rma_alloc_size == -1) { 1713730fce59SThomas Huth error_report("Unable to create RMA"); 171453018216SPaolo Bonzini exit(1); 171553018216SPaolo Bonzini } 171653018216SPaolo Bonzini 1717c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 171853018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 171953018216SPaolo Bonzini } else { 1720c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 172153018216SPaolo Bonzini 172253018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 172353018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 172453018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 172553018216SPaolo Bonzini * 172653018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 172753018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 172853018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 172953018216SPaolo Bonzini * isn't determined yet. 173053018216SPaolo Bonzini */ 173153018216SPaolo Bonzini if (kvm_enabled()) { 173253018216SPaolo Bonzini spapr->vrma_adjust = 1; 173353018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 173453018216SPaolo Bonzini } 1735912acdf4SBenjamin Herrenschmidt 1736912acdf4SBenjamin Herrenschmidt /* Actually we don't support unbounded RMA anymore since we 1737912acdf4SBenjamin Herrenschmidt * added proper emulation of HV mode. The max we can get is 1738912acdf4SBenjamin Herrenschmidt * 16G which also happens to be what we configure for PAPR 1739912acdf4SBenjamin Herrenschmidt * mode so make sure we don't do anything bigger than that 1740912acdf4SBenjamin Herrenschmidt */ 1741912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 174253018216SPaolo Bonzini } 174353018216SPaolo Bonzini 1744c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 1745d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 1746c4177479SAlexey Kardashevskiy spapr->rma_size); 1747c4177479SAlexey Kardashevskiy exit(1); 1748c4177479SAlexey Kardashevskiy } 1749c4177479SAlexey Kardashevskiy 1750b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 1751b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 175253018216SPaolo Bonzini 17537b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 175427f24582SBenjamin Herrenschmidt spapr->xics = xics_system_init(machine, 175594a94e4cSBharata B Rao DIV_ROUND_UP(max_cpus * smt, smp_threads), 1756161deaf2SBenjamin Herrenschmidt XICS_IRQS_SPAPR, &error_fatal); 17577b565160SDavid Gibson 1758224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 17597c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 1760224245bfSDavid Gibson } 1761224245bfSDavid Gibson 176253018216SPaolo Bonzini /* init CPUs */ 176319fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 176419fb2c36SBharata B Rao machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; 176553018216SPaolo Bonzini } 176694a94e4cSBharata B Rao 1767e703d2f7SGreg Kurz ppc_cpu_parse_features(machine->cpu_model); 1768e703d2f7SGreg Kurz 17693c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 177094a94e4cSBharata B Rao char *type = spapr_get_cpu_core_type(machine->cpu_model); 177194a94e4cSBharata B Rao 17724babfaf0SThomas Huth if (type == NULL) { 1773caebf378SCédric Le Goater error_report("Unable to find sPAPR CPU Core definition"); 1774caebf378SCédric Le Goater exit(1); 1775caebf378SCédric Le Goater } 1776caebf378SCédric Le Goater 177794a94e4cSBharata B Rao spapr->cores = g_new0(Object *, spapr_max_cores); 1778af81cf32SBharata B Rao for (i = 0; i < spapr_max_cores; i++) { 177912bf2d33SGreg Kurz int core_id = i * smp_threads; 1780af81cf32SBharata B Rao sPAPRDRConnector *drc = 1781af81cf32SBharata B Rao spapr_dr_connector_new(OBJECT(spapr), 178212bf2d33SGreg Kurz SPAPR_DR_CONNECTOR_TYPE_CPU, 178312bf2d33SGreg Kurz (core_id / smp_threads) * smt); 1784af81cf32SBharata B Rao 1785af81cf32SBharata B Rao qemu_register_reset(spapr_drc_reset, drc); 1786af81cf32SBharata B Rao 1787af81cf32SBharata B Rao if (i < spapr_cores) { 1788caebf378SCédric Le Goater Object *core = object_new(type); 178994a94e4cSBharata B Rao object_property_set_int(core, smp_threads, "nr-threads", 179094a94e4cSBharata B Rao &error_fatal); 179112bf2d33SGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 179294a94e4cSBharata B Rao &error_fatal); 179394a94e4cSBharata B Rao object_property_set_bool(core, true, "realized", &error_fatal); 179494a94e4cSBharata B Rao } 1795af81cf32SBharata B Rao } 179694a94e4cSBharata B Rao g_free(type); 179794a94e4cSBharata B Rao } else { 179853018216SPaolo Bonzini for (i = 0; i < smp_cpus; i++) { 179994a94e4cSBharata B Rao PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model); 180053018216SPaolo Bonzini if (cpu == NULL) { 1801569f4967SDavid Gibson error_report("Unable to find PowerPC CPU definition"); 180253018216SPaolo Bonzini exit(1); 180353018216SPaolo Bonzini } 1804569f4967SDavid Gibson spapr_cpu_init(spapr, cpu, &error_fatal); 180553018216SPaolo Bonzini } 180694a94e4cSBharata B Rao } 180753018216SPaolo Bonzini 1808026bfd89SDavid Gibson if (kvm_enabled()) { 1809026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 1810026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 1811ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 18125145ad4fSNathan Whitehorn 18135145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 18145145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 1815026bfd89SDavid Gibson } 1816026bfd89SDavid Gibson 181753018216SPaolo Bonzini /* allocate RAM */ 1818f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 1819fb164994SDavid Gibson machine->ram_size); 1820f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 182153018216SPaolo Bonzini 1822658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 1823658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 1824658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 1825658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 1826658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 1827658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 1828658fa66bSAlexey Kardashevskiy } 1829658fa66bSAlexey Kardashevskiy 18304a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 18314a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 18324a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 183371c9a3ddSBharata B Rao /* 183471c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 183571c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 183671c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 183771c9a3ddSBharata B Rao */ 183871c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 183971c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 18404a1c9cf0SBharata B Rao 184171c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 184271c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 184371c9a3ddSBharata B Rao } 184471c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 1845d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 1846d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 184771c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 1848d54e4d76SDavid Gibson exit(1); 18494a1c9cf0SBharata B Rao } 18504a1c9cf0SBharata B Rao 18514a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 18524a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 18534a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 18544a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 18554a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 18564a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 18574a1c9cf0SBharata B Rao } 18584a1c9cf0SBharata B Rao 1859224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1860224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 1861224245bfSDavid Gibson } 1862224245bfSDavid Gibson 186353018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 18644c56440dSStefan Weil if (!filename) { 1865730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 18664c56440dSStefan Weil exit(1); 18674c56440dSStefan Weil } 1868b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 18698afc22a2SZhou Jie if (spapr->rtas_size < 0) { 18708afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 18718afc22a2SZhou Jie exit(1); 18728afc22a2SZhou Jie } 1873b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 1874b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 1875730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 187653018216SPaolo Bonzini exit(1); 187753018216SPaolo Bonzini } 187853018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 1879730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 18802f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 188153018216SPaolo Bonzini exit(1); 188253018216SPaolo Bonzini } 188353018216SPaolo Bonzini g_free(filename); 188453018216SPaolo Bonzini 188553018216SPaolo Bonzini /* Set up EPOW events infrastructure */ 188653018216SPaolo Bonzini spapr_events_init(spapr); 188753018216SPaolo Bonzini 188812f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 188928df36a1SDavid Gibson spapr_rtc_create(spapr); 189012f42174SDavid Gibson 189153018216SPaolo Bonzini /* Set up VIO bus */ 189253018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 189353018216SPaolo Bonzini 189453018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 189553018216SPaolo Bonzini if (serial_hds[i]) { 189653018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 189753018216SPaolo Bonzini } 189853018216SPaolo Bonzini } 189953018216SPaolo Bonzini 190053018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 190153018216SPaolo Bonzini spapr_create_nvram(spapr); 190253018216SPaolo Bonzini 190353018216SPaolo Bonzini /* Set up PCI */ 190453018216SPaolo Bonzini spapr_pci_rtas_init(); 190553018216SPaolo Bonzini 190689dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 190753018216SPaolo Bonzini 190853018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 190953018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 191053018216SPaolo Bonzini 191153018216SPaolo Bonzini if (!nd->model) { 191253018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 191353018216SPaolo Bonzini } 191453018216SPaolo Bonzini 191553018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 191653018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 191753018216SPaolo Bonzini } else { 191829b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 191953018216SPaolo Bonzini } 192053018216SPaolo Bonzini } 192153018216SPaolo Bonzini 192253018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 192353018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 192453018216SPaolo Bonzini } 192553018216SPaolo Bonzini 192653018216SPaolo Bonzini /* Graphics */ 192714c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 192853018216SPaolo Bonzini spapr->has_graphics = true; 1929c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 193053018216SPaolo Bonzini } 193153018216SPaolo Bonzini 19324ee9ced9SMarcel Apfelbaum if (machine->usb) { 193357040d45SThomas Huth if (smc->use_ohci_by_default) { 193453018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 193557040d45SThomas Huth } else { 193657040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 193757040d45SThomas Huth } 1938c86580b8SMarkus Armbruster 193953018216SPaolo Bonzini if (spapr->has_graphics) { 1940c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 1941c86580b8SMarkus Armbruster 1942c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 1943c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 194453018216SPaolo Bonzini } 194553018216SPaolo Bonzini } 194653018216SPaolo Bonzini 194753018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 1948d54e4d76SDavid Gibson error_report( 1949d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 1950d54e4d76SDavid Gibson MIN_RMA_SLOF); 195153018216SPaolo Bonzini exit(1); 195253018216SPaolo Bonzini } 195353018216SPaolo Bonzini 195453018216SPaolo Bonzini if (kernel_filename) { 195553018216SPaolo Bonzini uint64_t lowaddr = 0; 195653018216SPaolo Bonzini 195753018216SPaolo Bonzini kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, 19587ef295eaSPeter Crosthwaite NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 19597ef295eaSPeter Crosthwaite 0, 0); 19603b66da82SAlexey Kardashevskiy if (kernel_size == ELF_LOAD_WRONG_ENDIAN) { 196116457e7fSBenjamin Herrenschmidt kernel_size = load_elf(kernel_filename, 196216457e7fSBenjamin Herrenschmidt translate_kernel_address, NULL, 19637ef295eaSPeter Crosthwaite NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 19647ef295eaSPeter Crosthwaite 0, 0); 196516457e7fSBenjamin Herrenschmidt kernel_le = kernel_size > 0; 196616457e7fSBenjamin Herrenschmidt } 196716457e7fSBenjamin Herrenschmidt if (kernel_size < 0) { 1968d54e4d76SDavid Gibson error_report("error loading %s: %s", 19693b66da82SAlexey Kardashevskiy kernel_filename, load_elf_strerror(kernel_size)); 197053018216SPaolo Bonzini exit(1); 197153018216SPaolo Bonzini } 197253018216SPaolo Bonzini 197353018216SPaolo Bonzini /* load initrd */ 197453018216SPaolo Bonzini if (initrd_filename) { 197553018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 197653018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 197753018216SPaolo Bonzini */ 197853018216SPaolo Bonzini initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff; 197953018216SPaolo Bonzini initrd_size = load_image_targphys(initrd_filename, initrd_base, 198053018216SPaolo Bonzini load_limit - initrd_base); 198153018216SPaolo Bonzini if (initrd_size < 0) { 1982d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 198353018216SPaolo Bonzini initrd_filename); 198453018216SPaolo Bonzini exit(1); 198553018216SPaolo Bonzini } 198653018216SPaolo Bonzini } else { 198753018216SPaolo Bonzini initrd_base = 0; 198853018216SPaolo Bonzini initrd_size = 0; 198953018216SPaolo Bonzini } 199053018216SPaolo Bonzini } 199153018216SPaolo Bonzini 19928e7ea787SAndreas Färber if (bios_name == NULL) { 19938e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 19948e7ea787SAndreas Färber } 19958e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 19964c56440dSStefan Weil if (!filename) { 199768fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 19984c56440dSStefan Weil exit(1); 19994c56440dSStefan Weil } 200053018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 200168fea5a0SThomas Huth if (fw_size <= 0) { 200268fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 200353018216SPaolo Bonzini exit(1); 200453018216SPaolo Bonzini } 200553018216SPaolo Bonzini g_free(filename); 200653018216SPaolo Bonzini 200728e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 200828e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 200928e02042SDavid Gibson * which predated MachineState but had a similar function */ 20104be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 20114be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 20124be21d56SDavid Gibson &savevm_htab_handlers, spapr); 20134be21d56SDavid Gibson 201453018216SPaolo Bonzini /* Prepare the device tree */ 20153bbf37f2SAndreas Färber spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size, 201616457e7fSBenjamin Herrenschmidt kernel_size, kernel_le, 201731fe14d1SNathan Fontenot kernel_cmdline, 201831fe14d1SNathan Fontenot spapr->check_exception_irq); 201953018216SPaolo Bonzini assert(spapr->fdt_skel != NULL); 20205b2128d2SAlexander Graf 202146503c2bSMichael Roth /* used by RTAS */ 202246503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 202346503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 202446503c2bSMichael Roth 20255b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 202653018216SPaolo Bonzini } 202753018216SPaolo Bonzini 2028135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 2029135a129aSAneesh Kumar K.V { 2030135a129aSAneesh Kumar K.V if (!vm_type) { 2031135a129aSAneesh Kumar K.V return 0; 2032135a129aSAneesh Kumar K.V } 2033135a129aSAneesh Kumar K.V 2034135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 2035135a129aSAneesh Kumar K.V return 1; 2036135a129aSAneesh Kumar K.V } 2037135a129aSAneesh Kumar K.V 2038135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2039135a129aSAneesh Kumar K.V return 2; 2040135a129aSAneesh Kumar K.V } 2041135a129aSAneesh Kumar K.V 2042135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2043135a129aSAneesh Kumar K.V exit(1); 2044135a129aSAneesh Kumar K.V } 2045135a129aSAneesh Kumar K.V 204671461b0fSAlexey Kardashevskiy /* 2047627b84f4SGonglei * Implementation of an interface to adjust firmware path 204871461b0fSAlexey Kardashevskiy * for the bootindex property handling. 204971461b0fSAlexey Kardashevskiy */ 205071461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 205171461b0fSAlexey Kardashevskiy DeviceState *dev) 205271461b0fSAlexey Kardashevskiy { 205371461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 205471461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 205571461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 205671461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 205771461b0fSAlexey Kardashevskiy 205871461b0fSAlexey Kardashevskiy if (d) { 205971461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 206071461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 206171461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 206271461b0fSAlexey Kardashevskiy 206371461b0fSAlexey Kardashevskiy if (spapr) { 206471461b0fSAlexey Kardashevskiy /* 206571461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 206671461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 206771461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 206871461b0fSAlexey Kardashevskiy */ 206971461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 207071461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 207171461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 207271461b0fSAlexey Kardashevskiy } else if (virtio) { 207371461b0fSAlexey Kardashevskiy /* 207471461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 207571461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 207671461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 207771461b0fSAlexey Kardashevskiy * the actual binding is: 207871461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 207971461b0fSAlexey Kardashevskiy */ 208071461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 208171461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 208271461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 208371461b0fSAlexey Kardashevskiy } else if (usb) { 208471461b0fSAlexey Kardashevskiy /* 208571461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 208671461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 208771461b0fSAlexey Kardashevskiy */ 208871461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 208971461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 209071461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 209171461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 209271461b0fSAlexey Kardashevskiy } 209371461b0fSAlexey Kardashevskiy } 209471461b0fSAlexey Kardashevskiy 209571461b0fSAlexey Kardashevskiy if (phb) { 209671461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 209771461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 209871461b0fSAlexey Kardashevskiy } 209971461b0fSAlexey Kardashevskiy 210071461b0fSAlexey Kardashevskiy return NULL; 210171461b0fSAlexey Kardashevskiy } 210271461b0fSAlexey Kardashevskiy 210323825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 210423825581SEduardo Habkost { 210528e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 210623825581SEduardo Habkost 210728e02042SDavid Gibson return g_strdup(spapr->kvm_type); 210823825581SEduardo Habkost } 210923825581SEduardo Habkost 211023825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 211123825581SEduardo Habkost { 211228e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 211323825581SEduardo Habkost 211428e02042SDavid Gibson g_free(spapr->kvm_type); 211528e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 211623825581SEduardo Habkost } 211723825581SEduardo Habkost 211823825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 211923825581SEduardo Habkost { 2120715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2121715c5407SDavid Gibson 2122715c5407SDavid Gibson spapr->htab_fd = -1; 212323825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 212423825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 212549d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 212649d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 212749d2e648SMarcel Apfelbaum NULL); 212823825581SEduardo Habkost } 212923825581SEduardo Habkost 213087bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 213187bbdd9cSDavid Gibson { 213287bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 213387bbdd9cSDavid Gibson 213487bbdd9cSDavid Gibson g_free(spapr->kvm_type); 213587bbdd9cSDavid Gibson } 213687bbdd9cSDavid Gibson 2137*e0eeb4a2SAlex Bennée static void ppc_cpu_do_nmi_on_cpu(CPUState *cs, void *arg) 213834316482SAlexey Kardashevskiy { 213934316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 214034316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 214134316482SAlexey Kardashevskiy } 214234316482SAlexey Kardashevskiy 214334316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 214434316482SAlexey Kardashevskiy { 214534316482SAlexey Kardashevskiy CPUState *cs; 214634316482SAlexey Kardashevskiy 214734316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 2148*e0eeb4a2SAlex Bennée async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, NULL); 214934316482SAlexey Kardashevskiy } 215034316482SAlexey Kardashevskiy } 215134316482SAlexey Kardashevskiy 2152c20d332aSBharata B Rao static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, 2153c20d332aSBharata B Rao uint32_t node, Error **errp) 2154c20d332aSBharata B Rao { 2155c20d332aSBharata B Rao sPAPRDRConnector *drc; 2156c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2157c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2158c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2159c20d332aSBharata B Rao void *fdt; 2160c20d332aSBharata B Rao 2161c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2162c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2163c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2164c20d332aSBharata B Rao g_assert(drc); 2165c20d332aSBharata B Rao 2166c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2167c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2168c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2169c20d332aSBharata B Rao 2170c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2171c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2172c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2173c20d332aSBharata B Rao } 21745dd5238cSJianjun Duan /* send hotplug notification to the 21755dd5238cSJianjun Duan * guest only in case of hotplugged memory 21765dd5238cSJianjun Duan */ 21775dd5238cSJianjun Duan if (dev->hotplugged) { 21780a417869SBharata B Rao spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); 2179c20d332aSBharata B Rao } 21805dd5238cSJianjun Duan } 2181c20d332aSBharata B Rao 2182c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2183c20d332aSBharata B Rao uint32_t node, Error **errp) 2184c20d332aSBharata B Rao { 2185c20d332aSBharata B Rao Error *local_err = NULL; 2186c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2187c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2188c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2189c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2190c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2191c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2192c20d332aSBharata B Rao uint64_t addr; 2193c20d332aSBharata B Rao 2194c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2195c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2196c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2197c20d332aSBharata B Rao goto out; 2198c20d332aSBharata B Rao } 2199c20d332aSBharata B Rao 2200d6a9b0b8SMichael S. Tsirkin pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 2201c20d332aSBharata B Rao if (local_err) { 2202c20d332aSBharata B Rao goto out; 2203c20d332aSBharata B Rao } 2204c20d332aSBharata B Rao 2205c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2206c20d332aSBharata B Rao if (local_err) { 2207c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2208c20d332aSBharata B Rao goto out; 2209c20d332aSBharata B Rao } 2210c20d332aSBharata B Rao 2211c20d332aSBharata B Rao spapr_add_lmbs(dev, addr, size, node, &error_abort); 2212c20d332aSBharata B Rao 2213c20d332aSBharata B Rao out: 2214c20d332aSBharata B Rao error_propagate(errp, local_err); 2215c20d332aSBharata B Rao } 2216c20d332aSBharata B Rao 2217af81cf32SBharata B Rao void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, 2218af81cf32SBharata B Rao sPAPRMachineState *spapr) 2219af81cf32SBharata B Rao { 2220af81cf32SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 2221af81cf32SBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 2222af81cf32SBharata B Rao int id = ppc_get_vcpu_dt_id(cpu); 2223af81cf32SBharata B Rao void *fdt; 2224af81cf32SBharata B Rao int offset, fdt_size; 2225af81cf32SBharata B Rao char *nodename; 2226af81cf32SBharata B Rao 2227af81cf32SBharata B Rao fdt = create_device_tree(&fdt_size); 2228af81cf32SBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 2229af81cf32SBharata B Rao offset = fdt_add_subnode(fdt, 0, nodename); 2230af81cf32SBharata B Rao 2231af81cf32SBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 2232af81cf32SBharata B Rao g_free(nodename); 2233af81cf32SBharata B Rao 2234af81cf32SBharata B Rao *fdt_offset = offset; 2235af81cf32SBharata B Rao return fdt; 2236af81cf32SBharata B Rao } 2237af81cf32SBharata B Rao 2238c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2239c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2240c20d332aSBharata B Rao { 2241c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2242c20d332aSBharata B Rao 2243c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2244b556854bSBharata B Rao int node; 2245c20d332aSBharata B Rao 2246c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2247c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2248c20d332aSBharata B Rao return; 2249c20d332aSBharata B Rao } 2250c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2251c20d332aSBharata B Rao if (*errp) { 2252c20d332aSBharata B Rao return; 2253c20d332aSBharata B Rao } 22541a5512bbSGonglei if (node < 0 || node >= MAX_NODES) { 22551a5512bbSGonglei error_setg(errp, "Invaild node %d", node); 22561a5512bbSGonglei return; 22571a5512bbSGonglei } 2258c20d332aSBharata B Rao 2259b556854bSBharata B Rao /* 2260b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2261b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2262b556854bSBharata B Rao * to the first node that has some memory. This causes two 2263b556854bSBharata B Rao * unexpected behaviours for the user. 2264b556854bSBharata B Rao * 2265b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2266b556854bSBharata B Rao * specified. 2267b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2268b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2269b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2270b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2271b556854bSBharata B Rao * 2272b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2273b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2274b556854bSBharata B Rao */ 2275b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2276b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2277b556854bSBharata B Rao node); 2278b556854bSBharata B Rao return; 2279b556854bSBharata B Rao } 2280b556854bSBharata B Rao 2281c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2282af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2283af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 2284c20d332aSBharata B Rao } 2285c20d332aSBharata B Rao } 2286c20d332aSBharata B Rao 2287c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2288c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2289c20d332aSBharata B Rao { 22903c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 22916f4b5c3eSBharata B Rao 2292c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2293c20d332aSBharata B Rao error_setg(errp, "Memory hot unplug not supported by sPAPR"); 22946f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 22953c0c47e3SDavid Gibson if (!mc->query_hotpluggable_cpus) { 22966f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 22976f4b5c3eSBharata B Rao return; 22986f4b5c3eSBharata B Rao } 22996f4b5c3eSBharata B Rao spapr_core_unplug(hotplug_dev, dev, errp); 2300c20d332aSBharata B Rao } 2301c20d332aSBharata B Rao } 2302c20d332aSBharata B Rao 230394a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 230494a94e4cSBharata B Rao DeviceState *dev, Error **errp) 230594a94e4cSBharata B Rao { 230694a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 230794a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 230894a94e4cSBharata B Rao } 230994a94e4cSBharata B Rao } 231094a94e4cSBharata B Rao 23117ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 2312c20d332aSBharata B Rao DeviceState *dev) 2313c20d332aSBharata B Rao { 231494a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 231594a94e4cSBharata B Rao object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2316c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2317c20d332aSBharata B Rao } 2318c20d332aSBharata B Rao return NULL; 2319c20d332aSBharata B Rao } 2320c20d332aSBharata B Rao 232120bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) 232220bb648dSDavid Gibson { 232320bb648dSDavid Gibson /* Allocate to NUMA nodes on a "socket" basis (not that concept of 232420bb648dSDavid Gibson * socket means much for the paravirtualized PAPR platform) */ 232520bb648dSDavid Gibson return cpu_index / smp_threads / smp_cores; 232620bb648dSDavid Gibson } 232720bb648dSDavid Gibson 23282474bfd4SIgor Mammedov static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine) 23292474bfd4SIgor Mammedov { 23302474bfd4SIgor Mammedov int i; 23312474bfd4SIgor Mammedov HotpluggableCPUList *head = NULL; 23322474bfd4SIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 23332474bfd4SIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 23342474bfd4SIgor Mammedov 23352474bfd4SIgor Mammedov for (i = 0; i < spapr_max_cores; i++) { 23362474bfd4SIgor Mammedov HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); 23372474bfd4SIgor Mammedov HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); 23382474bfd4SIgor Mammedov CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1); 23392474bfd4SIgor Mammedov 23402474bfd4SIgor Mammedov cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model); 23412474bfd4SIgor Mammedov cpu_item->vcpus_count = smp_threads; 234227393c33SPeter Krempa cpu_props->has_core_id = true; 234312bf2d33SGreg Kurz cpu_props->core_id = i * smp_threads; 23442474bfd4SIgor Mammedov /* TODO: add 'has_node/node' here to describe 23452474bfd4SIgor Mammedov to which node core belongs */ 23462474bfd4SIgor Mammedov 23472474bfd4SIgor Mammedov cpu_item->props = cpu_props; 23482474bfd4SIgor Mammedov if (spapr->cores[i]) { 23492474bfd4SIgor Mammedov cpu_item->has_qom_path = true; 23502474bfd4SIgor Mammedov cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]); 23512474bfd4SIgor Mammedov } 23522474bfd4SIgor Mammedov list_item->value = cpu_item; 23532474bfd4SIgor Mammedov list_item->next = head; 23542474bfd4SIgor Mammedov head = list_item; 23552474bfd4SIgor Mammedov } 23562474bfd4SIgor Mammedov return head; 23572474bfd4SIgor Mammedov } 23582474bfd4SIgor Mammedov 235929ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 236053018216SPaolo Bonzini { 236129ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 2362224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 236371461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 236434316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 2365c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 236629ee3247SAlexey Kardashevskiy 23670eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 2368fc9f38c3SDavid Gibson 2369fc9f38c3SDavid Gibson /* 2370fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 2371fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 2372fc9f38c3SDavid Gibson * these details for backwards compatibility 2373fc9f38c3SDavid Gibson */ 2374958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 2375958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 2376958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 237738b02bd8SAlexey Kardashevskiy mc->max_cpus = MAX_CPUMASK_BITS; 2378958db90cSMarcel Apfelbaum mc->no_parallel = 1; 23795b2128d2SAlexander Graf mc->default_boot_order = ""; 2380a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 2381958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 23829e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 2383e4024630SLaurent Vivier mc->pci_allow_0_address = true; 23847ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 238594a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 2386c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 2387c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 238820bb648dSDavid Gibson mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; 238900b4fbe2SMarcel Apfelbaum 2390fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 23913c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus; 239271461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 239334316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 239453018216SPaolo Bonzini } 239553018216SPaolo Bonzini 239629ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 239729ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 239829ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 23994aee7362SDavid Gibson .abstract = true, 24006ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 240123825581SEduardo Habkost .instance_init = spapr_machine_initfn, 240287bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 2403183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 240429ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 240571461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 240671461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 240734316482SAlexey Kardashevskiy { TYPE_NMI }, 2408c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 240971461b0fSAlexey Kardashevskiy { } 241071461b0fSAlexey Kardashevskiy }, 241129ee3247SAlexey Kardashevskiy }; 241229ee3247SAlexey Kardashevskiy 2413fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 24145013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 24155013c547SDavid Gibson void *data) \ 24165013c547SDavid Gibson { \ 24175013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 24185013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 2419fccbc785SDavid Gibson if (latest) { \ 2420fccbc785SDavid Gibson mc->alias = "pseries"; \ 2421fccbc785SDavid Gibson mc->is_default = 1; \ 2422fccbc785SDavid Gibson } \ 24235013c547SDavid Gibson } \ 24245013c547SDavid Gibson static void spapr_machine_##suffix##_instance_init(Object *obj) \ 24255013c547SDavid Gibson { \ 24265013c547SDavid Gibson MachineState *machine = MACHINE(obj); \ 24275013c547SDavid Gibson spapr_machine_##suffix##_instance_options(machine); \ 24285013c547SDavid Gibson } \ 24295013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 24305013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 24315013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 24325013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 24335013c547SDavid Gibson .instance_init = spapr_machine_##suffix##_instance_init, \ 24345013c547SDavid Gibson }; \ 24355013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 24365013c547SDavid Gibson { \ 24375013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 24385013c547SDavid Gibson } \ 24390e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 24405013c547SDavid Gibson 24411c5f29bbSDavid Gibson /* 24421ea1eefcSBharata B Rao * pseries-2.7 24431ea1eefcSBharata B Rao */ 24441ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine) 24451ea1eefcSBharata B Rao { 24461ea1eefcSBharata B Rao } 24471ea1eefcSBharata B Rao 24481ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 24491ea1eefcSBharata B Rao { 24501ea1eefcSBharata B Rao /* Defaults for the latest behaviour inherited from the base class */ 24511ea1eefcSBharata B Rao } 24521ea1eefcSBharata B Rao 24531ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_7, "2.7", true); 24541ea1eefcSBharata B Rao 24551ea1eefcSBharata B Rao /* 24564b23699cSDavid Gibson * pseries-2.6 24574b23699cSDavid Gibson */ 24581ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \ 2459ae4de14cSAlexey Kardashevskiy HW_COMPAT_2_6 \ 2460ae4de14cSAlexey Kardashevskiy { \ 2461ae4de14cSAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2462ae4de14cSAlexey Kardashevskiy .property = "ddw",\ 2463ae4de14cSAlexey Kardashevskiy .value = stringify(off),\ 2464ae4de14cSAlexey Kardashevskiy }, 24651ea1eefcSBharata B Rao 24664b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine) 24674b23699cSDavid Gibson { 24684b23699cSDavid Gibson } 24694b23699cSDavid Gibson 24704b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc) 24714b23699cSDavid Gibson { 24721ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 24733c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = NULL; 24741ea1eefcSBharata B Rao SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); 24754b23699cSDavid Gibson } 24764b23699cSDavid Gibson 24771ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 24784b23699cSDavid Gibson 24794b23699cSDavid Gibson /* 24801c5f29bbSDavid Gibson * pseries-2.5 24811c5f29bbSDavid Gibson */ 24824b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \ 248357c522f4SThomas Huth HW_COMPAT_2_5 \ 248457c522f4SThomas Huth { \ 248557c522f4SThomas Huth .driver = "spapr-vlan", \ 248657c522f4SThomas Huth .property = "use-rx-buffer-pools", \ 248757c522f4SThomas Huth .value = "off", \ 248857c522f4SThomas Huth }, 24894b23699cSDavid Gibson 24905013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine) 24911c5f29bbSDavid Gibson { 24925013c547SDavid Gibson } 24935013c547SDavid Gibson 24945013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc) 24955013c547SDavid Gibson { 249657040d45SThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 249757040d45SThomas Huth 24984b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 249957040d45SThomas Huth smc->use_ohci_by_default = true; 25004b23699cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5); 25011c5f29bbSDavid Gibson } 25021c5f29bbSDavid Gibson 25034b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 25041c5f29bbSDavid Gibson 25051c5f29bbSDavid Gibson /* 25061c5f29bbSDavid Gibson * pseries-2.4 25071c5f29bbSDavid Gibson */ 250880fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \ 250980fd50f9SCornelia Huck HW_COMPAT_2_4 251080fd50f9SCornelia Huck 25115013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine) 25121c5f29bbSDavid Gibson { 25135013c547SDavid Gibson spapr_machine_2_5_instance_options(machine); 25145013c547SDavid Gibson } 25151c5f29bbSDavid Gibson 25165013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 25175013c547SDavid Gibson { 2518fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 2519fc9f38c3SDavid Gibson 2520fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 2521fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 2522f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4); 25231c5f29bbSDavid Gibson } 25241c5f29bbSDavid Gibson 2525fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 25261c5f29bbSDavid Gibson 25271c5f29bbSDavid Gibson /* 25281c5f29bbSDavid Gibson * pseries-2.3 25291c5f29bbSDavid Gibson */ 253038ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 25317619c7b0SMichael Roth HW_COMPAT_2_3 \ 25327619c7b0SMichael Roth {\ 25337619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 25347619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 25357619c7b0SMichael Roth .value = "off",\ 25367619c7b0SMichael Roth }, 253738ff32c6SEduardo Habkost 25385013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine) 25391c5f29bbSDavid Gibson { 25405013c547SDavid Gibson spapr_machine_2_4_instance_options(machine); 25411c5f29bbSDavid Gibson savevm_skip_section_footers(); 25421c5f29bbSDavid Gibson global_state_set_optional(); 254309b5e30dSGreg Kurz savevm_skip_configuration(); 25441c5f29bbSDavid Gibson } 25451c5f29bbSDavid Gibson 25465013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc) 25471c5f29bbSDavid Gibson { 2548fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 2549f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3); 25501c5f29bbSDavid Gibson } 2551fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 25521c5f29bbSDavid Gibson 25531c5f29bbSDavid Gibson /* 25541c5f29bbSDavid Gibson * pseries-2.2 25551c5f29bbSDavid Gibson */ 25561c5f29bbSDavid Gibson 2557b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 25584dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 2559b194df47SAlexey Kardashevskiy {\ 2560b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2561b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 2562b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 2563dd754bafSEduardo Habkost }, 2564b194df47SAlexey Kardashevskiy 25655013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine) 2566b0e966d0SJason Wang { 25675013c547SDavid Gibson spapr_machine_2_3_instance_options(machine); 2568cba0e779SGreg Kurz machine->suppress_vmdesc = true; 2569b0e966d0SJason Wang } 2570b0e966d0SJason Wang 25715013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc) 2572b0e966d0SJason Wang { 2573fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 2574f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2); 25751c5f29bbSDavid Gibson } 2576fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 25771c5f29bbSDavid Gibson 25781c5f29bbSDavid Gibson /* 25791c5f29bbSDavid Gibson * pseries-2.1 25801c5f29bbSDavid Gibson */ 25811c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \ 25821c5f29bbSDavid Gibson HW_COMPAT_2_1 25831c5f29bbSDavid Gibson 25845013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine) 25851c5f29bbSDavid Gibson { 25865013c547SDavid Gibson spapr_machine_2_2_instance_options(machine); 25871c5f29bbSDavid Gibson } 25881c5f29bbSDavid Gibson 25895013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 2590b0e966d0SJason Wang { 2591fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 2592f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1); 25936026db45SAlexey Kardashevskiy } 2594fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 25956026db45SAlexey Kardashevskiy 259629ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 259729ee3247SAlexey Kardashevskiy { 259829ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 259929ee3247SAlexey Kardashevskiy } 260029ee3247SAlexey Kardashevskiy 260129ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 2602