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 */ 2753018216SPaolo Bonzini #include "sysemu/sysemu.h" 28e35704baSEduardo Habkost #include "sysemu/numa.h" 2953018216SPaolo Bonzini #include "hw/hw.h" 3071461b0fSAlexey Kardashevskiy #include "hw/fw-path-provider.h" 3153018216SPaolo Bonzini #include "elf.h" 3253018216SPaolo Bonzini #include "net/net.h" 33ad440b4aSAndrew Jones #include "sysemu/device_tree.h" 34fa1d36dfSMarkus Armbruster #include "sysemu/block-backend.h" 3553018216SPaolo Bonzini #include "sysemu/cpus.h" 3653018216SPaolo Bonzini #include "sysemu/kvm.h" 37c20d332aSBharata B Rao #include "sysemu/device_tree.h" 3853018216SPaolo Bonzini #include "kvm_ppc.h" 39ff14e817SDr. David Alan Gilbert #include "migration/migration.h" 404be21d56SDavid Gibson #include "mmu-hash64.h" 413794d548SAlexey Kardashevskiy #include "qom/cpu.h" 4253018216SPaolo Bonzini 4353018216SPaolo Bonzini #include "hw/boards.h" 440d09e41aSPaolo Bonzini #include "hw/ppc/ppc.h" 4553018216SPaolo Bonzini #include "hw/loader.h" 4653018216SPaolo Bonzini 470d09e41aSPaolo Bonzini #include "hw/ppc/spapr.h" 480d09e41aSPaolo Bonzini #include "hw/ppc/spapr_vio.h" 490d09e41aSPaolo Bonzini #include "hw/pci-host/spapr.h" 500d09e41aSPaolo Bonzini #include "hw/ppc/xics.h" 5153018216SPaolo Bonzini #include "hw/pci/msi.h" 5253018216SPaolo Bonzini 5353018216SPaolo Bonzini #include "hw/pci/pci.h" 5471461b0fSAlexey Kardashevskiy #include "hw/scsi/scsi.h" 5571461b0fSAlexey Kardashevskiy #include "hw/virtio/virtio-scsi.h" 5653018216SPaolo Bonzini 5753018216SPaolo Bonzini #include "exec/address-spaces.h" 5853018216SPaolo Bonzini #include "hw/usb.h" 5953018216SPaolo Bonzini #include "qemu/config-file.h" 60135a129aSAneesh Kumar K.V #include "qemu/error-report.h" 612a6593cbSAlexey Kardashevskiy #include "trace.h" 6234316482SAlexey Kardashevskiy #include "hw/nmi.h" 6353018216SPaolo Bonzini 6468a27b20SMichael S. Tsirkin #include "hw/compat.h" 65224245bfSDavid Gibson #include "qemu-common.h" 6668a27b20SMichael S. Tsirkin 6753018216SPaolo Bonzini #include <libfdt.h> 6853018216SPaolo Bonzini 6953018216SPaolo Bonzini /* SLOF memory layout: 7053018216SPaolo Bonzini * 7153018216SPaolo Bonzini * SLOF raw image loaded at 0, copies its romfs right below the flat 7253018216SPaolo Bonzini * device-tree, then position SLOF itself 31M below that 7353018216SPaolo Bonzini * 7453018216SPaolo Bonzini * So we set FW_OVERHEAD to 40MB which should account for all of that 7553018216SPaolo Bonzini * and more 7653018216SPaolo Bonzini * 7753018216SPaolo Bonzini * We load our kernel at 4M, leaving space for SLOF initial image 7853018216SPaolo Bonzini */ 7938b02bd8SAlexey Kardashevskiy #define FDT_MAX_SIZE 0x100000 8053018216SPaolo Bonzini #define RTAS_MAX_SIZE 0x10000 81b7d1f77aSBenjamin Herrenschmidt #define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */ 8253018216SPaolo Bonzini #define FW_MAX_SIZE 0x400000 8353018216SPaolo Bonzini #define FW_FILE_NAME "slof.bin" 8453018216SPaolo Bonzini #define FW_OVERHEAD 0x2800000 8553018216SPaolo Bonzini #define KERNEL_LOAD_ADDR FW_MAX_SIZE 8653018216SPaolo Bonzini 8753018216SPaolo Bonzini #define MIN_RMA_SLOF 128UL 8853018216SPaolo Bonzini 8953018216SPaolo Bonzini #define TIMEBASE_FREQ 512000000ULL 9053018216SPaolo Bonzini 9153018216SPaolo Bonzini #define PHANDLE_XICP 0x00001111 9253018216SPaolo Bonzini 9353018216SPaolo Bonzini #define HTAB_SIZE(spapr) (1ULL << ((spapr)->htab_shift)) 9453018216SPaolo Bonzini 95c04d6cfaSAnthony Liguori static XICSState *try_create_xics(const char *type, int nr_servers, 9634f2af3dSMarkus Armbruster int nr_irqs, Error **errp) 97c04d6cfaSAnthony Liguori { 9834f2af3dSMarkus Armbruster Error *err = NULL; 99c04d6cfaSAnthony Liguori DeviceState *dev; 100c04d6cfaSAnthony Liguori 101c04d6cfaSAnthony Liguori dev = qdev_create(NULL, type); 102c04d6cfaSAnthony Liguori qdev_prop_set_uint32(dev, "nr_servers", nr_servers); 103c04d6cfaSAnthony Liguori qdev_prop_set_uint32(dev, "nr_irqs", nr_irqs); 10434f2af3dSMarkus Armbruster object_property_set_bool(OBJECT(dev), true, "realized", &err); 10534f2af3dSMarkus Armbruster if (err) { 10634f2af3dSMarkus Armbruster error_propagate(errp, err); 10734f2af3dSMarkus Armbruster object_unparent(OBJECT(dev)); 108c04d6cfaSAnthony Liguori return NULL; 109c04d6cfaSAnthony Liguori } 1105a3d7b23SAlexey Kardashevskiy return XICS_COMMON(dev); 111c04d6cfaSAnthony Liguori } 112c04d6cfaSAnthony Liguori 113446f16a6SMarcel Apfelbaum static XICSState *xics_system_init(MachineState *machine, 114446f16a6SMarcel Apfelbaum int nr_servers, int nr_irqs) 115c04d6cfaSAnthony Liguori { 116c04d6cfaSAnthony Liguori XICSState *icp = NULL; 117c04d6cfaSAnthony Liguori 11811ad93f6SDavid Gibson if (kvm_enabled()) { 11934f2af3dSMarkus Armbruster Error *err = NULL; 12034f2af3dSMarkus Armbruster 121446f16a6SMarcel Apfelbaum if (machine_kernel_irqchip_allowed(machine)) { 12234f2af3dSMarkus Armbruster icp = try_create_xics(TYPE_KVM_XICS, nr_servers, nr_irqs, &err); 12311ad93f6SDavid Gibson } 124446f16a6SMarcel Apfelbaum if (machine_kernel_irqchip_required(machine) && !icp) { 12534f2af3dSMarkus Armbruster error_report("kernel_irqchip requested but unavailable: %s", 12634f2af3dSMarkus Armbruster error_get_pretty(err)); 12711ad93f6SDavid Gibson } 12811ad93f6SDavid Gibson } 12911ad93f6SDavid Gibson 13011ad93f6SDavid Gibson if (!icp) { 13134f2af3dSMarkus Armbruster icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, &error_abort); 132c04d6cfaSAnthony Liguori } 133c04d6cfaSAnthony Liguori 134c04d6cfaSAnthony Liguori return icp; 135c04d6cfaSAnthony Liguori } 136c04d6cfaSAnthony Liguori 137833d4668SAlexey Kardashevskiy static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, 138833d4668SAlexey Kardashevskiy int smt_threads) 139833d4668SAlexey Kardashevskiy { 140833d4668SAlexey Kardashevskiy int i, ret = 0; 141833d4668SAlexey Kardashevskiy uint32_t servers_prop[smt_threads]; 142833d4668SAlexey Kardashevskiy uint32_t gservers_prop[smt_threads * 2]; 143833d4668SAlexey Kardashevskiy int index = ppc_get_vcpu_dt_id(cpu); 144833d4668SAlexey Kardashevskiy 1456d9412eaSAlexey Kardashevskiy if (cpu->cpu_version) { 1464bce526eSLaurent Dufour ret = fdt_setprop_cell(fdt, offset, "cpu-version", cpu->cpu_version); 1476d9412eaSAlexey Kardashevskiy if (ret < 0) { 1486d9412eaSAlexey Kardashevskiy return ret; 1496d9412eaSAlexey Kardashevskiy } 1506d9412eaSAlexey Kardashevskiy } 1516d9412eaSAlexey Kardashevskiy 152833d4668SAlexey Kardashevskiy /* Build interrupt servers and gservers properties */ 153833d4668SAlexey Kardashevskiy for (i = 0; i < smt_threads; i++) { 154833d4668SAlexey Kardashevskiy servers_prop[i] = cpu_to_be32(index + i); 155833d4668SAlexey Kardashevskiy /* Hack, direct the group queues back to cpu 0 */ 156833d4668SAlexey Kardashevskiy gservers_prop[i*2] = cpu_to_be32(index + i); 157833d4668SAlexey Kardashevskiy gservers_prop[i*2 + 1] = 0; 158833d4668SAlexey Kardashevskiy } 159833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", 160833d4668SAlexey Kardashevskiy servers_prop, sizeof(servers_prop)); 161833d4668SAlexey Kardashevskiy if (ret < 0) { 162833d4668SAlexey Kardashevskiy return ret; 163833d4668SAlexey Kardashevskiy } 164833d4668SAlexey Kardashevskiy ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", 165833d4668SAlexey Kardashevskiy gservers_prop, sizeof(gservers_prop)); 166833d4668SAlexey Kardashevskiy 167833d4668SAlexey Kardashevskiy return ret; 168833d4668SAlexey Kardashevskiy } 169833d4668SAlexey Kardashevskiy 1700da6f3feSBharata B Rao static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, CPUState *cs) 1710da6f3feSBharata B Rao { 1720da6f3feSBharata B Rao int ret = 0; 1730da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 1740da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 1750da6f3feSBharata B Rao uint32_t associativity[] = {cpu_to_be32(0x5), 1760da6f3feSBharata B Rao cpu_to_be32(0x0), 1770da6f3feSBharata B Rao cpu_to_be32(0x0), 1780da6f3feSBharata B Rao cpu_to_be32(0x0), 1790da6f3feSBharata B Rao cpu_to_be32(cs->numa_node), 1800da6f3feSBharata B Rao cpu_to_be32(index)}; 1810da6f3feSBharata B Rao 1820da6f3feSBharata B Rao /* Advertise NUMA via ibm,associativity */ 1830da6f3feSBharata B Rao if (nb_numa_nodes > 1) { 1840da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, 1850da6f3feSBharata B Rao sizeof(associativity)); 1860da6f3feSBharata B Rao } 1870da6f3feSBharata B Rao 1880da6f3feSBharata B Rao return ret; 1890da6f3feSBharata B Rao } 1900da6f3feSBharata B Rao 19128e02042SDavid Gibson static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) 19253018216SPaolo Bonzini { 19382677ed2SAlexey Kardashevskiy int ret = 0, offset, cpus_offset; 19482677ed2SAlexey Kardashevskiy CPUState *cs; 19553018216SPaolo Bonzini char cpu_model[32]; 19653018216SPaolo Bonzini int smt = kvmppc_smt_threads(); 19753018216SPaolo Bonzini uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 19853018216SPaolo Bonzini 19982677ed2SAlexey Kardashevskiy CPU_FOREACH(cs) { 20082677ed2SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 20182677ed2SAlexey Kardashevskiy DeviceClass *dc = DEVICE_GET_CLASS(cs); 20282677ed2SAlexey Kardashevskiy int index = ppc_get_vcpu_dt_id(cpu); 20353018216SPaolo Bonzini 2040f20ba62SAlexey Kardashevskiy if ((index % smt) != 0) { 20553018216SPaolo Bonzini continue; 20653018216SPaolo Bonzini } 20753018216SPaolo Bonzini 20882677ed2SAlexey Kardashevskiy snprintf(cpu_model, 32, "%s@%x", dc->fw_name, index); 20953018216SPaolo Bonzini 21082677ed2SAlexey Kardashevskiy cpus_offset = fdt_path_offset(fdt, "/cpus"); 21182677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 21282677ed2SAlexey Kardashevskiy cpus_offset = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), 21382677ed2SAlexey Kardashevskiy "cpus"); 21482677ed2SAlexey Kardashevskiy if (cpus_offset < 0) { 21582677ed2SAlexey Kardashevskiy return cpus_offset; 21682677ed2SAlexey Kardashevskiy } 21782677ed2SAlexey Kardashevskiy } 21882677ed2SAlexey Kardashevskiy offset = fdt_subnode_offset(fdt, cpus_offset, cpu_model); 21982677ed2SAlexey Kardashevskiy if (offset < 0) { 22082677ed2SAlexey Kardashevskiy offset = fdt_add_subnode(fdt, cpus_offset, cpu_model); 22153018216SPaolo Bonzini if (offset < 0) { 22253018216SPaolo Bonzini return offset; 22353018216SPaolo Bonzini } 22482677ed2SAlexey Kardashevskiy } 22553018216SPaolo Bonzini 2260da6f3feSBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,pft-size", 2270da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)); 22853018216SPaolo Bonzini if (ret < 0) { 22953018216SPaolo Bonzini return ret; 23053018216SPaolo Bonzini } 23153018216SPaolo Bonzini 2320da6f3feSBharata B Rao ret = spapr_fixup_cpu_numa_dt(fdt, offset, cs); 23353018216SPaolo Bonzini if (ret < 0) { 23453018216SPaolo Bonzini return ret; 23553018216SPaolo Bonzini } 236833d4668SAlexey Kardashevskiy 23782677ed2SAlexey Kardashevskiy ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 2382a48d993SAlexey Kardashevskiy ppc_get_compat_smt_threads(cpu)); 239833d4668SAlexey Kardashevskiy if (ret < 0) { 240833d4668SAlexey Kardashevskiy return ret; 241833d4668SAlexey Kardashevskiy } 24253018216SPaolo Bonzini } 24353018216SPaolo Bonzini return ret; 24453018216SPaolo Bonzini } 24553018216SPaolo Bonzini 24653018216SPaolo Bonzini 24753018216SPaolo Bonzini static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop, 24853018216SPaolo Bonzini size_t maxsize) 24953018216SPaolo Bonzini { 25053018216SPaolo Bonzini size_t maxcells = maxsize / sizeof(uint32_t); 25153018216SPaolo Bonzini int i, j, count; 25253018216SPaolo Bonzini uint32_t *p = prop; 25353018216SPaolo Bonzini 25453018216SPaolo Bonzini for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) { 25553018216SPaolo Bonzini struct ppc_one_seg_page_size *sps = &env->sps.sps[i]; 25653018216SPaolo Bonzini 25753018216SPaolo Bonzini if (!sps->page_shift) { 25853018216SPaolo Bonzini break; 25953018216SPaolo Bonzini } 26053018216SPaolo Bonzini for (count = 0; count < PPC_PAGE_SIZES_MAX_SZ; count++) { 26153018216SPaolo Bonzini if (sps->enc[count].page_shift == 0) { 26253018216SPaolo Bonzini break; 26353018216SPaolo Bonzini } 26453018216SPaolo Bonzini } 26553018216SPaolo Bonzini if ((p - prop) >= (maxcells - 3 - count * 2)) { 26653018216SPaolo Bonzini break; 26753018216SPaolo Bonzini } 26853018216SPaolo Bonzini *(p++) = cpu_to_be32(sps->page_shift); 26953018216SPaolo Bonzini *(p++) = cpu_to_be32(sps->slb_enc); 27053018216SPaolo Bonzini *(p++) = cpu_to_be32(count); 27153018216SPaolo Bonzini for (j = 0; j < count; j++) { 27253018216SPaolo Bonzini *(p++) = cpu_to_be32(sps->enc[j].page_shift); 27353018216SPaolo Bonzini *(p++) = cpu_to_be32(sps->enc[j].pte_enc); 27453018216SPaolo Bonzini } 27553018216SPaolo Bonzini } 27653018216SPaolo Bonzini 27753018216SPaolo Bonzini return (p - prop) * sizeof(uint32_t); 27853018216SPaolo Bonzini } 27953018216SPaolo Bonzini 280b082d65aSAlexey Kardashevskiy static hwaddr spapr_node0_size(void) 281b082d65aSAlexey Kardashevskiy { 282fb164994SDavid Gibson MachineState *machine = MACHINE(qdev_get_machine()); 283fb164994SDavid Gibson 284b082d65aSAlexey Kardashevskiy if (nb_numa_nodes) { 285b082d65aSAlexey Kardashevskiy int i; 286b082d65aSAlexey Kardashevskiy for (i = 0; i < nb_numa_nodes; ++i) { 287b082d65aSAlexey Kardashevskiy if (numa_info[i].node_mem) { 288fb164994SDavid Gibson return MIN(pow2floor(numa_info[i].node_mem), 289fb164994SDavid Gibson machine->ram_size); 290b082d65aSAlexey Kardashevskiy } 291b082d65aSAlexey Kardashevskiy } 292b082d65aSAlexey Kardashevskiy } 293fb164994SDavid Gibson return machine->ram_size; 294b082d65aSAlexey Kardashevskiy } 295b082d65aSAlexey Kardashevskiy 29653018216SPaolo Bonzini #define _FDT(exp) \ 29753018216SPaolo Bonzini do { \ 29853018216SPaolo Bonzini int ret = (exp); \ 29953018216SPaolo Bonzini if (ret < 0) { \ 30053018216SPaolo Bonzini fprintf(stderr, "qemu: error creating device tree: %s: %s\n", \ 30153018216SPaolo Bonzini #exp, fdt_strerror(ret)); \ 30253018216SPaolo Bonzini exit(1); \ 30353018216SPaolo Bonzini } \ 30453018216SPaolo Bonzini } while (0) 30553018216SPaolo Bonzini 306a1d59c0fSAlexey Kardashevskiy static void add_str(GString *s, const gchar *s1) 307a1d59c0fSAlexey Kardashevskiy { 308a1d59c0fSAlexey Kardashevskiy g_string_append_len(s, s1, strlen(s1) + 1); 309a1d59c0fSAlexey Kardashevskiy } 31053018216SPaolo Bonzini 3113bbf37f2SAndreas Färber static void *spapr_create_fdt_skel(hwaddr initrd_base, 31253018216SPaolo Bonzini hwaddr initrd_size, 31353018216SPaolo Bonzini hwaddr kernel_size, 31416457e7fSBenjamin Herrenschmidt bool little_endian, 31553018216SPaolo Bonzini const char *kernel_cmdline, 31653018216SPaolo Bonzini uint32_t epow_irq) 31753018216SPaolo Bonzini { 31853018216SPaolo Bonzini void *fdt; 31953018216SPaolo Bonzini uint32_t start_prop = cpu_to_be32(initrd_base); 32053018216SPaolo Bonzini uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); 321a1d59c0fSAlexey Kardashevskiy GString *hypertas = g_string_sized_new(256); 322a1d59c0fSAlexey Kardashevskiy GString *qemu_hypertas = g_string_sized_new(256); 32353018216SPaolo Bonzini uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; 3249e734e3dSBharata B Rao uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)}; 32553018216SPaolo Bonzini unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; 326ef951443SNikunj A Dadhania char *buf; 32753018216SPaolo Bonzini 328a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-pft"); 329a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-term"); 330a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-dabr"); 331a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-interrupt"); 332a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-tce"); 333a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-vio"); 334a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-splpar"); 335a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-bulk"); 336a1d59c0fSAlexey Kardashevskiy add_str(hypertas, "hcall-set-mode"); 337a1d59c0fSAlexey Kardashevskiy add_str(qemu_hypertas, "hcall-memop1"); 338a1d59c0fSAlexey Kardashevskiy 33953018216SPaolo Bonzini fdt = g_malloc0(FDT_MAX_SIZE); 34053018216SPaolo Bonzini _FDT((fdt_create(fdt, FDT_MAX_SIZE))); 34153018216SPaolo Bonzini 34253018216SPaolo Bonzini if (kernel_size) { 34353018216SPaolo Bonzini _FDT((fdt_add_reservemap_entry(fdt, KERNEL_LOAD_ADDR, kernel_size))); 34453018216SPaolo Bonzini } 34553018216SPaolo Bonzini if (initrd_size) { 34653018216SPaolo Bonzini _FDT((fdt_add_reservemap_entry(fdt, initrd_base, initrd_size))); 34753018216SPaolo Bonzini } 34853018216SPaolo Bonzini _FDT((fdt_finish_reservemap(fdt))); 34953018216SPaolo Bonzini 35053018216SPaolo Bonzini /* Root node */ 35153018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, ""))); 35253018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "chrp"))); 35353018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)"))); 354fa388916SAnthony Liguori _FDT((fdt_property_string(fdt, "compatible", "qemu,pseries"))); 35553018216SPaolo Bonzini 356ef951443SNikunj A Dadhania /* 357ef951443SNikunj A Dadhania * Add info to guest to indentify which host is it being run on 358ef951443SNikunj A Dadhania * and what is the uuid of the guest 359ef951443SNikunj A Dadhania */ 360ef951443SNikunj A Dadhania if (kvmppc_get_host_model(&buf)) { 361ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "host-model", buf))); 362ef951443SNikunj A Dadhania g_free(buf); 363ef951443SNikunj A Dadhania } 364ef951443SNikunj A Dadhania if (kvmppc_get_host_serial(&buf)) { 365ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "host-serial", buf))); 366ef951443SNikunj A Dadhania g_free(buf); 367ef951443SNikunj A Dadhania } 368ef951443SNikunj A Dadhania 369ef951443SNikunj A Dadhania buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1], 370ef951443SNikunj A Dadhania qemu_uuid[2], qemu_uuid[3], qemu_uuid[4], 371ef951443SNikunj A Dadhania qemu_uuid[5], qemu_uuid[6], qemu_uuid[7], 372ef951443SNikunj A Dadhania qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], 373ef951443SNikunj A Dadhania qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], 374ef951443SNikunj A Dadhania qemu_uuid[14], qemu_uuid[15]); 375ef951443SNikunj A Dadhania 376ef951443SNikunj A Dadhania _FDT((fdt_property_string(fdt, "vm,uuid", buf))); 377ef951443SNikunj A Dadhania g_free(buf); 378ef951443SNikunj A Dadhania 3792c1aaa81SSam Bobroff if (qemu_get_vm_name()) { 3802c1aaa81SSam Bobroff _FDT((fdt_property_string(fdt, "ibm,partition-name", 3812c1aaa81SSam Bobroff qemu_get_vm_name()))); 3822c1aaa81SSam Bobroff } 3832c1aaa81SSam Bobroff 38453018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x2))); 38553018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x2))); 38653018216SPaolo Bonzini 38753018216SPaolo Bonzini /* /chosen */ 38853018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "chosen"))); 38953018216SPaolo Bonzini 39053018216SPaolo Bonzini /* Set Form1_affinity */ 39153018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,architecture-vec-5", vec5, sizeof(vec5)))); 39253018216SPaolo Bonzini 39353018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "bootargs", kernel_cmdline))); 39453018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-start", 39553018216SPaolo Bonzini &start_prop, sizeof(start_prop)))); 39653018216SPaolo Bonzini _FDT((fdt_property(fdt, "linux,initrd-end", 39753018216SPaolo Bonzini &end_prop, sizeof(end_prop)))); 39853018216SPaolo Bonzini if (kernel_size) { 39953018216SPaolo Bonzini uint64_t kprop[2] = { cpu_to_be64(KERNEL_LOAD_ADDR), 40053018216SPaolo Bonzini cpu_to_be64(kernel_size) }; 40153018216SPaolo Bonzini 40253018216SPaolo Bonzini _FDT((fdt_property(fdt, "qemu,boot-kernel", &kprop, sizeof(kprop)))); 40316457e7fSBenjamin Herrenschmidt if (little_endian) { 40416457e7fSBenjamin Herrenschmidt _FDT((fdt_property(fdt, "qemu,boot-kernel-le", NULL, 0))); 40516457e7fSBenjamin Herrenschmidt } 40653018216SPaolo Bonzini } 407cc84c0f3SAvik Sil if (boot_menu) { 408cc84c0f3SAvik Sil _FDT((fdt_property_cell(fdt, "qemu,boot-menu", boot_menu))); 409cc84c0f3SAvik Sil } 41053018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-width", graphic_width))); 41153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-height", graphic_height))); 41253018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "qemu,graphic-depth", graphic_depth))); 41353018216SPaolo Bonzini 41453018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 41553018216SPaolo Bonzini 41653018216SPaolo Bonzini /* RTAS */ 41753018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "rtas"))); 41853018216SPaolo Bonzini 419da95324eSAlexey Kardashevskiy if (!kvm_enabled() || kvmppc_spapr_use_multitce()) { 420da95324eSAlexey Kardashevskiy add_str(hypertas, "hcall-multi-tce"); 421da95324eSAlexey Kardashevskiy } 422a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "ibm,hypertas-functions", hypertas->str, 423a1d59c0fSAlexey Kardashevskiy hypertas->len))); 424a1d59c0fSAlexey Kardashevskiy g_string_free(hypertas, TRUE); 425a1d59c0fSAlexey Kardashevskiy _FDT((fdt_property(fdt, "qemu,hypertas-functions", qemu_hypertas->str, 426a1d59c0fSAlexey Kardashevskiy qemu_hypertas->len))); 427a1d59c0fSAlexey Kardashevskiy g_string_free(qemu_hypertas, TRUE); 42853018216SPaolo Bonzini 42953018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,associativity-reference-points", 43053018216SPaolo Bonzini refpoints, sizeof(refpoints)))); 43153018216SPaolo Bonzini 43253018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX))); 43379853e18STyrel Datwyler _FDT((fdt_property_cell(fdt, "rtas-event-scan-rate", 43479853e18STyrel Datwyler RTAS_EVENT_SCAN_RATE))); 43553018216SPaolo Bonzini 436a95f9922SSam Bobroff if (msi_supported) { 437a95f9922SSam Bobroff _FDT((fdt_property(fdt, "ibm,change-msix-capable", NULL, 0))); 438a95f9922SSam Bobroff } 439a95f9922SSam Bobroff 4402e14072fSNikunj A Dadhania /* 4419d632f5fSzhanghailiang * According to PAPR, rtas ibm,os-term does not guarantee a return 4422e14072fSNikunj A Dadhania * back to the guest cpu. 4432e14072fSNikunj A Dadhania * 4442e14072fSNikunj A Dadhania * While an additional ibm,extended-os-term property indicates that 4452e14072fSNikunj A Dadhania * rtas call return will always occur. Set this property. 4462e14072fSNikunj A Dadhania */ 4472e14072fSNikunj A Dadhania _FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0))); 4482e14072fSNikunj A Dadhania 44953018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 45053018216SPaolo Bonzini 45153018216SPaolo Bonzini /* interrupt controller */ 45253018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "interrupt-controller"))); 45353018216SPaolo Bonzini 45453018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", 45553018216SPaolo Bonzini "PowerPC-External-Interrupt-Presentation"))); 45653018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,ppc-xicp"))); 45753018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 45853018216SPaolo Bonzini _FDT((fdt_property(fdt, "ibm,interrupt-server-ranges", 45953018216SPaolo Bonzini interrupt_server_ranges_prop, 46053018216SPaolo Bonzini sizeof(interrupt_server_ranges_prop)))); 46153018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 2))); 46253018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "linux,phandle", PHANDLE_XICP))); 46353018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "phandle", PHANDLE_XICP))); 46453018216SPaolo Bonzini 46553018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 46653018216SPaolo Bonzini 46753018216SPaolo Bonzini /* vdevice */ 46853018216SPaolo Bonzini _FDT((fdt_begin_node(fdt, "vdevice"))); 46953018216SPaolo Bonzini 47053018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "device_type", "vdevice"))); 47153018216SPaolo Bonzini _FDT((fdt_property_string(fdt, "compatible", "IBM,vdevice"))); 47253018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#address-cells", 0x1))); 47353018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#size-cells", 0x0))); 47453018216SPaolo Bonzini _FDT((fdt_property_cell(fdt, "#interrupt-cells", 0x2))); 47553018216SPaolo Bonzini _FDT((fdt_property(fdt, "interrupt-controller", NULL, 0))); 47653018216SPaolo Bonzini 47753018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); 47853018216SPaolo Bonzini 47953018216SPaolo Bonzini /* event-sources */ 48053018216SPaolo Bonzini spapr_events_fdt_skel(fdt, epow_irq); 48153018216SPaolo Bonzini 482f7d69146SAlexander Graf /* /hypervisor node */ 483f7d69146SAlexander Graf if (kvm_enabled()) { 484f7d69146SAlexander Graf uint8_t hypercall[16]; 485f7d69146SAlexander Graf 486f7d69146SAlexander Graf /* indicate KVM hypercall interface */ 487f7d69146SAlexander Graf _FDT((fdt_begin_node(fdt, "hypervisor"))); 488f7d69146SAlexander Graf _FDT((fdt_property_string(fdt, "compatible", "linux,kvm"))); 489f7d69146SAlexander Graf if (kvmppc_has_cap_fixup_hcalls()) { 490f7d69146SAlexander Graf /* 491f7d69146SAlexander Graf * Older KVM versions with older guest kernels were broken with the 492f7d69146SAlexander Graf * magic page, don't allow the guest to map it. 493f7d69146SAlexander Graf */ 494f7d69146SAlexander Graf kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, 495f7d69146SAlexander Graf sizeof(hypercall)); 496f7d69146SAlexander Graf _FDT((fdt_property(fdt, "hcall-instructions", hypercall, 497f7d69146SAlexander Graf sizeof(hypercall)))); 498f7d69146SAlexander Graf } 499f7d69146SAlexander Graf _FDT((fdt_end_node(fdt))); 500f7d69146SAlexander Graf } 501f7d69146SAlexander Graf 50253018216SPaolo Bonzini _FDT((fdt_end_node(fdt))); /* close root node */ 50353018216SPaolo Bonzini _FDT((fdt_finish(fdt))); 50453018216SPaolo Bonzini 50553018216SPaolo Bonzini return fdt; 50653018216SPaolo Bonzini } 50753018216SPaolo Bonzini 50803d196b7SBharata B Rao static int spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, 50926a8c353SAlexey Kardashevskiy hwaddr size) 51026a8c353SAlexey Kardashevskiy { 51126a8c353SAlexey Kardashevskiy uint32_t associativity[] = { 51226a8c353SAlexey Kardashevskiy cpu_to_be32(0x4), /* length */ 51326a8c353SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(0x0), 514c3b4f589SAlexey Kardashevskiy cpu_to_be32(0x0), cpu_to_be32(nodeid) 51526a8c353SAlexey Kardashevskiy }; 51626a8c353SAlexey Kardashevskiy char mem_name[32]; 51726a8c353SAlexey Kardashevskiy uint64_t mem_reg_property[2]; 51826a8c353SAlexey Kardashevskiy int off; 51926a8c353SAlexey Kardashevskiy 52026a8c353SAlexey Kardashevskiy mem_reg_property[0] = cpu_to_be64(start); 52126a8c353SAlexey Kardashevskiy mem_reg_property[1] = cpu_to_be64(size); 52226a8c353SAlexey Kardashevskiy 52326a8c353SAlexey Kardashevskiy sprintf(mem_name, "memory@" TARGET_FMT_lx, start); 52426a8c353SAlexey Kardashevskiy off = fdt_add_subnode(fdt, 0, mem_name); 52526a8c353SAlexey Kardashevskiy _FDT(off); 52626a8c353SAlexey Kardashevskiy _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); 52726a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "reg", mem_reg_property, 52826a8c353SAlexey Kardashevskiy sizeof(mem_reg_property)))); 52926a8c353SAlexey Kardashevskiy _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, 53026a8c353SAlexey Kardashevskiy sizeof(associativity)))); 53103d196b7SBharata B Rao return off; 53226a8c353SAlexey Kardashevskiy } 53326a8c353SAlexey Kardashevskiy 53428e02042SDavid Gibson static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt) 53553018216SPaolo Bonzini { 536fb164994SDavid Gibson MachineState *machine = MACHINE(spapr); 5377db8a127SAlexey Kardashevskiy hwaddr mem_start, node_size; 5387db8a127SAlexey Kardashevskiy int i, nb_nodes = nb_numa_nodes; 5397db8a127SAlexey Kardashevskiy NodeInfo *nodes = numa_info; 5407db8a127SAlexey Kardashevskiy NodeInfo ramnode; 54153018216SPaolo Bonzini 5427db8a127SAlexey Kardashevskiy /* No NUMA nodes, assume there is just one node with whole RAM */ 5437db8a127SAlexey Kardashevskiy if (!nb_numa_nodes) { 5447db8a127SAlexey Kardashevskiy nb_nodes = 1; 545fb164994SDavid Gibson ramnode.node_mem = machine->ram_size; 5467db8a127SAlexey Kardashevskiy nodes = &ramnode; 5475fe269b1SPaul Mackerras } 54853018216SPaolo Bonzini 5497db8a127SAlexey Kardashevskiy for (i = 0, mem_start = 0; i < nb_nodes; ++i) { 5507db8a127SAlexey Kardashevskiy if (!nodes[i].node_mem) { 5517db8a127SAlexey Kardashevskiy continue; 55253018216SPaolo Bonzini } 553fb164994SDavid Gibson if (mem_start >= machine->ram_size) { 5545fe269b1SPaul Mackerras node_size = 0; 5555fe269b1SPaul Mackerras } else { 5567db8a127SAlexey Kardashevskiy node_size = nodes[i].node_mem; 557fb164994SDavid Gibson if (node_size > machine->ram_size - mem_start) { 558fb164994SDavid Gibson node_size = machine->ram_size - mem_start; 5595fe269b1SPaul Mackerras } 5605fe269b1SPaul Mackerras } 5617db8a127SAlexey Kardashevskiy if (!mem_start) { 5627db8a127SAlexey Kardashevskiy /* ppc_spapr_init() checks for rma_size <= node0_size already */ 563e8f986fcSBharata B Rao spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); 5647db8a127SAlexey Kardashevskiy mem_start += spapr->rma_size; 5657db8a127SAlexey Kardashevskiy node_size -= spapr->rma_size; 5667db8a127SAlexey Kardashevskiy } 5676010818cSAlexey Kardashevskiy for ( ; node_size; ) { 5686010818cSAlexey Kardashevskiy hwaddr sizetmp = pow2floor(node_size); 5696010818cSAlexey Kardashevskiy 5706010818cSAlexey Kardashevskiy /* mem_start != 0 here */ 5716010818cSAlexey Kardashevskiy if (ctzl(mem_start) < ctzl(sizetmp)) { 5726010818cSAlexey Kardashevskiy sizetmp = 1ULL << ctzl(mem_start); 5736010818cSAlexey Kardashevskiy } 5746010818cSAlexey Kardashevskiy 5756010818cSAlexey Kardashevskiy spapr_populate_memory_node(fdt, i, mem_start, sizetmp); 5766010818cSAlexey Kardashevskiy node_size -= sizetmp; 5776010818cSAlexey Kardashevskiy mem_start += sizetmp; 5786010818cSAlexey Kardashevskiy } 57953018216SPaolo Bonzini } 58053018216SPaolo Bonzini 58153018216SPaolo Bonzini return 0; 58253018216SPaolo Bonzini } 58353018216SPaolo Bonzini 5840da6f3feSBharata B Rao static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, 5850da6f3feSBharata B Rao sPAPRMachineState *spapr) 5860da6f3feSBharata B Rao { 5870da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 5880da6f3feSBharata B Rao CPUPPCState *env = &cpu->env; 5890da6f3feSBharata B Rao PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); 5900da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 5910da6f3feSBharata B Rao uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 5920da6f3feSBharata B Rao 0xffffffff, 0xffffffff}; 5930da6f3feSBharata B Rao uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ; 5940da6f3feSBharata B Rao uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 1000000000; 5950da6f3feSBharata B Rao uint32_t page_sizes_prop[64]; 5960da6f3feSBharata B Rao size_t page_sizes_prop_size; 59722419c2aSDavid Gibson uint32_t vcpus_per_socket = smp_threads * smp_cores; 5980da6f3feSBharata B Rao uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; 5990da6f3feSBharata B Rao 600*90da0d5aSBenjamin Herrenschmidt /* Note: we keep CI large pages off for now because a 64K capable guest 601*90da0d5aSBenjamin Herrenschmidt * provisioned with large pages might otherwise try to map a qemu 602*90da0d5aSBenjamin Herrenschmidt * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages 603*90da0d5aSBenjamin Herrenschmidt * even if that qemu runs on a 4k host. 604*90da0d5aSBenjamin Herrenschmidt * 605*90da0d5aSBenjamin Herrenschmidt * We can later add this bit back when we are confident this is not 606*90da0d5aSBenjamin Herrenschmidt * an issue (!HV KVM or 64K host) 607*90da0d5aSBenjamin Herrenschmidt */ 608*90da0d5aSBenjamin Herrenschmidt uint8_t pa_features_206[] = { 6, 0, 609*90da0d5aSBenjamin Herrenschmidt 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; 610*90da0d5aSBenjamin Herrenschmidt uint8_t pa_features_207[] = { 24, 0, 611*90da0d5aSBenjamin Herrenschmidt 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, 612*90da0d5aSBenjamin Herrenschmidt 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 613*90da0d5aSBenjamin Herrenschmidt 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 614*90da0d5aSBenjamin Herrenschmidt 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; 615*90da0d5aSBenjamin Herrenschmidt uint8_t *pa_features; 616*90da0d5aSBenjamin Herrenschmidt size_t pa_size; 617*90da0d5aSBenjamin Herrenschmidt 6180da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); 6190da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); 6200da6f3feSBharata B Rao 6210da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); 6220da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", 6230da6f3feSBharata B Rao env->dcache_line_size))); 6240da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", 6250da6f3feSBharata B Rao env->dcache_line_size))); 6260da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", 6270da6f3feSBharata B Rao env->icache_line_size))); 6280da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", 6290da6f3feSBharata B Rao env->icache_line_size))); 6300da6f3feSBharata B Rao 6310da6f3feSBharata B Rao if (pcc->l1_dcache_size) { 6320da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", 6330da6f3feSBharata B Rao pcc->l1_dcache_size))); 6340da6f3feSBharata B Rao } else { 6350da6f3feSBharata B Rao fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n"); 6360da6f3feSBharata B Rao } 6370da6f3feSBharata B Rao if (pcc->l1_icache_size) { 6380da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", 6390da6f3feSBharata B Rao pcc->l1_icache_size))); 6400da6f3feSBharata B Rao } else { 6410da6f3feSBharata B Rao fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n"); 6420da6f3feSBharata B Rao } 6430da6f3feSBharata B Rao 6440da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); 6450da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); 646fd5da5c4SThomas Huth _FDT((fdt_setprop_cell(fdt, offset, "slb-size", env->slb_nr))); 6470da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); 6480da6f3feSBharata B Rao _FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); 6490da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); 6500da6f3feSBharata B Rao 6510da6f3feSBharata B Rao if (env->spr_cb[SPR_PURR].oea_read) { 6520da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); 6530da6f3feSBharata B Rao } 6540da6f3feSBharata B Rao 6550da6f3feSBharata B Rao if (env->mmu_model & POWERPC_MMU_1TSEG) { 6560da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", 6570da6f3feSBharata B Rao segs, sizeof(segs)))); 6580da6f3feSBharata B Rao } 6590da6f3feSBharata B Rao 6600da6f3feSBharata B Rao /* Advertise VMX/VSX (vector extensions) if available 6610da6f3feSBharata B Rao * 0 / no property == no vector extensions 6620da6f3feSBharata B Rao * 1 == VMX / Altivec available 6630da6f3feSBharata B Rao * 2 == VSX available */ 6640da6f3feSBharata B Rao if (env->insns_flags & PPC_ALTIVEC) { 6650da6f3feSBharata B Rao uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; 6660da6f3feSBharata B Rao 6670da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); 6680da6f3feSBharata B Rao } 6690da6f3feSBharata B Rao 6700da6f3feSBharata B Rao /* Advertise DFP (Decimal Floating Point) if available 6710da6f3feSBharata B Rao * 0 / no property == no DFP 6720da6f3feSBharata B Rao * 1 == DFP available */ 6730da6f3feSBharata B Rao if (env->insns_flags2 & PPC2_DFP) { 6740da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,dfp", 1))); 6750da6f3feSBharata B Rao } 6760da6f3feSBharata B Rao 6770da6f3feSBharata B Rao page_sizes_prop_size = create_page_sizes_prop(env, page_sizes_prop, 6780da6f3feSBharata B Rao sizeof(page_sizes_prop)); 6790da6f3feSBharata B Rao if (page_sizes_prop_size) { 6800da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,segment-page-sizes", 6810da6f3feSBharata B Rao page_sizes_prop, page_sizes_prop_size))); 6820da6f3feSBharata B Rao } 6830da6f3feSBharata B Rao 684*90da0d5aSBenjamin Herrenschmidt /* Do the ibm,pa-features property, adjust it for ci-large-pages */ 685*90da0d5aSBenjamin Herrenschmidt if (env->mmu_model == POWERPC_MMU_2_06) { 686*90da0d5aSBenjamin Herrenschmidt pa_features = pa_features_206; 687*90da0d5aSBenjamin Herrenschmidt pa_size = sizeof(pa_features_206); 688*90da0d5aSBenjamin Herrenschmidt } else /* env->mmu_model == POWERPC_MMU_2_07 */ { 689*90da0d5aSBenjamin Herrenschmidt pa_features = pa_features_207; 690*90da0d5aSBenjamin Herrenschmidt pa_size = sizeof(pa_features_207); 691*90da0d5aSBenjamin Herrenschmidt } 692*90da0d5aSBenjamin Herrenschmidt if (env->ci_large_pages) { 693*90da0d5aSBenjamin Herrenschmidt pa_features[3] |= 0x20; 694*90da0d5aSBenjamin Herrenschmidt } 695*90da0d5aSBenjamin Herrenschmidt _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); 696*90da0d5aSBenjamin Herrenschmidt 6970da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", 69822419c2aSDavid Gibson cs->cpu_index / vcpus_per_socket))); 6990da6f3feSBharata B Rao 7000da6f3feSBharata B Rao _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", 7010da6f3feSBharata B Rao pft_size_prop, sizeof(pft_size_prop)))); 7020da6f3feSBharata B Rao 7030da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); 7040da6f3feSBharata B Rao 7050da6f3feSBharata B Rao _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, 7060da6f3feSBharata B Rao ppc_get_compat_smt_threads(cpu))); 7070da6f3feSBharata B Rao } 7080da6f3feSBharata B Rao 7090da6f3feSBharata B Rao static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) 7100da6f3feSBharata B Rao { 7110da6f3feSBharata B Rao CPUState *cs; 7120da6f3feSBharata B Rao int cpus_offset; 7130da6f3feSBharata B Rao char *nodename; 7140da6f3feSBharata B Rao int smt = kvmppc_smt_threads(); 7150da6f3feSBharata B Rao 7160da6f3feSBharata B Rao cpus_offset = fdt_add_subnode(fdt, 0, "cpus"); 7170da6f3feSBharata B Rao _FDT(cpus_offset); 7180da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#address-cells", 0x1))); 7190da6f3feSBharata B Rao _FDT((fdt_setprop_cell(fdt, cpus_offset, "#size-cells", 0x0))); 7200da6f3feSBharata B Rao 7210da6f3feSBharata B Rao /* 7220da6f3feSBharata B Rao * We walk the CPUs in reverse order to ensure that CPU DT nodes 7230da6f3feSBharata B Rao * created by fdt_add_subnode() end up in the right order in FDT 7240da6f3feSBharata B Rao * for the guest kernel the enumerate the CPUs correctly. 7250da6f3feSBharata B Rao */ 7260da6f3feSBharata B Rao CPU_FOREACH_REVERSE(cs) { 7270da6f3feSBharata B Rao PowerPCCPU *cpu = POWERPC_CPU(cs); 7280da6f3feSBharata B Rao int index = ppc_get_vcpu_dt_id(cpu); 7290da6f3feSBharata B Rao DeviceClass *dc = DEVICE_GET_CLASS(cs); 7300da6f3feSBharata B Rao int offset; 7310da6f3feSBharata B Rao 7320da6f3feSBharata B Rao if ((index % smt) != 0) { 7330da6f3feSBharata B Rao continue; 7340da6f3feSBharata B Rao } 7350da6f3feSBharata B Rao 7360da6f3feSBharata B Rao nodename = g_strdup_printf("%s@%x", dc->fw_name, index); 7370da6f3feSBharata B Rao offset = fdt_add_subnode(fdt, cpus_offset, nodename); 7380da6f3feSBharata B Rao g_free(nodename); 7390da6f3feSBharata B Rao _FDT(offset); 7400da6f3feSBharata B Rao spapr_populate_cpu_dt(cs, fdt, offset, spapr); 7410da6f3feSBharata B Rao } 7420da6f3feSBharata B Rao 7430da6f3feSBharata B Rao } 7440da6f3feSBharata B Rao 74503d196b7SBharata B Rao /* 74603d196b7SBharata B Rao * Adds ibm,dynamic-reconfiguration-memory node. 74703d196b7SBharata B Rao * Refer to docs/specs/ppc-spapr-hotplug.txt for the documentation 74803d196b7SBharata B Rao * of this device tree node. 74903d196b7SBharata B Rao */ 75003d196b7SBharata B Rao static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) 75103d196b7SBharata B Rao { 75203d196b7SBharata B Rao MachineState *machine = MACHINE(spapr); 75303d196b7SBharata B Rao int ret, i, offset; 75403d196b7SBharata B Rao uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 75503d196b7SBharata B Rao uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; 756e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 75703d196b7SBharata B Rao uint32_t *int_buf, *cur_index, buf_len; 7586663864eSBharata B Rao int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1; 75903d196b7SBharata B Rao 760ef001f06SThomas Huth /* 761ef001f06SThomas Huth * Allocate enough buffer size to fit in ibm,dynamic-memory 762ef001f06SThomas Huth * or ibm,associativity-lookup-arrays 763ef001f06SThomas Huth */ 764ef001f06SThomas Huth buf_len = MAX(nr_lmbs * SPAPR_DR_LMB_LIST_ENTRY_SIZE + 1, nr_nodes * 4 + 2) 765ef001f06SThomas Huth * sizeof(uint32_t); 76603d196b7SBharata B Rao cur_index = int_buf = g_malloc0(buf_len); 76703d196b7SBharata B Rao 76803d196b7SBharata B Rao offset = fdt_add_subnode(fdt, 0, "ibm,dynamic-reconfiguration-memory"); 76903d196b7SBharata B Rao 77003d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, 77103d196b7SBharata B Rao sizeof(prop_lmb_size)); 77203d196b7SBharata B Rao if (ret < 0) { 77303d196b7SBharata B Rao goto out; 77403d196b7SBharata B Rao } 77503d196b7SBharata B Rao 77603d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", 0xff); 77703d196b7SBharata B Rao if (ret < 0) { 77803d196b7SBharata B Rao goto out; 77903d196b7SBharata B Rao } 78003d196b7SBharata B Rao 78103d196b7SBharata B Rao ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-time", 0x0); 78203d196b7SBharata B Rao if (ret < 0) { 78303d196b7SBharata B Rao goto out; 78403d196b7SBharata B Rao } 78503d196b7SBharata B Rao 78603d196b7SBharata B Rao /* ibm,dynamic-memory */ 78703d196b7SBharata B Rao int_buf[0] = cpu_to_be32(nr_lmbs); 78803d196b7SBharata B Rao cur_index++; 78903d196b7SBharata B Rao for (i = 0; i < nr_lmbs; i++) { 79003d196b7SBharata B Rao sPAPRDRConnector *drc; 79103d196b7SBharata B Rao sPAPRDRConnectorClass *drck; 792e8f986fcSBharata B Rao uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;; 79303d196b7SBharata B Rao uint32_t *dynamic_memory = cur_index; 79403d196b7SBharata B Rao 79503d196b7SBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 79603d196b7SBharata B Rao addr/lmb_size); 79703d196b7SBharata B Rao g_assert(drc); 79803d196b7SBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 79903d196b7SBharata B Rao 80003d196b7SBharata B Rao dynamic_memory[0] = cpu_to_be32(addr >> 32); 80103d196b7SBharata B Rao dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); 80203d196b7SBharata B Rao dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); 80303d196b7SBharata B Rao dynamic_memory[3] = cpu_to_be32(0); /* reserved */ 80403d196b7SBharata B Rao dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); 80503d196b7SBharata B Rao if (addr < machine->ram_size || 80603d196b7SBharata B Rao memory_region_present(get_system_memory(), addr)) { 80703d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED); 80803d196b7SBharata B Rao } else { 80903d196b7SBharata B Rao dynamic_memory[5] = cpu_to_be32(0); 81003d196b7SBharata B Rao } 81103d196b7SBharata B Rao 81203d196b7SBharata B Rao cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE; 81303d196b7SBharata B Rao } 81403d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,dynamic-memory", int_buf, buf_len); 81503d196b7SBharata B Rao if (ret < 0) { 81603d196b7SBharata B Rao goto out; 81703d196b7SBharata B Rao } 81803d196b7SBharata B Rao 81903d196b7SBharata B Rao /* ibm,associativity-lookup-arrays */ 82003d196b7SBharata B Rao cur_index = int_buf; 8216663864eSBharata B Rao int_buf[0] = cpu_to_be32(nr_nodes); 82203d196b7SBharata B Rao int_buf[1] = cpu_to_be32(4); /* Number of entries per associativity list */ 82303d196b7SBharata B Rao cur_index += 2; 8246663864eSBharata B Rao for (i = 0; i < nr_nodes; i++) { 82503d196b7SBharata B Rao uint32_t associativity[] = { 82603d196b7SBharata B Rao cpu_to_be32(0x0), 82703d196b7SBharata B Rao cpu_to_be32(0x0), 82803d196b7SBharata B Rao cpu_to_be32(0x0), 82903d196b7SBharata B Rao cpu_to_be32(i) 83003d196b7SBharata B Rao }; 83103d196b7SBharata B Rao memcpy(cur_index, associativity, sizeof(associativity)); 83203d196b7SBharata B Rao cur_index += 4; 83303d196b7SBharata B Rao } 83403d196b7SBharata B Rao ret = fdt_setprop(fdt, offset, "ibm,associativity-lookup-arrays", int_buf, 83503d196b7SBharata B Rao (cur_index - int_buf) * sizeof(uint32_t)); 83603d196b7SBharata B Rao out: 83703d196b7SBharata B Rao g_free(int_buf); 83803d196b7SBharata B Rao return ret; 83903d196b7SBharata B Rao } 84003d196b7SBharata B Rao 84103d196b7SBharata B Rao int spapr_h_cas_compose_response(sPAPRMachineState *spapr, 84203d196b7SBharata B Rao target_ulong addr, target_ulong size, 84303d196b7SBharata B Rao bool cpu_update, bool memory_update) 84403d196b7SBharata B Rao { 84503d196b7SBharata B Rao void *fdt, *fdt_skel; 84603d196b7SBharata B Rao sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; 84703d196b7SBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 84803d196b7SBharata B Rao 84903d196b7SBharata B Rao size -= sizeof(hdr); 85003d196b7SBharata B Rao 85103d196b7SBharata B Rao /* Create sceleton */ 85203d196b7SBharata B Rao fdt_skel = g_malloc0(size); 85303d196b7SBharata B Rao _FDT((fdt_create(fdt_skel, size))); 85403d196b7SBharata B Rao _FDT((fdt_begin_node(fdt_skel, ""))); 85503d196b7SBharata B Rao _FDT((fdt_end_node(fdt_skel))); 85603d196b7SBharata B Rao _FDT((fdt_finish(fdt_skel))); 85703d196b7SBharata B Rao fdt = g_malloc0(size); 85803d196b7SBharata B Rao _FDT((fdt_open_into(fdt_skel, fdt, size))); 85903d196b7SBharata B Rao g_free(fdt_skel); 86003d196b7SBharata B Rao 86103d196b7SBharata B Rao /* Fixup cpu nodes */ 86203d196b7SBharata B Rao if (cpu_update) { 86303d196b7SBharata B Rao _FDT((spapr_fixup_cpu_dt(fdt, spapr))); 86403d196b7SBharata B Rao } 86503d196b7SBharata B Rao 86603d196b7SBharata B Rao /* Generate memory nodes or ibm,dynamic-reconfiguration-memory node */ 86703d196b7SBharata B Rao if (memory_update && smc->dr_lmb_enabled) { 86803d196b7SBharata B Rao _FDT((spapr_populate_drconf_memory(spapr, fdt))); 86903d196b7SBharata B Rao } 87003d196b7SBharata B Rao 87103d196b7SBharata B Rao /* Pack resulting tree */ 87203d196b7SBharata B Rao _FDT((fdt_pack(fdt))); 87303d196b7SBharata B Rao 87403d196b7SBharata B Rao if (fdt_totalsize(fdt) + sizeof(hdr) > size) { 87503d196b7SBharata B Rao trace_spapr_cas_failed(size); 87603d196b7SBharata B Rao return -1; 87703d196b7SBharata B Rao } 87803d196b7SBharata B Rao 87903d196b7SBharata B Rao cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); 88003d196b7SBharata B Rao cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); 88103d196b7SBharata B Rao trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); 88203d196b7SBharata B Rao g_free(fdt); 88303d196b7SBharata B Rao 88403d196b7SBharata B Rao return 0; 88503d196b7SBharata B Rao } 88603d196b7SBharata B Rao 88728e02042SDavid Gibson static void spapr_finalize_fdt(sPAPRMachineState *spapr, 88853018216SPaolo Bonzini hwaddr fdt_addr, 88953018216SPaolo Bonzini hwaddr rtas_addr, 89053018216SPaolo Bonzini hwaddr rtas_size) 89153018216SPaolo Bonzini { 8925b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 893c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 8945b2128d2SAlexander Graf const char *boot_device = machine->boot_order; 89571461b0fSAlexey Kardashevskiy int ret, i; 89671461b0fSAlexey Kardashevskiy size_t cb = 0; 89771461b0fSAlexey Kardashevskiy char *bootlist; 89853018216SPaolo Bonzini void *fdt; 89953018216SPaolo Bonzini sPAPRPHBState *phb; 90053018216SPaolo Bonzini 90153018216SPaolo Bonzini fdt = g_malloc(FDT_MAX_SIZE); 90253018216SPaolo Bonzini 90353018216SPaolo Bonzini /* open out the base tree into a temp buffer for the final tweaks */ 90453018216SPaolo Bonzini _FDT((fdt_open_into(spapr->fdt_skel, fdt, FDT_MAX_SIZE))); 90553018216SPaolo Bonzini 906e8f986fcSBharata B Rao ret = spapr_populate_memory(spapr, fdt); 907e8f986fcSBharata B Rao if (ret < 0) { 908e8f986fcSBharata B Rao fprintf(stderr, "couldn't setup memory nodes in fdt\n"); 909e8f986fcSBharata B Rao exit(1); 91053018216SPaolo Bonzini } 91153018216SPaolo Bonzini 91253018216SPaolo Bonzini ret = spapr_populate_vdevice(spapr->vio_bus, fdt); 91353018216SPaolo Bonzini if (ret < 0) { 91453018216SPaolo Bonzini fprintf(stderr, "couldn't setup vio devices in fdt\n"); 91553018216SPaolo Bonzini exit(1); 91653018216SPaolo Bonzini } 91753018216SPaolo Bonzini 9184d9392beSThomas Huth if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL)) { 9194d9392beSThomas Huth ret = spapr_rng_populate_dt(fdt); 9204d9392beSThomas Huth if (ret < 0) { 9214d9392beSThomas Huth fprintf(stderr, "could not set up rng device in the fdt\n"); 9224d9392beSThomas Huth exit(1); 9234d9392beSThomas Huth } 9244d9392beSThomas Huth } 9254d9392beSThomas Huth 92653018216SPaolo Bonzini QLIST_FOREACH(phb, &spapr->phbs, list) { 92753018216SPaolo Bonzini ret = spapr_populate_pci_dt(phb, PHANDLE_XICP, fdt); 92853018216SPaolo Bonzini } 92953018216SPaolo Bonzini 93053018216SPaolo Bonzini if (ret < 0) { 93153018216SPaolo Bonzini fprintf(stderr, "couldn't setup PCI devices in fdt\n"); 93253018216SPaolo Bonzini exit(1); 93353018216SPaolo Bonzini } 93453018216SPaolo Bonzini 93553018216SPaolo Bonzini /* RTAS */ 93653018216SPaolo Bonzini ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); 93753018216SPaolo Bonzini if (ret < 0) { 93853018216SPaolo Bonzini fprintf(stderr, "Couldn't set up RTAS device tree properties\n"); 93953018216SPaolo Bonzini } 94053018216SPaolo Bonzini 9410da6f3feSBharata B Rao /* cpus */ 9420da6f3feSBharata B Rao spapr_populate_cpus_dt_node(fdt, spapr); 94353018216SPaolo Bonzini 94471461b0fSAlexey Kardashevskiy bootlist = get_boot_devices_list(&cb, true); 94571461b0fSAlexey Kardashevskiy if (cb && bootlist) { 94671461b0fSAlexey Kardashevskiy int offset = fdt_path_offset(fdt, "/chosen"); 94771461b0fSAlexey Kardashevskiy if (offset < 0) { 94871461b0fSAlexey Kardashevskiy exit(1); 94971461b0fSAlexey Kardashevskiy } 95071461b0fSAlexey Kardashevskiy for (i = 0; i < cb; i++) { 95171461b0fSAlexey Kardashevskiy if (bootlist[i] == '\n') { 95271461b0fSAlexey Kardashevskiy bootlist[i] = ' '; 95371461b0fSAlexey Kardashevskiy } 95471461b0fSAlexey Kardashevskiy 95571461b0fSAlexey Kardashevskiy } 95671461b0fSAlexey Kardashevskiy ret = fdt_setprop_string(fdt, offset, "qemu,boot-list", bootlist); 95771461b0fSAlexey Kardashevskiy } 95871461b0fSAlexey Kardashevskiy 9595b2128d2SAlexander Graf if (boot_device && strlen(boot_device)) { 9605b2128d2SAlexander Graf int offset = fdt_path_offset(fdt, "/chosen"); 9615b2128d2SAlexander Graf 9625b2128d2SAlexander Graf if (offset < 0) { 9635b2128d2SAlexander Graf exit(1); 9645b2128d2SAlexander Graf } 9655b2128d2SAlexander Graf fdt_setprop_string(fdt, offset, "qemu,boot-device", boot_device); 9665b2128d2SAlexander Graf } 9675b2128d2SAlexander Graf 96853018216SPaolo Bonzini if (!spapr->has_graphics) { 96953018216SPaolo Bonzini spapr_populate_chosen_stdout(fdt, spapr->vio_bus); 97053018216SPaolo Bonzini } 97153018216SPaolo Bonzini 972c20d332aSBharata B Rao if (smc->dr_lmb_enabled) { 973c20d332aSBharata B Rao _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB)); 974c20d332aSBharata B Rao } 975c20d332aSBharata B Rao 97653018216SPaolo Bonzini _FDT((fdt_pack(fdt))); 97753018216SPaolo Bonzini 97853018216SPaolo Bonzini if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { 979730fce59SThomas Huth error_report("FDT too big ! 0x%x bytes (max is 0x%x)", 98053018216SPaolo Bonzini fdt_totalsize(fdt), FDT_MAX_SIZE); 98153018216SPaolo Bonzini exit(1); 98253018216SPaolo Bonzini } 98353018216SPaolo Bonzini 984ad440b4aSAndrew Jones qemu_fdt_dumpdtb(fdt, fdt_totalsize(fdt)); 98553018216SPaolo Bonzini cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt)); 98653018216SPaolo Bonzini 987a21a7a70SGonglei g_free(bootlist); 98853018216SPaolo Bonzini g_free(fdt); 98953018216SPaolo Bonzini } 99053018216SPaolo Bonzini 99153018216SPaolo Bonzini static uint64_t translate_kernel_address(void *opaque, uint64_t addr) 99253018216SPaolo Bonzini { 99353018216SPaolo Bonzini return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR; 99453018216SPaolo Bonzini } 99553018216SPaolo Bonzini 99653018216SPaolo Bonzini static void emulate_spapr_hypercall(PowerPCCPU *cpu) 99753018216SPaolo Bonzini { 99853018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 99953018216SPaolo Bonzini 100053018216SPaolo Bonzini if (msr_pr) { 100153018216SPaolo Bonzini hcall_dprintf("Hypercall made with MSR[PR]=1\n"); 100253018216SPaolo Bonzini env->gpr[3] = H_PRIVILEGE; 100353018216SPaolo Bonzini } else { 100453018216SPaolo Bonzini env->gpr[3] = spapr_hypercall(cpu, env->gpr[3], &env->gpr[4]); 100553018216SPaolo Bonzini } 100653018216SPaolo Bonzini } 100753018216SPaolo Bonzini 1008e6b8fd24SSamuel Mendoza-Jonas #define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2)) 1009e6b8fd24SSamuel Mendoza-Jonas #define HPTE_VALID(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_VALID) 1010e6b8fd24SSamuel Mendoza-Jonas #define HPTE_DIRTY(_hpte) (tswap64(*((uint64_t *)(_hpte))) & HPTE64_V_HPTE_DIRTY) 1011e6b8fd24SSamuel Mendoza-Jonas #define CLEAN_HPTE(_hpte) ((*(uint64_t *)(_hpte)) &= tswap64(~HPTE64_V_HPTE_DIRTY)) 1012e6b8fd24SSamuel Mendoza-Jonas #define DIRTY_HPTE(_hpte) ((*(uint64_t *)(_hpte)) |= tswap64(HPTE64_V_HPTE_DIRTY)) 1013e6b8fd24SSamuel Mendoza-Jonas 1014b817772aSBharata B Rao static void spapr_alloc_htab(sPAPRMachineState *spapr) 101553018216SPaolo Bonzini { 101653018216SPaolo Bonzini long shift; 1017e6b8fd24SSamuel Mendoza-Jonas int index; 101853018216SPaolo Bonzini 101953018216SPaolo Bonzini /* allocate hash page table. For now we always make this 16mb, 102053018216SPaolo Bonzini * later we should probably make it scale to the size of guest 102153018216SPaolo Bonzini * RAM */ 102253018216SPaolo Bonzini 102353018216SPaolo Bonzini shift = kvmppc_reset_htab(spapr->htab_shift); 102453018216SPaolo Bonzini 102553018216SPaolo Bonzini if (shift > 0) { 102653018216SPaolo Bonzini /* Kernel handles htab, we don't need to allocate one */ 10277735fedaSBharata B Rao if (shift != spapr->htab_shift) { 10287735fedaSBharata B Rao error_setg(&error_abort, "Failed to allocate HTAB of requested size, try with smaller maxmem"); 10297735fedaSBharata B Rao } 10307735fedaSBharata B Rao 103153018216SPaolo Bonzini spapr->htab_shift = shift; 10327c43bca0SAneesh Kumar K.V kvmppc_kern_htab = true; 1033b817772aSBharata B Rao } else { 1034b817772aSBharata B Rao /* Allocate htab */ 1035b817772aSBharata B Rao spapr->htab = qemu_memalign(HTAB_SIZE(spapr), HTAB_SIZE(spapr)); 103601a57972SSamuel Mendoza-Jonas 1037b817772aSBharata B Rao /* And clear it */ 1038b817772aSBharata B Rao memset(spapr->htab, 0, HTAB_SIZE(spapr)); 1039b817772aSBharata B Rao 1040b817772aSBharata B Rao for (index = 0; index < HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; index++) { 1041b817772aSBharata B Rao DIRTY_HPTE(HPTE(spapr->htab, index)); 1042b817772aSBharata B Rao } 1043b817772aSBharata B Rao } 1044b817772aSBharata B Rao } 1045b817772aSBharata B Rao 1046b817772aSBharata B Rao /* 1047b817772aSBharata B Rao * Clear HTAB entries during reset. 1048b817772aSBharata B Rao * 1049b817772aSBharata B Rao * If host kernel has allocated HTAB, KVM_PPC_ALLOCATE_HTAB ioctl is 1050b817772aSBharata B Rao * used to clear HTAB. Otherwise QEMU-allocated HTAB is cleared manually. 1051b817772aSBharata B Rao */ 1052b817772aSBharata B Rao static void spapr_reset_htab(sPAPRMachineState *spapr) 1053b817772aSBharata B Rao { 1054b817772aSBharata B Rao long shift; 1055b817772aSBharata B Rao int index; 1056b817772aSBharata B Rao 1057b817772aSBharata B Rao shift = kvmppc_reset_htab(spapr->htab_shift); 1058b817772aSBharata B Rao if (shift > 0) { 10597735fedaSBharata B Rao if (shift != spapr->htab_shift) { 10607735fedaSBharata B Rao error_setg(&error_abort, "Requested HTAB allocation failed during reset"); 10617735fedaSBharata B Rao } 10627735fedaSBharata B Rao 106301a57972SSamuel Mendoza-Jonas /* Tell readers to update their file descriptor */ 106401a57972SSamuel Mendoza-Jonas if (spapr->htab_fd >= 0) { 106501a57972SSamuel Mendoza-Jonas spapr->htab_fd_stale = true; 106601a57972SSamuel Mendoza-Jonas } 106753018216SPaolo Bonzini } else { 106853018216SPaolo Bonzini memset(spapr->htab, 0, HTAB_SIZE(spapr)); 1069e6b8fd24SSamuel Mendoza-Jonas 1070e6b8fd24SSamuel Mendoza-Jonas for (index = 0; index < HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; index++) { 1071e6b8fd24SSamuel Mendoza-Jonas DIRTY_HPTE(HPTE(spapr->htab, index)); 1072e6b8fd24SSamuel Mendoza-Jonas } 107353018216SPaolo Bonzini } 107453018216SPaolo Bonzini 107553018216SPaolo Bonzini /* Update the RMA size if necessary */ 107653018216SPaolo Bonzini if (spapr->vrma_adjust) { 1077b082d65aSAlexey Kardashevskiy spapr->rma_size = kvmppc_rma_size(spapr_node0_size(), 1078b082d65aSAlexey Kardashevskiy spapr->htab_shift); 107953018216SPaolo Bonzini } 108053018216SPaolo Bonzini } 108153018216SPaolo Bonzini 10829e3f9733SAlexander Graf static int find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque) 10839e3f9733SAlexander Graf { 10849e3f9733SAlexander Graf bool matched = false; 10859e3f9733SAlexander Graf 10869e3f9733SAlexander Graf if (object_dynamic_cast(OBJECT(sbdev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { 10879e3f9733SAlexander Graf matched = true; 10889e3f9733SAlexander Graf } 10899e3f9733SAlexander Graf 10909e3f9733SAlexander Graf if (!matched) { 10919e3f9733SAlexander Graf error_report("Device %s is not supported by this machine yet.", 10929e3f9733SAlexander Graf qdev_fw_name(DEVICE(sbdev))); 10939e3f9733SAlexander Graf exit(1); 10949e3f9733SAlexander Graf } 10959e3f9733SAlexander Graf 10969e3f9733SAlexander Graf return 0; 10979e3f9733SAlexander Graf } 10989e3f9733SAlexander Graf 109901a57972SSamuel Mendoza-Jonas /* 110001a57972SSamuel Mendoza-Jonas * A guest reset will cause spapr->htab_fd to become stale if being used. 110101a57972SSamuel Mendoza-Jonas * Reopen the file descriptor to make sure the whole HTAB is properly read. 110201a57972SSamuel Mendoza-Jonas */ 110328e02042SDavid Gibson static int spapr_check_htab_fd(sPAPRMachineState *spapr) 110401a57972SSamuel Mendoza-Jonas { 110501a57972SSamuel Mendoza-Jonas int rc = 0; 110601a57972SSamuel Mendoza-Jonas 110701a57972SSamuel Mendoza-Jonas if (spapr->htab_fd_stale) { 110801a57972SSamuel Mendoza-Jonas close(spapr->htab_fd); 110901a57972SSamuel Mendoza-Jonas spapr->htab_fd = kvmppc_get_htab_fd(false); 111001a57972SSamuel Mendoza-Jonas if (spapr->htab_fd < 0) { 111101a57972SSamuel Mendoza-Jonas error_report("Unable to open fd for reading hash table from KVM: " 111201a57972SSamuel Mendoza-Jonas "%s", strerror(errno)); 111301a57972SSamuel Mendoza-Jonas rc = -1; 111401a57972SSamuel Mendoza-Jonas } 111501a57972SSamuel Mendoza-Jonas spapr->htab_fd_stale = false; 111601a57972SSamuel Mendoza-Jonas } 111701a57972SSamuel Mendoza-Jonas 111801a57972SSamuel Mendoza-Jonas return rc; 111901a57972SSamuel Mendoza-Jonas } 112001a57972SSamuel Mendoza-Jonas 112153018216SPaolo Bonzini static void ppc_spapr_reset(void) 112253018216SPaolo Bonzini { 112328e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 1124182735efSAndreas Färber PowerPCCPU *first_ppc_cpu; 1125b7d1f77aSBenjamin Herrenschmidt uint32_t rtas_limit; 1126259186a7SAndreas Färber 11279e3f9733SAlexander Graf /* Check for unknown sysbus devices */ 11289e3f9733SAlexander Graf foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); 11299e3f9733SAlexander Graf 113053018216SPaolo Bonzini /* Reset the hash table & recalc the RMA */ 113153018216SPaolo Bonzini spapr_reset_htab(spapr); 113253018216SPaolo Bonzini 113353018216SPaolo Bonzini qemu_devices_reset(); 113453018216SPaolo Bonzini 1135b7d1f77aSBenjamin Herrenschmidt /* 1136b7d1f77aSBenjamin Herrenschmidt * We place the device tree and RTAS just below either the top of the RMA, 1137b7d1f77aSBenjamin Herrenschmidt * or just below 2GB, whichever is lowere, so that it can be 1138b7d1f77aSBenjamin Herrenschmidt * processed with 32-bit real mode code if necessary 1139b7d1f77aSBenjamin Herrenschmidt */ 1140b7d1f77aSBenjamin Herrenschmidt rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); 1141b7d1f77aSBenjamin Herrenschmidt spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE; 1142b7d1f77aSBenjamin Herrenschmidt spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE; 1143b7d1f77aSBenjamin Herrenschmidt 114453018216SPaolo Bonzini /* Load the fdt */ 114553018216SPaolo Bonzini spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr, 114653018216SPaolo Bonzini spapr->rtas_size); 114753018216SPaolo Bonzini 1148b7d1f77aSBenjamin Herrenschmidt /* Copy RTAS over */ 1149b7d1f77aSBenjamin Herrenschmidt cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob, 1150b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size); 1151b7d1f77aSBenjamin Herrenschmidt 115253018216SPaolo Bonzini /* Set up the entry state */ 1153182735efSAndreas Färber first_ppc_cpu = POWERPC_CPU(first_cpu); 1154182735efSAndreas Färber first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; 1155182735efSAndreas Färber first_ppc_cpu->env.gpr[5] = 0; 1156182735efSAndreas Färber first_cpu->halted = 0; 11571b718907SDavid Gibson first_ppc_cpu->env.nip = SPAPR_ENTRY_POINT; 115853018216SPaolo Bonzini 115953018216SPaolo Bonzini } 116053018216SPaolo Bonzini 116153018216SPaolo Bonzini static void spapr_cpu_reset(void *opaque) 116253018216SPaolo Bonzini { 116328e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); 116453018216SPaolo Bonzini PowerPCCPU *cpu = opaque; 1165259186a7SAndreas Färber CPUState *cs = CPU(cpu); 116653018216SPaolo Bonzini CPUPPCState *env = &cpu->env; 116753018216SPaolo Bonzini 1168259186a7SAndreas Färber cpu_reset(cs); 116953018216SPaolo Bonzini 117053018216SPaolo Bonzini /* All CPUs start halted. CPU0 is unhalted from the machine level 117153018216SPaolo Bonzini * reset code and the rest are explicitly started up by the guest 117253018216SPaolo Bonzini * using an RTAS call */ 1173259186a7SAndreas Färber cs->halted = 1; 117453018216SPaolo Bonzini 117553018216SPaolo Bonzini env->spr[SPR_HIOR] = 0; 117653018216SPaolo Bonzini 11774be21d56SDavid Gibson env->external_htab = (uint8_t *)spapr->htab; 11785736245cSAneesh Kumar K.V if (kvm_enabled() && !env->external_htab) { 11795736245cSAneesh Kumar K.V /* 11805736245cSAneesh Kumar K.V * HV KVM, set external_htab to 1 so our ppc_hash64_load_hpte* 11815736245cSAneesh Kumar K.V * functions do the right thing. 11825736245cSAneesh Kumar K.V */ 11835736245cSAneesh Kumar K.V env->external_htab = (void *)1; 11845736245cSAneesh Kumar K.V } 118553018216SPaolo Bonzini env->htab_base = -1; 1186f3c75d42SAneesh Kumar K.V /* 1187f3c75d42SAneesh Kumar K.V * htab_mask is the mask used to normalize hash value to PTEG index. 1188f3c75d42SAneesh Kumar K.V * htab_shift is log2 of hash table size. 1189f3c75d42SAneesh Kumar K.V * We have 8 hpte per group, and each hpte is 16 bytes. 1190f3c75d42SAneesh Kumar K.V * ie have 128 bytes per hpte entry. 1191f3c75d42SAneesh Kumar K.V */ 119228e02042SDavid Gibson env->htab_mask = (1ULL << (spapr->htab_shift - 7)) - 1; 1193ec4936e1SStefan Weil env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab | 119453018216SPaolo Bonzini (spapr->htab_shift - 18); 119553018216SPaolo Bonzini } 119653018216SPaolo Bonzini 119728e02042SDavid Gibson static void spapr_create_nvram(sPAPRMachineState *spapr) 119853018216SPaolo Bonzini { 11992ff3de68SMarkus Armbruster DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); 12003978b863SPaolo Bonzini DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); 120153018216SPaolo Bonzini 12023978b863SPaolo Bonzini if (dinfo) { 12034be74634SMarkus Armbruster qdev_prop_set_drive_nofail(dev, "drive", blk_by_legacy_dinfo(dinfo)); 120453018216SPaolo Bonzini } 120553018216SPaolo Bonzini 120653018216SPaolo Bonzini qdev_init_nofail(dev); 120753018216SPaolo Bonzini 120853018216SPaolo Bonzini spapr->nvram = (struct sPAPRNVRAM *)dev; 120953018216SPaolo Bonzini } 121053018216SPaolo Bonzini 121128e02042SDavid Gibson static void spapr_rtc_create(sPAPRMachineState *spapr) 121228df36a1SDavid Gibson { 121328df36a1SDavid Gibson DeviceState *dev = qdev_create(NULL, TYPE_SPAPR_RTC); 121428df36a1SDavid Gibson 121528df36a1SDavid Gibson qdev_init_nofail(dev); 121628df36a1SDavid Gibson spapr->rtc = dev; 121774e5ae28SDavid Gibson 121874e5ae28SDavid Gibson object_property_add_alias(qdev_get_machine(), "rtc-time", 121974e5ae28SDavid Gibson OBJECT(spapr->rtc), "date", NULL); 122028df36a1SDavid Gibson } 122128df36a1SDavid Gibson 122253018216SPaolo Bonzini /* Returns whether we want to use VGA or not */ 122353018216SPaolo Bonzini static int spapr_vga_init(PCIBus *pci_bus) 122453018216SPaolo Bonzini { 122553018216SPaolo Bonzini switch (vga_interface_type) { 122653018216SPaolo Bonzini case VGA_NONE: 12277effdaa3SMark Wu return false; 12287effdaa3SMark Wu case VGA_DEVICE: 12297effdaa3SMark Wu return true; 123053018216SPaolo Bonzini case VGA_STD: 1231b798c190SBenjamin Herrenschmidt case VGA_VIRTIO: 123253018216SPaolo Bonzini return pci_vga_init(pci_bus) != NULL; 123353018216SPaolo Bonzini default: 123453018216SPaolo Bonzini fprintf(stderr, "This vga model is not supported," 123553018216SPaolo Bonzini "currently it only supports -vga std\n"); 123653018216SPaolo Bonzini exit(0); 123753018216SPaolo Bonzini } 123853018216SPaolo Bonzini } 123953018216SPaolo Bonzini 1240880ae7deSDavid Gibson static int spapr_post_load(void *opaque, int version_id) 1241880ae7deSDavid Gibson { 124228e02042SDavid Gibson sPAPRMachineState *spapr = (sPAPRMachineState *)opaque; 1243880ae7deSDavid Gibson int err = 0; 1244880ae7deSDavid Gibson 1245631b22eaSStefan Weil /* In earlier versions, there was no separate qdev for the PAPR 1246880ae7deSDavid Gibson * RTC, so the RTC offset was stored directly in sPAPREnvironment. 1247880ae7deSDavid Gibson * So when migrating from those versions, poke the incoming offset 1248880ae7deSDavid Gibson * value into the RTC device */ 1249880ae7deSDavid Gibson if (version_id < 3) { 1250880ae7deSDavid Gibson err = spapr_rtc_import_offset(spapr->rtc, spapr->rtc_offset); 1251880ae7deSDavid Gibson } 1252880ae7deSDavid Gibson 1253880ae7deSDavid Gibson return err; 1254880ae7deSDavid Gibson } 1255880ae7deSDavid Gibson 1256880ae7deSDavid Gibson static bool version_before_3(void *opaque, int version_id) 1257880ae7deSDavid Gibson { 1258880ae7deSDavid Gibson return version_id < 3; 1259880ae7deSDavid Gibson } 1260880ae7deSDavid Gibson 12614be21d56SDavid Gibson static const VMStateDescription vmstate_spapr = { 12624be21d56SDavid Gibson .name = "spapr", 1263880ae7deSDavid Gibson .version_id = 3, 12644be21d56SDavid Gibson .minimum_version_id = 1, 1265880ae7deSDavid Gibson .post_load = spapr_post_load, 12664be21d56SDavid Gibson .fields = (VMStateField[]) { 1267880ae7deSDavid Gibson /* used to be @next_irq */ 1268880ae7deSDavid Gibson VMSTATE_UNUSED_BUFFER(version_before_3, 0, 4), 12694be21d56SDavid Gibson 12704be21d56SDavid Gibson /* RTC offset */ 127128e02042SDavid Gibson VMSTATE_UINT64_TEST(rtc_offset, sPAPRMachineState, version_before_3), 1272880ae7deSDavid Gibson 127328e02042SDavid Gibson VMSTATE_PPC_TIMEBASE_V(tb, sPAPRMachineState, 2), 12744be21d56SDavid Gibson VMSTATE_END_OF_LIST() 12754be21d56SDavid Gibson }, 12764be21d56SDavid Gibson }; 12774be21d56SDavid Gibson 12784be21d56SDavid Gibson static int htab_save_setup(QEMUFile *f, void *opaque) 12794be21d56SDavid Gibson { 128028e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 12814be21d56SDavid Gibson 12824be21d56SDavid Gibson /* "Iteration" header */ 12834be21d56SDavid Gibson qemu_put_be32(f, spapr->htab_shift); 12844be21d56SDavid Gibson 1285e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 1286e68cb8b4SAlexey Kardashevskiy spapr->htab_save_index = 0; 1287e68cb8b4SAlexey Kardashevskiy spapr->htab_first_pass = true; 1288e68cb8b4SAlexey Kardashevskiy } else { 1289e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1290e68cb8b4SAlexey Kardashevskiy 1291e68cb8b4SAlexey Kardashevskiy spapr->htab_fd = kvmppc_get_htab_fd(false); 129201a57972SSamuel Mendoza-Jonas spapr->htab_fd_stale = false; 1293e68cb8b4SAlexey Kardashevskiy if (spapr->htab_fd < 0) { 1294e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Unable to open fd for reading hash table from KVM: %s\n", 1295e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1296e68cb8b4SAlexey Kardashevskiy return -1; 1297e68cb8b4SAlexey Kardashevskiy } 12984be21d56SDavid Gibson } 12994be21d56SDavid Gibson 1300e68cb8b4SAlexey Kardashevskiy 1301e68cb8b4SAlexey Kardashevskiy return 0; 1302e68cb8b4SAlexey Kardashevskiy } 13034be21d56SDavid Gibson 130428e02042SDavid Gibson static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, 13054be21d56SDavid Gibson int64_t max_ns) 13064be21d56SDavid Gibson { 13074be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 13084be21d56SDavid Gibson int index = spapr->htab_save_index; 1309bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13104be21d56SDavid Gibson 13114be21d56SDavid Gibson assert(spapr->htab_first_pass); 13124be21d56SDavid Gibson 13134be21d56SDavid Gibson do { 13144be21d56SDavid Gibson int chunkstart; 13154be21d56SDavid Gibson 13164be21d56SDavid Gibson /* Consume invalid HPTEs */ 13174be21d56SDavid Gibson while ((index < htabslots) 13184be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13194be21d56SDavid Gibson index++; 13204be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13214be21d56SDavid Gibson } 13224be21d56SDavid Gibson 13234be21d56SDavid Gibson /* Consume valid HPTEs */ 13244be21d56SDavid Gibson chunkstart = index; 1325338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13264be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13274be21d56SDavid Gibson index++; 13284be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13294be21d56SDavid Gibson } 13304be21d56SDavid Gibson 13314be21d56SDavid Gibson if (index > chunkstart) { 13324be21d56SDavid Gibson int n_valid = index - chunkstart; 13334be21d56SDavid Gibson 13344be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 13354be21d56SDavid Gibson qemu_put_be16(f, n_valid); 13364be21d56SDavid Gibson qemu_put_be16(f, 0); 13374be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 13384be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 13394be21d56SDavid Gibson 1340bc72ad67SAlex Bligh if ((qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 13414be21d56SDavid Gibson break; 13424be21d56SDavid Gibson } 13434be21d56SDavid Gibson } 13444be21d56SDavid Gibson } while ((index < htabslots) && !qemu_file_rate_limit(f)); 13454be21d56SDavid Gibson 13464be21d56SDavid Gibson if (index >= htabslots) { 13474be21d56SDavid Gibson assert(index == htabslots); 13484be21d56SDavid Gibson index = 0; 13494be21d56SDavid Gibson spapr->htab_first_pass = false; 13504be21d56SDavid Gibson } 13514be21d56SDavid Gibson spapr->htab_save_index = index; 13524be21d56SDavid Gibson } 13534be21d56SDavid Gibson 135428e02042SDavid Gibson static int htab_save_later_pass(QEMUFile *f, sPAPRMachineState *spapr, 13554be21d56SDavid Gibson int64_t max_ns) 13564be21d56SDavid Gibson { 13574be21d56SDavid Gibson bool final = max_ns < 0; 13584be21d56SDavid Gibson int htabslots = HTAB_SIZE(spapr) / HASH_PTE_SIZE_64; 13594be21d56SDavid Gibson int examined = 0, sent = 0; 13604be21d56SDavid Gibson int index = spapr->htab_save_index; 1361bc72ad67SAlex Bligh int64_t starttime = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); 13624be21d56SDavid Gibson 13634be21d56SDavid Gibson assert(!spapr->htab_first_pass); 13644be21d56SDavid Gibson 13654be21d56SDavid Gibson do { 13664be21d56SDavid Gibson int chunkstart, invalidstart; 13674be21d56SDavid Gibson 13684be21d56SDavid Gibson /* Consume non-dirty HPTEs */ 13694be21d56SDavid Gibson while ((index < htabslots) 13704be21d56SDavid Gibson && !HPTE_DIRTY(HPTE(spapr->htab, index))) { 13714be21d56SDavid Gibson index++; 13724be21d56SDavid Gibson examined++; 13734be21d56SDavid Gibson } 13744be21d56SDavid Gibson 13754be21d56SDavid Gibson chunkstart = index; 13764be21d56SDavid Gibson /* Consume valid dirty HPTEs */ 1377338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - chunkstart < USHRT_MAX) 13784be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13794be21d56SDavid Gibson && HPTE_VALID(HPTE(spapr->htab, index))) { 13804be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13814be21d56SDavid Gibson index++; 13824be21d56SDavid Gibson examined++; 13834be21d56SDavid Gibson } 13844be21d56SDavid Gibson 13854be21d56SDavid Gibson invalidstart = index; 13864be21d56SDavid Gibson /* Consume invalid dirty HPTEs */ 1387338c25b6SSamuel Mendoza-Jonas while ((index < htabslots) && (index - invalidstart < USHRT_MAX) 13884be21d56SDavid Gibson && HPTE_DIRTY(HPTE(spapr->htab, index)) 13894be21d56SDavid Gibson && !HPTE_VALID(HPTE(spapr->htab, index))) { 13904be21d56SDavid Gibson CLEAN_HPTE(HPTE(spapr->htab, index)); 13914be21d56SDavid Gibson index++; 13924be21d56SDavid Gibson examined++; 13934be21d56SDavid Gibson } 13944be21d56SDavid Gibson 13954be21d56SDavid Gibson if (index > chunkstart) { 13964be21d56SDavid Gibson int n_valid = invalidstart - chunkstart; 13974be21d56SDavid Gibson int n_invalid = index - invalidstart; 13984be21d56SDavid Gibson 13994be21d56SDavid Gibson qemu_put_be32(f, chunkstart); 14004be21d56SDavid Gibson qemu_put_be16(f, n_valid); 14014be21d56SDavid Gibson qemu_put_be16(f, n_invalid); 14024be21d56SDavid Gibson qemu_put_buffer(f, HPTE(spapr->htab, chunkstart), 14034be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 14044be21d56SDavid Gibson sent += index - chunkstart; 14054be21d56SDavid Gibson 1406bc72ad67SAlex Bligh if (!final && (qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - starttime) > max_ns) { 14074be21d56SDavid Gibson break; 14084be21d56SDavid Gibson } 14094be21d56SDavid Gibson } 14104be21d56SDavid Gibson 14114be21d56SDavid Gibson if (examined >= htabslots) { 14124be21d56SDavid Gibson break; 14134be21d56SDavid Gibson } 14144be21d56SDavid Gibson 14154be21d56SDavid Gibson if (index >= htabslots) { 14164be21d56SDavid Gibson assert(index == htabslots); 14174be21d56SDavid Gibson index = 0; 14184be21d56SDavid Gibson } 14194be21d56SDavid Gibson } while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final)); 14204be21d56SDavid Gibson 14214be21d56SDavid Gibson if (index >= htabslots) { 14224be21d56SDavid Gibson assert(index == htabslots); 14234be21d56SDavid Gibson index = 0; 14244be21d56SDavid Gibson } 14254be21d56SDavid Gibson 14264be21d56SDavid Gibson spapr->htab_save_index = index; 14274be21d56SDavid Gibson 1428e68cb8b4SAlexey Kardashevskiy return (examined >= htabslots) && (sent == 0) ? 1 : 0; 14294be21d56SDavid Gibson } 14304be21d56SDavid Gibson 1431e68cb8b4SAlexey Kardashevskiy #define MAX_ITERATION_NS 5000000 /* 5 ms */ 1432e68cb8b4SAlexey Kardashevskiy #define MAX_KVM_BUF_SIZE 2048 1433e68cb8b4SAlexey Kardashevskiy 14344be21d56SDavid Gibson static int htab_save_iterate(QEMUFile *f, void *opaque) 14354be21d56SDavid Gibson { 143628e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 1437e68cb8b4SAlexey Kardashevskiy int rc = 0; 14384be21d56SDavid Gibson 14394be21d56SDavid Gibson /* Iteration header */ 14404be21d56SDavid Gibson qemu_put_be32(f, 0); 14414be21d56SDavid Gibson 1442e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1443e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1444e68cb8b4SAlexey Kardashevskiy 144501a57972SSamuel Mendoza-Jonas rc = spapr_check_htab_fd(spapr); 144601a57972SSamuel Mendoza-Jonas if (rc < 0) { 144701a57972SSamuel Mendoza-Jonas return rc; 144801a57972SSamuel Mendoza-Jonas } 144901a57972SSamuel Mendoza-Jonas 1450e68cb8b4SAlexey Kardashevskiy rc = kvmppc_save_htab(f, spapr->htab_fd, 1451e68cb8b4SAlexey Kardashevskiy MAX_KVM_BUF_SIZE, MAX_ITERATION_NS); 1452e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1453e68cb8b4SAlexey Kardashevskiy return rc; 1454e68cb8b4SAlexey Kardashevskiy } 1455e68cb8b4SAlexey Kardashevskiy } else if (spapr->htab_first_pass) { 14564be21d56SDavid Gibson htab_save_first_pass(f, spapr, MAX_ITERATION_NS); 14574be21d56SDavid Gibson } else { 1458e68cb8b4SAlexey Kardashevskiy rc = htab_save_later_pass(f, spapr, MAX_ITERATION_NS); 14594be21d56SDavid Gibson } 14604be21d56SDavid Gibson 14614be21d56SDavid Gibson /* End marker */ 14624be21d56SDavid Gibson qemu_put_be32(f, 0); 14634be21d56SDavid Gibson qemu_put_be16(f, 0); 14644be21d56SDavid Gibson qemu_put_be16(f, 0); 14654be21d56SDavid Gibson 1466e68cb8b4SAlexey Kardashevskiy return rc; 14674be21d56SDavid Gibson } 14684be21d56SDavid Gibson 14694be21d56SDavid Gibson static int htab_save_complete(QEMUFile *f, void *opaque) 14704be21d56SDavid Gibson { 147128e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 14724be21d56SDavid Gibson 14734be21d56SDavid Gibson /* Iteration header */ 14744be21d56SDavid Gibson qemu_put_be32(f, 0); 14754be21d56SDavid Gibson 1476e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1477e68cb8b4SAlexey Kardashevskiy int rc; 1478e68cb8b4SAlexey Kardashevskiy 1479e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1480e68cb8b4SAlexey Kardashevskiy 148101a57972SSamuel Mendoza-Jonas rc = spapr_check_htab_fd(spapr); 148201a57972SSamuel Mendoza-Jonas if (rc < 0) { 148301a57972SSamuel Mendoza-Jonas return rc; 148401a57972SSamuel Mendoza-Jonas } 148501a57972SSamuel Mendoza-Jonas 1486e68cb8b4SAlexey Kardashevskiy rc = kvmppc_save_htab(f, spapr->htab_fd, MAX_KVM_BUF_SIZE, -1); 1487e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1488e68cb8b4SAlexey Kardashevskiy return rc; 1489e68cb8b4SAlexey Kardashevskiy } 1490e68cb8b4SAlexey Kardashevskiy close(spapr->htab_fd); 1491e68cb8b4SAlexey Kardashevskiy spapr->htab_fd = -1; 1492e68cb8b4SAlexey Kardashevskiy } else { 14934be21d56SDavid Gibson htab_save_later_pass(f, spapr, -1); 1494e68cb8b4SAlexey Kardashevskiy } 14954be21d56SDavid Gibson 14964be21d56SDavid Gibson /* End marker */ 14974be21d56SDavid Gibson qemu_put_be32(f, 0); 14984be21d56SDavid Gibson qemu_put_be16(f, 0); 14994be21d56SDavid Gibson qemu_put_be16(f, 0); 15004be21d56SDavid Gibson 15014be21d56SDavid Gibson return 0; 15024be21d56SDavid Gibson } 15034be21d56SDavid Gibson 15044be21d56SDavid Gibson static int htab_load(QEMUFile *f, void *opaque, int version_id) 15054be21d56SDavid Gibson { 150628e02042SDavid Gibson sPAPRMachineState *spapr = opaque; 15074be21d56SDavid Gibson uint32_t section_hdr; 1508e68cb8b4SAlexey Kardashevskiy int fd = -1; 15094be21d56SDavid Gibson 15104be21d56SDavid Gibson if (version_id < 1 || version_id > 1) { 15114be21d56SDavid Gibson fprintf(stderr, "htab_load() bad version\n"); 15124be21d56SDavid Gibson return -EINVAL; 15134be21d56SDavid Gibson } 15144be21d56SDavid Gibson 15154be21d56SDavid Gibson section_hdr = qemu_get_be32(f); 15164be21d56SDavid Gibson 15174be21d56SDavid Gibson if (section_hdr) { 15184be21d56SDavid Gibson /* First section, just the hash shift */ 15194be21d56SDavid Gibson if (spapr->htab_shift != section_hdr) { 1520613e7a76SBharata B Rao error_report("htab_shift mismatch: source %d target %d", 1521613e7a76SBharata B Rao section_hdr, spapr->htab_shift); 15224be21d56SDavid Gibson return -EINVAL; 15234be21d56SDavid Gibson } 15244be21d56SDavid Gibson return 0; 15254be21d56SDavid Gibson } 15264be21d56SDavid Gibson 1527e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1528e68cb8b4SAlexey Kardashevskiy assert(kvm_enabled()); 1529e68cb8b4SAlexey Kardashevskiy 1530e68cb8b4SAlexey Kardashevskiy fd = kvmppc_get_htab_fd(true); 1531e68cb8b4SAlexey Kardashevskiy if (fd < 0) { 1532e68cb8b4SAlexey Kardashevskiy fprintf(stderr, "Unable to open fd to restore KVM hash table: %s\n", 1533e68cb8b4SAlexey Kardashevskiy strerror(errno)); 1534e68cb8b4SAlexey Kardashevskiy } 1535e68cb8b4SAlexey Kardashevskiy } 1536e68cb8b4SAlexey Kardashevskiy 15374be21d56SDavid Gibson while (true) { 15384be21d56SDavid Gibson uint32_t index; 15394be21d56SDavid Gibson uint16_t n_valid, n_invalid; 15404be21d56SDavid Gibson 15414be21d56SDavid Gibson index = qemu_get_be32(f); 15424be21d56SDavid Gibson n_valid = qemu_get_be16(f); 15434be21d56SDavid Gibson n_invalid = qemu_get_be16(f); 15444be21d56SDavid Gibson 15454be21d56SDavid Gibson if ((index == 0) && (n_valid == 0) && (n_invalid == 0)) { 15464be21d56SDavid Gibson /* End of Stream */ 15474be21d56SDavid Gibson break; 15484be21d56SDavid Gibson } 15494be21d56SDavid Gibson 1550e68cb8b4SAlexey Kardashevskiy if ((index + n_valid + n_invalid) > 15514be21d56SDavid Gibson (HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) { 15524be21d56SDavid Gibson /* Bad index in stream */ 15534be21d56SDavid Gibson fprintf(stderr, "htab_load() bad index %d (%hd+%hd entries) " 1554e68cb8b4SAlexey Kardashevskiy "in htab stream (htab_shift=%d)\n", index, n_valid, n_invalid, 1555e68cb8b4SAlexey Kardashevskiy spapr->htab_shift); 15564be21d56SDavid Gibson return -EINVAL; 15574be21d56SDavid Gibson } 15584be21d56SDavid Gibson 1559e68cb8b4SAlexey Kardashevskiy if (spapr->htab) { 15604be21d56SDavid Gibson if (n_valid) { 15614be21d56SDavid Gibson qemu_get_buffer(f, HPTE(spapr->htab, index), 15624be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_valid); 15634be21d56SDavid Gibson } 15644be21d56SDavid Gibson if (n_invalid) { 15654be21d56SDavid Gibson memset(HPTE(spapr->htab, index + n_valid), 0, 15664be21d56SDavid Gibson HASH_PTE_SIZE_64 * n_invalid); 15674be21d56SDavid Gibson } 1568e68cb8b4SAlexey Kardashevskiy } else { 1569e68cb8b4SAlexey Kardashevskiy int rc; 1570e68cb8b4SAlexey Kardashevskiy 1571e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1572e68cb8b4SAlexey Kardashevskiy 1573e68cb8b4SAlexey Kardashevskiy rc = kvmppc_load_htab_chunk(f, fd, index, n_valid, n_invalid); 1574e68cb8b4SAlexey Kardashevskiy if (rc < 0) { 1575e68cb8b4SAlexey Kardashevskiy return rc; 1576e68cb8b4SAlexey Kardashevskiy } 1577e68cb8b4SAlexey Kardashevskiy } 1578e68cb8b4SAlexey Kardashevskiy } 1579e68cb8b4SAlexey Kardashevskiy 1580e68cb8b4SAlexey Kardashevskiy if (!spapr->htab) { 1581e68cb8b4SAlexey Kardashevskiy assert(fd >= 0); 1582e68cb8b4SAlexey Kardashevskiy close(fd); 15834be21d56SDavid Gibson } 15844be21d56SDavid Gibson 15854be21d56SDavid Gibson return 0; 15864be21d56SDavid Gibson } 15874be21d56SDavid Gibson 15884be21d56SDavid Gibson static SaveVMHandlers savevm_htab_handlers = { 15894be21d56SDavid Gibson .save_live_setup = htab_save_setup, 15904be21d56SDavid Gibson .save_live_iterate = htab_save_iterate, 15914be21d56SDavid Gibson .save_live_complete = htab_save_complete, 15924be21d56SDavid Gibson .load_state = htab_load, 15934be21d56SDavid Gibson }; 15944be21d56SDavid Gibson 15955b2128d2SAlexander Graf static void spapr_boot_set(void *opaque, const char *boot_device, 15965b2128d2SAlexander Graf Error **errp) 15975b2128d2SAlexander Graf { 15985b2128d2SAlexander Graf MachineState *machine = MACHINE(qdev_get_machine()); 15995b2128d2SAlexander Graf machine->boot_order = g_strdup(boot_device); 16005b2128d2SAlexander Graf } 16015b2128d2SAlexander Graf 1602bab99ea0SBharata B Rao static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu) 1603bab99ea0SBharata B Rao { 1604bab99ea0SBharata B Rao CPUPPCState *env = &cpu->env; 1605bab99ea0SBharata B Rao 1606bab99ea0SBharata B Rao /* Set time-base frequency to 512 MHz */ 1607bab99ea0SBharata B Rao cpu_ppc_tb_init(env, TIMEBASE_FREQ); 1608bab99ea0SBharata B Rao 1609bab99ea0SBharata B Rao /* PAPR always has exception vectors in RAM not ROM. To ensure this, 1610bab99ea0SBharata B Rao * MSR[IP] should never be set. 1611bab99ea0SBharata B Rao */ 1612bab99ea0SBharata B Rao env->msr_mask &= ~(1 << 6); 1613bab99ea0SBharata B Rao 1614bab99ea0SBharata B Rao /* Tell KVM that we're in PAPR mode */ 1615bab99ea0SBharata B Rao if (kvm_enabled()) { 1616bab99ea0SBharata B Rao kvmppc_set_papr(cpu); 1617bab99ea0SBharata B Rao } 1618bab99ea0SBharata B Rao 1619bab99ea0SBharata B Rao if (cpu->max_compat) { 1620bab99ea0SBharata B Rao if (ppc_set_compat(cpu, cpu->max_compat) < 0) { 1621bab99ea0SBharata B Rao exit(1); 1622bab99ea0SBharata B Rao } 1623bab99ea0SBharata B Rao } 1624bab99ea0SBharata B Rao 1625bab99ea0SBharata B Rao xics_cpu_setup(spapr->icp, cpu); 1626bab99ea0SBharata B Rao 1627bab99ea0SBharata B Rao qemu_register_reset(spapr_cpu_reset, cpu); 1628bab99ea0SBharata B Rao } 1629bab99ea0SBharata B Rao 1630224245bfSDavid Gibson /* 1631224245bfSDavid Gibson * Reset routine for LMB DR devices. 1632224245bfSDavid Gibson * 1633224245bfSDavid Gibson * Unlike PCI DR devices, LMB DR devices explicitly register this reset 1634224245bfSDavid Gibson * routine. Reset for PCI DR devices will be handled by PHB reset routine 1635224245bfSDavid Gibson * when it walks all its children devices. LMB devices reset occurs 1636224245bfSDavid Gibson * as part of spapr_ppc_reset(). 1637224245bfSDavid Gibson */ 1638224245bfSDavid Gibson static void spapr_drc_reset(void *opaque) 1639224245bfSDavid Gibson { 1640224245bfSDavid Gibson sPAPRDRConnector *drc = opaque; 1641224245bfSDavid Gibson DeviceState *d = DEVICE(drc); 1642224245bfSDavid Gibson 1643224245bfSDavid Gibson if (d) { 1644224245bfSDavid Gibson device_reset(d); 1645224245bfSDavid Gibson } 1646224245bfSDavid Gibson } 1647224245bfSDavid Gibson 1648224245bfSDavid Gibson static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) 1649224245bfSDavid Gibson { 1650224245bfSDavid Gibson MachineState *machine = MACHINE(spapr); 1651224245bfSDavid Gibson uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE; 1652e8f986fcSBharata B Rao uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size; 1653224245bfSDavid Gibson int i; 1654224245bfSDavid Gibson 1655224245bfSDavid Gibson for (i = 0; i < nr_lmbs; i++) { 1656224245bfSDavid Gibson sPAPRDRConnector *drc; 1657224245bfSDavid Gibson uint64_t addr; 1658224245bfSDavid Gibson 1659e8f986fcSBharata B Rao addr = i * lmb_size + spapr->hotplug_memory.base; 1660224245bfSDavid Gibson drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, 1661224245bfSDavid Gibson addr/lmb_size); 1662224245bfSDavid Gibson qemu_register_reset(spapr_drc_reset, drc); 1663224245bfSDavid Gibson } 1664224245bfSDavid Gibson } 1665224245bfSDavid Gibson 1666224245bfSDavid Gibson /* 1667224245bfSDavid Gibson * If RAM size, maxmem size and individual node mem sizes aren't aligned 1668224245bfSDavid Gibson * to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest 1669224245bfSDavid Gibson * since we can't support such unaligned sizes with DRCONF_MEMORY. 1670224245bfSDavid Gibson */ 1671224245bfSDavid Gibson static void spapr_validate_node_memory(MachineState *machine) 1672224245bfSDavid Gibson { 1673224245bfSDavid Gibson int i; 1674224245bfSDavid Gibson 1675224245bfSDavid Gibson if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE || 1676224245bfSDavid Gibson machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) { 1677224245bfSDavid Gibson error_report("Can't support memory configuration where RAM size " 1678224245bfSDavid Gibson "0x" RAM_ADDR_FMT " or maxmem size " 1679224245bfSDavid Gibson "0x" RAM_ADDR_FMT " isn't aligned to %llu MB", 1680224245bfSDavid Gibson machine->ram_size, machine->maxram_size, 1681224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 1682224245bfSDavid Gibson exit(EXIT_FAILURE); 1683224245bfSDavid Gibson } 1684224245bfSDavid Gibson 1685224245bfSDavid Gibson for (i = 0; i < nb_numa_nodes; i++) { 1686224245bfSDavid Gibson if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) { 1687224245bfSDavid Gibson error_report("Can't support memory configuration where memory size" 1688224245bfSDavid Gibson " %" PRIx64 " of node %d isn't aligned to %llu MB", 1689224245bfSDavid Gibson numa_info[i].node_mem, i, 1690224245bfSDavid Gibson SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 1691224245bfSDavid Gibson exit(EXIT_FAILURE); 1692224245bfSDavid Gibson } 1693224245bfSDavid Gibson } 1694224245bfSDavid Gibson } 1695224245bfSDavid Gibson 169653018216SPaolo Bonzini /* pSeries LPAR / sPAPR hardware init */ 16973ef96221SMarcel Apfelbaum static void ppc_spapr_init(MachineState *machine) 169853018216SPaolo Bonzini { 169928e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(machine); 1700224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); 17013ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 17023ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 17033ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 170453018216SPaolo Bonzini PowerPCCPU *cpu; 170553018216SPaolo Bonzini PCIHostState *phb; 170653018216SPaolo Bonzini int i; 170753018216SPaolo Bonzini MemoryRegion *sysmem = get_system_memory(); 170853018216SPaolo Bonzini MemoryRegion *ram = g_new(MemoryRegion, 1); 1709658fa66bSAlexey Kardashevskiy MemoryRegion *rma_region; 1710658fa66bSAlexey Kardashevskiy void *rma = NULL; 171153018216SPaolo Bonzini hwaddr rma_alloc_size; 1712b082d65aSAlexey Kardashevskiy hwaddr node0_size = spapr_node0_size(); 171353018216SPaolo Bonzini uint32_t initrd_base = 0; 171453018216SPaolo Bonzini long kernel_size = 0, initrd_size = 0; 1715b7d1f77aSBenjamin Herrenschmidt long load_limit, fw_size; 171616457e7fSBenjamin Herrenschmidt bool kernel_le = false; 171753018216SPaolo Bonzini char *filename; 171853018216SPaolo Bonzini 171953018216SPaolo Bonzini msi_supported = true; 172053018216SPaolo Bonzini 172153018216SPaolo Bonzini QLIST_INIT(&spapr->phbs); 172253018216SPaolo Bonzini 172353018216SPaolo Bonzini cpu_ppc_hypercall = emulate_spapr_hypercall; 172453018216SPaolo Bonzini 172553018216SPaolo Bonzini /* Allocate RMA if necessary */ 1726658fa66bSAlexey Kardashevskiy rma_alloc_size = kvmppc_alloc_rma(&rma); 172753018216SPaolo Bonzini 172853018216SPaolo Bonzini if (rma_alloc_size == -1) { 1729730fce59SThomas Huth error_report("Unable to create RMA"); 173053018216SPaolo Bonzini exit(1); 173153018216SPaolo Bonzini } 173253018216SPaolo Bonzini 1733c4177479SAlexey Kardashevskiy if (rma_alloc_size && (rma_alloc_size < node0_size)) { 173453018216SPaolo Bonzini spapr->rma_size = rma_alloc_size; 173553018216SPaolo Bonzini } else { 1736c4177479SAlexey Kardashevskiy spapr->rma_size = node0_size; 173753018216SPaolo Bonzini 173853018216SPaolo Bonzini /* With KVM, we don't actually know whether KVM supports an 173953018216SPaolo Bonzini * unbounded RMA (PR KVM) or is limited by the hash table size 174053018216SPaolo Bonzini * (HV KVM using VRMA), so we always assume the latter 174153018216SPaolo Bonzini * 174253018216SPaolo Bonzini * In that case, we also limit the initial allocations for RTAS 174353018216SPaolo Bonzini * etc... to 256M since we have no way to know what the VRMA size 174453018216SPaolo Bonzini * is going to be as it depends on the size of the hash table 174553018216SPaolo Bonzini * isn't determined yet. 174653018216SPaolo Bonzini */ 174753018216SPaolo Bonzini if (kvm_enabled()) { 174853018216SPaolo Bonzini spapr->vrma_adjust = 1; 174953018216SPaolo Bonzini spapr->rma_size = MIN(spapr->rma_size, 0x10000000); 175053018216SPaolo Bonzini } 175153018216SPaolo Bonzini } 175253018216SPaolo Bonzini 1753c4177479SAlexey Kardashevskiy if (spapr->rma_size > node0_size) { 1754c4177479SAlexey Kardashevskiy fprintf(stderr, "Error: Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")\n", 1755c4177479SAlexey Kardashevskiy spapr->rma_size); 1756c4177479SAlexey Kardashevskiy exit(1); 1757c4177479SAlexey Kardashevskiy } 1758c4177479SAlexey Kardashevskiy 1759b7d1f77aSBenjamin Herrenschmidt /* Setup a load limit for the ramdisk leaving room for SLOF and FDT */ 1760b7d1f77aSBenjamin Herrenschmidt load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD; 176153018216SPaolo Bonzini 176253018216SPaolo Bonzini /* We aim for a hash table of size 1/128 the size of RAM. The 176353018216SPaolo Bonzini * normal rule of thumb is 1/64 the size of RAM, but that's much 176453018216SPaolo Bonzini * more than needed for the Linux guests we support. */ 176553018216SPaolo Bonzini spapr->htab_shift = 18; /* Minimum architected size */ 176653018216SPaolo Bonzini while (spapr->htab_shift <= 46) { 1767ce881f77SBharata B Rao if ((1ULL << (spapr->htab_shift + 7)) >= machine->maxram_size) { 176853018216SPaolo Bonzini break; 176953018216SPaolo Bonzini } 177053018216SPaolo Bonzini spapr->htab_shift++; 177153018216SPaolo Bonzini } 1772b817772aSBharata B Rao spapr_alloc_htab(spapr); 177353018216SPaolo Bonzini 17747b565160SDavid Gibson /* Set up Interrupt Controller before we create the VCPUs */ 1775446f16a6SMarcel Apfelbaum spapr->icp = xics_system_init(machine, 17769e734e3dSBharata B Rao DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(), 1777f303f117SGreg Kurz smp_threads), 17787b565160SDavid Gibson XICS_IRQS); 17797b565160SDavid Gibson 1780224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1781224245bfSDavid Gibson spapr_validate_node_memory(machine); 1782224245bfSDavid Gibson } 1783224245bfSDavid Gibson 178453018216SPaolo Bonzini /* init CPUs */ 178519fb2c36SBharata B Rao if (machine->cpu_model == NULL) { 178619fb2c36SBharata B Rao machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; 178753018216SPaolo Bonzini } 178853018216SPaolo Bonzini for (i = 0; i < smp_cpus; i++) { 178919fb2c36SBharata B Rao cpu = cpu_ppc_init(machine->cpu_model); 179053018216SPaolo Bonzini if (cpu == NULL) { 179153018216SPaolo Bonzini fprintf(stderr, "Unable to find PowerPC CPU definition\n"); 179253018216SPaolo Bonzini exit(1); 179353018216SPaolo Bonzini } 1794bab99ea0SBharata B Rao spapr_cpu_init(spapr, cpu); 179553018216SPaolo Bonzini } 179653018216SPaolo Bonzini 1797026bfd89SDavid Gibson if (kvm_enabled()) { 1798026bfd89SDavid Gibson /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ 1799026bfd89SDavid Gibson kvmppc_enable_logical_ci_hcalls(); 1800ef9971ddSAlexey Kardashevskiy kvmppc_enable_set_mode_hcall(); 1801026bfd89SDavid Gibson } 1802026bfd89SDavid Gibson 180353018216SPaolo Bonzini /* allocate RAM */ 1804f92f5da1SAlexey Kardashevskiy memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", 1805fb164994SDavid Gibson machine->ram_size); 1806f92f5da1SAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, ram); 180753018216SPaolo Bonzini 1808658fa66bSAlexey Kardashevskiy if (rma_alloc_size && rma) { 1809658fa66bSAlexey Kardashevskiy rma_region = g_new(MemoryRegion, 1); 1810658fa66bSAlexey Kardashevskiy memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma", 1811658fa66bSAlexey Kardashevskiy rma_alloc_size, rma); 1812658fa66bSAlexey Kardashevskiy vmstate_register_ram_global(rma_region); 1813658fa66bSAlexey Kardashevskiy memory_region_add_subregion(sysmem, 0, rma_region); 1814658fa66bSAlexey Kardashevskiy } 1815658fa66bSAlexey Kardashevskiy 18164a1c9cf0SBharata B Rao /* initialize hotplug memory address space */ 18174a1c9cf0SBharata B Rao if (machine->ram_size < machine->maxram_size) { 18184a1c9cf0SBharata B Rao ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; 18194a1c9cf0SBharata B Rao 18204a1c9cf0SBharata B Rao if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) { 182119a35c9eSBharata B Rao error_report("Specified number of memory slots %"PRIu64" exceeds max supported %d\n", 182219a35c9eSBharata B Rao machine->ram_slots, SPAPR_MAX_RAM_SLOTS); 18234a1c9cf0SBharata B Rao exit(EXIT_FAILURE); 18244a1c9cf0SBharata B Rao } 18254a1c9cf0SBharata B Rao 18264a1c9cf0SBharata B Rao spapr->hotplug_memory.base = ROUND_UP(machine->ram_size, 18274a1c9cf0SBharata B Rao SPAPR_HOTPLUG_MEM_ALIGN); 18284a1c9cf0SBharata B Rao memory_region_init(&spapr->hotplug_memory.mr, OBJECT(spapr), 18294a1c9cf0SBharata B Rao "hotplug-memory", hotplug_mem_size); 18304a1c9cf0SBharata B Rao memory_region_add_subregion(sysmem, spapr->hotplug_memory.base, 18314a1c9cf0SBharata B Rao &spapr->hotplug_memory.mr); 18324a1c9cf0SBharata B Rao } 18334a1c9cf0SBharata B Rao 1834224245bfSDavid Gibson if (smc->dr_lmb_enabled) { 1835224245bfSDavid Gibson spapr_create_lmb_dr_connectors(spapr); 1836224245bfSDavid Gibson } 1837224245bfSDavid Gibson 183853018216SPaolo Bonzini filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); 18394c56440dSStefan Weil if (!filename) { 1840730fce59SThomas Huth error_report("Could not find LPAR rtas '%s'", "spapr-rtas.bin"); 18414c56440dSStefan Weil exit(1); 18424c56440dSStefan Weil } 1843b7d1f77aSBenjamin Herrenschmidt spapr->rtas_size = get_image_size(filename); 1844b7d1f77aSBenjamin Herrenschmidt spapr->rtas_blob = g_malloc(spapr->rtas_size); 1845b7d1f77aSBenjamin Herrenschmidt if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) { 1846730fce59SThomas Huth error_report("Could not load LPAR rtas '%s'", filename); 184753018216SPaolo Bonzini exit(1); 184853018216SPaolo Bonzini } 184953018216SPaolo Bonzini if (spapr->rtas_size > RTAS_MAX_SIZE) { 1850730fce59SThomas Huth error_report("RTAS too big ! 0x%zx bytes (max is 0x%x)", 18512f285bddSPeter Maydell (size_t)spapr->rtas_size, RTAS_MAX_SIZE); 185253018216SPaolo Bonzini exit(1); 185353018216SPaolo Bonzini } 185453018216SPaolo Bonzini g_free(filename); 185553018216SPaolo Bonzini 185653018216SPaolo Bonzini /* Set up EPOW events infrastructure */ 185753018216SPaolo Bonzini spapr_events_init(spapr); 185853018216SPaolo Bonzini 185912f42174SDavid Gibson /* Set up the RTC RTAS interfaces */ 186028df36a1SDavid Gibson spapr_rtc_create(spapr); 186112f42174SDavid Gibson 186253018216SPaolo Bonzini /* Set up VIO bus */ 186353018216SPaolo Bonzini spapr->vio_bus = spapr_vio_bus_init(); 186453018216SPaolo Bonzini 186553018216SPaolo Bonzini for (i = 0; i < MAX_SERIAL_PORTS; i++) { 186653018216SPaolo Bonzini if (serial_hds[i]) { 186753018216SPaolo Bonzini spapr_vty_create(spapr->vio_bus, serial_hds[i]); 186853018216SPaolo Bonzini } 186953018216SPaolo Bonzini } 187053018216SPaolo Bonzini 187153018216SPaolo Bonzini /* We always have at least the nvram device on VIO */ 187253018216SPaolo Bonzini spapr_create_nvram(spapr); 187353018216SPaolo Bonzini 187453018216SPaolo Bonzini /* Set up PCI */ 187553018216SPaolo Bonzini spapr_pci_rtas_init(); 187653018216SPaolo Bonzini 187789dfd6e1SDavid Gibson phb = spapr_create_phb(spapr, 0); 187853018216SPaolo Bonzini 187953018216SPaolo Bonzini for (i = 0; i < nb_nics; i++) { 188053018216SPaolo Bonzini NICInfo *nd = &nd_table[i]; 188153018216SPaolo Bonzini 188253018216SPaolo Bonzini if (!nd->model) { 188353018216SPaolo Bonzini nd->model = g_strdup("ibmveth"); 188453018216SPaolo Bonzini } 188553018216SPaolo Bonzini 188653018216SPaolo Bonzini if (strcmp(nd->model, "ibmveth") == 0) { 188753018216SPaolo Bonzini spapr_vlan_create(spapr->vio_bus, nd); 188853018216SPaolo Bonzini } else { 188929b358f9SDavid Gibson pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); 189053018216SPaolo Bonzini } 189153018216SPaolo Bonzini } 189253018216SPaolo Bonzini 189353018216SPaolo Bonzini for (i = 0; i <= drive_get_max_bus(IF_SCSI); i++) { 189453018216SPaolo Bonzini spapr_vscsi_create(spapr->vio_bus); 189553018216SPaolo Bonzini } 189653018216SPaolo Bonzini 189753018216SPaolo Bonzini /* Graphics */ 189853018216SPaolo Bonzini if (spapr_vga_init(phb->bus)) { 189953018216SPaolo Bonzini spapr->has_graphics = true; 1900c6e76503SPaolo Bonzini machine->usb |= defaults_enabled() && !machine->usb_disabled; 190153018216SPaolo Bonzini } 190253018216SPaolo Bonzini 19034ee9ced9SMarcel Apfelbaum if (machine->usb) { 190453018216SPaolo Bonzini pci_create_simple(phb->bus, -1, "pci-ohci"); 1905c86580b8SMarkus Armbruster 190653018216SPaolo Bonzini if (spapr->has_graphics) { 1907c86580b8SMarkus Armbruster USBBus *usb_bus = usb_bus_find(-1); 1908c86580b8SMarkus Armbruster 1909c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-kbd"); 1910c86580b8SMarkus Armbruster usb_create_simple(usb_bus, "usb-mouse"); 191153018216SPaolo Bonzini } 191253018216SPaolo Bonzini } 191353018216SPaolo Bonzini 191453018216SPaolo Bonzini if (spapr->rma_size < (MIN_RMA_SLOF << 20)) { 191553018216SPaolo Bonzini fprintf(stderr, "qemu: pSeries SLOF firmware requires >= " 191653018216SPaolo Bonzini "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF); 191753018216SPaolo Bonzini exit(1); 191853018216SPaolo Bonzini } 191953018216SPaolo Bonzini 192053018216SPaolo Bonzini if (kernel_filename) { 192153018216SPaolo Bonzini uint64_t lowaddr = 0; 192253018216SPaolo Bonzini 192353018216SPaolo Bonzini kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, 19244ecd4d16SPeter Crosthwaite NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0); 19253b66da82SAlexey Kardashevskiy if (kernel_size == ELF_LOAD_WRONG_ENDIAN) { 192616457e7fSBenjamin Herrenschmidt kernel_size = load_elf(kernel_filename, 192716457e7fSBenjamin Herrenschmidt translate_kernel_address, NULL, 19284ecd4d16SPeter Crosthwaite NULL, &lowaddr, NULL, 0, PPC_ELF_MACHINE, 0); 192916457e7fSBenjamin Herrenschmidt kernel_le = kernel_size > 0; 193016457e7fSBenjamin Herrenschmidt } 193116457e7fSBenjamin Herrenschmidt if (kernel_size < 0) { 19323b66da82SAlexey Kardashevskiy fprintf(stderr, "qemu: error loading %s: %s\n", 19333b66da82SAlexey Kardashevskiy kernel_filename, load_elf_strerror(kernel_size)); 193453018216SPaolo Bonzini exit(1); 193553018216SPaolo Bonzini } 193653018216SPaolo Bonzini 193753018216SPaolo Bonzini /* load initrd */ 193853018216SPaolo Bonzini if (initrd_filename) { 193953018216SPaolo Bonzini /* Try to locate the initrd in the gap between the kernel 194053018216SPaolo Bonzini * and the firmware. Add a bit of space just in case 194153018216SPaolo Bonzini */ 194253018216SPaolo Bonzini initrd_base = (KERNEL_LOAD_ADDR + kernel_size + 0x1ffff) & ~0xffff; 194353018216SPaolo Bonzini initrd_size = load_image_targphys(initrd_filename, initrd_base, 194453018216SPaolo Bonzini load_limit - initrd_base); 194553018216SPaolo Bonzini if (initrd_size < 0) { 194653018216SPaolo Bonzini fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", 194753018216SPaolo Bonzini initrd_filename); 194853018216SPaolo Bonzini exit(1); 194953018216SPaolo Bonzini } 195053018216SPaolo Bonzini } else { 195153018216SPaolo Bonzini initrd_base = 0; 195253018216SPaolo Bonzini initrd_size = 0; 195353018216SPaolo Bonzini } 195453018216SPaolo Bonzini } 195553018216SPaolo Bonzini 19568e7ea787SAndreas Färber if (bios_name == NULL) { 19578e7ea787SAndreas Färber bios_name = FW_FILE_NAME; 19588e7ea787SAndreas Färber } 19598e7ea787SAndreas Färber filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); 19604c56440dSStefan Weil if (!filename) { 196168fea5a0SThomas Huth error_report("Could not find LPAR firmware '%s'", bios_name); 19624c56440dSStefan Weil exit(1); 19634c56440dSStefan Weil } 196453018216SPaolo Bonzini fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); 196568fea5a0SThomas Huth if (fw_size <= 0) { 196668fea5a0SThomas Huth error_report("Could not load LPAR firmware '%s'", filename); 196753018216SPaolo Bonzini exit(1); 196853018216SPaolo Bonzini } 196953018216SPaolo Bonzini g_free(filename); 197053018216SPaolo Bonzini 197128e02042SDavid Gibson /* FIXME: Should register things through the MachineState's qdev 197228e02042SDavid Gibson * interface, this is a legacy from the sPAPREnvironment structure 197328e02042SDavid Gibson * which predated MachineState but had a similar function */ 19744be21d56SDavid Gibson vmstate_register(NULL, 0, &vmstate_spapr, spapr); 19754be21d56SDavid Gibson register_savevm_live(NULL, "spapr/htab", -1, 1, 19764be21d56SDavid Gibson &savevm_htab_handlers, spapr); 19774be21d56SDavid Gibson 197853018216SPaolo Bonzini /* Prepare the device tree */ 19793bbf37f2SAndreas Färber spapr->fdt_skel = spapr_create_fdt_skel(initrd_base, initrd_size, 198016457e7fSBenjamin Herrenschmidt kernel_size, kernel_le, 198131fe14d1SNathan Fontenot kernel_cmdline, 198231fe14d1SNathan Fontenot spapr->check_exception_irq); 198353018216SPaolo Bonzini assert(spapr->fdt_skel != NULL); 19845b2128d2SAlexander Graf 198546503c2bSMichael Roth /* used by RTAS */ 198646503c2bSMichael Roth QTAILQ_INIT(&spapr->ccs_list); 198746503c2bSMichael Roth qemu_register_reset(spapr_ccs_reset_hook, spapr); 198846503c2bSMichael Roth 19895b2128d2SAlexander Graf qemu_register_boot_set(spapr_boot_set, spapr); 199053018216SPaolo Bonzini } 199153018216SPaolo Bonzini 1992135a129aSAneesh Kumar K.V static int spapr_kvm_type(const char *vm_type) 1993135a129aSAneesh Kumar K.V { 1994135a129aSAneesh Kumar K.V if (!vm_type) { 1995135a129aSAneesh Kumar K.V return 0; 1996135a129aSAneesh Kumar K.V } 1997135a129aSAneesh Kumar K.V 1998135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "HV")) { 1999135a129aSAneesh Kumar K.V return 1; 2000135a129aSAneesh Kumar K.V } 2001135a129aSAneesh Kumar K.V 2002135a129aSAneesh Kumar K.V if (!strcmp(vm_type, "PR")) { 2003135a129aSAneesh Kumar K.V return 2; 2004135a129aSAneesh Kumar K.V } 2005135a129aSAneesh Kumar K.V 2006135a129aSAneesh Kumar K.V error_report("Unknown kvm-type specified '%s'", vm_type); 2007135a129aSAneesh Kumar K.V exit(1); 2008135a129aSAneesh Kumar K.V } 2009135a129aSAneesh Kumar K.V 201071461b0fSAlexey Kardashevskiy /* 2011627b84f4SGonglei * Implementation of an interface to adjust firmware path 201271461b0fSAlexey Kardashevskiy * for the bootindex property handling. 201371461b0fSAlexey Kardashevskiy */ 201471461b0fSAlexey Kardashevskiy static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, 201571461b0fSAlexey Kardashevskiy DeviceState *dev) 201671461b0fSAlexey Kardashevskiy { 201771461b0fSAlexey Kardashevskiy #define CAST(type, obj, name) \ 201871461b0fSAlexey Kardashevskiy ((type *)object_dynamic_cast(OBJECT(obj), (name))) 201971461b0fSAlexey Kardashevskiy SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); 202071461b0fSAlexey Kardashevskiy sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); 202171461b0fSAlexey Kardashevskiy 202271461b0fSAlexey Kardashevskiy if (d) { 202371461b0fSAlexey Kardashevskiy void *spapr = CAST(void, bus->parent, "spapr-vscsi"); 202471461b0fSAlexey Kardashevskiy VirtIOSCSI *virtio = CAST(VirtIOSCSI, bus->parent, TYPE_VIRTIO_SCSI); 202571461b0fSAlexey Kardashevskiy USBDevice *usb = CAST(USBDevice, bus->parent, TYPE_USB_DEVICE); 202671461b0fSAlexey Kardashevskiy 202771461b0fSAlexey Kardashevskiy if (spapr) { 202871461b0fSAlexey Kardashevskiy /* 202971461b0fSAlexey Kardashevskiy * Replace "channel@0/disk@0,0" with "disk@8000000000000000": 203071461b0fSAlexey Kardashevskiy * We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun 203171461b0fSAlexey Kardashevskiy * in the top 16 bits of the 64-bit LUN 203271461b0fSAlexey Kardashevskiy */ 203371461b0fSAlexey Kardashevskiy unsigned id = 0x8000 | (d->id << 8) | d->lun; 203471461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 203571461b0fSAlexey Kardashevskiy (uint64_t)id << 48); 203671461b0fSAlexey Kardashevskiy } else if (virtio) { 203771461b0fSAlexey Kardashevskiy /* 203871461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (target << 8) | lun 203971461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 204071461b0fSAlexey Kardashevskiy * Note: the quote above is from SLOF and it is wrong, 204171461b0fSAlexey Kardashevskiy * the actual binding is: 204271461b0fSAlexey Kardashevskiy * swap 0100 or 10 << or 20 << ( target lun-id -- srplun ) 204371461b0fSAlexey Kardashevskiy */ 204471461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (d->id << 16) | d->lun; 204571461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 204671461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 204771461b0fSAlexey Kardashevskiy } else if (usb) { 204871461b0fSAlexey Kardashevskiy /* 204971461b0fSAlexey Kardashevskiy * We use SRP luns of the form 01000000 | (usb-port << 16) | lun 205071461b0fSAlexey Kardashevskiy * in the top 32 bits of the 64-bit LUN 205171461b0fSAlexey Kardashevskiy */ 205271461b0fSAlexey Kardashevskiy unsigned usb_port = atoi(usb->port->path); 205371461b0fSAlexey Kardashevskiy unsigned id = 0x1000000 | (usb_port << 16) | d->lun; 205471461b0fSAlexey Kardashevskiy return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), 205571461b0fSAlexey Kardashevskiy (uint64_t)id << 32); 205671461b0fSAlexey Kardashevskiy } 205771461b0fSAlexey Kardashevskiy } 205871461b0fSAlexey Kardashevskiy 205971461b0fSAlexey Kardashevskiy if (phb) { 206071461b0fSAlexey Kardashevskiy /* Replace "pci" with "pci@800000020000000" */ 206171461b0fSAlexey Kardashevskiy return g_strdup_printf("pci@%"PRIX64, phb->buid); 206271461b0fSAlexey Kardashevskiy } 206371461b0fSAlexey Kardashevskiy 206471461b0fSAlexey Kardashevskiy return NULL; 206571461b0fSAlexey Kardashevskiy } 206671461b0fSAlexey Kardashevskiy 206723825581SEduardo Habkost static char *spapr_get_kvm_type(Object *obj, Error **errp) 206823825581SEduardo Habkost { 206928e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 207023825581SEduardo Habkost 207128e02042SDavid Gibson return g_strdup(spapr->kvm_type); 207223825581SEduardo Habkost } 207323825581SEduardo Habkost 207423825581SEduardo Habkost static void spapr_set_kvm_type(Object *obj, const char *value, Error **errp) 207523825581SEduardo Habkost { 207628e02042SDavid Gibson sPAPRMachineState *spapr = SPAPR_MACHINE(obj); 207723825581SEduardo Habkost 207828e02042SDavid Gibson g_free(spapr->kvm_type); 207928e02042SDavid Gibson spapr->kvm_type = g_strdup(value); 208023825581SEduardo Habkost } 208123825581SEduardo Habkost 208223825581SEduardo Habkost static void spapr_machine_initfn(Object *obj) 208323825581SEduardo Habkost { 208423825581SEduardo Habkost object_property_add_str(obj, "kvm-type", 208523825581SEduardo Habkost spapr_get_kvm_type, spapr_set_kvm_type, NULL); 208649d2e648SMarcel Apfelbaum object_property_set_description(obj, "kvm-type", 208749d2e648SMarcel Apfelbaum "Specifies the KVM virtualization mode (HV, PR)", 208849d2e648SMarcel Apfelbaum NULL); 208923825581SEduardo Habkost } 209023825581SEduardo Habkost 209134316482SAlexey Kardashevskiy static void ppc_cpu_do_nmi_on_cpu(void *arg) 209234316482SAlexey Kardashevskiy { 209334316482SAlexey Kardashevskiy CPUState *cs = arg; 209434316482SAlexey Kardashevskiy 209534316482SAlexey Kardashevskiy cpu_synchronize_state(cs); 209634316482SAlexey Kardashevskiy ppc_cpu_do_system_reset(cs); 209734316482SAlexey Kardashevskiy } 209834316482SAlexey Kardashevskiy 209934316482SAlexey Kardashevskiy static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) 210034316482SAlexey Kardashevskiy { 210134316482SAlexey Kardashevskiy CPUState *cs; 210234316482SAlexey Kardashevskiy 210334316482SAlexey Kardashevskiy CPU_FOREACH(cs) { 210434316482SAlexey Kardashevskiy async_run_on_cpu(cs, ppc_cpu_do_nmi_on_cpu, cs); 210534316482SAlexey Kardashevskiy } 210634316482SAlexey Kardashevskiy } 210734316482SAlexey Kardashevskiy 2108c20d332aSBharata B Rao static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size, 2109c20d332aSBharata B Rao uint32_t node, Error **errp) 2110c20d332aSBharata B Rao { 2111c20d332aSBharata B Rao sPAPRDRConnector *drc; 2112c20d332aSBharata B Rao sPAPRDRConnectorClass *drck; 2113c20d332aSBharata B Rao uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; 2114c20d332aSBharata B Rao int i, fdt_offset, fdt_size; 2115c20d332aSBharata B Rao void *fdt; 2116c20d332aSBharata B Rao 2117c20d332aSBharata B Rao /* 2118c20d332aSBharata B Rao * Check for DRC connectors and send hotplug notification to the 2119c20d332aSBharata B Rao * guest only in case of hotplugged memory. This allows cold plugged 2120c20d332aSBharata B Rao * memory to be specified at boot time. 2121c20d332aSBharata B Rao */ 2122c20d332aSBharata B Rao if (!dev->hotplugged) { 2123c20d332aSBharata B Rao return; 2124c20d332aSBharata B Rao } 2125c20d332aSBharata B Rao 2126c20d332aSBharata B Rao for (i = 0; i < nr_lmbs; i++) { 2127c20d332aSBharata B Rao drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, 2128c20d332aSBharata B Rao addr/SPAPR_MEMORY_BLOCK_SIZE); 2129c20d332aSBharata B Rao g_assert(drc); 2130c20d332aSBharata B Rao 2131c20d332aSBharata B Rao fdt = create_device_tree(&fdt_size); 2132c20d332aSBharata B Rao fdt_offset = spapr_populate_memory_node(fdt, node, addr, 2133c20d332aSBharata B Rao SPAPR_MEMORY_BLOCK_SIZE); 2134c20d332aSBharata B Rao 2135c20d332aSBharata B Rao drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); 2136c20d332aSBharata B Rao drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp); 2137c20d332aSBharata B Rao addr += SPAPR_MEMORY_BLOCK_SIZE; 2138c20d332aSBharata B Rao } 21390a417869SBharata B Rao spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); 2140c20d332aSBharata B Rao } 2141c20d332aSBharata B Rao 2142c20d332aSBharata B Rao static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, 2143c20d332aSBharata B Rao uint32_t node, Error **errp) 2144c20d332aSBharata B Rao { 2145c20d332aSBharata B Rao Error *local_err = NULL; 2146c20d332aSBharata B Rao sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); 2147c20d332aSBharata B Rao PCDIMMDevice *dimm = PC_DIMM(dev); 2148c20d332aSBharata B Rao PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); 2149c20d332aSBharata B Rao MemoryRegion *mr = ddc->get_memory_region(dimm); 2150c20d332aSBharata B Rao uint64_t align = memory_region_get_alignment(mr); 2151c20d332aSBharata B Rao uint64_t size = memory_region_size(mr); 2152c20d332aSBharata B Rao uint64_t addr; 2153c20d332aSBharata B Rao 2154c20d332aSBharata B Rao if (size % SPAPR_MEMORY_BLOCK_SIZE) { 2155c20d332aSBharata B Rao error_setg(&local_err, "Hotplugged memory size must be a multiple of " 2156c20d332aSBharata B Rao "%lld MB", SPAPR_MEMORY_BLOCK_SIZE/M_BYTE); 2157c20d332aSBharata B Rao goto out; 2158c20d332aSBharata B Rao } 2159c20d332aSBharata B Rao 2160df0acdedSIgor Mammedov pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, false, &local_err); 2161c20d332aSBharata B Rao if (local_err) { 2162c20d332aSBharata B Rao goto out; 2163c20d332aSBharata B Rao } 2164c20d332aSBharata B Rao 2165c20d332aSBharata B Rao addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); 2166c20d332aSBharata B Rao if (local_err) { 2167c20d332aSBharata B Rao pc_dimm_memory_unplug(dev, &ms->hotplug_memory, mr); 2168c20d332aSBharata B Rao goto out; 2169c20d332aSBharata B Rao } 2170c20d332aSBharata B Rao 2171c20d332aSBharata B Rao spapr_add_lmbs(dev, addr, size, node, &error_abort); 2172c20d332aSBharata B Rao 2173c20d332aSBharata B Rao out: 2174c20d332aSBharata B Rao error_propagate(errp, local_err); 2175c20d332aSBharata B Rao } 2176c20d332aSBharata B Rao 2177c20d332aSBharata B Rao static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, 2178c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2179c20d332aSBharata B Rao { 2180c20d332aSBharata B Rao sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); 2181c20d332aSBharata B Rao 2182c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2183b556854bSBharata B Rao int node; 2184c20d332aSBharata B Rao 2185c20d332aSBharata B Rao if (!smc->dr_lmb_enabled) { 2186c20d332aSBharata B Rao error_setg(errp, "Memory hotplug not supported for this machine"); 2187c20d332aSBharata B Rao return; 2188c20d332aSBharata B Rao } 2189c20d332aSBharata B Rao node = object_property_get_int(OBJECT(dev), PC_DIMM_NODE_PROP, errp); 2190c20d332aSBharata B Rao if (*errp) { 2191c20d332aSBharata B Rao return; 2192c20d332aSBharata B Rao } 2193c20d332aSBharata B Rao 2194b556854bSBharata B Rao /* 2195b556854bSBharata B Rao * Currently PowerPC kernel doesn't allow hot-adding memory to 2196b556854bSBharata B Rao * memory-less node, but instead will silently add the memory 2197b556854bSBharata B Rao * to the first node that has some memory. This causes two 2198b556854bSBharata B Rao * unexpected behaviours for the user. 2199b556854bSBharata B Rao * 2200b556854bSBharata B Rao * - Memory gets hotplugged to a different node than what the user 2201b556854bSBharata B Rao * specified. 2202b556854bSBharata B Rao * - Since pc-dimm subsystem in QEMU still thinks that memory belongs 2203b556854bSBharata B Rao * to memory-less node, a reboot will set things accordingly 2204b556854bSBharata B Rao * and the previously hotplugged memory now ends in the right node. 2205b556854bSBharata B Rao * This appears as if some memory moved from one node to another. 2206b556854bSBharata B Rao * 2207b556854bSBharata B Rao * So until kernel starts supporting memory hotplug to memory-less 2208b556854bSBharata B Rao * nodes, just prevent such attempts upfront in QEMU. 2209b556854bSBharata B Rao */ 2210b556854bSBharata B Rao if (nb_numa_nodes && !numa_info[node].node_mem) { 2211b556854bSBharata B Rao error_setg(errp, "Can't hotplug memory to memory-less node %d", 2212b556854bSBharata B Rao node); 2213b556854bSBharata B Rao return; 2214b556854bSBharata B Rao } 2215b556854bSBharata B Rao 2216c20d332aSBharata B Rao spapr_memory_plug(hotplug_dev, dev, node, errp); 2217c20d332aSBharata B Rao } 2218c20d332aSBharata B Rao } 2219c20d332aSBharata B Rao 2220c20d332aSBharata B Rao static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, 2221c20d332aSBharata B Rao DeviceState *dev, Error **errp) 2222c20d332aSBharata B Rao { 2223c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2224c20d332aSBharata B Rao error_setg(errp, "Memory hot unplug not supported by sPAPR"); 2225c20d332aSBharata B Rao } 2226c20d332aSBharata B Rao } 2227c20d332aSBharata B Rao 2228c20d332aSBharata B Rao static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, 2229c20d332aSBharata B Rao DeviceState *dev) 2230c20d332aSBharata B Rao { 2231c20d332aSBharata B Rao if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { 2232c20d332aSBharata B Rao return HOTPLUG_HANDLER(machine); 2233c20d332aSBharata B Rao } 2234c20d332aSBharata B Rao return NULL; 2235c20d332aSBharata B Rao } 2236c20d332aSBharata B Rao 223720bb648dSDavid Gibson static unsigned spapr_cpu_index_to_socket_id(unsigned cpu_index) 223820bb648dSDavid Gibson { 223920bb648dSDavid Gibson /* Allocate to NUMA nodes on a "socket" basis (not that concept of 224020bb648dSDavid Gibson * socket means much for the paravirtualized PAPR platform) */ 224120bb648dSDavid Gibson return cpu_index / smp_threads / smp_cores; 224220bb648dSDavid Gibson } 224320bb648dSDavid Gibson 224429ee3247SAlexey Kardashevskiy static void spapr_machine_class_init(ObjectClass *oc, void *data) 224553018216SPaolo Bonzini { 224629ee3247SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 2247224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 224871461b0fSAlexey Kardashevskiy FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); 224934316482SAlexey Kardashevskiy NMIClass *nc = NMI_CLASS(oc); 2250c20d332aSBharata B Rao HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); 225129ee3247SAlexey Kardashevskiy 2252958db90cSMarcel Apfelbaum mc->init = ppc_spapr_init; 2253958db90cSMarcel Apfelbaum mc->reset = ppc_spapr_reset; 2254958db90cSMarcel Apfelbaum mc->block_default_type = IF_SCSI; 225538b02bd8SAlexey Kardashevskiy mc->max_cpus = MAX_CPUMASK_BITS; 2256958db90cSMarcel Apfelbaum mc->no_parallel = 1; 22575b2128d2SAlexander Graf mc->default_boot_order = ""; 2258a34944feSNikunj A Dadhania mc->default_ram_size = 512 * M_BYTE; 2259958db90cSMarcel Apfelbaum mc->kvm_type = spapr_kvm_type; 22609e3f9733SAlexander Graf mc->has_dynamic_sysbus = true; 2261e4024630SLaurent Vivier mc->pci_allow_0_address = true; 2262c20d332aSBharata B Rao mc->get_hotplug_handler = spapr_get_hotpug_handler; 2263c20d332aSBharata B Rao hc->plug = spapr_machine_device_plug; 2264c20d332aSBharata B Rao hc->unplug = spapr_machine_device_unplug; 226520bb648dSDavid Gibson mc->cpu_index_to_socket_id = spapr_cpu_index_to_socket_id; 226600b4fbe2SMarcel Apfelbaum 2267224245bfSDavid Gibson smc->dr_lmb_enabled = false; 226871461b0fSAlexey Kardashevskiy fwc->get_dev_path = spapr_get_fw_dev_path; 226934316482SAlexey Kardashevskiy nc->nmi_monitor_handler = spapr_nmi; 227053018216SPaolo Bonzini } 227153018216SPaolo Bonzini 227229ee3247SAlexey Kardashevskiy static const TypeInfo spapr_machine_info = { 227329ee3247SAlexey Kardashevskiy .name = TYPE_SPAPR_MACHINE, 227429ee3247SAlexey Kardashevskiy .parent = TYPE_MACHINE, 22754aee7362SDavid Gibson .abstract = true, 22766ca1502eSAlexey Kardashevskiy .instance_size = sizeof(sPAPRMachineState), 227723825581SEduardo Habkost .instance_init = spapr_machine_initfn, 2278183930c0SDavid Gibson .class_size = sizeof(sPAPRMachineClass), 227929ee3247SAlexey Kardashevskiy .class_init = spapr_machine_class_init, 228071461b0fSAlexey Kardashevskiy .interfaces = (InterfaceInfo[]) { 228171461b0fSAlexey Kardashevskiy { TYPE_FW_PATH_PROVIDER }, 228234316482SAlexey Kardashevskiy { TYPE_NMI }, 2283c20d332aSBharata B Rao { TYPE_HOTPLUG_HANDLER }, 228471461b0fSAlexey Kardashevskiy { } 228571461b0fSAlexey Kardashevskiy }, 228629ee3247SAlexey Kardashevskiy }; 228729ee3247SAlexey Kardashevskiy 228838ff32c6SEduardo Habkost #define SPAPR_COMPAT_2_3 \ 22897619c7b0SMichael Roth HW_COMPAT_2_3 \ 22907619c7b0SMichael Roth {\ 22917619c7b0SMichael Roth .driver = "spapr-pci-host-bridge",\ 22927619c7b0SMichael Roth .property = "dynamic-reconfiguration",\ 22937619c7b0SMichael Roth .value = "off",\ 22947619c7b0SMichael Roth }, 229538ff32c6SEduardo Habkost 2296b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_2 \ 229738ff32c6SEduardo Habkost SPAPR_COMPAT_2_3 \ 22984dfd8eaaSEduardo Habkost HW_COMPAT_2_2 \ 2299b194df47SAlexey Kardashevskiy {\ 2300b194df47SAlexey Kardashevskiy .driver = TYPE_SPAPR_PCI_HOST_BRIDGE,\ 2301b194df47SAlexey Kardashevskiy .property = "mem_win_size",\ 2302b194df47SAlexey Kardashevskiy .value = "0x20000000",\ 2303dd754bafSEduardo Habkost }, 2304b194df47SAlexey Kardashevskiy 2305b194df47SAlexey Kardashevskiy #define SPAPR_COMPAT_2_1 \ 23064dfd8eaaSEduardo Habkost SPAPR_COMPAT_2_2 \ 23074dfd8eaaSEduardo Habkost HW_COMPAT_2_1 2308b194df47SAlexey Kardashevskiy 2309d25228e7SJason Wang static void spapr_compat_2_3(Object *obj) 2310d25228e7SJason Wang { 2311ff14e817SDr. David Alan Gilbert savevm_skip_section_footers(); 231213d16814SJuan Quintela global_state_set_optional(); 2313d25228e7SJason Wang } 2314d25228e7SJason Wang 2315b0e966d0SJason Wang static void spapr_compat_2_2(Object *obj) 2316b0e966d0SJason Wang { 2317d25228e7SJason Wang spapr_compat_2_3(obj); 2318b0e966d0SJason Wang } 2319b0e966d0SJason Wang 2320b0e966d0SJason Wang static void spapr_compat_2_1(Object *obj) 2321b0e966d0SJason Wang { 2322b0e966d0SJason Wang spapr_compat_2_2(obj); 2323b0e966d0SJason Wang } 2324b0e966d0SJason Wang 2325d25228e7SJason Wang static void spapr_machine_2_3_instance_init(Object *obj) 2326d25228e7SJason Wang { 2327d25228e7SJason Wang spapr_compat_2_3(obj); 2328d25228e7SJason Wang spapr_machine_initfn(obj); 2329d25228e7SJason Wang } 2330d25228e7SJason Wang 2331b0e966d0SJason Wang static void spapr_machine_2_2_instance_init(Object *obj) 2332b0e966d0SJason Wang { 2333b0e966d0SJason Wang spapr_compat_2_2(obj); 2334b0e966d0SJason Wang spapr_machine_initfn(obj); 2335b0e966d0SJason Wang } 2336b0e966d0SJason Wang 2337b0e966d0SJason Wang static void spapr_machine_2_1_instance_init(Object *obj) 2338b0e966d0SJason Wang { 2339b0e966d0SJason Wang spapr_compat_2_1(obj); 2340b0e966d0SJason Wang spapr_machine_initfn(obj); 2341b0e966d0SJason Wang } 2342b0e966d0SJason Wang 23436026db45SAlexey Kardashevskiy static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data) 23446026db45SAlexey Kardashevskiy { 23456026db45SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 234668a27b20SMichael S. Tsirkin static GlobalProperty compat_props[] = { 2347dd754bafSEduardo Habkost SPAPR_COMPAT_2_1 234868a27b20SMichael S. Tsirkin { /* end of list */ } 234968a27b20SMichael S. Tsirkin }; 23506026db45SAlexey Kardashevskiy 23516026db45SAlexey Kardashevskiy mc->desc = "pSeries Logical Partition (PAPR compliant) v2.1"; 235268a27b20SMichael S. Tsirkin mc->compat_props = compat_props; 23536026db45SAlexey Kardashevskiy } 23546026db45SAlexey Kardashevskiy 23556026db45SAlexey Kardashevskiy static const TypeInfo spapr_machine_2_1_info = { 2356b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.1"), 23576026db45SAlexey Kardashevskiy .parent = TYPE_SPAPR_MACHINE, 23586026db45SAlexey Kardashevskiy .class_init = spapr_machine_2_1_class_init, 2359b0e966d0SJason Wang .instance_init = spapr_machine_2_1_instance_init, 23606026db45SAlexey Kardashevskiy }; 23616026db45SAlexey Kardashevskiy 23624aee7362SDavid Gibson static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data) 23634aee7362SDavid Gibson { 2364b194df47SAlexey Kardashevskiy static GlobalProperty compat_props[] = { 2365dd754bafSEduardo Habkost SPAPR_COMPAT_2_2 2366b194df47SAlexey Kardashevskiy { /* end of list */ } 2367b194df47SAlexey Kardashevskiy }; 23684aee7362SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); 23694aee7362SDavid Gibson 23704aee7362SDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant) v2.2"; 2371b194df47SAlexey Kardashevskiy mc->compat_props = compat_props; 23724aee7362SDavid Gibson } 23734aee7362SDavid Gibson 23744aee7362SDavid Gibson static const TypeInfo spapr_machine_2_2_info = { 2375b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.2"), 23764aee7362SDavid Gibson .parent = TYPE_SPAPR_MACHINE, 23774aee7362SDavid Gibson .class_init = spapr_machine_2_2_class_init, 2378b0e966d0SJason Wang .instance_init = spapr_machine_2_2_instance_init, 23794aee7362SDavid Gibson }; 23804aee7362SDavid Gibson 23813dab0244SAlexey Kardashevskiy static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data) 23823dab0244SAlexey Kardashevskiy { 2383a1a45612SDavid Gibson static GlobalProperty compat_props[] = { 23847619c7b0SMichael Roth SPAPR_COMPAT_2_3 2385a1a45612SDavid Gibson { /* end of list */ } 2386a1a45612SDavid Gibson }; 23873dab0244SAlexey Kardashevskiy MachineClass *mc = MACHINE_CLASS(oc); 23883dab0244SAlexey Kardashevskiy 23893dab0244SAlexey Kardashevskiy mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3"; 2390a1a45612SDavid Gibson mc->compat_props = compat_props; 23913dab0244SAlexey Kardashevskiy } 23923dab0244SAlexey Kardashevskiy 23933dab0244SAlexey Kardashevskiy static const TypeInfo spapr_machine_2_3_info = { 2394b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.3"), 23953dab0244SAlexey Kardashevskiy .parent = TYPE_SPAPR_MACHINE, 23963dab0244SAlexey Kardashevskiy .class_init = spapr_machine_2_3_class_init, 2397d25228e7SJason Wang .instance_init = spapr_machine_2_3_instance_init, 2398d25228e7SJason Wang }; 2399d25228e7SJason Wang 2400d25228e7SJason Wang static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data) 2401d25228e7SJason Wang { 2402d25228e7SJason Wang MachineClass *mc = MACHINE_CLASS(oc); 2403d25228e7SJason Wang 2404d25228e7SJason Wang mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4"; 2405d25228e7SJason Wang mc->alias = "pseries"; 2406fb0fc8f6SDavid Gibson mc->is_default = 0; 2407d25228e7SJason Wang } 2408d25228e7SJason Wang 2409d25228e7SJason Wang static const TypeInfo spapr_machine_2_4_info = { 2410b9f072d0SEduardo Habkost .name = MACHINE_TYPE_NAME("pseries-2.4"), 2411d25228e7SJason Wang .parent = TYPE_SPAPR_MACHINE, 2412d25228e7SJason Wang .class_init = spapr_machine_2_4_class_init, 24133dab0244SAlexey Kardashevskiy }; 24143dab0244SAlexey Kardashevskiy 2415fb0fc8f6SDavid Gibson static void spapr_machine_2_5_class_init(ObjectClass *oc, void *data) 2416fb0fc8f6SDavid Gibson { 2417fb0fc8f6SDavid Gibson MachineClass *mc = MACHINE_CLASS(oc); 2418224245bfSDavid Gibson sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); 2419fb0fc8f6SDavid Gibson 2420fb0fc8f6SDavid Gibson mc->name = "pseries-2.5"; 2421fb0fc8f6SDavid Gibson mc->desc = "pSeries Logical Partition (PAPR compliant) v2.5"; 2422fb0fc8f6SDavid Gibson mc->alias = "pseries"; 2423fb0fc8f6SDavid Gibson mc->is_default = 1; 2424224245bfSDavid Gibson smc->dr_lmb_enabled = true; 2425fb0fc8f6SDavid Gibson } 2426fb0fc8f6SDavid Gibson 2427fb0fc8f6SDavid Gibson static const TypeInfo spapr_machine_2_5_info = { 2428fb0fc8f6SDavid Gibson .name = MACHINE_TYPE_NAME("pseries-2.5"), 2429fb0fc8f6SDavid Gibson .parent = TYPE_SPAPR_MACHINE, 2430fb0fc8f6SDavid Gibson .class_init = spapr_machine_2_5_class_init, 2431fb0fc8f6SDavid Gibson }; 2432fb0fc8f6SDavid Gibson 243329ee3247SAlexey Kardashevskiy static void spapr_machine_register_types(void) 243429ee3247SAlexey Kardashevskiy { 243529ee3247SAlexey Kardashevskiy type_register_static(&spapr_machine_info); 24366026db45SAlexey Kardashevskiy type_register_static(&spapr_machine_2_1_info); 24374aee7362SDavid Gibson type_register_static(&spapr_machine_2_2_info); 24383dab0244SAlexey Kardashevskiy type_register_static(&spapr_machine_2_3_info); 2439d25228e7SJason Wang type_register_static(&spapr_machine_2_4_info); 2440fb0fc8f6SDavid Gibson type_register_static(&spapr_machine_2_5_info); 244129ee3247SAlexey Kardashevskiy } 244229ee3247SAlexey Kardashevskiy 244329ee3247SAlexey Kardashevskiy type_init(spapr_machine_register_types) 2444