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 274a19f7fb0SDavid Gibson static void *spapr_create_fdt_skel(sPAPRMachineState *spapr) 27553018216SPaolo Bonzini { 276a19f7fb0SDavid Gibson MachineState *machine = MACHINE(spapr); 27753018216SPaolo Bonzini void *fdt; 278a19f7fb0SDavid Gibson uint32_t start_prop = cpu_to_be32(spapr->initrd_base); 279a19f7fb0SDavid Gibson uint32_t end_prop = cpu_to_be32(spapr->initrd_base + spapr->initrd_size); 280a1d59c0fSAlexey Kardashevskiy GString *hypertas = g_string_sized_new(256); 281a1d59c0fSAlexey Kardashevskiy GString *qemu_hypertas = g_string_sized_new(256); 28253018216SPaolo Bonzini uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; 28353018216SPaolo Bonzini unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; 284ef951443SNikunj A Dadhania char *buf; 28553018216SPaolo Bonzini 286a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-pft"); 287a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-term"); 288a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-dabr"); 289a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-interrupt"); 290a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-tce"); 291a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-vio"); 292a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-splpar"); 293a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-bulk"); 294a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-set-mode"); 2956cc09e26SThomas Huth add_str(hypertas, "hcall-sprg0"); 2966cc09e26SThomas Huth add_str(hypertas, "hcall-copy"); 2976cc09e26SThomas Huth add_str(hypertas, "hcall-debug"); 298a1d59c0fSAlexey Kardashevskiy add_str(qemu_hypertas, "hcall-memop1"); 299a1d59c0fSAlexey Kardashevskiy 30053018216SPaolo Bonzini fdt = g_malloc0(FDT_MAX_SIZE); 30153018216SPaolo Bonzini _FDT((fdt_create(fdt, FDT_MAX_SIZE))); 30253018216SPaolo Bonzini 30353018216SPaolo Bonzini _FDT((fdt_finish_reservemap(fdt))); 30453018216SPaolo Bonzini 30553018216SPaolo Bonzini /* Root node */ 30653018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, ""))); 30753018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "chrp"))); 30853018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)"))); 309fa388916SAnthony Liguori _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries"))); 31053018216SPaolo Bonzini 311ef951443SNikunj A Dadhania /* 312ef951443SNikunj A Dadhania * Add info to guest to indentify which host is it being run on 313ef951443SNikunj A Dadhania * and what is the uuid of the guest 314ef951443SNikunj A Dadhania */ 315ef951443SNikunj A Dadhania if (kvmppc_get_host_model(&buf)) { 316ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "host-model", buf))); 317ef951443SNikunj A Dadhania g_free(buf); 318ef951443SNikunj A Dadhania } 319ef951443SNikunj A Dadhania if (kvmppc_get_host_serial(&buf)) { 320ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "host-serial", buf))); 321ef951443SNikunj A Dadhania g_free(buf); 322ef951443SNikunj A Dadhania } 323ef951443SNikunj A Dadhania 3249c5ce8dbSFam Zheng buf = qemu_uuid_unparse_strdup(&qemu_uuid); 325ef951443SNikunj A Dadhania 326ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "vm,uuid", buf))); 3273dc0a66dSAlexey Kardashevskiy if (qemu_uuid_set) { 3283dc0a66dSAlexey Kardashevskiy _FDT((fdt_property_string(fdt, "system-id", buf))); 3293dc0a66dSAlexey Kardashevskiy } 330ef951443SNikunj A Dadhania g_free(buf); 331ef951443SNikunj A Dadhania 3322c1aaa81SSam Bobroff if (qemu_get_vm_name()) { 3332c1aaa81SSam Bobroff _FDT((fdt_property_string(fdt, "ibm,partition-name", 3342c1aaa81SSam Bobroff qemu_get_vm_name()))); 3352c1aaa81SSam Bobroff } 3362c1aaa81SSam Bobroff 33753018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x2))); 33853018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x2))); 33953018216SPaolo Bonzini 34053018216SPaolo Bonzini /* /chosen */ 34153018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "chosen"))); 34253018216SPaolo Bonzini 34353018216SPaolo Bonzini /* Set Form1_affinity */ 34453018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5)))); 34553018216SPaolo Bonzini 346a19f7fb0SDavid Gibson _FDT((fdt_property_string(fdt, "bootargs", machine->kernel_cmdline))); 34753018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-start", 34853018216SPaolo Bonzini &start_prop, sizeof(start_prop)))); 34953018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-end", 35053018216SPaolo Bonzini &end_prop, sizeof(end_prop)))); 351a19f7fb0SDavid Gibson if (spapr->kernel_size) { 35253018216SPaolo Bonzini uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 353a19f7fb0SDavid Gibson cpu_to_be64(spapr->kernel_size) }; 35453018216SPaolo Bonzini 35553018216SPaolo Bonzini _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop)))); 356a19f7fb0SDavid Gibson if (spapr->kernel_le) { 35716457e7fSBenjamin Herrenschmidt _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0))); 35816457e7fSBenjamin Herrenschmidt } 35953018216SPaolo Bonzini } 360cc84c0f3SAvik Sil if (boot_menu) { 361cc84c0f3SAvik Sil _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu))); 362cc84c0f3SAvik Sil } 36353018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width))); 36453018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height))); 36553018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth))); 36653018216SPaolo Bonzini 36753018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 36853018216SPaolo Bonzini 36953018216SPaolo Bonzini /* RTAS */ 37053018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "rtas"))); 37153018216SPaolo Bonzini 372da95324eSAlexey Kardashevskiy if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 373da95324eSAlexey Kardashevskiy add_str(hypertas, "hcall-multi-tce"); 374da95324eSAlexey Kardashevskiy } 375a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str, 376a1d59c0fSAlexey Kardashevskiy hypertas->len))); 377a1d59c0fSAlexey Kardashevskiy g_string_free(hypertas, TRUE); 378a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str, 379a1d59c0fSAlexey Kardashevskiy qemu_hypertas->len))); 380a1d59c0fSAlexey Kardashevskiy g_string_free(qemu_hypertas, TRUE); 38153018216SPaolo Bonzini 38253018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,associativity-reference-points", 38353018216SPaolo Bonzini refpoints, sizeof(refpoints)))); 38453018216SPaolo Bonzini 38553018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX))); 38679853e18STyrel Datwyler _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", 38779853e18STyrel Datwyler RTAS_EVENT_SCAN_RATE))); 38853018216SPaolo Bonzini 389226419d6SMichael S. Tsirkin if (msi_nonbroken) { 390a95f9922SSam Bobroff _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0))); 391a95f9922SSam Bobroff } 392a95f9922SSam Bobroff 3932e14072fSNikunj A Dadhania /* 3949d632f5fSzhanghailiang * According to PAPR, rtas ibm,os-term does not guarantee a return 3952e14072fSNikunj A Dadhania * back to the guest cpu. 3962e14072fSNikunj A Dadhania * 3972e14072fSNikunj A Dadhania * While an additional ibm,extended-os-term property indicates that 3982e14072fSNikunj A Dadhania * rtas call return will always occur. Set this property. 3992e14072fSNikunj A Dadhania */ 4002e14072fSNikunj A Dadhania _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0))); 4012e14072fSNikunj A Dadhania 40253018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 40353018216SPaolo Bonzini 40453018216SPaolo Bonzini /* vdevice */ 40553018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "vdevice"))); 40653018216SPaolo Bonzini 40753018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "vdevice"))); 40853018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice"))); 40953018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x1))); 41053018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x0))); 41153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2))); 41253018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 41353018216SPaolo Bonzini 41453018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 41553018216SPaolo Bonzini 41653018216SPaolo Bonzini /* event-sources */ 417a19f7fb0SDavid Gibson spapr_events_fdt_skel(fdt, spapr->check_exception_irq); 41853018216SPaolo Bonzini 419f7d69146SAlexander Graf /* /hypervisor node */ 420f7d69146SAlexander Graf if (kvm_enabled()) { 421f7d69146SAlexander Graf uint8_t hypercall[16]; 422f7d69146SAlexander Graf 423f7d69146SAlexander Graf /* indicate KVM hypercall interface */ 424f7d69146SAlexander Graf _FDT((fdt_begin_node(fdt, "hypervisor"))); 425f7d69146SAlexander Graf _FDT((fdt_property_string(fdt, "compatible", "linux,kvm"))); 426f7d69146SAlexander Graf if (kvmppc_has_cap_fixup_hcalls()) { 427f7d69146SAlexander Graf /* 428f7d69146SAlexander Graf * Older KVM versions with older guest kernels were broken with the 429f7d69146SAlexander Graf * magic page, don't allow the guest to map it. 430f7d69146SAlexander Graf */ 4310ddbd053SAlexey Kardashevskiy if (!kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 4320ddbd053SAlexey Kardashevskiy sizeof(hypercall))) { 433f7d69146SAlexander Graf _FDT((fdt_property(fdt, "hcall-instructions", hypercall, 434f7d69146SAlexander Graf sizeof(hypercall)))); 435f7d69146SAlexander Graf } 4360ddbd053SAlexey Kardashevskiy } 437f7d69146SAlexander Graf _FDT((fdt_end_node(fdt))); 438f7d69146SAlexander Graf } 439f7d69146SAlexander Graf 44053018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); /* close root node */ 44153018216SPaolo Bonzini _FDT((fdt_finish(fdt))); 44253018216SPaolo Bonzini 44353018216SPaolo Bonzini return fdt; 44453018216SPaolo Bonzini } 44553018216SPaolo Bonzini 44603d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 44726a8c353SAlexey Kardashevskiy hwaddr size) 44826a8c353SAlexey Kardashevskiy { 44926a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 45026a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 45126a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 452c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 45326a8c353SAlexey Kardashevskiy }; 45426a8c353SAlexey Kardashevskiy char mem_name[32]; 45526a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 45626a8c353SAlexey Kardashevskiy int off; 45726a8c353SAlexey Kardashevskiy 45826a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 45926a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 46026a8c353SAlexey Kardashevskiy 46126a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 46226a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 46326a8c353SAlexey Kardashevskiy _FDT(off); 46426a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 46526a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 46626a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 46726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 46826a8c353SAlexey Kardashevskiy sizeof(associativity)))); 46903d196b7SBharata B Rao return off; 47026a8c353SAlexey Kardashevskiy } 47126a8c353SAlexey Kardashevskiy 47228e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 47353018216SPaolo Bonzini { 474fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 4757db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 4767db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 4777db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 4787db8a127SAlexey Kardashevskiy NodeInfo ramnode; 47953018216SPaolo Bonzini 4807db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 4817db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 4827db8a127SAlexey Kardashevskiy nb_nodes = 1; 483fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 4847db8a127SAlexey Kardashevskiy nodes = &ramnode; 4855fe269b1SPaul Mackerras } 48653018216SPaolo Bonzini 4877db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 4887db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 4897db8a127SAlexey Kardashevskiy continue; 49053018216SPaolo Bonzini } 491fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 4925fe269b1SPaul Mackerras node_size = 0; 4935fe269b1SPaul Mackerras } else { 4947db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 495fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 496fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 4975fe269b1SPaul Mackerras } 4985fe269b1SPaul Mackerras } 4997db8a127SAlexey Kardashevskiy if (!mem_start) { 5007db8a127SAlexey Kardashevskiy /* ppc_spapr_init() checks for rma_size <= node0_size already */ 501e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 5027db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 5037db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 5047db8a127SAlexey Kardashevskiy } 5056010818cSAlexey Kardashevskiy for ( ; node_size; ) { 5066010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 5076010818cSAlexey Kardashevskiy 5086010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 5096010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 5106010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 5116010818cSAlexey Kardashevskiy } 5126010818cSAlexey Kardashevskiy 5136010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 5146010818cSAlexey Kardashevskiy node_size -= sizetmp; 5156010818cSAlexey Kardashevskiy mem_start += sizetmp; 5166010818cSAlexey Kardashevskiy } 51753018216SPaolo Bonzini } 51853018216SPaolo Bonzini 51953018216SPaolo Bonzini return 0; 52053018216SPaolo Bonzini } 52153018216SPaolo Bonzini 522230bf719SThomas Huth /* Populate the "ibm,pa-features" property */ 523230bf719SThomas Huth static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset) 524230bf719SThomas Huth { 525230bf719SThomas Huth uint8_t pa_features_206[] = { 6, 0, 526230bf719SThomas Huth 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 527230bf719SThomas Huth uint8_t pa_features_207[] = { 24, 0, 528230bf719SThomas Huth 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 529230bf719SThomas Huth 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 530230bf719SThomas Huth 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 531bac3bf28SThomas Huth 0x80, 0x00, 0x80, 0x00, 0x00, 0x00 }; 532230bf719SThomas Huth uint8_t *pa_features; 533230bf719SThomas Huth size_t pa_size; 534230bf719SThomas Huth 5354cbec30dSThomas Huth switch (env->mmu_model) { 5364cbec30dSThomas Huth case POWERPC_MMU_2_06: 5374cbec30dSThomas Huth case POWERPC_MMU_2_06a: 538230bf719SThomas Huth pa_features = pa_features_206; 539230bf719SThomas Huth pa_size = sizeof(pa_features_206); 5404cbec30dSThomas Huth break; 5414cbec30dSThomas Huth case POWERPC_MMU_2_07: 5424cbec30dSThomas Huth case POWERPC_MMU_2_07a: 543230bf719SThomas Huth pa_features = pa_features_207; 544230bf719SThomas Huth pa_size = sizeof(pa_features_207); 5454cbec30dSThomas Huth break; 5464cbec30dSThomas Huth default: 5474cbec30dSThomas Huth return; 548230bf719SThomas Huth } 549230bf719SThomas Huth 550230bf719SThomas Huth if (env->ci_large_pages) { 551230bf719SThomas Huth /* 552230bf719SThomas Huth * Note: we keep CI large pages off by default because a 64K capable 553230bf719SThomas Huth * guest provisioned with large pages might otherwise try to map a qemu 554230bf719SThomas Huth * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 555230bf719SThomas Huth * even if that qemu runs on a 4k host. 556230bf719SThomas Huth * We dd this bit back here if we are confident this is not an issue 557230bf719SThomas Huth */ 558230bf719SThomas Huth pa_features[3] |= 0x20; 559230bf719SThomas Huth } 560bac3bf28SThomas Huth if (kvmppc_has_cap_htm() && pa_size > 24) { 561bac3bf28SThomas Huth pa_features[24] |= 0x80; /* Transactional memory support */ 562bac3bf28SThomas Huth } 563230bf719SThomas Huth 564230bf719SThomas Huth _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 565230bf719SThomas Huth } 566230bf719SThomas Huth 5670da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 5680da6f3feSBharata B Rao sPAPRMachineState *spapr) 5690da6f3feSBharata B Rao { 5700da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 5710da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 5720da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 5730da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 5740da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 5750da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 576afd10a0fSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() 577afd10a0fSBharata B Rao : SPAPR_TIMEBASE_FREQ; 5780da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 5790da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 5800da6f3feSBharata B Rao size_t page_sizes_prop_size; 58122419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 5820da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 583af81cf32SBharata B Rao sPAPRDRConnector *drc; 584af81cf32SBharata B Rao sPAPRDRConnectorClass *drck; 585af81cf32SBharata B Rao int drc_index; 586af81cf32SBharata B Rao 587af81cf32SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); 588af81cf32SBharata B Rao if (drc) { 589af81cf32SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 590af81cf32SBharata B Rao drc_index = drck->get_index(drc); 591af81cf32SBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); 592af81cf32SBharata B Rao } 5930da6f3feSBharata B Rao 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 660230bf719SThomas Huth spapr_populate_pa_features(env, fdt, offset); 66190da0d5aSBenjamin Herrenschmidt 6620da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 66322419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 6640da6f3feSBharata B Rao 6650da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 6660da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 6670da6f3feSBharata B Rao 6680da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 6690da6f3feSBharata B Rao 6700da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 6710da6f3feSBharata B Rao ppc_get_compat_smt_threads(cpu))); 6720da6f3feSBharata B Rao } 6730da6f3feSBharata B Rao 6740da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 6750da6f3feSBharata B Rao { 6760da6f3feSBharata B Rao CPUState *cs; 6770da6f3feSBharata B Rao int cpus_offset; 6780da6f3feSBharata B Rao char *nodename; 6790da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 6800da6f3feSBharata B Rao 6810da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 6820da6f3feSBharata B Rao _FDT(cpus_offset); 6830da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 6840da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 6850da6f3feSBharata B Rao 6860da6f3feSBharata B Rao /* 6870da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 6880da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 6890da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 6900da6f3feSBharata B Rao */ 6910da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 6920da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 6930da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 6940da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 6950da6f3feSBharata B Rao int offset; 6960da6f3feSBharata B Rao 6970da6f3feSBharata B Rao if ((index % smt) != 0) { 6980da6f3feSBharata B Rao continue; 6990da6f3feSBharata B Rao } 7000da6f3feSBharata B Rao 7010da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 7020da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 7030da6f3feSBharata B Rao g_free(nodename); 7040da6f3feSBharata B Rao _FDT(offset); 7050da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 7060da6f3feSBharata B Rao } 7070da6f3feSBharata B Rao 7080da6f3feSBharata B Rao } 7090da6f3feSBharata B Rao 71003d196b7SBharata B Rao /* 71103d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 71203d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 71303d196b7SBharata B Rao * of this device tree node. 71403d196b7SBharata B Rao */ 71503d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 71603d196b7SBharata B Rao { 71703d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 71803d196b7SBharata B Rao int ret, i, offset; 71903d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 72003d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 721d0e5a8f2SBharata B Rao uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size; 722d0e5a8f2SBharata B Rao uint32_t nr_lmbs = (spapr->hotplug_memory.base + 723d0e5a8f2SBharata B Rao memory_region_size(&spapr->hotplug_memory.mr)) / 724d0e5a8f2SBharata B Rao lmb_size; 72503d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 7266663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 72703d196b7SBharata B Rao 728ef001f06SThomas Huth /* 729d0e5a8f2SBharata B Rao * Don't create the node if there is no hotpluggable memory 73016c25aefSBharata B Rao */ 731d0e5a8f2SBharata B Rao if (machine->ram_size == machine->maxram_size) { 73216c25aefSBharata B Rao return 0; 73316c25aefSBharata B Rao } 73416c25aefSBharata B Rao 73516c25aefSBharata B Rao /* 736ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 737ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 738ef001f06SThomas Huth */ 739ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 740ef001f06SThomas Huth * sizeof(uint32_t); 74103d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 74203d196b7SBharata B Rao 74303d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 74403d196b7SBharata B Rao 74503d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 74603d196b7SBharata B Rao sizeof(prop_lmb_size)); 74703d196b7SBharata B Rao if (ret < 0) { 74803d196b7SBharata B Rao goto out; 74903d196b7SBharata B Rao } 75003d196b7SBharata B Rao 75103d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 75203d196b7SBharata B Rao if (ret < 0) { 75303d196b7SBharata B Rao goto out; 75403d196b7SBharata B Rao } 75503d196b7SBharata B Rao 75603d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 75703d196b7SBharata B Rao if (ret < 0) { 75803d196b7SBharata B Rao goto out; 75903d196b7SBharata B Rao } 76003d196b7SBharata B Rao 76103d196b7SBharata B Rao /* ibm,dynamic-memory */ 76203d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 76303d196b7SBharata B Rao cur_index++; 76403d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 765d0e5a8f2SBharata B Rao uint64_t addr = i * lmb_size; 76603d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 76703d196b7SBharata B Rao 768d0e5a8f2SBharata B Rao if (i >= hotplug_lmb_start) { 769d0e5a8f2SBharata B Rao sPAPRDRConnector *drc; 770d0e5a8f2SBharata B Rao sPAPRDRConnectorClass *drck; 771d0e5a8f2SBharata B Rao 772d0e5a8f2SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); 77303d196b7SBharata B Rao g_assert(drc); 77403d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 77503d196b7SBharata B Rao 77603d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 77703d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 77803d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 77903d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 78003d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 781d0e5a8f2SBharata B Rao if (memory_region_present(get_system_memory(), addr)) { 78203d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 78303d196b7SBharata B Rao } else { 78403d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 78503d196b7SBharata B Rao } 786d0e5a8f2SBharata B Rao } else { 787d0e5a8f2SBharata B Rao /* 788d0e5a8f2SBharata B Rao * LMB information for RMA, boot time RAM and gap b/n RAM and 789d0e5a8f2SBharata B Rao * hotplug memory region -- all these are marked as reserved 790d0e5a8f2SBharata B Rao * and as having no valid DRC. 791d0e5a8f2SBharata B Rao */ 792d0e5a8f2SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 793d0e5a8f2SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 794d0e5a8f2SBharata B Rao dynamic_memory[2] = cpu_to_be32(0); 795d0e5a8f2SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 796d0e5a8f2SBharata B Rao dynamic_memory[4] = cpu_to_be32(-1); 797d0e5a8f2SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED | 798d0e5a8f2SBharata B Rao SPAPR_LMB_FLAGS_DRC_INVALID); 799d0e5a8f2SBharata B Rao } 80003d196b7SBharata B Rao 80103d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 80203d196b7SBharata B Rao } 80303d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 80403d196b7SBharata B Rao if (ret < 0) { 80503d196b7SBharata B Rao goto out; 80603d196b7SBharata B Rao } 80703d196b7SBharata B Rao 80803d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 80903d196b7SBharata B Rao cur_index = int_buf; 8106663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 81103d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 81203d196b7SBharata B Rao cur_index += 2; 8136663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 81403d196b7SBharata B Rao uint32_t associativity[] = { 81503d196b7SBharata B Rao cpu_to_be32(0x0), 81603d196b7SBharata B Rao cpu_to_be32(0x0), 81703d196b7SBharata B Rao cpu_to_be32(0x0), 81803d196b7SBharata B Rao cpu_to_be32(i) 81903d196b7SBharata B Rao }; 82003d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 82103d196b7SBharata B Rao cur_index += 4; 82203d196b7SBharata B Rao } 82303d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 82403d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 82503d196b7SBharata B Rao out: 82603d196b7SBharata B Rao g_free(int_buf); 82703d196b7SBharata B Rao return ret; 82803d196b7SBharata B Rao } 82903d196b7SBharata B Rao 83003d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 83103d196b7SBharata B Rao target_ulong addr, target_ulong size, 83203d196b7SBharata B Rao bool cpu_update, bool memory_update) 83303d196b7SBharata B Rao { 83403d196b7SBharata B Rao void *fdt, *fdt_skel; 83503d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 83603d196b7SBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 83703d196b7SBharata B Rao 83803d196b7SBharata B Rao size -= sizeof(hdr); 83903d196b7SBharata B Rao 84003d196b7SBharata B Rao /* Create sceleton */ 84103d196b7SBharata B Rao fdt_skel = g_malloc0(size); 84203d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 84303d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 84403d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 84503d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 84603d196b7SBharata B Rao fdt = g_malloc0(size); 84703d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 84803d196b7SBharata B Rao g_free(fdt_skel); 84903d196b7SBharata B Rao 85003d196b7SBharata B Rao /* Fixup cpu nodes */ 85103d196b7SBharata B Rao if (cpu_update) { 85203d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 85303d196b7SBharata B Rao } 85403d196b7SBharata B Rao 85516c25aefSBharata B Rao /* Generate ibm,dynamic-reconfiguration-memory node if required */ 85603d196b7SBharata B Rao if (memory_update && smc->dr_lmb_enabled) { 85703d196b7SBharata B Rao _FDT((spapr_populate_drconf_memory(spapr, fdt))); 85803d196b7SBharata B Rao } 85903d196b7SBharata B Rao 86003d196b7SBharata B Rao /* Pack resulting tree */ 86103d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 86203d196b7SBharata B Rao 86303d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 86403d196b7SBharata B Rao trace_spapr_cas_failed(size); 86503d196b7SBharata B Rao return -1; 86603d196b7SBharata B Rao } 86703d196b7SBharata B Rao 86803d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 86903d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 87003d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 87103d196b7SBharata B Rao g_free(fdt); 87203d196b7SBharata B Rao 87303d196b7SBharata B Rao return 0; 87403d196b7SBharata B Rao } 87503d196b7SBharata B Rao 876997b6cfcSDavid Gibson static void *spapr_build_fdt(sPAPRMachineState *spapr, 87753018216SPaolo Bonzini hwaddr rtas_addr, 87853018216SPaolo Bonzini hwaddr rtas_size) 87953018216SPaolo Bonzini { 8805b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 8813c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 882c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 8835b2128d2SAlexander Graf const char *boot_device = machine->boot_order; 88471461b0fSAlexey Kardashevskiy int ret, i; 88571461b0fSAlexey Kardashevskiy size_t cb = 0; 88671461b0fSAlexey Kardashevskiy char *bootlist; 88753018216SPaolo Bonzini void *fdt; 88853018216SPaolo Bonzini sPAPRPHBState *phb; 88953018216SPaolo Bonzini 89053018216SPaolo Bonzini fdt = g_malloc(FDT_MAX_SIZE); 89153018216SPaolo Bonzini 89253018216SPaolo Bonzini /* open out the base tree into a temp buffer for the final tweaks */ 89353018216SPaolo Bonzini _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); 89453018216SPaolo Bonzini 895*9b9a1908SDavid Gibson /* /interrupt controller */ 896*9b9a1908SDavid Gibson spapr_dt_xics(spapr->xics, fdt, PHANDLE_XICP); 897*9b9a1908SDavid Gibson 898e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 899e8f986fcSBharata B Rao if (ret < 0) { 900ce9863b7SCédric Le Goater error_report("couldn't setup memory nodes in fdt"); 901e8f986fcSBharata B Rao exit(1); 90253018216SPaolo Bonzini } 90353018216SPaolo Bonzini 90453018216SPaolo Bonzini ret = spapr_populate_vdevice(spapr->vio_bus, fdt); 90553018216SPaolo Bonzini if (ret < 0) { 906ce9863b7SCédric Le Goater error_report("couldn't setup vio devices in fdt"); 90753018216SPaolo Bonzini exit(1); 90853018216SPaolo Bonzini } 90953018216SPaolo Bonzini 9104d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 9114d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 9124d9392beSThomas Huth if (ret < 0) { 913ce9863b7SCédric Le Goater error_report("could not set up rng device in the fdt"); 9144d9392beSThomas Huth exit(1); 9154d9392beSThomas Huth } 9164d9392beSThomas Huth } 9174d9392beSThomas Huth 91853018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 91953018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 92053018216SPaolo Bonzini if (ret < 0) { 921da34fed7SThomas Huth error_report("couldn't setup PCI devices in fdt"); 92253018216SPaolo Bonzini exit(1); 92353018216SPaolo Bonzini } 924da34fed7SThomas Huth } 92553018216SPaolo Bonzini 92653018216SPaolo Bonzini /* RTAS */ 92753018216SPaolo Bonzini ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); 92853018216SPaolo Bonzini if (ret < 0) { 929ce9863b7SCédric Le Goater error_report("Couldn't set up RTAS device tree properties"); 93053018216SPaolo Bonzini } 93153018216SPaolo Bonzini 9320da6f3feSBharata B Rao /* cpus */ 9330da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 93453018216SPaolo Bonzini 93571461b0fSAlexey Kardashevskiy bootlist = get_boot_devices_list(&cb, true); 93671461b0fSAlexey Kardashevskiy if (cb && bootlist) { 93771461b0fSAlexey Kardashevskiy int offset = fdt_path_offset(fdt, "/chosen"); 93871461b0fSAlexey Kardashevskiy if (offset < 0) { 93971461b0fSAlexey Kardashevskiy exit(1); 94071461b0fSAlexey Kardashevskiy } 94171461b0fSAlexey Kardashevskiy for (i = 0; i < cb; i++) { 94271461b0fSAlexey Kardashevskiy if (bootlist[i] == '\n') { 94371461b0fSAlexey Kardashevskiy bootlist[i] = ' '; 94471461b0fSAlexey Kardashevskiy } 94571461b0fSAlexey Kardashevskiy 94671461b0fSAlexey Kardashevskiy } 94771461b0fSAlexey Kardashevskiy ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); 94871461b0fSAlexey Kardashevskiy } 94971461b0fSAlexey Kardashevskiy 9505b2128d2SAlexander Graf if (boot_device && strlen(boot_device)) { 9515b2128d2SAlexander Graf int offset = fdt_path_offset(fdt, "/chosen"); 9525b2128d2SAlexander Graf 9535b2128d2SAlexander Graf if (offset < 0) { 9545b2128d2SAlexander Graf exit(1); 9555b2128d2SAlexander Graf } 9565b2128d2SAlexander Graf fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device); 9575b2128d2SAlexander Graf } 9585b2128d2SAlexander Graf 95953018216SPaolo Bonzini if (!spapr->has_graphics) { 96053018216SPaolo Bonzini spapr_populate_chosen_stdout(fdt, spapr->vio_bus); 96153018216SPaolo Bonzini } 96253018216SPaolo Bonzini 963c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 964c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 965c20d332aSBharata B Rao } 966c20d332aSBharata B Rao 9673c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 968af81cf32SBharata B Rao int offset = fdt_path_offset(fdt, "/cpus"); 969af81cf32SBharata B Rao ret = spapr_drc_populate_dt(fdt, offset, NULL, 970af81cf32SBharata B Rao SPAPR_DR_CONNECTOR_TYPE_CPU); 971af81cf32SBharata B Rao if (ret < 0) { 972af81cf32SBharata B Rao error_report("Couldn't set up CPU DR device tree properties"); 973af81cf32SBharata B Rao exit(1); 974af81cf32SBharata B Rao } 975af81cf32SBharata B Rao } 976af81cf32SBharata B Rao 977a21a7a70SGonglei g_free(bootlist); 978cf6e5223SDavid Gibson 979cf6e5223SDavid Gibson /* Build memory reserve map */ 980cf6e5223SDavid Gibson if (spapr->kernel_size) { 981cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, KERNEL_LOAD_ADDR, spapr->kernel_size))); 982cf6e5223SDavid Gibson } 983cf6e5223SDavid Gibson if (spapr->initrd_size) { 984cf6e5223SDavid Gibson _FDT((fdt_add_mem_rsv(fdt, spapr->initrd_base, spapr->initrd_size))); 985cf6e5223SDavid Gibson } 986cf6e5223SDavid Gibson 987997b6cfcSDavid Gibson return fdt; 98853018216SPaolo Bonzini } 98953018216SPaolo Bonzini 99053018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 99153018216SPaolo Bonzini { 99253018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 99353018216SPaolo Bonzini } 99453018216SPaolo Bonzini 99553018216SPaolo Bonzini static void emulate_spapr_hypercall(PowerPCCPU *cpu) 99653018216SPaolo Bonzini { 99753018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 99853018216SPaolo Bonzini 99953018216SPaolo Bonzini if (msr_pr) { 100053018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 100153018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 100253018216SPaolo Bonzini } else { 100353018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 100453018216SPaolo Bonzini } 100553018216SPaolo Bonzini } 100653018216SPaolo Bonzini 1007e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1008e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1009e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1010e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1011e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1012e6b8fd24SSamuel Mendoza-Jonas 1013715c5407SDavid Gibson /* 1014715c5407SDavid Gibson * Get the fd to access the kernel htab, re-opening it if necessary 1015715c5407SDavid Gibson */ 1016715c5407SDavid Gibson static int get_htab_fd(sPAPRMachineState *spapr) 1017715c5407SDavid Gibson { 1018715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1019715c5407SDavid Gibson return spapr->htab_fd; 1020715c5407SDavid Gibson } 1021715c5407SDavid Gibson 1022715c5407SDavid Gibson spapr->htab_fd = kvmppc_get_htab_fd(false); 1023715c5407SDavid Gibson if (spapr->htab_fd < 0) { 1024715c5407SDavid Gibson error_report("Unable to open fd for reading hash table from KVM: %s", 1025715c5407SDavid Gibson strerror(errno)); 1026715c5407SDavid Gibson } 1027715c5407SDavid Gibson 1028715c5407SDavid Gibson return spapr->htab_fd; 1029715c5407SDavid Gibson } 1030715c5407SDavid Gibson 1031715c5407SDavid Gibson static void close_htab_fd(sPAPRMachineState *spapr) 1032715c5407SDavid Gibson { 1033715c5407SDavid Gibson if (spapr->htab_fd >= 0) { 1034715c5407SDavid Gibson close(spapr->htab_fd); 1035715c5407SDavid Gibson } 1036715c5407SDavid Gibson spapr->htab_fd = -1; 1037715c5407SDavid Gibson } 1038715c5407SDavid Gibson 10398dfe8e7fSDavid Gibson static int spapr_hpt_shift_for_ramsize(uint64_t ramsize) 10408dfe8e7fSDavid Gibson { 10418dfe8e7fSDavid Gibson int shift; 10428dfe8e7fSDavid Gibson 10438dfe8e7fSDavid Gibson /* We aim for a hash table of size 1/128 the size of RAM (rounded 10448dfe8e7fSDavid Gibson * up). The PAPR recommendation is actually 1/64 of RAM size, but 10458dfe8e7fSDavid Gibson * that's much more than is needed for Linux guests */ 10468dfe8e7fSDavid Gibson shift = ctz64(pow2ceil(ramsize)) - 7; 10478dfe8e7fSDavid Gibson shift = MAX(shift, 18); /* Minimum architected size */ 10488dfe8e7fSDavid Gibson shift = MIN(shift, 46); /* Maximum architected size */ 10498dfe8e7fSDavid Gibson return shift; 10508dfe8e7fSDavid Gibson } 10518dfe8e7fSDavid Gibson 1052c5f54f3eSDavid Gibson static void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, 1053c5f54f3eSDavid Gibson Error **errp) 105453018216SPaolo Bonzini { 1055c5f54f3eSDavid Gibson long rc; 105653018216SPaolo Bonzini 1057c5f54f3eSDavid Gibson /* Clean up any HPT info from a previous boot */ 1058c5f54f3eSDavid Gibson g_free(spapr->htab); 1059c5f54f3eSDavid Gibson spapr->htab = NULL; 1060c5f54f3eSDavid Gibson spapr->htab_shift = 0; 1061c5f54f3eSDavid Gibson close_htab_fd(spapr); 106253018216SPaolo Bonzini 1063c5f54f3eSDavid Gibson rc = kvmppc_reset_htab(shift); 1064c5f54f3eSDavid Gibson if (rc < 0) { 1065c5f54f3eSDavid Gibson /* kernel-side HPT needed, but couldn't allocate one */ 1066c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1067c5f54f3eSDavid Gibson "Failed to allocate KVM HPT of order %d (try smaller maxmem?)", 1068c5f54f3eSDavid Gibson shift); 1069c5f54f3eSDavid Gibson /* This is almost certainly fatal, but if the caller really 1070c5f54f3eSDavid Gibson * wants to carry on with shift == 0, it's welcome to try */ 1071c5f54f3eSDavid Gibson } else if (rc > 0) { 1072c5f54f3eSDavid Gibson /* kernel-side HPT allocated */ 1073c5f54f3eSDavid Gibson if (rc != shift) { 1074c5f54f3eSDavid Gibson error_setg(errp, 1075c5f54f3eSDavid Gibson "Requested order %d HPT, but kernel allocated order %ld (try smaller maxmem?)", 1076c5f54f3eSDavid Gibson shift, rc); 10777735fedaSBharata B Rao } 10787735fedaSBharata B Rao 107953018216SPaolo Bonzini spapr->htab_shift = shift; 1080c18ad9a5SDavid Gibson spapr->htab = NULL; 1081b817772aSBharata B Rao } else { 1082c5f54f3eSDavid Gibson /* kernel-side HPT not needed, allocate in userspace instead */ 1083c5f54f3eSDavid Gibson size_t size = 1ULL << shift; 1084c5f54f3eSDavid Gibson int i; 108501a57972SSamuel Mendoza-Jonas 1086c5f54f3eSDavid Gibson spapr->htab = qemu_memalign(size, size); 1087c5f54f3eSDavid Gibson if (!spapr->htab) { 1088c5f54f3eSDavid Gibson error_setg_errno(errp, errno, 1089c5f54f3eSDavid Gibson "Could not allocate HPT of order %d", shift); 1090c5f54f3eSDavid Gibson return; 1091b817772aSBharata B Rao } 1092b817772aSBharata B Rao 1093c5f54f3eSDavid Gibson memset(spapr->htab, 0, size); 1094c5f54f3eSDavid Gibson spapr->htab_shift = shift; 1095b817772aSBharata B Rao 1096c5f54f3eSDavid Gibson for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { 1097c5f54f3eSDavid Gibson DIRTY_HPTE(HPTE(spapr->htab, i)); 10987735fedaSBharata B Rao } 109953018216SPaolo Bonzini } 110053018216SPaolo Bonzini } 110153018216SPaolo Bonzini 11024f01a637SDavid Gibson static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 11039e3f9733SAlexander Graf { 11049e3f9733SAlexander Graf bool matched = false; 11059e3f9733SAlexander Graf 11069e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 11079e3f9733SAlexander Graf matched = true; 11089e3f9733SAlexander Graf } 11099e3f9733SAlexander Graf 11109e3f9733SAlexander Graf if (!matched) { 11119e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 11129e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 11139e3f9733SAlexander Graf exit(1); 11149e3f9733SAlexander Graf } 11159e3f9733SAlexander Graf } 11169e3f9733SAlexander Graf 111753018216SPaolo Bonzini static void ppc_spapr_reset(void) 111853018216SPaolo Bonzini { 1119c5f54f3eSDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 1120c5f54f3eSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1121182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1122b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1123cae172abSDavid Gibson hwaddr rtas_addr, fdt_addr; 1124997b6cfcSDavid Gibson void *fdt; 1125997b6cfcSDavid Gibson int rc; 1126259186a7SAndreas Färber 11279e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 11289e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 11299e3f9733SAlexander Graf 1130c5f54f3eSDavid Gibson /* Allocate and/or reset the hash page table */ 1131c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, 1132c5f54f3eSDavid Gibson spapr_hpt_shift_for_ramsize(machine->maxram_size), 1133c5f54f3eSDavid Gibson &error_fatal); 1134c5f54f3eSDavid Gibson 1135c5f54f3eSDavid Gibson /* Update the RMA size if necessary */ 1136c5f54f3eSDavid Gibson if (spapr->vrma_adjust) { 1137c5f54f3eSDavid Gibson spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1138c5f54f3eSDavid Gibson spapr->htab_shift); 1139c5f54f3eSDavid Gibson } 114053018216SPaolo Bonzini 114153018216SPaolo Bonzini qemu_devices_reset(); 114253018216SPaolo Bonzini 1143b7d1f77aSBenjamin Herrenschmidt /* 1144b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1145b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1146b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1147b7d1f77aSBenjamin Herrenschmidt */ 1148b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1149cae172abSDavid Gibson rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1150cae172abSDavid Gibson fdt_addr = rtas_addr - FDT_MAX_SIZE; 1151b7d1f77aSBenjamin Herrenschmidt 1152cae172abSDavid Gibson fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size); 115353018216SPaolo Bonzini 11542cac78c1SDavid Gibson spapr_load_rtas(spapr, fdt, rtas_addr); 1155b7d1f77aSBenjamin Herrenschmidt 1156997b6cfcSDavid Gibson rc = fdt_pack(fdt); 1157997b6cfcSDavid Gibson 1158997b6cfcSDavid Gibson /* Should only fail if we've built a corrupted tree */ 1159997b6cfcSDavid Gibson assert(rc == 0); 1160997b6cfcSDavid Gibson 1161997b6cfcSDavid Gibson if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 1162997b6cfcSDavid Gibson error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 1163997b6cfcSDavid Gibson fdt_totalsize(fdt), FDT_MAX_SIZE); 1164997b6cfcSDavid Gibson exit(1); 1165997b6cfcSDavid Gibson } 1166997b6cfcSDavid Gibson 1167997b6cfcSDavid Gibson /* Load the fdt */ 1168997b6cfcSDavid Gibson qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 1169cae172abSDavid Gibson cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 1170997b6cfcSDavid Gibson g_free(fdt); 1171997b6cfcSDavid Gibson 117253018216SPaolo Bonzini /* Set up the entry state */ 1173182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1174cae172abSDavid Gibson first_ppc_cpu->env.gpr[3] = fdt_addr; 1175182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1176182735efSAndreas Färber first_cpu->halted = 0; 11771b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 117853018216SPaolo Bonzini 117953018216SPaolo Bonzini } 118053018216SPaolo Bonzini 118128e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 118253018216SPaolo Bonzini { 11832ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 11843978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 118553018216SPaolo Bonzini 11863978b863SPaolo Bonzini if (dinfo) { 11876231a6daSMarkus Armbruster qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo), 11886231a6daSMarkus Armbruster &error_fatal); 118953018216SPaolo Bonzini } 119053018216SPaolo Bonzini 119153018216SPaolo Bonzini qdev_init_nofail(dev); 119253018216SPaolo Bonzini 119353018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 119453018216SPaolo Bonzini } 119553018216SPaolo Bonzini 119628e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 119728df36a1SDavid Gibson { 119828df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 119928df36a1SDavid Gibson 120028df36a1SDavid Gibson qdev_init_nofail(dev); 120128df36a1SDavid Gibson spapr->rtc = dev; 120274e5ae28SDavid Gibson 120374e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 120474e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 120528df36a1SDavid Gibson } 120628df36a1SDavid Gibson 120753018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 120814c6a894SDavid Gibson static bool spapr_vga_init(PCIBus *pci_bus, Error **errp) 120953018216SPaolo Bonzini { 121053018216SPaolo Bonzini switch (vga_interface_type) { 121153018216SPaolo Bonzini case VGA_NONE: 12127effdaa3SMark Wu return false; 12137effdaa3SMark Wu case VGA_DEVICE: 12147effdaa3SMark Wu return true; 121553018216SPaolo Bonzini case VGA_STD: 1216b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 121753018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 121853018216SPaolo Bonzini default: 121914c6a894SDavid Gibson error_setg(errp, 122014c6a894SDavid Gibson "Unsupported VGA mode, only -vga std or -vga virtio is supported"); 122114c6a894SDavid Gibson return false; 122253018216SPaolo Bonzini } 122353018216SPaolo Bonzini } 122453018216SPaolo Bonzini 1225880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1226880ae7deSDavid Gibson { 122728e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1228880ae7deSDavid Gibson int err = 0; 1229880ae7deSDavid Gibson 1230631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1231880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1232880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1233880ae7deSDavid Gibson * value into the RTC device */ 1234880ae7deSDavid Gibson if (version_id < 3) { 1235880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1236880ae7deSDavid Gibson } 1237880ae7deSDavid Gibson 1238880ae7deSDavid Gibson return err; 1239880ae7deSDavid Gibson } 1240880ae7deSDavid Gibson 1241880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1242880ae7deSDavid Gibson { 1243880ae7deSDavid Gibson return version_id < 3; 1244880ae7deSDavid Gibson } 1245880ae7deSDavid Gibson 12464be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 12474be21d56SDavid Gibson .name = "spapr", 1248880ae7deSDavid Gibson .version_id = 3, 12494be21d56SDavid Gibson .minimum_version_id = 1, 1250880ae7deSDavid Gibson .post_load = spapr_post_load, 12514be21d56SDavid Gibson .fields = (VMStateField[]) { 1252880ae7deSDavid Gibson /* used to be @next_irq */ 1253880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 12544be21d56SDavid Gibson 12554be21d56SDavid Gibson /* RTC offset */ 125628e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1257880ae7deSDavid Gibson 125828e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 12594be21d56SDavid Gibson VMSTATE_END_OF_LIST() 12604be21d56SDavid Gibson }, 12614be21d56SDavid Gibson }; 12624be21d56SDavid Gibson 12634be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 12644be21d56SDavid Gibson { 126528e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 12664be21d56SDavid Gibson 12674be21d56SDavid Gibson /* "Iteration" header */ 12684be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 12694be21d56SDavid Gibson 1270e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1271e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1272e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1273e68cb8b4SAlexey Kardashevskiy } else { 1274e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 12754be21d56SDavid Gibson } 12764be21d56SDavid Gibson 1277e68cb8b4SAlexey Kardashevskiy 1278e68cb8b4SAlexey Kardashevskiy return 0; 1279e68cb8b4SAlexey Kardashevskiy } 12804be21d56SDavid Gibson 128128e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 12824be21d56SDavid Gibson int64_t max_ns) 12834be21d56SDavid Gibson { 1284378bc217SDavid Gibson bool has_timeout = max_ns != -1; 12854be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 12864be21d56SDavid Gibson int index = spapr->htab_save_index; 1287bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 12884be21d56SDavid Gibson 12894be21d56SDavid Gibson assert(spapr->htab_first_pass); 12904be21d56SDavid Gibson 12914be21d56SDavid Gibson do { 12924be21d56SDavid Gibson int chunkstart; 12934be21d56SDavid Gibson 12944be21d56SDavid Gibson /* Consume invalid HPTEs */ 12954be21d56SDavid Gibson while ((index < htabslots) 12964be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 12974be21d56SDavid Gibson index++; 12984be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 12994be21d56SDavid Gibson } 13004be21d56SDavid Gibson 13014be21d56SDavid Gibson /* Consume valid HPTEs */ 13024be21d56SDavid Gibson chunkstart = index; 1303338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13044be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13054be21d56SDavid Gibson index++; 13064be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13074be21d56SDavid Gibson } 13084be21d56SDavid Gibson 13094be21d56SDavid Gibson if (index > chunkstart) { 13104be21d56SDavid Gibson int n_valid = index - chunkstart; 13114be21d56SDavid Gibson 13124be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13134be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13144be21d56SDavid Gibson qemu_put_be16(f, 0); 13154be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13164be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13174be21d56SDavid Gibson 1318378bc217SDavid Gibson if (has_timeout && 1319378bc217SDavid Gibson (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13204be21d56SDavid Gibson break; 13214be21d56SDavid Gibson } 13224be21d56SDavid Gibson } 13234be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 13244be21d56SDavid Gibson 13254be21d56SDavid Gibson if (index >= htabslots) { 13264be21d56SDavid Gibson assert(index == htabslots); 13274be21d56SDavid Gibson index = 0; 13284be21d56SDavid Gibson spapr->htab_first_pass = false; 13294be21d56SDavid Gibson } 13304be21d56SDavid Gibson spapr->htab_save_index = index; 13314be21d56SDavid Gibson } 13324be21d56SDavid Gibson 133328e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 13344be21d56SDavid Gibson int64_t max_ns) 13354be21d56SDavid Gibson { 13364be21d56SDavid Gibson bool final = max_ns < 0; 13374be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 13384be21d56SDavid Gibson int examined = 0, sent = 0; 13394be21d56SDavid Gibson int index = spapr->htab_save_index; 1340bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13414be21d56SDavid Gibson 13424be21d56SDavid Gibson assert(!spapr->htab_first_pass); 13434be21d56SDavid Gibson 13444be21d56SDavid Gibson do { 13454be21d56SDavid Gibson int chunkstart, invalidstart; 13464be21d56SDavid Gibson 13474be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 13484be21d56SDavid Gibson while ((index < htabslots) 13494be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 13504be21d56SDavid Gibson index++; 13514be21d56SDavid Gibson examined++; 13524be21d56SDavid Gibson } 13534be21d56SDavid Gibson 13544be21d56SDavid Gibson chunkstart = index; 13554be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1356338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13574be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13584be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13594be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13604be21d56SDavid Gibson index++; 13614be21d56SDavid Gibson examined++; 13624be21d56SDavid Gibson } 13634be21d56SDavid Gibson 13644be21d56SDavid Gibson invalidstart = index; 13654be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1366338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 13674be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13684be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13694be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13704be21d56SDavid Gibson index++; 13714be21d56SDavid Gibson examined++; 13724be21d56SDavid Gibson } 13734be21d56SDavid Gibson 13744be21d56SDavid Gibson if (index > chunkstart) { 13754be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 13764be21d56SDavid Gibson int n_invalid = index - invalidstart; 13774be21d56SDavid Gibson 13784be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13794be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13804be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 13814be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13824be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13834be21d56SDavid Gibson sent += index - chunkstart; 13844be21d56SDavid Gibson 1385bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13864be21d56SDavid Gibson break; 13874be21d56SDavid Gibson } 13884be21d56SDavid Gibson } 13894be21d56SDavid Gibson 13904be21d56SDavid Gibson if (examined >= htabslots) { 13914be21d56SDavid Gibson break; 13924be21d56SDavid Gibson } 13934be21d56SDavid Gibson 13944be21d56SDavid Gibson if (index >= htabslots) { 13954be21d56SDavid Gibson assert(index == htabslots); 13964be21d56SDavid Gibson index = 0; 13974be21d56SDavid Gibson } 13984be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 13994be21d56SDavid Gibson 14004be21d56SDavid Gibson if (index >= htabslots) { 14014be21d56SDavid Gibson assert(index == htabslots); 14024be21d56SDavid Gibson index = 0; 14034be21d56SDavid Gibson } 14044be21d56SDavid Gibson 14054be21d56SDavid Gibson spapr->htab_save_index = index; 14064be21d56SDavid Gibson 1407e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 14084be21d56SDavid Gibson } 14094be21d56SDavid Gibson 1410e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1411e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1412e68cb8b4SAlexey Kardashevskiy 14134be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 14144be21d56SDavid Gibson { 141528e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1416715c5407SDavid Gibson int fd; 1417e68cb8b4SAlexey Kardashevskiy int rc = 0; 14184be21d56SDavid Gibson 14194be21d56SDavid Gibson /* Iteration header */ 14204be21d56SDavid Gibson qemu_put_be32(f, 0); 14214be21d56SDavid Gibson 1422e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1423e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1424e68cb8b4SAlexey Kardashevskiy 1425715c5407SDavid Gibson fd = get_htab_fd(spapr); 1426715c5407SDavid Gibson if (fd < 0) { 1427715c5407SDavid Gibson return fd; 142801a57972SSamuel Mendoza-Jonas } 142901a57972SSamuel Mendoza-Jonas 1430715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1431e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1432e68cb8b4SAlexey Kardashevskiy return rc; 1433e68cb8b4SAlexey Kardashevskiy } 1434e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 14354be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 14364be21d56SDavid Gibson } else { 1437e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 14384be21d56SDavid Gibson } 14394be21d56SDavid Gibson 14404be21d56SDavid Gibson /* End marker */ 14414be21d56SDavid Gibson qemu_put_be32(f, 0); 14424be21d56SDavid Gibson qemu_put_be16(f, 0); 14434be21d56SDavid Gibson qemu_put_be16(f, 0); 14444be21d56SDavid Gibson 1445e68cb8b4SAlexey Kardashevskiy return rc; 14464be21d56SDavid Gibson } 14474be21d56SDavid Gibson 14484be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 14494be21d56SDavid Gibson { 145028e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1451715c5407SDavid Gibson int fd; 14524be21d56SDavid Gibson 14534be21d56SDavid Gibson /* Iteration header */ 14544be21d56SDavid Gibson qemu_put_be32(f, 0); 14554be21d56SDavid Gibson 1456e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1457e68cb8b4SAlexey Kardashevskiy int rc; 1458e68cb8b4SAlexey Kardashevskiy 1459e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1460e68cb8b4SAlexey Kardashevskiy 1461715c5407SDavid Gibson fd = get_htab_fd(spapr); 1462715c5407SDavid Gibson if (fd < 0) { 1463715c5407SDavid Gibson return fd; 146401a57972SSamuel Mendoza-Jonas } 146501a57972SSamuel Mendoza-Jonas 1466715c5407SDavid Gibson rc = kvmppc_save_htab(f, fd, MAX_KVM_BUF_SIZE, -1); 1467e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1468e68cb8b4SAlexey Kardashevskiy return rc; 1469e68cb8b4SAlexey Kardashevskiy } 1470e68cb8b4SAlexey Kardashevskiy } else { 1471378bc217SDavid Gibson if (spapr->htab_first_pass) { 1472378bc217SDavid Gibson htab_save_first_pass(f, spapr, -1); 1473378bc217SDavid Gibson } 14744be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1475e68cb8b4SAlexey Kardashevskiy } 14764be21d56SDavid Gibson 14774be21d56SDavid Gibson /* End marker */ 14784be21d56SDavid Gibson qemu_put_be32(f, 0); 14794be21d56SDavid Gibson qemu_put_be16(f, 0); 14804be21d56SDavid Gibson qemu_put_be16(f, 0); 14814be21d56SDavid Gibson 14824be21d56SDavid Gibson return 0; 14834be21d56SDavid Gibson } 14844be21d56SDavid Gibson 14854be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 14864be21d56SDavid Gibson { 148728e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 14884be21d56SDavid Gibson uint32_t section_hdr; 1489e68cb8b4SAlexey Kardashevskiy int fd = -1; 14904be21d56SDavid Gibson 14914be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 149298a5d100SDavid Gibson error_report("htab_load() bad version"); 14934be21d56SDavid Gibson return -EINVAL; 14944be21d56SDavid Gibson } 14954be21d56SDavid Gibson 14964be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 14974be21d56SDavid Gibson 14984be21d56SDavid Gibson if (section_hdr) { 14999897e462SGreg Kurz Error *local_err = NULL; 1500c5f54f3eSDavid Gibson 1501c5f54f3eSDavid Gibson /* First section gives the htab size */ 1502c5f54f3eSDavid Gibson spapr_reallocate_hpt(spapr, section_hdr, &local_err); 1503c5f54f3eSDavid Gibson if (local_err) { 1504c5f54f3eSDavid Gibson error_report_err(local_err); 15054be21d56SDavid Gibson return -EINVAL; 15064be21d56SDavid Gibson } 15074be21d56SDavid Gibson return 0; 15084be21d56SDavid Gibson } 15094be21d56SDavid Gibson 1510e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1511e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1512e68cb8b4SAlexey Kardashevskiy 1513e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1514e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 151598a5d100SDavid Gibson error_report("Unable to open fd to restore KVM hash table: %s", 1516e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1517e68cb8b4SAlexey Kardashevskiy } 1518e68cb8b4SAlexey Kardashevskiy } 1519e68cb8b4SAlexey Kardashevskiy 15204be21d56SDavid Gibson while (true) { 15214be21d56SDavid Gibson uint32_t index; 15224be21d56SDavid Gibson uint16_t n_valid, n_invalid; 15234be21d56SDavid Gibson 15244be21d56SDavid Gibson index = qemu_get_be32(f); 15254be21d56SDavid Gibson n_valid = qemu_get_be16(f); 15264be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 15274be21d56SDavid Gibson 15284be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 15294be21d56SDavid Gibson /* End of Stream */ 15304be21d56SDavid Gibson break; 15314be21d56SDavid Gibson } 15324be21d56SDavid Gibson 1533e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 15344be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 15354be21d56SDavid Gibson /* Bad index in stream */ 153698a5d100SDavid Gibson error_report( 153798a5d100SDavid Gibson "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)", 153898a5d100SDavid Gibson index, n_valid, n_invalid, spapr->htab_shift); 15394be21d56SDavid Gibson return -EINVAL; 15404be21d56SDavid Gibson } 15414be21d56SDavid Gibson 1542e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 15434be21d56SDavid Gibson if (n_valid) { 15444be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 15454be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 15464be21d56SDavid Gibson } 15474be21d56SDavid Gibson if (n_invalid) { 15484be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 15494be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 15504be21d56SDavid Gibson } 1551e68cb8b4SAlexey Kardashevskiy } else { 1552e68cb8b4SAlexey Kardashevskiy int rc; 1553e68cb8b4SAlexey Kardashevskiy 1554e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1555e68cb8b4SAlexey Kardashevskiy 1556e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1557e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1558e68cb8b4SAlexey Kardashevskiy return rc; 1559e68cb8b4SAlexey Kardashevskiy } 1560e68cb8b4SAlexey Kardashevskiy } 1561e68cb8b4SAlexey Kardashevskiy } 1562e68cb8b4SAlexey Kardashevskiy 1563e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1564e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1565e68cb8b4SAlexey Kardashevskiy close(fd); 15664be21d56SDavid Gibson } 15674be21d56SDavid Gibson 15684be21d56SDavid Gibson return 0; 15694be21d56SDavid Gibson } 15704be21d56SDavid Gibson 1571c573fc03SThomas Huth static void htab_cleanup(void *opaque) 1572c573fc03SThomas Huth { 1573c573fc03SThomas Huth sPAPRMachineState *spapr = opaque; 1574c573fc03SThomas Huth 1575c573fc03SThomas Huth close_htab_fd(spapr); 1576c573fc03SThomas Huth } 1577c573fc03SThomas Huth 15784be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 15794be21d56SDavid Gibson .save_live_setup = htab_save_setup, 15804be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 1581a3e06c3dSDr. David Alan Gilbert .save_live_complete_precopy = htab_save_complete, 1582c573fc03SThomas Huth .cleanup = htab_cleanup, 15834be21d56SDavid Gibson .load_state = htab_load, 15844be21d56SDavid Gibson }; 15854be21d56SDavid Gibson 15865b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 15875b2128d2SAlexander Graf Error **errp) 15885b2128d2SAlexander Graf { 15895b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 15905b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 15915b2128d2SAlexander Graf } 15925b2128d2SAlexander Graf 1593224245bfSDavid Gibson /* 1594224245bfSDavid Gibson * Reset routine for LMB DR devices. 1595224245bfSDavid Gibson * 1596224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1597224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1598224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1599224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1600224245bfSDavid Gibson */ 1601224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1602224245bfSDavid Gibson { 1603224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1604224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1605224245bfSDavid Gibson 1606224245bfSDavid Gibson if (d) { 1607224245bfSDavid Gibson device_reset(d); 1608224245bfSDavid Gibson } 1609224245bfSDavid Gibson } 1610224245bfSDavid Gibson 1611224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1612224245bfSDavid Gibson { 1613224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1614224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1615e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1616224245bfSDavid Gibson int i; 1617224245bfSDavid Gibson 1618224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1619224245bfSDavid Gibson sPAPRDRConnector *drc; 1620224245bfSDavid Gibson uint64_t addr; 1621224245bfSDavid Gibson 1622e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1623224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1624224245bfSDavid Gibson addr/lmb_size); 1625224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1626224245bfSDavid Gibson } 1627224245bfSDavid Gibson } 1628224245bfSDavid Gibson 1629224245bfSDavid Gibson /* 1630224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1631224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1632224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1633224245bfSDavid Gibson */ 16347c150d6fSDavid Gibson static void spapr_validate_node_memory(MachineState *machine, Error **errp) 1635224245bfSDavid Gibson { 1636224245bfSDavid Gibson int i; 1637224245bfSDavid Gibson 16387c150d6fSDavid Gibson if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16397c150d6fSDavid Gibson error_setg(errp, "Memory size 0x" RAM_ADDR_FMT 16407c150d6fSDavid Gibson " is not aligned to %llu MiB", 16417c150d6fSDavid Gibson machine->ram_size, 1642224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16437c150d6fSDavid Gibson return; 16447c150d6fSDavid Gibson } 16457c150d6fSDavid Gibson 16467c150d6fSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) { 16477c150d6fSDavid Gibson error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT 16487c150d6fSDavid Gibson " is not aligned to %llu MiB", 16497c150d6fSDavid Gibson machine->ram_size, 16507c150d6fSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16517c150d6fSDavid Gibson return; 1652224245bfSDavid Gibson } 1653224245bfSDavid Gibson 1654224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1655224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 16567c150d6fSDavid Gibson error_setg(errp, 16577c150d6fSDavid Gibson "Node %d memory size 0x%" PRIx64 16587c150d6fSDavid Gibson " is not aligned to %llu MiB", 16597c150d6fSDavid Gibson i, numa_info[i].node_mem, 1660224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE / M_BYTE); 16617c150d6fSDavid Gibson return; 1662224245bfSDavid Gibson } 1663224245bfSDavid Gibson } 1664224245bfSDavid Gibson } 1665224245bfSDavid Gibson 166653018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 16673ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 166853018216SPaolo Bonzini { 166928e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 16703c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(machine); 1671224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 16723ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 16733ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 167453018216SPaolo Bonzini PCIHostState *phb; 167553018216SPaolo Bonzini int i; 167653018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 167753018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1678658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1679658fa66bSAlexey Kardashevskiy void *rma = NULL; 168053018216SPaolo Bonzini hwaddr rma_alloc_size; 1681b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 1682b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 168353018216SPaolo Bonzini char *filename; 168494a94e4cSBharata B Rao int smt = kvmppc_smt_threads(); 168594a94e4cSBharata B Rao int spapr_cores = smp_cpus / smp_threads; 168694a94e4cSBharata B Rao int spapr_max_cores = max_cpus / smp_threads; 168794a94e4cSBharata B Rao 16883c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 168994a94e4cSBharata B Rao if (smp_cpus % smp_threads) { 169094a94e4cSBharata B Rao error_report("smp_cpus (%u) must be multiple of threads (%u)", 169194a94e4cSBharata B Rao smp_cpus, smp_threads); 169294a94e4cSBharata B Rao exit(1); 169394a94e4cSBharata B Rao } 169494a94e4cSBharata B Rao if (max_cpus % smp_threads) { 169594a94e4cSBharata B Rao error_report("max_cpus (%u) must be multiple of threads (%u)", 169694a94e4cSBharata B Rao max_cpus, smp_threads); 169794a94e4cSBharata B Rao exit(1); 169894a94e4cSBharata B Rao } 169994a94e4cSBharata B Rao } 170053018216SPaolo Bonzini 1701226419d6SMichael S. Tsirkin msi_nonbroken = true; 170253018216SPaolo Bonzini 170353018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 170453018216SPaolo Bonzini 170553018216SPaolo Bonzini cpu_ppc_hypercall = emulate_spapr_hypercall; 170653018216SPaolo Bonzini 170753018216SPaolo Bonzini /* Allocate RMA if necessary */ 1708658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 170953018216SPaolo Bonzini 171053018216SPaolo Bonzini if (rma_alloc_size == -1) { 1711730fce59SThomas Huth error_report("Unable to create RMA"); 171253018216SPaolo Bonzini exit(1); 171353018216SPaolo Bonzini } 171453018216SPaolo Bonzini 1715c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 171653018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 171753018216SPaolo Bonzini } else { 1718c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 171953018216SPaolo Bonzini 172053018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 172153018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 172253018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 172353018216SPaolo Bonzini * 172453018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 172553018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 172653018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 172753018216SPaolo Bonzini * isn't determined yet. 172853018216SPaolo Bonzini */ 172953018216SPaolo Bonzini if (kvm_enabled()) { 173053018216SPaolo Bonzini spapr->vrma_adjust = 1; 173153018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 173253018216SPaolo Bonzini } 1733912acdf4SBenjamin Herrenschmidt 1734912acdf4SBenjamin Herrenschmidt /* Actually we don't support unbounded RMA anymore since we 1735912acdf4SBenjamin Herrenschmidt * added proper emulation of HV mode. The max we can get is 1736912acdf4SBenjamin Herrenschmidt * 16G which also happens to be what we configure for PAPR 1737912acdf4SBenjamin Herrenschmidt * mode so make sure we don't do anything bigger than that 1738912acdf4SBenjamin Herrenschmidt */ 1739912acdf4SBenjamin Herrenschmidt spapr->rma_size = MIN(spapr->rma_size, 0x400000000ull); 174053018216SPaolo Bonzini } 174153018216SPaolo Bonzini 1742c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 1743d54e4d76SDavid Gibson error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")", 1744c4177479SAlexey Kardashevskiy spapr->rma_size); 1745c4177479SAlexey Kardashevskiy exit(1); 1746c4177479SAlexey Kardashevskiy } 1747c4177479SAlexey Kardashevskiy 1748b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 1749b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 175053018216SPaolo Bonzini 17517b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 175227f24582SBenjamin Herrenschmidt spapr->xics = xics_system_init(machine, 175394a94e4cSBharata B Rao DIV_ROUND_UP(max_cpus * smt, smp_threads), 1754161deaf2SBenjamin Herrenschmidt XICS_IRQS_SPAPR, &error_fatal); 17557b565160SDavid Gibson 1756224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 17577c150d6fSDavid Gibson spapr_validate_node_memory(machine, &error_fatal); 1758224245bfSDavid Gibson } 1759224245bfSDavid Gibson 176053018216SPaolo Bonzini /* init CPUs */ 176119fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 17623daa4a9fSThomas Huth machine->cpu_model = kvm_enabled() ? "host" : smc->tcg_default_cpu; 176353018216SPaolo Bonzini } 176494a94e4cSBharata B Rao 1765e703d2f7SGreg Kurz ppc_cpu_parse_features(machine->cpu_model); 1766e703d2f7SGreg Kurz 17673c0c47e3SDavid Gibson if (mc->query_hotpluggable_cpus) { 176894a94e4cSBharata B Rao char *type = spapr_get_cpu_core_type(machine->cpu_model); 176994a94e4cSBharata B Rao 17704babfaf0SThomas Huth if (type == NULL) { 1771caebf378SCédric Le Goater error_report("Unable to find sPAPR CPU Core definition"); 1772caebf378SCédric Le Goater exit(1); 1773caebf378SCédric Le Goater } 1774caebf378SCédric Le Goater 177594a94e4cSBharata B Rao spapr->cores = g_new0(Object *, spapr_max_cores); 1776af81cf32SBharata B Rao for (i = 0; i < spapr_max_cores; i++) { 177712bf2d33SGreg Kurz int core_id = i * smp_threads; 1778af81cf32SBharata B Rao sPAPRDRConnector *drc = 1779af81cf32SBharata B Rao spapr_dr_connector_new(OBJECT(spapr), 178012bf2d33SGreg Kurz SPAPR_DR_CONNECTOR_TYPE_CPU, 178112bf2d33SGreg Kurz (core_id / smp_threads) * smt); 1782af81cf32SBharata B Rao 1783af81cf32SBharata B Rao qemu_register_reset(spapr_drc_reset, drc); 1784af81cf32SBharata B Rao 1785af81cf32SBharata B Rao if (i < spapr_cores) { 1786caebf378SCédric Le Goater Object *core = object_new(type); 178794a94e4cSBharata B Rao object_property_set_int(core, smp_threads, "nr-threads", 178894a94e4cSBharata B Rao &error_fatal); 178912bf2d33SGreg Kurz object_property_set_int(core, core_id, CPU_CORE_PROP_CORE_ID, 179094a94e4cSBharata B Rao &error_fatal); 179194a94e4cSBharata B Rao object_property_set_bool(core, true, "realized", &error_fatal); 179294a94e4cSBharata B Rao } 1793af81cf32SBharata B Rao } 179494a94e4cSBharata B Rao g_free(type); 179594a94e4cSBharata B Rao } else { 179653018216SPaolo Bonzini for (i = 0; i < smp_cpus; i++) { 179794a94e4cSBharata B Rao PowerPCCPU *cpu = cpu_ppc_init(machine->cpu_model); 179853018216SPaolo Bonzini if (cpu == NULL) { 1799569f4967SDavid Gibson error_report("Unable to find PowerPC CPU definition"); 180053018216SPaolo Bonzini exit(1); 180153018216SPaolo Bonzini } 1802569f4967SDavid Gibson spapr_cpu_init(spapr, cpu, &error_fatal); 180353018216SPaolo Bonzini } 180494a94e4cSBharata B Rao } 180553018216SPaolo Bonzini 1806026bfd89SDavid Gibson if (kvm_enabled()) { 1807026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 1808026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 1809ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 18105145ad4fSNathan Whitehorn 18115145ad4fSNathan Whitehorn /* H_CLEAR_MOD/_REF are mandatory in PAPR, but off by default */ 18125145ad4fSNathan Whitehorn kvmppc_enable_clear_ref_mod_hcalls(); 1813026bfd89SDavid Gibson } 1814026bfd89SDavid Gibson 181553018216SPaolo Bonzini /* allocate RAM */ 1816f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 1817fb164994SDavid Gibson machine->ram_size); 1818f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 181953018216SPaolo Bonzini 1820658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 1821658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 1822658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 1823658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 1824658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 1825658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 1826658fa66bSAlexey Kardashevskiy } 1827658fa66bSAlexey Kardashevskiy 18284a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 18294a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 18304a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 183171c9a3ddSBharata B Rao /* 183271c9a3ddSBharata B Rao * Limit the number of hotpluggable memory slots to half the number 183371c9a3ddSBharata B Rao * slots that KVM supports, leaving the other half for PCI and other 183471c9a3ddSBharata B Rao * devices. However ensure that number of slots doesn't drop below 32. 183571c9a3ddSBharata B Rao */ 183671c9a3ddSBharata B Rao int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 : 183771c9a3ddSBharata B Rao SPAPR_MAX_RAM_SLOTS; 18384a1c9cf0SBharata B Rao 183971c9a3ddSBharata B Rao if (max_memslots < SPAPR_MAX_RAM_SLOTS) { 184071c9a3ddSBharata B Rao max_memslots = SPAPR_MAX_RAM_SLOTS; 184171c9a3ddSBharata B Rao } 184271c9a3ddSBharata B Rao if (machine->ram_slots > max_memslots) { 1843d54e4d76SDavid Gibson error_report("Specified number of memory slots %" 1844d54e4d76SDavid Gibson PRIu64" exceeds max supported %d", 184571c9a3ddSBharata B Rao machine->ram_slots, max_memslots); 1846d54e4d76SDavid Gibson exit(1); 18474a1c9cf0SBharata B Rao } 18484a1c9cf0SBharata B Rao 18494a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 18504a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 18514a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 18524a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 18534a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 18544a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 18554a1c9cf0SBharata B Rao } 18564a1c9cf0SBharata B Rao 1857224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1858224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 1859224245bfSDavid Gibson } 1860224245bfSDavid Gibson 186153018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 18624c56440dSStefan Weil if (!filename) { 1863730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 18644c56440dSStefan Weil exit(1); 18654c56440dSStefan Weil } 1866b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 18678afc22a2SZhou Jie if (spapr->rtas_size < 0) { 18688afc22a2SZhou Jie error_report("Could not get size of LPAR rtas '%s'", filename); 18698afc22a2SZhou Jie exit(1); 18708afc22a2SZhou Jie } 1871b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 1872b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 1873730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 187453018216SPaolo Bonzini exit(1); 187553018216SPaolo Bonzini } 187653018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 1877730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 18782f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 187953018216SPaolo Bonzini exit(1); 188053018216SPaolo Bonzini } 188153018216SPaolo Bonzini g_free(filename); 188253018216SPaolo Bonzini 188353018216SPaolo Bonzini /* Set up EPOW events infrastructure */ 188453018216SPaolo Bonzini spapr_events_init(spapr); 188553018216SPaolo Bonzini 188612f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 188728df36a1SDavid Gibson spapr_rtc_create(spapr); 188812f42174SDavid Gibson 188953018216SPaolo Bonzini /* Set up VIO bus */ 189053018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 189153018216SPaolo Bonzini 189253018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 189353018216SPaolo Bonzini if (serial_hds[i]) { 189453018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 189553018216SPaolo Bonzini } 189653018216SPaolo Bonzini } 189753018216SPaolo Bonzini 189853018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 189953018216SPaolo Bonzini spapr_create_nvram(spapr); 190053018216SPaolo Bonzini 190153018216SPaolo Bonzini /* Set up PCI */ 190253018216SPaolo Bonzini spapr_pci_rtas_init(); 190353018216SPaolo Bonzini 190489dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 190553018216SPaolo Bonzini 190653018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 190753018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 190853018216SPaolo Bonzini 190953018216SPaolo Bonzini if (!nd->model) { 191053018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 191153018216SPaolo Bonzini } 191253018216SPaolo Bonzini 191353018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 191453018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 191553018216SPaolo Bonzini } else { 191629b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 191753018216SPaolo Bonzini } 191853018216SPaolo Bonzini } 191953018216SPaolo Bonzini 192053018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 192153018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 192253018216SPaolo Bonzini } 192353018216SPaolo Bonzini 192453018216SPaolo Bonzini /* Graphics */ 192514c6a894SDavid Gibson if (spapr_vga_init(phb->bus, &error_fatal)) { 192653018216SPaolo Bonzini spapr->has_graphics = true; 1927c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 192853018216SPaolo Bonzini } 192953018216SPaolo Bonzini 19304ee9ced9SMarcel Apfelbaum if (machine->usb) { 193157040d45SThomas Huth if (smc->use_ohci_by_default) { 193253018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 193357040d45SThomas Huth } else { 193457040d45SThomas Huth pci_create_simple(phb->bus, -1, "nec-usb-xhci"); 193557040d45SThomas Huth } 1936c86580b8SMarkus Armbruster 193753018216SPaolo Bonzini if (spapr->has_graphics) { 1938c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 1939c86580b8SMarkus Armbruster 1940c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 1941c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 194253018216SPaolo Bonzini } 194353018216SPaolo Bonzini } 194453018216SPaolo Bonzini 194553018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 1946d54e4d76SDavid Gibson error_report( 1947d54e4d76SDavid Gibson "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)", 1948d54e4d76SDavid Gibson MIN_RMA_SLOF); 194953018216SPaolo Bonzini exit(1); 195053018216SPaolo Bonzini } 195153018216SPaolo Bonzini 195253018216SPaolo Bonzini if (kernel_filename) { 195353018216SPaolo Bonzini uint64_t lowaddr = 0; 195453018216SPaolo Bonzini 1955a19f7fb0SDavid Gibson spapr->kernel_size = load_elf(kernel_filename, translate_kernel_address, 1956a19f7fb0SDavid Gibson NULL, NULL, &lowaddr, NULL, 1, 1957a19f7fb0SDavid Gibson PPC_ELF_MACHINE, 0, 0); 1958a19f7fb0SDavid Gibson if (spapr->kernel_size == ELF_LOAD_WRONG_ENDIAN) { 1959a19f7fb0SDavid Gibson spapr->kernel_size = load_elf(kernel_filename, 1960a19f7fb0SDavid Gibson translate_kernel_address, NULL, NULL, 1961a19f7fb0SDavid Gibson &lowaddr, NULL, 0, PPC_ELF_MACHINE, 19627ef295eaSPeter Crosthwaite 0, 0); 1963a19f7fb0SDavid Gibson spapr->kernel_le = spapr->kernel_size > 0; 196416457e7fSBenjamin Herrenschmidt } 1965a19f7fb0SDavid Gibson if (spapr->kernel_size < 0) { 1966a19f7fb0SDavid Gibson error_report("error loading %s: %s", kernel_filename, 1967a19f7fb0SDavid Gibson load_elf_strerror(spapr->kernel_size)); 196853018216SPaolo Bonzini exit(1); 196953018216SPaolo Bonzini } 197053018216SPaolo Bonzini 197153018216SPaolo Bonzini /* load initrd */ 197253018216SPaolo Bonzini if (initrd_filename) { 197353018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 197453018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 197553018216SPaolo Bonzini */ 1976a19f7fb0SDavid Gibson spapr->initrd_base = (KERNEL_LOAD_ADDR + spapr->kernel_size 1977a19f7fb0SDavid Gibson + 0x1ffff) & ~0xffff; 1978a19f7fb0SDavid Gibson spapr->initrd_size = load_image_targphys(initrd_filename, 1979a19f7fb0SDavid Gibson spapr->initrd_base, 1980a19f7fb0SDavid Gibson load_limit 1981a19f7fb0SDavid Gibson - spapr->initrd_base); 1982a19f7fb0SDavid Gibson if (spapr->initrd_size < 0) { 1983d54e4d76SDavid Gibson error_report("could not load initial ram disk '%s'", 198453018216SPaolo Bonzini initrd_filename); 198553018216SPaolo Bonzini exit(1); 198653018216SPaolo Bonzini } 198753018216SPaolo Bonzini } 198853018216SPaolo Bonzini } 198953018216SPaolo Bonzini 19908e7ea787SAndreas Färber if (bios_name == NULL) { 19918e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 19928e7ea787SAndreas Färber } 19938e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 19944c56440dSStefan Weil if (!filename) { 199568fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 19964c56440dSStefan Weil exit(1); 19974c56440dSStefan Weil } 199853018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 199968fea5a0SThomas Huth if (fw_size <= 0) { 200068fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 200153018216SPaolo Bonzini exit(1); 200253018216SPaolo Bonzini } 200353018216SPaolo Bonzini g_free(filename); 200453018216SPaolo Bonzini 200528e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 200628e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 200728e02042SDavid Gibson * which predated MachineState but had a similar function */ 20084be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 20094be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 20104be21d56SDavid Gibson &savevm_htab_handlers, spapr); 20114be21d56SDavid Gibson 201253018216SPaolo Bonzini /* Prepare the device tree */ 2013a19f7fb0SDavid Gibson spapr->fdt_skel = spapr_create_fdt_skel(spapr); 201453018216SPaolo Bonzini assert(spapr->fdt_skel != NULL); 20155b2128d2SAlexander Graf 201646503c2bSMichael Roth /* used by RTAS */ 201746503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 201846503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 201946503c2bSMichael Roth 20205b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 202153018216SPaolo Bonzini } 202253018216SPaolo Bonzini 2023135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 2024135a129aSAneesh Kumar K.V { 2025135a129aSAneesh Kumar K.V if (!vm_type) { 2026135a129aSAneesh Kumar K.V return 0; 2027135a129aSAneesh Kumar K.V } 2028135a129aSAneesh Kumar K.V 2029135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 2030135a129aSAneesh Kumar K.V return 1; 2031135a129aSAneesh Kumar K.V } 2032135a129aSAneesh Kumar K.V 2033135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2034135a129aSAneesh Kumar K.V return 2; 2035135a129aSAneesh Kumar K.V } 2036135a129aSAneesh Kumar K.V 2037135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2038135a129aSAneesh Kumar K.V exit(1); 2039135a129aSAneesh Kumar K.V } 2040135a129aSAneesh Kumar K.V 204171461b0fSAlexey Kardashevskiy /* 2042627b84f4SGonglei * Implementation of an interface to adjust firmware path 204371461b0fSAlexey Kardashevskiy * for the bootindex property handling. 204471461b0fSAlexey Kardashevskiy */ 204571461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 204671461b0fSAlexey Kardashevskiy DeviceState *dev) 204771461b0fSAlexey Kardashevskiy { 204871461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 204971461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 205071461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 205171461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 205271461b0fSAlexey Kardashevskiy 205371461b0fSAlexey Kardashevskiy if (d) { 205471461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 205571461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 205671461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 205771461b0fSAlexey Kardashevskiy 205871461b0fSAlexey Kardashevskiy if (spapr) { 205971461b0fSAlexey Kardashevskiy /* 206071461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 206171461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 206271461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 206371461b0fSAlexey Kardashevskiy */ 206471461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 206571461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 206671461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 206771461b0fSAlexey Kardashevskiy } else if (virtio) { 206871461b0fSAlexey Kardashevskiy /* 206971461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 207071461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 207171461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 207271461b0fSAlexey Kardashevskiy * the actual binding is: 207371461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 207471461b0fSAlexey Kardashevskiy */ 207571461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 207671461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 207771461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 207871461b0fSAlexey Kardashevskiy } else if (usb) { 207971461b0fSAlexey Kardashevskiy /* 208071461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 208171461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 208271461b0fSAlexey Kardashevskiy */ 208371461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 208471461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 208571461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 208671461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 208771461b0fSAlexey Kardashevskiy } 208871461b0fSAlexey Kardashevskiy } 208971461b0fSAlexey Kardashevskiy 209071461b0fSAlexey Kardashevskiy if (phb) { 209171461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 209271461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 209371461b0fSAlexey Kardashevskiy } 209471461b0fSAlexey Kardashevskiy 209571461b0fSAlexey Kardashevskiy return NULL; 209671461b0fSAlexey Kardashevskiy } 209771461b0fSAlexey Kardashevskiy 209823825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 209923825581SEduardo Habkost { 210028e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 210123825581SEduardo Habkost 210228e02042SDavid Gibson return g_strdup(spapr->kvm_type); 210323825581SEduardo Habkost } 210423825581SEduardo Habkost 210523825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 210623825581SEduardo Habkost { 210728e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 210823825581SEduardo Habkost 210928e02042SDavid Gibson g_free(spapr->kvm_type); 211028e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 211123825581SEduardo Habkost } 211223825581SEduardo Habkost 211323825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 211423825581SEduardo Habkost { 2115715c5407SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 2116715c5407SDavid Gibson 2117715c5407SDavid Gibson spapr->htab_fd = -1; 211823825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 211923825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 212049d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 212149d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 212249d2e648SMarcel Apfelbaum NULL); 212323825581SEduardo Habkost } 212423825581SEduardo Habkost 212587bbdd9cSDavid Gibson static void spapr_machine_finalizefn(Object *obj) 212687bbdd9cSDavid Gibson { 212787bbdd9cSDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 212887bbdd9cSDavid Gibson 212987bbdd9cSDavid Gibson g_free(spapr->kvm_type); 213087bbdd9cSDavid Gibson } 213187bbdd9cSDavid Gibson 2132e0eeb4a2SAlex Bennée static void ppc_cpu_do_nmi_on_cpu(CPUState *cs, void *arg) 213334316482SAlexey Kardashevskiy { 213434316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 213534316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 213634316482SAlexey Kardashevskiy } 213734316482SAlexey Kardashevskiy 213834316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 213934316482SAlexey Kardashevskiy { 214034316482SAlexey Kardashevskiy CPUState *cs; 214134316482SAlexey Kardashevskiy 214234316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 2143e0eeb4a2SAlex Bennée async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, NULL); 214434316482SAlexey Kardashevskiy } 214534316482SAlexey Kardashevskiy } 214634316482SAlexey Kardashevskiy 2147c20d332aSBharata B Rao static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, 2148c20d332aSBharata B Rao uint32_t node, Error **errp) 2149c20d332aSBharata B Rao { 2150c20d332aSBharata B Rao sPAPRDRConnector *drc; 2151c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2152c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2153c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2154c20d332aSBharata B Rao void *fdt; 2155c20d332aSBharata B Rao 2156c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2157c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2158c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2159c20d332aSBharata B Rao g_assert(drc); 2160c20d332aSBharata B Rao 2161c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2162c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2163c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2164c20d332aSBharata B Rao 2165c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2166c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2167c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2168c20d332aSBharata B Rao } 21695dd5238cSJianjun Duan /* send hotplug notification to the 21705dd5238cSJianjun Duan * guest only in case of hotplugged memory 21715dd5238cSJianjun Duan */ 21725dd5238cSJianjun Duan if (dev->hotplugged) { 21730a417869SBharata B Rao spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); 2174c20d332aSBharata B Rao } 21755dd5238cSJianjun Duan } 2176c20d332aSBharata B Rao 2177c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2178c20d332aSBharata B Rao uint32_t node, Error **errp) 2179c20d332aSBharata B Rao { 2180c20d332aSBharata B Rao Error *local_err = NULL; 2181c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2182c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2183c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2184c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2185c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2186c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2187c20d332aSBharata B Rao uint64_t addr; 2188c20d332aSBharata B Rao 2189c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2190c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2191c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2192c20d332aSBharata B Rao goto out; 2193c20d332aSBharata B Rao } 2194c20d332aSBharata B Rao 2195d6a9b0b8SMichael S. Tsirkin pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err); 2196c20d332aSBharata B Rao if (local_err) { 2197c20d332aSBharata B Rao goto out; 2198c20d332aSBharata B Rao } 2199c20d332aSBharata B Rao 2200c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2201c20d332aSBharata B Rao if (local_err) { 2202c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2203c20d332aSBharata B Rao goto out; 2204c20d332aSBharata B Rao } 2205c20d332aSBharata B Rao 2206c20d332aSBharata B Rao spapr_add_lmbs(dev, addr, size, node, &error_abort); 2207c20d332aSBharata B Rao 2208c20d332aSBharata B Rao out: 2209c20d332aSBharata B Rao error_propagate(errp, local_err); 2210c20d332aSBharata B Rao } 2211c20d332aSBharata B Rao 2212af81cf32SBharata B Rao void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset, 2213af81cf32SBharata B Rao sPAPRMachineState *spapr) 2214af81cf32SBharata B Rao { 2215af81cf32SBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 2216af81cf32SBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 2217af81cf32SBharata B Rao int id = ppc_get_vcpu_dt_id(cpu); 2218af81cf32SBharata B Rao void *fdt; 2219af81cf32SBharata B Rao int offset, fdt_size; 2220af81cf32SBharata B Rao char *nodename; 2221af81cf32SBharata B Rao 2222af81cf32SBharata B Rao fdt = create_device_tree(&fdt_size); 2223af81cf32SBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, id); 2224af81cf32SBharata B Rao offset = fdt_add_subnode(fdt, 0, nodename); 2225af81cf32SBharata B Rao 2226af81cf32SBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 2227af81cf32SBharata B Rao g_free(nodename); 2228af81cf32SBharata B Rao 2229af81cf32SBharata B Rao *fdt_offset = offset; 2230af81cf32SBharata B Rao return fdt; 2231af81cf32SBharata B Rao } 2232af81cf32SBharata B Rao 2233c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2234c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2235c20d332aSBharata B Rao { 2236c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2237c20d332aSBharata B Rao 2238c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2239b556854bSBharata B Rao int node; 2240c20d332aSBharata B Rao 2241c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2242c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2243c20d332aSBharata B Rao return; 2244c20d332aSBharata B Rao } 2245c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2246c20d332aSBharata B Rao if (*errp) { 2247c20d332aSBharata B Rao return; 2248c20d332aSBharata B Rao } 22491a5512bbSGonglei if (node < 0 || node >= MAX_NODES) { 22501a5512bbSGonglei error_setg(errp, "Invaild node %d", node); 22511a5512bbSGonglei return; 22521a5512bbSGonglei } 2253c20d332aSBharata B Rao 2254b556854bSBharata B Rao /* 2255b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2256b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2257b556854bSBharata B Rao * to the first node that has some memory. This causes two 2258b556854bSBharata B Rao * unexpected behaviours for the user. 2259b556854bSBharata B Rao * 2260b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2261b556854bSBharata B Rao * specified. 2262b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2263b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2264b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2265b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2266b556854bSBharata B Rao * 2267b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2268b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2269b556854bSBharata B Rao */ 2270b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2271b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2272b556854bSBharata B Rao node); 2273b556854bSBharata B Rao return; 2274b556854bSBharata B Rao } 2275b556854bSBharata B Rao 2276c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2277af81cf32SBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2278af81cf32SBharata B Rao spapr_core_plug(hotplug_dev, dev, errp); 2279c20d332aSBharata B Rao } 2280c20d332aSBharata B Rao } 2281c20d332aSBharata B Rao 2282c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2283c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2284c20d332aSBharata B Rao { 22853c0c47e3SDavid Gibson MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); 22866f4b5c3eSBharata B Rao 2287c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2288c20d332aSBharata B Rao error_setg(errp, "Memory hot unplug not supported by sPAPR"); 22896f4b5c3eSBharata B Rao } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 22903c0c47e3SDavid Gibson if (!mc->query_hotpluggable_cpus) { 22916f4b5c3eSBharata B Rao error_setg(errp, "CPU hot unplug not supported on this machine"); 22926f4b5c3eSBharata B Rao return; 22936f4b5c3eSBharata B Rao } 22946f4b5c3eSBharata B Rao spapr_core_unplug(hotplug_dev, dev, errp); 2295c20d332aSBharata B Rao } 2296c20d332aSBharata B Rao } 2297c20d332aSBharata B Rao 229894a94e4cSBharata B Rao static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, 229994a94e4cSBharata B Rao DeviceState *dev, Error **errp) 230094a94e4cSBharata B Rao { 230194a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 230294a94e4cSBharata B Rao spapr_core_pre_plug(hotplug_dev, dev, errp); 230394a94e4cSBharata B Rao } 230494a94e4cSBharata B Rao } 230594a94e4cSBharata B Rao 23067ebaf795SBharata B Rao static HotplugHandler *spapr_get_hotplug_handler(MachineState *machine, 2307c20d332aSBharata B Rao DeviceState *dev) 2308c20d332aSBharata B Rao { 230994a94e4cSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) || 231094a94e4cSBharata B Rao object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { 2311c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2312c20d332aSBharata B Rao } 2313c20d332aSBharata B Rao return NULL; 2314c20d332aSBharata B Rao } 2315c20d332aSBharata B Rao 231620bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) 231720bb648dSDavid Gibson { 231820bb648dSDavid Gibson /* Allocate to NUMA nodes on a "socket" basis (not that concept of 231920bb648dSDavid Gibson * socket means much for the paravirtualized PAPR platform) */ 232020bb648dSDavid Gibson return cpu_index / smp_threads / smp_cores; 232120bb648dSDavid Gibson } 232220bb648dSDavid Gibson 23232474bfd4SIgor Mammedov static HotpluggableCPUList *spapr_query_hotpluggable_cpus(MachineState *machine) 23242474bfd4SIgor Mammedov { 23252474bfd4SIgor Mammedov int i; 23262474bfd4SIgor Mammedov HotpluggableCPUList *head = NULL; 23272474bfd4SIgor Mammedov sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 23282474bfd4SIgor Mammedov int spapr_max_cores = max_cpus / smp_threads; 23292474bfd4SIgor Mammedov 23302474bfd4SIgor Mammedov for (i = 0; i < spapr_max_cores; i++) { 23312474bfd4SIgor Mammedov HotpluggableCPUList *list_item = g_new0(typeof(*list_item), 1); 23322474bfd4SIgor Mammedov HotpluggableCPU *cpu_item = g_new0(typeof(*cpu_item), 1); 23332474bfd4SIgor Mammedov CpuInstanceProperties *cpu_props = g_new0(typeof(*cpu_props), 1); 23342474bfd4SIgor Mammedov 23352474bfd4SIgor Mammedov cpu_item->type = spapr_get_cpu_core_type(machine->cpu_model); 23362474bfd4SIgor Mammedov cpu_item->vcpus_count = smp_threads; 233727393c33SPeter Krempa cpu_props->has_core_id = true; 233812bf2d33SGreg Kurz cpu_props->core_id = i * smp_threads; 23392474bfd4SIgor Mammedov /* TODO: add 'has_node/node' here to describe 23402474bfd4SIgor Mammedov to which node core belongs */ 23412474bfd4SIgor Mammedov 23422474bfd4SIgor Mammedov cpu_item->props = cpu_props; 23432474bfd4SIgor Mammedov if (spapr->cores[i]) { 23442474bfd4SIgor Mammedov cpu_item->has_qom_path = true; 23452474bfd4SIgor Mammedov cpu_item->qom_path = object_get_canonical_path(spapr->cores[i]); 23462474bfd4SIgor Mammedov } 23472474bfd4SIgor Mammedov list_item->value = cpu_item; 23482474bfd4SIgor Mammedov list_item->next = head; 23492474bfd4SIgor Mammedov head = list_item; 23502474bfd4SIgor Mammedov } 23512474bfd4SIgor Mammedov return head; 23522474bfd4SIgor Mammedov } 23532474bfd4SIgor Mammedov 23546737d9adSDavid Gibson static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, 2355daa23699SDavid Gibson uint64_t *buid, hwaddr *pio, 2356daa23699SDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 23576737d9adSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 23586737d9adSDavid Gibson { 2359357d1e3bSDavid Gibson /* 2360357d1e3bSDavid Gibson * New-style PHB window placement. 2361357d1e3bSDavid Gibson * 2362357d1e3bSDavid Gibson * Goals: Gives large (1TiB), naturally aligned 64-bit MMIO window 2363357d1e3bSDavid Gibson * for each PHB, in addition to 2GiB 32-bit MMIO and 64kiB PIO 2364357d1e3bSDavid Gibson * windows. 2365357d1e3bSDavid Gibson * 2366357d1e3bSDavid Gibson * Some guest kernels can't work with MMIO windows above 1<<46 2367357d1e3bSDavid Gibson * (64TiB), so we place up to 31 PHBs in the area 32TiB..64TiB 2368357d1e3bSDavid Gibson * 2369357d1e3bSDavid Gibson * 32TiB..(33TiB+1984kiB) contains the 64kiB PIO windows for each 2370357d1e3bSDavid Gibson * PHB stacked together. (32TiB+2GiB)..(32TiB+64GiB) contains the 2371357d1e3bSDavid Gibson * 2GiB 32-bit MMIO windows for each PHB. Then 33..64TiB has the 2372357d1e3bSDavid Gibson * 1TiB 64-bit MMIO windows for each PHB. 2373357d1e3bSDavid Gibson */ 23746737d9adSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 2375357d1e3bSDavid Gibson const int max_phbs = 2376357d1e3bSDavid Gibson (SPAPR_PCI_LIMIT - SPAPR_PCI_BASE) / SPAPR_PCI_MEM64_WIN_SIZE - 1; 23776737d9adSDavid Gibson int i; 23786737d9adSDavid Gibson 2379357d1e3bSDavid Gibson /* Sanity check natural alignments */ 2380357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_BASE % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 2381357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_LIMIT % SPAPR_PCI_MEM64_WIN_SIZE) != 0); 2382357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM64_WIN_SIZE % SPAPR_PCI_MEM32_WIN_SIZE) != 0); 2383357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((SPAPR_PCI_MEM32_WIN_SIZE % SPAPR_PCI_IO_WIN_SIZE) != 0); 2384357d1e3bSDavid Gibson /* Sanity check bounds */ 2385357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_IO_WIN_SIZE) > SPAPR_PCI_MEM32_WIN_SIZE); 2386357d1e3bSDavid Gibson QEMU_BUILD_BUG_ON((max_phbs * SPAPR_PCI_MEM32_WIN_SIZE) > SPAPR_PCI_MEM64_WIN_SIZE); 23872efff1c0SDavid Gibson 2388357d1e3bSDavid Gibson if (index >= max_phbs) { 23896737d9adSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 2390357d1e3bSDavid Gibson max_phbs - 1); 23916737d9adSDavid Gibson return; 23926737d9adSDavid Gibson } 23936737d9adSDavid Gibson 23946737d9adSDavid Gibson *buid = base_buid + index; 23956737d9adSDavid Gibson for (i = 0; i < n_dma; ++i) { 23966737d9adSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 23976737d9adSDavid Gibson } 23986737d9adSDavid Gibson 2399357d1e3bSDavid Gibson *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; 2400357d1e3bSDavid Gibson *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; 2401357d1e3bSDavid Gibson *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; 24026737d9adSDavid Gibson } 24036737d9adSDavid Gibson 240429ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 240553018216SPaolo Bonzini { 240629ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 2407224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 240871461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 240934316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 2410c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 241129ee3247SAlexey Kardashevskiy 24120eb9054cSDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant)"; 2413fc9f38c3SDavid Gibson 2414fc9f38c3SDavid Gibson /* 2415fc9f38c3SDavid Gibson * We set up the default / latest behaviour here. The class_init 2416fc9f38c3SDavid Gibson * functions for the specific versioned machine types can override 2417fc9f38c3SDavid Gibson * these details for backwards compatibility 2418fc9f38c3SDavid Gibson */ 2419958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 2420958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 2421958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 2422079019f2SIgor Mammedov mc->max_cpus = 255; 2423958db90cSMarcel Apfelbaum mc->no_parallel = 1; 24245b2128d2SAlexander Graf mc->default_boot_order = ""; 2425a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 2426958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 24279e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 2428e4024630SLaurent Vivier mc->pci_allow_0_address = true; 24297ebaf795SBharata B Rao mc->get_hotplug_handler = spapr_get_hotplug_handler; 243094a94e4cSBharata B Rao hc->pre_plug = spapr_machine_device_pre_plug; 2431c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 2432c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 243320bb648dSDavid Gibson mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; 243400b4fbe2SMarcel Apfelbaum 2435fc9f38c3SDavid Gibson smc->dr_lmb_enabled = true; 24363daa4a9fSThomas Huth smc->tcg_default_cpu = "POWER8"; 24373c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = spapr_query_hotpluggable_cpus; 243871461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 243934316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 24406737d9adSDavid Gibson smc->phb_placement = spapr_phb_placement; 244153018216SPaolo Bonzini } 244253018216SPaolo Bonzini 244329ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 244429ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 244529ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 24464aee7362SDavid Gibson .abstract = true, 24476ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 244823825581SEduardo Habkost .instance_init = spapr_machine_initfn, 244987bbdd9cSDavid Gibson .instance_finalize = spapr_machine_finalizefn, 2450183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 245129ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 245271461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 245371461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 245434316482SAlexey Kardashevskiy { TYPE_NMI }, 2455c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 245671461b0fSAlexey Kardashevskiy { } 245771461b0fSAlexey Kardashevskiy }, 245829ee3247SAlexey Kardashevskiy }; 245929ee3247SAlexey Kardashevskiy 2460fccbc785SDavid Gibson #define DEFINE_SPAPR_MACHINE(suffix, verstr, latest) \ 24615013c547SDavid Gibson static void spapr_machine_##suffix##_class_init(ObjectClass *oc, \ 24625013c547SDavid Gibson void *data) \ 24635013c547SDavid Gibson { \ 24645013c547SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); \ 24655013c547SDavid Gibson spapr_machine_##suffix##_class_options(mc); \ 2466fccbc785SDavid Gibson if (latest) { \ 2467fccbc785SDavid Gibson mc->alias = "pseries"; \ 2468fccbc785SDavid Gibson mc->is_default = 1; \ 2469fccbc785SDavid Gibson } \ 24705013c547SDavid Gibson } \ 24715013c547SDavid Gibson static void spapr_machine_##suffix##_instance_init(Object *obj) \ 24725013c547SDavid Gibson { \ 24735013c547SDavid Gibson MachineState *machine = MACHINE(obj); \ 24745013c547SDavid Gibson spapr_machine_##suffix##_instance_options(machine); \ 24755013c547SDavid Gibson } \ 24765013c547SDavid Gibson static const TypeInfo spapr_machine_##suffix##_info = { \ 24775013c547SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-" verstr), \ 24785013c547SDavid Gibson .parent = TYPE_SPAPR_MACHINE, \ 24795013c547SDavid Gibson .class_init = spapr_machine_##suffix##_class_init, \ 24805013c547SDavid Gibson .instance_init = spapr_machine_##suffix##_instance_init, \ 24815013c547SDavid Gibson }; \ 24825013c547SDavid Gibson static void spapr_machine_register_##suffix(void) \ 24835013c547SDavid Gibson { \ 24845013c547SDavid Gibson type_register(&spapr_machine_##suffix##_info); \ 24855013c547SDavid Gibson } \ 24860e6aac87SEduardo Habkost type_init(spapr_machine_register_##suffix) 24875013c547SDavid Gibson 24881c5f29bbSDavid Gibson /* 2489db800b21SDavid Gibson * pseries-2.8 2490db800b21SDavid Gibson */ 2491db800b21SDavid Gibson static void spapr_machine_2_8_instance_options(MachineState *machine) 2492db800b21SDavid Gibson { 2493db800b21SDavid Gibson } 2494db800b21SDavid Gibson 2495db800b21SDavid Gibson static void spapr_machine_2_8_class_options(MachineClass *mc) 2496db800b21SDavid Gibson { 2497db800b21SDavid Gibson /* Defaults for the latest behaviour inherited from the base class */ 2498db800b21SDavid Gibson } 2499db800b21SDavid Gibson 2500db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_8, "2.8", true); 2501db800b21SDavid Gibson 2502db800b21SDavid Gibson /* 25031ea1eefcSBharata B Rao * pseries-2.7 25041ea1eefcSBharata B Rao */ 2505db800b21SDavid Gibson #define SPAPR_COMPAT_2_7 \ 2506db800b21SDavid Gibson HW_COMPAT_2_7 \ 2507357d1e3bSDavid Gibson { \ 2508357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 2509357d1e3bSDavid Gibson .property = "mem_win_size", \ 2510357d1e3bSDavid Gibson .value = stringify(SPAPR_PCI_2_7_MMIO_WIN_SIZE),\ 2511357d1e3bSDavid Gibson }, \ 2512357d1e3bSDavid Gibson { \ 2513357d1e3bSDavid Gibson .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ 2514357d1e3bSDavid Gibson .property = "mem64_win_size", \ 2515357d1e3bSDavid Gibson .value = "0", \ 2516357d1e3bSDavid Gibson }, 2517357d1e3bSDavid Gibson 2518357d1e3bSDavid Gibson static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, 2519357d1e3bSDavid Gibson uint64_t *buid, hwaddr *pio, 2520357d1e3bSDavid Gibson hwaddr *mmio32, hwaddr *mmio64, 2521357d1e3bSDavid Gibson unsigned n_dma, uint32_t *liobns, Error **errp) 2522357d1e3bSDavid Gibson { 2523357d1e3bSDavid Gibson /* Legacy PHB placement for pseries-2.7 and earlier machine types */ 2524357d1e3bSDavid Gibson const uint64_t base_buid = 0x800000020000000ULL; 2525357d1e3bSDavid Gibson const hwaddr phb_spacing = 0x1000000000ULL; /* 64 GiB */ 2526357d1e3bSDavid Gibson const hwaddr mmio_offset = 0xa0000000; /* 2 GiB + 512 MiB */ 2527357d1e3bSDavid Gibson const hwaddr pio_offset = 0x80000000; /* 2 GiB */ 2528357d1e3bSDavid Gibson const uint32_t max_index = 255; 2529357d1e3bSDavid Gibson const hwaddr phb0_alignment = 0x10000000000ULL; /* 1 TiB */ 2530357d1e3bSDavid Gibson 2531357d1e3bSDavid Gibson uint64_t ram_top = MACHINE(spapr)->ram_size; 2532357d1e3bSDavid Gibson hwaddr phb0_base, phb_base; 2533357d1e3bSDavid Gibson int i; 2534357d1e3bSDavid Gibson 2535357d1e3bSDavid Gibson /* Do we have hotpluggable memory? */ 2536357d1e3bSDavid Gibson if (MACHINE(spapr)->maxram_size > ram_top) { 2537357d1e3bSDavid Gibson /* Can't just use maxram_size, because there may be an 2538357d1e3bSDavid Gibson * alignment gap between normal and hotpluggable memory 2539357d1e3bSDavid Gibson * regions */ 2540357d1e3bSDavid Gibson ram_top = spapr->hotplug_memory.base + 2541357d1e3bSDavid Gibson memory_region_size(&spapr->hotplug_memory.mr); 2542357d1e3bSDavid Gibson } 2543357d1e3bSDavid Gibson 2544357d1e3bSDavid Gibson phb0_base = QEMU_ALIGN_UP(ram_top, phb0_alignment); 2545357d1e3bSDavid Gibson 2546357d1e3bSDavid Gibson if (index > max_index) { 2547357d1e3bSDavid Gibson error_setg(errp, "\"index\" for PAPR PHB is too large (max %u)", 2548357d1e3bSDavid Gibson max_index); 2549357d1e3bSDavid Gibson return; 2550357d1e3bSDavid Gibson } 2551357d1e3bSDavid Gibson 2552357d1e3bSDavid Gibson *buid = base_buid + index; 2553357d1e3bSDavid Gibson for (i = 0; i < n_dma; ++i) { 2554357d1e3bSDavid Gibson liobns[i] = SPAPR_PCI_LIOBN(index, i); 2555357d1e3bSDavid Gibson } 2556357d1e3bSDavid Gibson 2557357d1e3bSDavid Gibson phb_base = phb0_base + index * phb_spacing; 2558357d1e3bSDavid Gibson *pio = phb_base + pio_offset; 2559357d1e3bSDavid Gibson *mmio32 = phb_base + mmio_offset; 2560357d1e3bSDavid Gibson /* 2561357d1e3bSDavid Gibson * We don't set the 64-bit MMIO window, relying on the PHB's 2562357d1e3bSDavid Gibson * fallback behaviour of automatically splitting a large "32-bit" 2563357d1e3bSDavid Gibson * window into contiguous 32-bit and 64-bit windows 2564357d1e3bSDavid Gibson */ 2565357d1e3bSDavid Gibson } 2566db800b21SDavid Gibson 25671ea1eefcSBharata B Rao static void spapr_machine_2_7_instance_options(MachineState *machine) 25681ea1eefcSBharata B Rao { 2569672de881SMichael Roth spapr_machine_2_8_instance_options(machine); 25701ea1eefcSBharata B Rao } 25711ea1eefcSBharata B Rao 25721ea1eefcSBharata B Rao static void spapr_machine_2_7_class_options(MachineClass *mc) 25731ea1eefcSBharata B Rao { 25743daa4a9fSThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 25753daa4a9fSThomas Huth 2576db800b21SDavid Gibson spapr_machine_2_8_class_options(mc); 25773daa4a9fSThomas Huth smc->tcg_default_cpu = "POWER7"; 2578db800b21SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_7); 2579357d1e3bSDavid Gibson smc->phb_placement = phb_placement_2_7; 25801ea1eefcSBharata B Rao } 25811ea1eefcSBharata B Rao 2582db800b21SDavid Gibson DEFINE_SPAPR_MACHINE(2_7, "2.7", false); 25831ea1eefcSBharata B Rao 25841ea1eefcSBharata B Rao /* 25854b23699cSDavid Gibson * pseries-2.6 25864b23699cSDavid Gibson */ 25871ea1eefcSBharata B Rao #define SPAPR_COMPAT_2_6 \ 2588ae4de14cSAlexey Kardashevskiy HW_COMPAT_2_6 \ 2589ae4de14cSAlexey Kardashevskiy { \ 2590ae4de14cSAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2591ae4de14cSAlexey Kardashevskiy .property = "ddw",\ 2592ae4de14cSAlexey Kardashevskiy .value = stringify(off),\ 2593ae4de14cSAlexey Kardashevskiy }, 25941ea1eefcSBharata B Rao 25954b23699cSDavid Gibson static void spapr_machine_2_6_instance_options(MachineState *machine) 25964b23699cSDavid Gibson { 2597672de881SMichael Roth spapr_machine_2_7_instance_options(machine); 25984b23699cSDavid Gibson } 25994b23699cSDavid Gibson 26004b23699cSDavid Gibson static void spapr_machine_2_6_class_options(MachineClass *mc) 26014b23699cSDavid Gibson { 26021ea1eefcSBharata B Rao spapr_machine_2_7_class_options(mc); 26033c0c47e3SDavid Gibson mc->query_hotpluggable_cpus = NULL; 26041ea1eefcSBharata B Rao SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6); 26054b23699cSDavid Gibson } 26064b23699cSDavid Gibson 26071ea1eefcSBharata B Rao DEFINE_SPAPR_MACHINE(2_6, "2.6", false); 26084b23699cSDavid Gibson 26094b23699cSDavid Gibson /* 26101c5f29bbSDavid Gibson * pseries-2.5 26111c5f29bbSDavid Gibson */ 26124b23699cSDavid Gibson #define SPAPR_COMPAT_2_5 \ 261357c522f4SThomas Huth HW_COMPAT_2_5 \ 261457c522f4SThomas Huth { \ 261557c522f4SThomas Huth .driver = "spapr-vlan", \ 261657c522f4SThomas Huth .property = "use-rx-buffer-pools", \ 261757c522f4SThomas Huth .value = "off", \ 261857c522f4SThomas Huth }, 26194b23699cSDavid Gibson 26205013c547SDavid Gibson static void spapr_machine_2_5_instance_options(MachineState *machine) 26211c5f29bbSDavid Gibson { 2622672de881SMichael Roth spapr_machine_2_6_instance_options(machine); 26235013c547SDavid Gibson } 26245013c547SDavid Gibson 26255013c547SDavid Gibson static void spapr_machine_2_5_class_options(MachineClass *mc) 26265013c547SDavid Gibson { 262757040d45SThomas Huth sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 262857040d45SThomas Huth 26294b23699cSDavid Gibson spapr_machine_2_6_class_options(mc); 263057040d45SThomas Huth smc->use_ohci_by_default = true; 26314b23699cSDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_5); 26321c5f29bbSDavid Gibson } 26331c5f29bbSDavid Gibson 26344b23699cSDavid Gibson DEFINE_SPAPR_MACHINE(2_5, "2.5", false); 26351c5f29bbSDavid Gibson 26361c5f29bbSDavid Gibson /* 26371c5f29bbSDavid Gibson * pseries-2.4 26381c5f29bbSDavid Gibson */ 263980fd50f9SCornelia Huck #define SPAPR_COMPAT_2_4 \ 264080fd50f9SCornelia Huck HW_COMPAT_2_4 264180fd50f9SCornelia Huck 26425013c547SDavid Gibson static void spapr_machine_2_4_instance_options(MachineState *machine) 26431c5f29bbSDavid Gibson { 26445013c547SDavid Gibson spapr_machine_2_5_instance_options(machine); 26455013c547SDavid Gibson } 26461c5f29bbSDavid Gibson 26475013c547SDavid Gibson static void spapr_machine_2_4_class_options(MachineClass *mc) 26485013c547SDavid Gibson { 2649fc9f38c3SDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(mc); 2650fc9f38c3SDavid Gibson 2651fc9f38c3SDavid Gibson spapr_machine_2_5_class_options(mc); 2652fc9f38c3SDavid Gibson smc->dr_lmb_enabled = false; 2653f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_4); 26541c5f29bbSDavid Gibson } 26551c5f29bbSDavid Gibson 2656fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_4, "2.4", false); 26571c5f29bbSDavid Gibson 26581c5f29bbSDavid Gibson /* 26591c5f29bbSDavid Gibson * pseries-2.3 26601c5f29bbSDavid Gibson */ 266138ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 26627619c7b0SMichael Roth HW_COMPAT_2_3 \ 26637619c7b0SMichael Roth {\ 26647619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 26657619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 26667619c7b0SMichael Roth .value = "off",\ 26677619c7b0SMichael Roth }, 266838ff32c6SEduardo Habkost 26695013c547SDavid Gibson static void spapr_machine_2_3_instance_options(MachineState *machine) 26701c5f29bbSDavid Gibson { 26715013c547SDavid Gibson spapr_machine_2_4_instance_options(machine); 26721c5f29bbSDavid Gibson savevm_skip_section_footers(); 26731c5f29bbSDavid Gibson global_state_set_optional(); 267409b5e30dSGreg Kurz savevm_skip_configuration(); 26751c5f29bbSDavid Gibson } 26761c5f29bbSDavid Gibson 26775013c547SDavid Gibson static void spapr_machine_2_3_class_options(MachineClass *mc) 26781c5f29bbSDavid Gibson { 2679fc9f38c3SDavid Gibson spapr_machine_2_4_class_options(mc); 2680f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_3); 26811c5f29bbSDavid Gibson } 2682fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_3, "2.3", false); 26831c5f29bbSDavid Gibson 26841c5f29bbSDavid Gibson /* 26851c5f29bbSDavid Gibson * pseries-2.2 26861c5f29bbSDavid Gibson */ 26871c5f29bbSDavid Gibson 2688b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 26894dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 2690b194df47SAlexey Kardashevskiy {\ 2691b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2692b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 2693b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 2694dd754bafSEduardo Habkost }, 2695b194df47SAlexey Kardashevskiy 26965013c547SDavid Gibson static void spapr_machine_2_2_instance_options(MachineState *machine) 2697b0e966d0SJason Wang { 26985013c547SDavid Gibson spapr_machine_2_3_instance_options(machine); 2699cba0e779SGreg Kurz machine->suppress_vmdesc = true; 2700b0e966d0SJason Wang } 2701b0e966d0SJason Wang 27025013c547SDavid Gibson static void spapr_machine_2_2_class_options(MachineClass *mc) 2703b0e966d0SJason Wang { 2704fc9f38c3SDavid Gibson spapr_machine_2_3_class_options(mc); 2705f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_2); 27061c5f29bbSDavid Gibson } 2707fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_2, "2.2", false); 27081c5f29bbSDavid Gibson 27091c5f29bbSDavid Gibson /* 27101c5f29bbSDavid Gibson * pseries-2.1 27111c5f29bbSDavid Gibson */ 27121c5f29bbSDavid Gibson #define SPAPR_COMPAT_2_1 \ 27131c5f29bbSDavid Gibson HW_COMPAT_2_1 27141c5f29bbSDavid Gibson 27155013c547SDavid Gibson static void spapr_machine_2_1_instance_options(MachineState *machine) 27161c5f29bbSDavid Gibson { 27175013c547SDavid Gibson spapr_machine_2_2_instance_options(machine); 27181c5f29bbSDavid Gibson } 27191c5f29bbSDavid Gibson 27205013c547SDavid Gibson static void spapr_machine_2_1_class_options(MachineClass *mc) 2721b0e966d0SJason Wang { 2722fc9f38c3SDavid Gibson spapr_machine_2_2_class_options(mc); 2723f949b4e5SDavid Gibson SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_1); 27246026db45SAlexey Kardashevskiy } 2725fccbc785SDavid Gibson DEFINE_SPAPR_MACHINE(2_1, "2.1", false); 27266026db45SAlexey Kardashevskiy 272729ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 272829ee3247SAlexey Kardashevskiy { 272929ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 273029ee3247SAlexey Kardashevskiy } 273129ee3247SAlexey Kardashevskiy 273229ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 2733